sticker: finish stickers api

v3.3
Demian 2 months ago
parent 32b47a49ef
commit 435ad606fa

@ -163,6 +163,19 @@ func addFileToWriter(writer *multipart.Writer, filename, field string, file inte
return err
}
func (f *File) process(name string, files map[string]File) string {
switch {
case f.InCloud():
return f.FileID
case f.FileURL != "":
return f.FileURL
case f.OnDisk() || f.FileReader != nil:
files[name] = *f
return "attach://" + name
}
return ""
}
func (b *Bot) sendText(to Recipient, text string, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),

@ -305,21 +305,8 @@ func (b *Bot) SendAlbum(to Recipient, a Album, opts ...interface{}) ([]Message,
files := make(map[string]File)
for i, x := range a {
var (
repr string
data []byte
file = x.MediaFile()
)
switch {
case file.InCloud():
repr = file.FileID
case file.FileURL != "":
repr = file.FileURL
case file.OnDisk() || file.FileReader != nil:
repr = "attach://" + strconv.Itoa(i)
files[strconv.Itoa(i)] = *file
default:
repr := x.MediaFile().process(strconv.Itoa(i), files)
if repr == "" {
return nil, fmt.Errorf("telebot: album entry #%d does not exist", i)
}
@ -332,7 +319,7 @@ func (b *Bot) SendAlbum(to Recipient, a Album, opts ...interface{}) ([]Message,
im.ParseMode = sendOpts.ParseMode
}
data, _ = json.Marshal(im)
data, _ := json.Marshal(im)
media[i] = string(data)
}

@ -24,6 +24,9 @@ var (
b, _ = newTestBot() // cached bot instance to avoid getMe method flooding
to = &Chat{ID: chatID} // to chat recipient for send and edit methods
user = &User{ID: userID} // to user recipient for some special cases
logo = FromURL("https://telegra.ph/file/c95b8fe46dd3df15d12e5.png")
thumb = FromURL("https://telegra.ph/file/fe28e378784b3a4e367fb.png")
)
func defaultSettings() Settings {
@ -502,7 +505,7 @@ func TestBot(t *testing.T) {
assert.Equal(t, ErrBadRecipient, err)
photo := &Photo{
File: FromURL("https://telegra.ph/file/65c5237b040ebf80ec278.jpg"),
File: logo,
Caption: t.Name(),
}
var msg *Message

@ -280,6 +280,7 @@ func (v *VideoNote) MediaFile() *File {
// Sticker object represents a WebP image, so-called sticker.
type Sticker struct {
File
Type StickerSetType `json:"type"`
Width int `json:"width"`
Height int `json:"height"`
Animated bool `json:"is_animated"`
@ -287,13 +288,10 @@ type Sticker struct {
Thumbnail *Photo `json:"thumbnail"`
Emoji string `json:"emoji"`
SetName string `json:"set_name"`
MaskPosition *MaskPosition `json:"mask_position"`
PremiumAnimation *File `json:"premium_animation"`
Type StickerSetType `json:"type"`
MaskPosition *MaskPosition `json:"mask_position"`
CustomEmoji string `json:"custom_emoji_id"`
Repaint bool `json:"needs_repainting"`
Emojis []string `json:"emoji_list"`
Keywords []string `json:"keywords"`
}
func (s *Sticker) MediaType() string {
@ -304,12 +302,6 @@ func (s *Sticker) MediaFile() *File {
return &s.File
}
func (s *Sticker) InputMedia() InputMedia {
return InputMedia{
Type: s.MediaType(),
}
}
// Contact object represents a contact to Telegram user.
type Contact struct {
PhoneNumber string `json:"phone_number"`

@ -2,24 +2,34 @@ package telebot
import (
"encoding/json"
"errors"
"fmt"
"strconv"
)
type StickerSetType = string
type (
StickerSetType = string
StickerSetFormat = string
MaskFeature = string
)
const (
StickerRegular = "regular"
StickerMask = "mask"
StickerCustomEmoji = "custom_emoji"
StickerRegular StickerSetType = "regular"
StickerMask StickerSetType = "mask"
StickerCustomEmoji StickerSetType = "custom_emoji"
)
type StickerSetFormat = string
const (
StickerStatic StickerSetFormat = "static"
StickerAnimated StickerSetFormat = "animated"
StickerVideo StickerSetFormat = "video"
)
const (
StickerStatic = "static"
StickerAnimated = "animated"
StickerVideo = "video"
MaskForehead MaskFeature = "forehead"
MaskEyes MaskFeature = "eyes"
MaskMouth MaskFeature = "mouth"
MaskChin MaskFeature = "chin"
)
// StickerSet represents a sticker set.
@ -31,12 +41,23 @@ type StickerSet struct {
Animated bool `json:"is_animated"`
Video bool `json:"is_video"`
Stickers []Sticker `json:"stickers"`
Sticker Sticker `json:"sticker"`
Thumbnail *Photo `json:"thumbnail"`
Emojis string `json:"emojis"`
ContainsMasks bool `json:"contains_masks"` // FIXME: can be removed
MaskPosition *MaskPosition `json:"mask_position"`
Repaint bool `json:"needs_repainting"`
// Input is a field used in createNewStickerSet method to specify a list
// of pre-defined stickers of type InputSticker to add to the set.
Input []InputSticker
}
type InputSticker struct {
File
Sticker string `json:"sticker"`
MaskPosition *MaskPosition `json:"mask_position"`
Emojis []string `json:"emoji_list"`
Keywords []string `json:"keywords"`
}
// MaskPosition describes the position on faces where
@ -48,28 +69,14 @@ type MaskPosition struct {
Scale float32 `json:"scale"`
}
// MaskFeature defines sticker mask position.
type MaskFeature string
const (
FeatureForehead MaskFeature = "forehead"
FeatureEyes MaskFeature = "eyes"
FeatureMouth MaskFeature = "mouth"
FeatureChin MaskFeature = "chin"
)
// UploadSticker uploads a PNG file with a sticker for later use.
func (b *Bot) UploadSticker(to Recipient, s StickerSet) (*File, error) {
files := map[string]File{
"sticker": s.Sticker.File,
}
// UploadSticker uploads a sticker file for later use.
func (b *Bot) UploadSticker(to Recipient, format StickerSetFormat, f File) (*File, error) {
params := map[string]string{
"user_id": to.Recipient(),
"sticker_format": s.Format,
"sticker_format": format,
}
data, err := b.sendFiles("uploadStickerFile", files, params)
data, err := b.sendFiles("uploadStickerFile", map[string]File{"0": f}, params)
if err != nil {
return nil, err
}
@ -100,56 +107,51 @@ func (b *Bot) StickerSet(name string) (*StickerSet, error) {
}
// CreateStickerSet creates a new sticker set.
func (b *Bot) CreateStickerSet(to Recipient, s StickerSet) error {
func (b *Bot) CreateStickerSet(of Recipient, set *StickerSet) error {
files := make(map[string]File)
for i, sticker := range s.Stickers {
key := fmt.Sprint("sticker", i)
files[key] = sticker.File
for i, s := range set.Input {
repr := s.File.process(strconv.Itoa(i), files)
if repr == "" {
return fmt.Errorf("telebot: sticker #%d does not exist", i+1)
}
set.Input[i].Sticker = repr
}
data, err := json.Marshal(s.Stickers)
if err != nil {
return err
}
data, _ := json.Marshal(set.Input)
params := map[string]string{
"user_id": to.Recipient(),
"name": s.Name,
"title": s.Title,
"sticker_type": s.Type,
"sticker_format": s.Format,
"stickers": string(data),
"needs_repainting": strconv.FormatBool(s.Repaint),
"user_id": of.Recipient(),
"name": set.Name,
"title": set.Title,
"sticker_format": set.Format,
"stickers": string(data),
}
if set.Type != "" {
params["sticker_type"] = set.Type
}
if set.Repaint {
params["needs_repainting"] = "true"
}
_, err = b.sendFiles("createNewStickerSet", files, params)
_, err := b.sendFiles("createNewStickerSet", files, params)
return err
}
// AddStickerToSet adds a new sticker to the existing sticker set.
func (b *Bot) AddStickerToSet(to Recipient, s StickerSet) error {
var (
files = make(map[string]File)
sticker = s.Sticker
)
files["sticker"] = sticker.File
params := map[string]string{
"user_id": to.Recipient(),
"name": s.Name,
func (b *Bot) AddStickerToSet(of Recipient, name string, sticker InputSticker) error {
files := make(map[string]File)
repr := sticker.File.process("0", files)
if repr == "" {
return errors.New("telebot: sticker does not exist")
}
if sticker.Emojis != nil {
data, _ := json.Marshal(s.Emojis)
params["emoji_list"] = string(data)
}
if s.MaskPosition != nil {
data, _ := json.Marshal(s.MaskPosition)
params["mask_position"] = string(data)
}
if sticker.Keywords != nil {
data, _ := json.Marshal(sticker.Keywords)
params["keywords"] = string(data)
sticker.Sticker = repr
data, _ := json.Marshal(sticker)
params := map[string]string{
"user_id": of.Recipient(),
"name": name,
"sticker": string(data),
}
_, err := b.sendFiles("addStickerToSet", files, params)
@ -182,25 +184,24 @@ func (b *Bot) DeleteSticker(sticker string) error {
// up to 32 kilobytes in size.
//
// Animated sticker set thumbnail can't be uploaded via HTTP URL.
func (b *Bot) SetStickerSetThumb(to Recipient, s StickerSet) error {
var (
sticker = s.Sticker
files = make(map[string]File)
)
files["thumbnail"] = sticker.File
data, err := json.Marshal(sticker.File)
if err != nil {
return err
func (b *Bot) SetStickerSetThumb(of Recipient, set *StickerSet) error {
if set.Thumbnail == nil {
return errors.New("telebot: thumbnail is required")
}
files := make(map[string]File)
repr := set.Thumbnail.File.process("thumb", files)
if repr == "" {
return errors.New("telebot: thumbnail does not exist")
}
params := map[string]string{
"name": s.Name,
"user_id": to.Recipient(),
"thumbnail": string(data),
"user_id": of.Recipient(),
"name": set.Name,
"thumbnail": repr,
}
_, err = b.sendFiles("setStickerSetThumbnail", files, params)
_, err := b.sendFiles("setStickerSetThumbnail", files, params)
return err
}
@ -223,8 +224,8 @@ func (b *Bot) DeleteStickerSet(name string) error {
return err
}
// SetStickerEmojiList changes the list of emoji assigned to a regular or custom emoji sticker.
func (b *Bot) SetStickerEmojiList(sticker string, emojis []string) error {
// SetStickerEmojis changes the list of emoji assigned to a regular or custom emoji sticker.
func (b *Bot) SetStickerEmojis(sticker string, emojis []string) error {
data, err := json.Marshal(emojis)
if err != nil {
return err

@ -0,0 +1,61 @@
package telebot
import (
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestStickerSet(t *testing.T) {
if b == nil {
t.Skip("Cached bot instance is bad (probably wrong or empty TELEBOT_SECRET)")
}
if userID == 0 {
t.Skip("USER_ID is required for StickerSet methods test")
}
input := []InputSticker{
{
File: FromURL("https://placehold.co/512/000000/FFFFFF/png"),
Emojis: []string{"🤖"},
Keywords: []string{"telebot", "robot", "bot"},
},
{
File: FromURL("https://placehold.co/512/000000/999999/png"),
Emojis: []string{"🤖"},
Keywords: []string{"telebot", "robot", "bot"},
},
}
original := &StickerSet{
Name: fmt.Sprintf("telebot_%d_by_%s", time.Now().Unix(), b.Me.Username),
Type: StickerRegular,
Format: StickerStatic,
Title: "Telebot Stickers",
Input: input[:1],
}
// 1
err := b.CreateStickerSet(user, original)
require.NoError(t, err)
// 2
err = b.AddStickerToSet(user, original.Name, input[1])
require.NoError(t, err)
original.Thumbnail = &Photo{File: thumb}
err = b.SetStickerSetThumb(user, original)
require.NoError(t, err)
set, err := b.StickerSet(original.Name)
require.NoError(t, err)
require.Equal(t, original.Name, set.Name)
require.Equal(t, len(input), len(set.Stickers))
_, err = b.Send(user, &set.Stickers[0])
require.NoError(t, err)
_, err = b.Send(user, &set.Stickers[1])
require.NoError(t, err)
}
Loading…
Cancel
Save