|
|
|
@ -91,14 +91,14 @@ type Settings struct {
|
|
|
|
|
type Update struct {
|
|
|
|
|
ID int `json:"update_id"`
|
|
|
|
|
|
|
|
|
|
Message *Message `json:"message,omitempty"`
|
|
|
|
|
EditedMessage *Message `json:"edited_message,omitempty"`
|
|
|
|
|
ChannelPost *Message `json:"channel_post,omitempty"`
|
|
|
|
|
EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
|
|
|
|
|
Callback *Callback `json:"callback_query,omitempty"`
|
|
|
|
|
Query *Query `json:"inline_query,omitempty"`
|
|
|
|
|
Message *Message `json:"message,omitempty"`
|
|
|
|
|
EditedMessage *Message `json:"edited_message,omitempty"`
|
|
|
|
|
ChannelPost *Message `json:"channel_post,omitempty"`
|
|
|
|
|
EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
|
|
|
|
|
Callback *Callback `json:"callback_query,omitempty"`
|
|
|
|
|
Query *Query `json:"inline_query,omitempty"`
|
|
|
|
|
ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result,omitempty"`
|
|
|
|
|
PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"`
|
|
|
|
|
PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ChosenInlineResult represents a result of an inline query that was chosen
|
|
|
|
@ -106,11 +106,10 @@ type Update struct {
|
|
|
|
|
type ChosenInlineResult struct {
|
|
|
|
|
From User `json:"from"`
|
|
|
|
|
Location *Location `json:"location,omitempty"`
|
|
|
|
|
ResultID string `json:"result_id"`
|
|
|
|
|
Query string `json:"query"`
|
|
|
|
|
ResultID string `json:"result_id"`
|
|
|
|
|
Query string `json:"query"`
|
|
|
|
|
// Inline messages only!
|
|
|
|
|
MessageID string `json:"inline_message_id"`
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type PreCheckoutQuery struct {
|
|
|
|
@ -744,121 +743,121 @@ func (b *Bot) EditCaption(originalMsg Editable, caption string) (*Message, error
|
|
|
|
|
// bot.EditMedia(msg, &tb.Video{File: tb.FromURL("http://video.mp4")});
|
|
|
|
|
//
|
|
|
|
|
func (b *Bot) EditMedia(message Editable, inputMedia InputMedia, options ...interface{}) (*Message, error) {
|
|
|
|
|
var mediaRepr string;
|
|
|
|
|
var jsonRepr []byte;
|
|
|
|
|
var thumb *Photo;
|
|
|
|
|
var mediaRepr string
|
|
|
|
|
var jsonRepr []byte
|
|
|
|
|
var thumb *Photo
|
|
|
|
|
|
|
|
|
|
file := make(map[string]File);
|
|
|
|
|
file := make(map[string]File)
|
|
|
|
|
|
|
|
|
|
f := inputMedia.MediaFile();
|
|
|
|
|
f := inputMedia.MediaFile()
|
|
|
|
|
|
|
|
|
|
if f.InCloud() {
|
|
|
|
|
mediaRepr = f.FileID;
|
|
|
|
|
mediaRepr = f.FileID
|
|
|
|
|
} else if f.FileURL != "" {
|
|
|
|
|
mediaRepr = f.FileURL;
|
|
|
|
|
mediaRepr = f.FileURL
|
|
|
|
|
} else if f.OnDisk() || f.FileReader != nil {
|
|
|
|
|
s := f.FileLocal;
|
|
|
|
|
if (f.FileReader != nil) {
|
|
|
|
|
s = "0";
|
|
|
|
|
s := f.FileLocal
|
|
|
|
|
if f.FileReader != nil {
|
|
|
|
|
s = "0"
|
|
|
|
|
}
|
|
|
|
|
mediaRepr = "attach://" + s;
|
|
|
|
|
file[s] = *f;
|
|
|
|
|
mediaRepr = "attach://" + s
|
|
|
|
|
file[s] = *f
|
|
|
|
|
} else {
|
|
|
|
|
return nil, errors.Errorf(
|
|
|
|
|
"telebot: can't edit media, it doesn't exist anywhere");
|
|
|
|
|
"telebot: can't edit media, it doesn't exist anywhere")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type FileJson struct {
|
|
|
|
|
// All types.
|
|
|
|
|
Type string `json:"type"`
|
|
|
|
|
Caption string `json:"caption"`
|
|
|
|
|
Media string `json:"media"`
|
|
|
|
|
Type string `json:"type"`
|
|
|
|
|
Caption string `json:"caption"`
|
|
|
|
|
Media string `json:"media"`
|
|
|
|
|
|
|
|
|
|
// Video.
|
|
|
|
|
Width int `json:"width,omitempty"`
|
|
|
|
|
Height int `json:"height,omitempty"`
|
|
|
|
|
SupportsStreaming bool `json:"supports_streaming,omitempty"`
|
|
|
|
|
Width int `json:"width,omitempty"`
|
|
|
|
|
Height int `json:"height,omitempty"`
|
|
|
|
|
SupportsStreaming bool `json:"supports_streaming,omitempty"`
|
|
|
|
|
|
|
|
|
|
// Video and audio.
|
|
|
|
|
Duration int `json:"duration,omitempty"`
|
|
|
|
|
Duration int `json:"duration,omitempty"`
|
|
|
|
|
|
|
|
|
|
// Document.
|
|
|
|
|
FileName string `json:"file_name"`
|
|
|
|
|
FileName string `json:"file_name"`
|
|
|
|
|
|
|
|
|
|
// Document, video and audio.
|
|
|
|
|
Thumbnail string `json:"thumb,omitempty"`
|
|
|
|
|
MIME string `json:"mime_type,omitempty"`
|
|
|
|
|
Thumbnail string `json:"thumb,omitempty"`
|
|
|
|
|
MIME string `json:"mime_type,omitempty"`
|
|
|
|
|
|
|
|
|
|
// Audio.
|
|
|
|
|
Title string `json:"title,omitempty"`
|
|
|
|
|
Performer string `json:"performer,omitempty"`
|
|
|
|
|
Title string `json:"title,omitempty"`
|
|
|
|
|
Performer string `json:"performer,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resultMedia := &FileJson {Media: mediaRepr};
|
|
|
|
|
resultMedia := &FileJson{Media: mediaRepr}
|
|
|
|
|
|
|
|
|
|
switch y := inputMedia.(type) {
|
|
|
|
|
case *Photo:
|
|
|
|
|
resultMedia.Type = "photo";
|
|
|
|
|
resultMedia.Caption = y.Caption;
|
|
|
|
|
case *Video:
|
|
|
|
|
resultMedia.Type = "video";
|
|
|
|
|
resultMedia.Caption = y.Caption;
|
|
|
|
|
resultMedia.Width = y.Width;
|
|
|
|
|
resultMedia.Height = y.Height;
|
|
|
|
|
resultMedia.Duration = y.Duration;
|
|
|
|
|
resultMedia.SupportsStreaming = y.SupportsStreaming;
|
|
|
|
|
resultMedia.MIME = y.MIME;
|
|
|
|
|
thumb = y.Thumbnail;
|
|
|
|
|
if thumb != nil {
|
|
|
|
|
resultMedia.Thumbnail = "attach://thumb";
|
|
|
|
|
}
|
|
|
|
|
case *Document:
|
|
|
|
|
resultMedia.Type = "document";
|
|
|
|
|
resultMedia.Caption = y.Caption;
|
|
|
|
|
resultMedia.FileName = y.FileName;
|
|
|
|
|
resultMedia.MIME = y.MIME;
|
|
|
|
|
thumb = y.Thumbnail;
|
|
|
|
|
if thumb != nil {
|
|
|
|
|
resultMedia.Thumbnail = "attach://thumb";
|
|
|
|
|
}
|
|
|
|
|
case *Audio:
|
|
|
|
|
resultMedia.Type = "audio";
|
|
|
|
|
resultMedia.Caption = y.Caption;
|
|
|
|
|
resultMedia.Duration = y.Duration;
|
|
|
|
|
resultMedia.MIME = y.MIME;
|
|
|
|
|
resultMedia.Title = y.Title;
|
|
|
|
|
resultMedia.Performer = y.Performer;
|
|
|
|
|
default:
|
|
|
|
|
return nil, errors.Errorf("telebot: inputMedia entry is not valid");
|
|
|
|
|
case *Photo:
|
|
|
|
|
resultMedia.Type = "photo"
|
|
|
|
|
resultMedia.Caption = y.Caption
|
|
|
|
|
case *Video:
|
|
|
|
|
resultMedia.Type = "video"
|
|
|
|
|
resultMedia.Caption = y.Caption
|
|
|
|
|
resultMedia.Width = y.Width
|
|
|
|
|
resultMedia.Height = y.Height
|
|
|
|
|
resultMedia.Duration = y.Duration
|
|
|
|
|
resultMedia.SupportsStreaming = y.SupportsStreaming
|
|
|
|
|
resultMedia.MIME = y.MIME
|
|
|
|
|
thumb = y.Thumbnail
|
|
|
|
|
if thumb != nil {
|
|
|
|
|
resultMedia.Thumbnail = "attach://thumb"
|
|
|
|
|
}
|
|
|
|
|
case *Document:
|
|
|
|
|
resultMedia.Type = "document"
|
|
|
|
|
resultMedia.Caption = y.Caption
|
|
|
|
|
resultMedia.FileName = y.FileName
|
|
|
|
|
resultMedia.MIME = y.MIME
|
|
|
|
|
thumb = y.Thumbnail
|
|
|
|
|
if thumb != nil {
|
|
|
|
|
resultMedia.Thumbnail = "attach://thumb"
|
|
|
|
|
}
|
|
|
|
|
case *Audio:
|
|
|
|
|
resultMedia.Type = "audio"
|
|
|
|
|
resultMedia.Caption = y.Caption
|
|
|
|
|
resultMedia.Duration = y.Duration
|
|
|
|
|
resultMedia.MIME = y.MIME
|
|
|
|
|
resultMedia.Title = y.Title
|
|
|
|
|
resultMedia.Performer = y.Performer
|
|
|
|
|
default:
|
|
|
|
|
return nil, errors.Errorf("telebot: inputMedia entry is not valid")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
messageID, chatID := message.MessageSig();
|
|
|
|
|
messageID, chatID := message.MessageSig()
|
|
|
|
|
|
|
|
|
|
jsonRepr, _ = json.Marshal(resultMedia);
|
|
|
|
|
params := map[string]string{};
|
|
|
|
|
params["media"] = string(jsonRepr);
|
|
|
|
|
jsonRepr, _ = json.Marshal(resultMedia)
|
|
|
|
|
params := map[string]string{}
|
|
|
|
|
params["media"] = string(jsonRepr)
|
|
|
|
|
|
|
|
|
|
// If inline message.
|
|
|
|
|
if chatID == 0 {
|
|
|
|
|
params["inline_message_id"] = messageID;
|
|
|
|
|
params["inline_message_id"] = messageID
|
|
|
|
|
} else {
|
|
|
|
|
params["chat_id"] = strconv.FormatInt(chatID, 10);
|
|
|
|
|
params["message_id"] = messageID;
|
|
|
|
|
params["chat_id"] = strconv.FormatInt(chatID, 10)
|
|
|
|
|
params["message_id"] = messageID
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if thumb != nil {
|
|
|
|
|
file["thumb"] = *thumb.MediaFile();
|
|
|
|
|
file["thumb"] = *thumb.MediaFile()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sendOpts := extractOptions(options);
|
|
|
|
|
embedSendOptions(params, sendOpts);
|
|
|
|
|
sendOpts := extractOptions(options)
|
|
|
|
|
embedSendOptions(params, sendOpts)
|
|
|
|
|
|
|
|
|
|
respJSON, err := b.sendFiles("editMessageMedia", file, params);
|
|
|
|
|
respJSON, err := b.sendFiles("editMessageMedia", file, params)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err;
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return extractMsgResponse(respJSON);
|
|
|
|
|
return extractMsgResponse(respJSON)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Delete removes the message, including service messages,
|
|
|
|
@ -1054,6 +1053,7 @@ func (b *Bot) GetFile(file *File) (io.ReadCloser, error) {
|
|
|
|
|
|
|
|
|
|
return resp.Body, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// StopLiveLocation should be called to stop broadcasting live message location
|
|
|
|
|
// before Location.LivePeriod expires.
|
|
|
|
|
//
|
|
|
|
@ -1357,3 +1357,139 @@ func (b *Bot) FileURLByID(fileID string) (string, error) {
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("%s/file/bot%s/%s", b.URL, b.Token, f.FilePath), nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// UploadStickerFile returns uploaded File on success.
|
|
|
|
|
func (b *Bot) UploadStickerFile(userID int, pngSticker *File) (*File, error) {
|
|
|
|
|
files := map[string]File{
|
|
|
|
|
"png_sticker": *pngSticker,
|
|
|
|
|
}
|
|
|
|
|
params := map[string]string{
|
|
|
|
|
"user_id": strconv.Itoa(userID),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
respJSON, err := b.sendFiles("uploadStickerFile", files, params)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var resp struct {
|
|
|
|
|
Ok bool
|
|
|
|
|
Result File
|
|
|
|
|
Description string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !resp.Ok {
|
|
|
|
|
return nil, errors.Errorf("api error: %s", resp.Description)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &resp.Result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetStickerSet returns StickerSet on success.
|
|
|
|
|
func (b *Bot) GetStickerSet(name string) (*StickerSet, error) {
|
|
|
|
|
respJSON, err := b.Raw("getStickerSet", map[string]string{"name": name})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var resp struct {
|
|
|
|
|
Ok bool
|
|
|
|
|
Description string
|
|
|
|
|
Result *StickerSet
|
|
|
|
|
}
|
|
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !resp.Ok {
|
|
|
|
|
return nil, errors.Errorf("api error: %s", resp.Description)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resp.Result, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CreateNewStickerSet creates new sticker set.
|
|
|
|
|
func (b *Bot) CreateNewStickerSet(sp StickerSetParams, containsMasks bool, maskPosition MaskPosition) error {
|
|
|
|
|
files := map[string]File{
|
|
|
|
|
"png_sticker": *sp.PngSticker,
|
|
|
|
|
}
|
|
|
|
|
params := map[string]string{
|
|
|
|
|
"user_id": strconv.Itoa(sp.UserID),
|
|
|
|
|
"name": sp.Name,
|
|
|
|
|
"title": sp.Title,
|
|
|
|
|
"emojis": sp.Emojis,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if containsMasks {
|
|
|
|
|
mp, err := json.Marshal(&maskPosition)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
params["mask_position"] = string(mp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
respJSON, err := b.sendFiles("createNewStickerSet", files, params)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return extractOkResponse(respJSON)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AddStickerToSet adds new sticker to existing sticker set.
|
|
|
|
|
func (b *Bot) AddStickerToSet(sp StickerSetParams, maskPosition MaskPosition) error {
|
|
|
|
|
files := map[string]File{
|
|
|
|
|
"png_sticker": *sp.PngSticker,
|
|
|
|
|
}
|
|
|
|
|
params := map[string]string{
|
|
|
|
|
"user_id": strconv.Itoa(sp.UserID),
|
|
|
|
|
"name": sp.Name,
|
|
|
|
|
"title": sp.Title,
|
|
|
|
|
"emojis": sp.Emojis,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if maskPosition != (MaskPosition{}) {
|
|
|
|
|
mp, err := json.Marshal(&maskPosition)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
params["mask_position"] = string(mp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
respJSON, err := b.sendFiles("addStickerToSet", files, params)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return extractOkResponse(respJSON)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetStickerPositionInSet moves a sticker in set to a specific position.
|
|
|
|
|
func (b *Bot) SetStickerPositionInSet(sticker string, position int) error {
|
|
|
|
|
params := map[string]string{
|
|
|
|
|
"sticker": sticker,
|
|
|
|
|
"position": strconv.Itoa(position),
|
|
|
|
|
}
|
|
|
|
|
respJSON, err := b.Raw("setStickerPositionInSet", params)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return extractOkResponse(respJSON)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// DeleteStickerFromSet deletes sticker from set created by the bot.
|
|
|
|
|
func (b *Bot) DeleteStickerFromSet(sticker string) error {
|
|
|
|
|
respJSON, err := b.Raw("deleteStickerFromSet", map[string]string{"sticker": sticker})
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return extractOkResponse(respJSON)
|
|
|
|
|
}
|
|
|
|
|