all repos — telegram-bot-api @ 4ec899a62e8ea13f540cdc27b943642958836d4e

Golang bindings for the Telegram Bot API

configs.go (view raw)

   1package tgbotapi
   2
   3import (
   4	"encoding/json"
   5	"io"
   6	"net/url"
   7	"strconv"
   8)
   9
  10// Telegram constants
  11const (
  12	// APIEndpoint is the endpoint for all API methods,
  13	// with formatting for Sprintf.
  14	APIEndpoint = "https://api.telegram.org/bot%s/%s"
  15	// FileEndpoint is the endpoint for downloading a file from Telegram.
  16	FileEndpoint = "https://api.telegram.org/file/bot%s/%s"
  17)
  18
  19// Constant values for ChatActions
  20const (
  21	ChatTyping         = "typing"
  22	ChatUploadPhoto    = "upload_photo"
  23	ChatRecordVideo    = "record_video"
  24	ChatUploadVideo    = "upload_video"
  25	ChatRecordAudio    = "record_audio"
  26	ChatUploadAudio    = "upload_audio"
  27	ChatUploadDocument = "upload_document"
  28	ChatFindLocation   = "find_location"
  29)
  30
  31// API errors
  32const (
  33	// ErrAPIForbidden happens when a token is bad
  34	ErrAPIForbidden = "forbidden"
  35)
  36
  37// Constant values for ParseMode in MessageConfig
  38const (
  39	ModeMarkdown = "Markdown"
  40	ModeHTML     = "HTML"
  41)
  42
  43// Library errors
  44const (
  45	// ErrBadFileType happens when you pass an unknown type
  46	ErrBadFileType = "bad file type"
  47	ErrBadURL      = "bad or empty url"
  48)
  49
  50// Chattable is any config type that can be sent.
  51type Chattable interface {
  52	values() (url.Values, error)
  53	method() string
  54}
  55
  56// Fileable is any config type that can be sent that includes a file.
  57type Fileable interface {
  58	Chattable
  59	params() (map[string]string, error)
  60	name() string
  61	getFile() interface{}
  62	useExistingFile() bool
  63}
  64
  65// BaseChat is base type for all chat config types.
  66type BaseChat struct {
  67	ChatID              int64 // required
  68	ChannelUsername     string
  69	ReplyToMessageID    int
  70	ReplyMarkup         interface{}
  71	DisableNotification bool
  72}
  73
  74// values returns url.Values representation of BaseChat
  75func (chat *BaseChat) values() (url.Values, error) {
  76	v := url.Values{}
  77	if chat.ChannelUsername != "" {
  78		v.Add("chat_id", chat.ChannelUsername)
  79	} else {
  80		v.Add("chat_id", strconv.FormatInt(chat.ChatID, 10))
  81	}
  82
  83	if chat.ReplyToMessageID != 0 {
  84		v.Add("reply_to_message_id", strconv.Itoa(chat.ReplyToMessageID))
  85	}
  86
  87	if chat.ReplyMarkup != nil {
  88		data, err := json.Marshal(chat.ReplyMarkup)
  89		if err != nil {
  90			return v, err
  91		}
  92
  93		v.Add("reply_markup", string(data))
  94	}
  95
  96	v.Add("disable_notification", strconv.FormatBool(chat.DisableNotification))
  97
  98	return v, nil
  99}
 100
 101// BaseFile is a base type for all file config types.
 102type BaseFile struct {
 103	BaseChat
 104	File        interface{}
 105	FileID      string
 106	UseExisting bool
 107	MimeType    string
 108	FileSize    int
 109}
 110
 111// params returns a map[string]string representation of BaseFile.
 112func (file BaseFile) params() (map[string]string, error) {
 113	params := make(map[string]string)
 114
 115	if file.ChannelUsername != "" {
 116		params["chat_id"] = file.ChannelUsername
 117	} else {
 118		params["chat_id"] = strconv.FormatInt(file.ChatID, 10)
 119	}
 120
 121	if file.ReplyToMessageID != 0 {
 122		params["reply_to_message_id"] = strconv.Itoa(file.ReplyToMessageID)
 123	}
 124
 125	if file.ReplyMarkup != nil {
 126		data, err := json.Marshal(file.ReplyMarkup)
 127		if err != nil {
 128			return params, err
 129		}
 130
 131		params["reply_markup"] = string(data)
 132	}
 133
 134	if file.MimeType != "" {
 135		params["mime_type"] = file.MimeType
 136	}
 137
 138	if file.FileSize > 0 {
 139		params["file_size"] = strconv.Itoa(file.FileSize)
 140	}
 141
 142	params["disable_notification"] = strconv.FormatBool(file.DisableNotification)
 143
 144	return params, nil
 145}
 146
 147// getFile returns the file.
 148func (file BaseFile) getFile() interface{} {
 149	return file.File
 150}
 151
 152// useExistingFile returns if the BaseFile has already been uploaded.
 153func (file BaseFile) useExistingFile() bool {
 154	return file.UseExisting
 155}
 156
 157// BaseEdit is base type of all chat edits.
 158type BaseEdit struct {
 159	ChatID          int64
 160	ChannelUsername string
 161	MessageID       int
 162	InlineMessageID string
 163	ReplyMarkup     *InlineKeyboardMarkup
 164}
 165
 166func (edit BaseEdit) values() (url.Values, error) {
 167	v := url.Values{}
 168
 169	if edit.InlineMessageID == "" {
 170		if edit.ChannelUsername != "" {
 171			v.Add("chat_id", edit.ChannelUsername)
 172		} else {
 173			v.Add("chat_id", strconv.FormatInt(edit.ChatID, 10))
 174		}
 175		v.Add("message_id", strconv.Itoa(edit.MessageID))
 176	} else {
 177		v.Add("inline_message_id", edit.InlineMessageID)
 178	}
 179
 180	if edit.ReplyMarkup != nil {
 181		data, err := json.Marshal(edit.ReplyMarkup)
 182		if err != nil {
 183			return v, err
 184		}
 185		v.Add("reply_markup", string(data))
 186	}
 187
 188	return v, nil
 189}
 190
 191// MessageConfig contains information about a SendMessage request.
 192type MessageConfig struct {
 193	BaseChat
 194	Text                  string
 195	ParseMode             string
 196	DisableWebPagePreview bool
 197}
 198
 199// values returns a url.Values representation of MessageConfig.
 200func (config MessageConfig) values() (url.Values, error) {
 201	v, err := config.BaseChat.values()
 202	if err != nil {
 203		return v, err
 204	}
 205	v.Add("text", config.Text)
 206	v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
 207	if config.ParseMode != "" {
 208		v.Add("parse_mode", config.ParseMode)
 209	}
 210
 211	return v, nil
 212}
 213
 214// method returns Telegram API method name for sending Message.
 215func (config MessageConfig) method() string {
 216	return "sendMessage"
 217}
 218
 219// ForwardConfig contains information about a ForwardMessage request.
 220type ForwardConfig struct {
 221	BaseChat
 222	FromChatID          int64 // required
 223	FromChannelUsername string
 224	MessageID           int // required
 225}
 226
 227// values returns a url.Values representation of ForwardConfig.
 228func (config ForwardConfig) values() (url.Values, error) {
 229	v, err := config.BaseChat.values()
 230	if err != nil {
 231		return v, err
 232	}
 233	v.Add("from_chat_id", strconv.FormatInt(config.FromChatID, 10))
 234	v.Add("message_id", strconv.Itoa(config.MessageID))
 235	return v, nil
 236}
 237
 238// method returns Telegram API method name for sending Forward.
 239func (config ForwardConfig) method() string {
 240	return "forwardMessage"
 241}
 242
 243// PhotoConfig contains information about a SendPhoto request.
 244type PhotoConfig struct {
 245	BaseFile
 246	Caption string
 247}
 248
 249// Params returns a map[string]string representation of PhotoConfig.
 250func (config PhotoConfig) params() (map[string]string, error) {
 251	params, _ := config.BaseFile.params()
 252
 253	if config.Caption != "" {
 254		params["caption"] = config.Caption
 255	}
 256
 257	return params, nil
 258}
 259
 260// Values returns a url.Values representation of PhotoConfig.
 261func (config PhotoConfig) values() (url.Values, error) {
 262	v, err := config.BaseChat.values()
 263	if err != nil {
 264		return v, err
 265	}
 266
 267	v.Add(config.name(), config.FileID)
 268	if config.Caption != "" {
 269		v.Add("caption", config.Caption)
 270	}
 271	return v, nil
 272}
 273
 274// name returns the field name for the Photo.
 275func (config PhotoConfig) name() string {
 276	return "photo"
 277}
 278
 279// method returns Telegram API method name for sending Photo.
 280func (config PhotoConfig) method() string {
 281	return "sendPhoto"
 282}
 283
 284// AudioConfig contains information about a SendAudio request.
 285type AudioConfig struct {
 286	BaseFile
 287	Caption   string
 288	Duration  int
 289	Performer string
 290	Title     string
 291}
 292
 293// values returns a url.Values representation of AudioConfig.
 294func (config AudioConfig) values() (url.Values, error) {
 295	v, err := config.BaseChat.values()
 296	if err != nil {
 297		return v, err
 298	}
 299
 300	v.Add(config.name(), config.FileID)
 301	if config.Duration != 0 {
 302		v.Add("duration", strconv.Itoa(config.Duration))
 303	}
 304
 305	if config.Performer != "" {
 306		v.Add("performer", config.Performer)
 307	}
 308	if config.Title != "" {
 309		v.Add("title", config.Title)
 310	}
 311	if config.Caption != "" {
 312		v.Add("caption", config.Caption)
 313	}
 314
 315	return v, nil
 316}
 317
 318// params returns a map[string]string representation of AudioConfig.
 319func (config AudioConfig) params() (map[string]string, error) {
 320	params, _ := config.BaseFile.params()
 321
 322	if config.Duration != 0 {
 323		params["duration"] = strconv.Itoa(config.Duration)
 324	}
 325
 326	if config.Performer != "" {
 327		params["performer"] = config.Performer
 328	}
 329	if config.Title != "" {
 330		params["title"] = config.Title
 331	}
 332	if config.Caption != "" {
 333		params["caption"] = config.Caption
 334	}
 335
 336	return params, nil
 337}
 338
 339// name returns the field name for the Audio.
 340func (config AudioConfig) name() string {
 341	return "audio"
 342}
 343
 344// method returns Telegram API method name for sending Audio.
 345func (config AudioConfig) method() string {
 346	return "sendAudio"
 347}
 348
 349// DocumentConfig contains information about a SendDocument request.
 350type DocumentConfig struct {
 351	BaseFile
 352	Caption string
 353}
 354
 355// values returns a url.Values representation of DocumentConfig.
 356func (config DocumentConfig) values() (url.Values, error) {
 357	v, err := config.BaseChat.values()
 358	if err != nil {
 359		return v, err
 360	}
 361
 362	v.Add(config.name(), config.FileID)
 363	if config.Caption != "" {
 364		v.Add("caption", config.Caption)
 365	}
 366
 367	return v, nil
 368}
 369
 370// params returns a map[string]string representation of DocumentConfig.
 371func (config DocumentConfig) params() (map[string]string, error) {
 372	params, _ := config.BaseFile.params()
 373
 374	if config.Caption != "" {
 375		params["caption"] = config.Caption
 376	}
 377
 378	return params, nil
 379}
 380
 381// name returns the field name for the Document.
 382func (config DocumentConfig) name() string {
 383	return "document"
 384}
 385
 386// method returns Telegram API method name for sending Document.
 387func (config DocumentConfig) method() string {
 388	return "sendDocument"
 389}
 390
 391// StickerConfig contains information about a SendSticker request.
 392type StickerConfig struct {
 393	BaseFile
 394}
 395
 396// values returns a url.Values representation of StickerConfig.
 397func (config StickerConfig) values() (url.Values, error) {
 398	v, err := config.BaseChat.values()
 399	if err != nil {
 400		return v, err
 401	}
 402
 403	v.Add(config.name(), config.FileID)
 404
 405	return v, nil
 406}
 407
 408// params returns a map[string]string representation of StickerConfig.
 409func (config StickerConfig) params() (map[string]string, error) {
 410	params, _ := config.BaseFile.params()
 411
 412	return params, nil
 413}
 414
 415// name returns the field name for the Sticker.
 416func (config StickerConfig) name() string {
 417	return "sticker"
 418}
 419
 420// method returns Telegram API method name for sending Sticker.
 421func (config StickerConfig) method() string {
 422	return "sendSticker"
 423}
 424
 425// VideoConfig contains information about a SendVideo request.
 426type VideoConfig struct {
 427	BaseFile
 428	Duration int
 429	Caption  string
 430}
 431
 432// values returns a url.Values representation of VideoConfig.
 433func (config VideoConfig) values() (url.Values, error) {
 434	v, err := config.BaseChat.values()
 435	if err != nil {
 436		return v, err
 437	}
 438
 439	v.Add(config.name(), config.FileID)
 440	if config.Duration != 0 {
 441		v.Add("duration", strconv.Itoa(config.Duration))
 442	}
 443	if config.Caption != "" {
 444		v.Add("caption", config.Caption)
 445	}
 446
 447	return v, nil
 448}
 449
 450// params returns a map[string]string representation of VideoConfig.
 451func (config VideoConfig) params() (map[string]string, error) {
 452	params, _ := config.BaseFile.params()
 453
 454	if config.Caption != "" {
 455		params["caption"] = config.Caption
 456	}
 457
 458	return params, nil
 459}
 460
 461// name returns the field name for the Video.
 462func (config VideoConfig) name() string {
 463	return "video"
 464}
 465
 466// method returns Telegram API method name for sending Video.
 467func (config VideoConfig) method() string {
 468	return "sendVideo"
 469}
 470
 471// VideoNoteConfig contains information about a SendVideoNote request.
 472type VideoNoteConfig struct {
 473	BaseFile
 474	Duration int
 475	Length   int
 476}
 477
 478// values returns a url.Values representation of VideoNoteConfig.
 479func (config VideoNoteConfig) values() (url.Values, error) {
 480	v, err := config.BaseChat.values()
 481	if err != nil {
 482		return v, err
 483	}
 484
 485	v.Add(config.name(), config.FileID)
 486	if config.Duration != 0 {
 487		v.Add("duration", strconv.Itoa(config.Duration))
 488	}
 489
 490	// Telegram API seems to have a bug, if no length is provided or it is 0, it will send an error response
 491	if config.Length != 0 {
 492		v.Add("length", strconv.Itoa(config.Length))
 493	}
 494
 495	return v, nil
 496}
 497
 498// params returns a map[string]string representation of VideoNoteConfig.
 499func (config VideoNoteConfig) params() (map[string]string, error) {
 500	params, _ := config.BaseFile.params()
 501
 502	if config.Length != 0 {
 503		params["length"] = strconv.Itoa(config.Length)
 504	}
 505	if config.Duration != 0 {
 506		params["duration"] = strconv.Itoa(config.Duration)
 507	}
 508
 509	return params, nil
 510}
 511
 512// name returns the field name for the VideoNote.
 513func (config VideoNoteConfig) name() string {
 514	return "video_note"
 515}
 516
 517// method returns Telegram API method name for sending VideoNote.
 518func (config VideoNoteConfig) method() string {
 519	return "sendVideoNote"
 520}
 521
 522// VoiceConfig contains information about a SendVoice request.
 523type VoiceConfig struct {
 524	BaseFile
 525	Caption  string
 526	Duration int
 527}
 528
 529// values returns a url.Values representation of VoiceConfig.
 530func (config VoiceConfig) values() (url.Values, error) {
 531	v, err := config.BaseChat.values()
 532	if err != nil {
 533		return v, err
 534	}
 535
 536	v.Add(config.name(), config.FileID)
 537	if config.Duration != 0 {
 538		v.Add("duration", strconv.Itoa(config.Duration))
 539	}
 540	if config.Caption != "" {
 541		v.Add("caption", config.Caption)
 542	}
 543
 544	return v, nil
 545}
 546
 547// params returns a map[string]string representation of VoiceConfig.
 548func (config VoiceConfig) params() (map[string]string, error) {
 549	params, _ := config.BaseFile.params()
 550
 551	if config.Duration != 0 {
 552		params["duration"] = strconv.Itoa(config.Duration)
 553	}
 554	if config.Caption != "" {
 555		params["caption"] = config.Caption
 556	}
 557
 558	return params, nil
 559}
 560
 561// name returns the field name for the Voice.
 562func (config VoiceConfig) name() string {
 563	return "voice"
 564}
 565
 566// method returns Telegram API method name for sending Voice.
 567func (config VoiceConfig) method() string {
 568	return "sendVoice"
 569}
 570
 571// LocationConfig contains information about a SendLocation request.
 572type LocationConfig struct {
 573	BaseChat
 574	Latitude   float64 // required
 575	Longitude  float64 // required
 576	LivePeriod int     // optional
 577}
 578
 579// values returns a url.Values representation of LocationConfig.
 580func (config LocationConfig) values() (url.Values, error) {
 581	v, err := config.BaseChat.values()
 582	if err != nil {
 583		return v, err
 584	}
 585
 586	v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
 587	v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
 588	if config.LivePeriod != 0 {
 589		v.Add("live_period", strconv.Itoa(config.LivePeriod))
 590	}
 591
 592	return v, nil
 593}
 594
 595// method returns Telegram API method name for sending Location.
 596func (config LocationConfig) method() string {
 597	return "sendLocation"
 598}
 599
 600// LocationConfig contains information about a SendLocation request.
 601type EditMessageLiveLocationConfig struct {
 602	BaseEdit
 603	Latitude   float64 // required
 604	Longitude  float64 // required
 605}
 606
 607// values returns a url.Values representation of EditMessageLiveLocationConfig.
 608func (config EditMessageLiveLocationConfig) values() (url.Values, error) {
 609	v, err := config.BaseEdit.values()
 610	if err != nil {
 611		return v, err
 612	}
 613
 614	v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
 615	v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
 616
 617	return v, nil
 618}
 619
 620// method returns Telegram API method name for edit message Live Location.
 621func (config EditMessageLiveLocationConfig) method() string {
 622	return "editMessageLiveLocation"
 623}
 624
 625// LocationConfig contains information about a StopMessageLiveLocation request.
 626type StopMessageLiveLocationConfig struct {
 627	BaseEdit
 628}
 629
 630// values returns a url.Values representation of StopMessageLiveLocationConfig.
 631func (config StopMessageLiveLocationConfig) values() (url.Values, error) {
 632	v, err := config.BaseEdit.values()
 633	if err != nil {
 634		return v, err
 635	}
 636
 637	return v, nil
 638}
 639
 640// method returns Telegram API method name for stop message Live Location.
 641func (config StopMessageLiveLocationConfig) method() string {
 642	return "stopMessageLiveLocation"
 643}
 644
 645// VenueConfig contains information about a SendVenue request.
 646type VenueConfig struct {
 647	BaseChat
 648	Latitude     float64 // required
 649	Longitude    float64 // required
 650	Title        string  // required
 651	Address      string  // required
 652	FoursquareID string
 653}
 654
 655func (config VenueConfig) values() (url.Values, error) {
 656	v, err := config.BaseChat.values()
 657	if err != nil {
 658		return v, err
 659	}
 660
 661	v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
 662	v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
 663	v.Add("title", config.Title)
 664	v.Add("address", config.Address)
 665	if config.FoursquareID != "" {
 666		v.Add("foursquare_id", config.FoursquareID)
 667	}
 668
 669	return v, nil
 670}
 671
 672func (config VenueConfig) method() string {
 673	return "sendVenue"
 674}
 675
 676// ContactConfig allows you to send a contact.
 677type ContactConfig struct {
 678	BaseChat
 679	PhoneNumber string
 680	FirstName   string
 681	LastName    string
 682}
 683
 684func (config ContactConfig) values() (url.Values, error) {
 685	v, err := config.BaseChat.values()
 686	if err != nil {
 687		return v, err
 688	}
 689
 690	v.Add("phone_number", config.PhoneNumber)
 691	v.Add("first_name", config.FirstName)
 692	v.Add("last_name", config.LastName)
 693
 694	return v, nil
 695}
 696
 697func (config ContactConfig) method() string {
 698	return "sendContact"
 699}
 700
 701// GameConfig allows you to send a game.
 702type GameConfig struct {
 703	BaseChat
 704	GameShortName string
 705}
 706
 707func (config GameConfig) values() (url.Values, error) {
 708	v, err := config.BaseChat.values()
 709	if err != nil {
 710		return v, err
 711	}
 712
 713	v.Add("game_short_name", config.GameShortName)
 714
 715	return v, nil
 716}
 717
 718func (config GameConfig) method() string {
 719	return "sendGame"
 720}
 721
 722// SetGameScoreConfig allows you to update the game score in a chat.
 723type SetGameScoreConfig struct {
 724	UserID             int
 725	Score              int
 726	Force              bool
 727	DisableEditMessage bool
 728	ChatID             int
 729	ChannelUsername    string
 730	MessageID          int
 731	InlineMessageID    string
 732}
 733
 734func (config SetGameScoreConfig) values() (url.Values, error) {
 735	v := url.Values{}
 736
 737	v.Add("user_id", strconv.Itoa(config.UserID))
 738	v.Add("score", strconv.Itoa(config.Score))
 739	if config.InlineMessageID == "" {
 740		if config.ChannelUsername == "" {
 741			v.Add("chat_id", strconv.Itoa(config.ChatID))
 742		} else {
 743			v.Add("chat_id", config.ChannelUsername)
 744		}
 745		v.Add("message_id", strconv.Itoa(config.MessageID))
 746	} else {
 747		v.Add("inline_message_id", config.InlineMessageID)
 748	}
 749	v.Add("disable_edit_message", strconv.FormatBool(config.DisableEditMessage))
 750
 751	return v, nil
 752}
 753
 754func (config SetGameScoreConfig) method() string {
 755	return "setGameScore"
 756}
 757
 758// GetGameHighScoresConfig allows you to fetch the high scores for a game.
 759type GetGameHighScoresConfig struct {
 760	UserID          int
 761	ChatID          int
 762	ChannelUsername string
 763	MessageID       int
 764	InlineMessageID string
 765}
 766
 767func (config GetGameHighScoresConfig) values() (url.Values, error) {
 768	v := url.Values{}
 769
 770	v.Add("user_id", strconv.Itoa(config.UserID))
 771	if config.InlineMessageID == "" {
 772		if config.ChannelUsername == "" {
 773			v.Add("chat_id", strconv.Itoa(config.ChatID))
 774		} else {
 775			v.Add("chat_id", config.ChannelUsername)
 776		}
 777		v.Add("message_id", strconv.Itoa(config.MessageID))
 778	} else {
 779		v.Add("inline_message_id", config.InlineMessageID)
 780	}
 781
 782	return v, nil
 783}
 784
 785func (config GetGameHighScoresConfig) method() string {
 786	return "getGameHighScores"
 787}
 788
 789// ChatActionConfig contains information about a SendChatAction request.
 790type ChatActionConfig struct {
 791	BaseChat
 792	Action string // required
 793}
 794
 795// values returns a url.Values representation of ChatActionConfig.
 796func (config ChatActionConfig) values() (url.Values, error) {
 797	v, err := config.BaseChat.values()
 798	if err != nil {
 799		return v, err
 800	}
 801	v.Add("action", config.Action)
 802	return v, nil
 803}
 804
 805// method returns Telegram API method name for sending ChatAction.
 806func (config ChatActionConfig) method() string {
 807	return "sendChatAction"
 808}
 809
 810// EditMessageTextConfig allows you to modify the text in a message.
 811type EditMessageTextConfig struct {
 812	BaseEdit
 813	Text                  string
 814	ParseMode             string
 815	DisableWebPagePreview bool
 816}
 817
 818func (config EditMessageTextConfig) values() (url.Values, error) {
 819	v, err := config.BaseEdit.values()
 820	if err != nil {
 821		return v, err
 822	}
 823
 824	v.Add("text", config.Text)
 825	v.Add("parse_mode", config.ParseMode)
 826	v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
 827
 828	return v, nil
 829}
 830
 831func (config EditMessageTextConfig) method() string {
 832	return "editMessageText"
 833}
 834
 835// EditMessageCaptionConfig allows you to modify the caption of a message.
 836type EditMessageCaptionConfig struct {
 837	BaseEdit
 838	Caption string
 839}
 840
 841func (config EditMessageCaptionConfig) values() (url.Values, error) {
 842	v, _ := config.BaseEdit.values()
 843
 844	v.Add("caption", config.Caption)
 845
 846	return v, nil
 847}
 848
 849func (config EditMessageCaptionConfig) method() string {
 850	return "editMessageCaption"
 851}
 852
 853// EditMessageReplyMarkupConfig allows you to modify the reply markup
 854// of a message.
 855type EditMessageReplyMarkupConfig struct {
 856	BaseEdit
 857}
 858
 859func (config EditMessageReplyMarkupConfig) values() (url.Values, error) {
 860	return config.BaseEdit.values()
 861}
 862
 863func (config EditMessageReplyMarkupConfig) method() string {
 864	return "editMessageReplyMarkup"
 865}
 866
 867// UserProfilePhotosConfig contains information about a
 868// GetUserProfilePhotos request.
 869type UserProfilePhotosConfig struct {
 870	UserID int
 871	Offset int
 872	Limit  int
 873}
 874
 875// FileConfig has information about a file hosted on Telegram.
 876type FileConfig struct {
 877	FileID string
 878}
 879
 880// UpdateConfig contains information about a GetUpdates request.
 881type UpdateConfig struct {
 882	Offset  int
 883	Limit   int
 884	Timeout int
 885}
 886
 887// WebhookConfig contains information about a SetWebhook request.
 888type WebhookConfig struct {
 889	URL            *url.URL
 890	Certificate    interface{}
 891	MaxConnections int
 892}
 893
 894func (config WebhookConfig) method() string {
 895	return "setWebhook"
 896}
 897
 898func (config WebhookConfig) values() (url.Values, error) {
 899	v := url.Values{}
 900
 901	if config.URL != nil {
 902		v.Add("url", config.URL.String())
 903	}
 904	if config.MaxConnections != 0 {
 905		v.Add("max_connections", strconv.Itoa(config.MaxConnections))
 906	}
 907
 908	return v, nil
 909}
 910
 911func (config WebhookConfig) params() (map[string]string, error) {
 912	params := make(map[string]string)
 913
 914	if config.URL != nil {
 915		params["url"] = config.URL.String()
 916	}
 917	if config.MaxConnections != 0 {
 918		params["max_connections"] = strconv.Itoa(config.MaxConnections)
 919	}
 920
 921	return params, nil
 922}
 923
 924func (config WebhookConfig) name() string {
 925	return "certificate"
 926}
 927
 928func (config WebhookConfig) getFile() interface{} {
 929	return config.Certificate
 930}
 931
 932func (config WebhookConfig) useExistingFile() bool {
 933	return config.URL != nil
 934}
 935
 936// RemoveWebhookConfig is a helper to remove a webhook.
 937type RemoveWebhookConfig struct {
 938}
 939
 940func (config RemoveWebhookConfig) method() string {
 941	return "setWebhook"
 942}
 943
 944func (config RemoveWebhookConfig) values() (url.Values, error) {
 945	return url.Values{}, nil
 946}
 947
 948// FileBytes contains information about a set of bytes to upload
 949// as a File.
 950type FileBytes struct {
 951	Name  string
 952	Bytes []byte
 953}
 954
 955// FileReader contains information about a reader to upload as a File.
 956// If Size is -1, it will read the entire Reader into memory to
 957// calculate a Size.
 958type FileReader struct {
 959	Name   string
 960	Reader io.Reader
 961	Size   int64
 962}
 963
 964// InlineConfig contains information on making an InlineQuery response.
 965type InlineConfig struct {
 966	InlineQueryID     string        `json:"inline_query_id"`
 967	Results           []interface{} `json:"results"`
 968	CacheTime         int           `json:"cache_time"`
 969	IsPersonal        bool          `json:"is_personal"`
 970	NextOffset        string        `json:"next_offset"`
 971	SwitchPMText      string        `json:"switch_pm_text"`
 972	SwitchPMParameter string        `json:"switch_pm_parameter"`
 973}
 974
 975func (config InlineConfig) method() string {
 976	return "answerInlineQuery"
 977}
 978
 979func (config InlineConfig) values() (url.Values, error) {
 980	v := url.Values{}
 981
 982	v.Add("inline_query_id", config.InlineQueryID)
 983	v.Add("cache_time", strconv.Itoa(config.CacheTime))
 984	v.Add("is_personal", strconv.FormatBool(config.IsPersonal))
 985	v.Add("next_offset", config.NextOffset)
 986	data, err := json.Marshal(config.Results)
 987	if err != nil {
 988		return v, err
 989	}
 990	v.Add("results", string(data))
 991	v.Add("switch_pm_text", config.SwitchPMText)
 992	v.Add("switch_pm_parameter", config.SwitchPMParameter)
 993
 994	return v, nil
 995}
 996
 997// CallbackConfig contains information on making a CallbackQuery response.
 998type CallbackConfig struct {
 999	CallbackQueryID string `json:"callback_query_id"`
1000	Text            string `json:"text"`
1001	ShowAlert       bool   `json:"show_alert"`
1002	URL             string `json:"url"`
1003	CacheTime       int    `json:"cache_time"`
1004}
1005
1006func (config CallbackConfig) method() string {
1007	return "answerCallbackQuery"
1008}
1009
1010func (config CallbackConfig) values() (url.Values, error) {
1011	v := url.Values{}
1012
1013	v.Add("callback_query_id", config.CallbackQueryID)
1014	if config.Text != "" {
1015		v.Add("text", config.Text)
1016	}
1017	v.Add("show_alert", strconv.FormatBool(config.ShowAlert))
1018	if config.URL != "" {
1019		v.Add("url", config.URL)
1020	}
1021	v.Add("cache_time", strconv.Itoa(config.CacheTime))
1022
1023	return v, nil
1024}
1025
1026// ChatMemberConfig contains information about a user in a chat for use
1027// with administrative functions such as kicking or unbanning a user.
1028type ChatMemberConfig struct {
1029	ChatID             int64
1030	SuperGroupUsername string
1031	ChannelUsername    string
1032	UserID             int
1033}
1034
1035// UnbanChatMemberConfig allows you to unban a user.
1036type UnbanChatMemberConfig struct {
1037	ChatMemberConfig
1038}
1039
1040func (config UnbanChatMemberConfig) method() string {
1041	return "unbanChatMember"
1042}
1043
1044func (config UnbanChatMemberConfig) values() (url.Values, error) {
1045	v := url.Values{}
1046
1047	if config.SuperGroupUsername != "" {
1048		v.Add("chat_id", config.SuperGroupUsername)
1049	} else if config.ChannelUsername != "" {
1050		v.Add("chat_id", config.ChannelUsername)
1051	} else {
1052		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1053	}
1054	v.Add("user_id", strconv.Itoa(config.UserID))
1055
1056	return v, nil
1057}
1058
1059// KickChatMemberConfig contains extra fields to kick user
1060type KickChatMemberConfig struct {
1061	ChatMemberConfig
1062	UntilDate int64
1063}
1064
1065func (config KickChatMemberConfig) method() string {
1066	return "kickChatMember"
1067}
1068
1069func (config KickChatMemberConfig) values() (url.Values, error) {
1070	v := url.Values{}
1071
1072	if config.SuperGroupUsername == "" {
1073		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1074	} else {
1075		v.Add("chat_id", config.SuperGroupUsername)
1076	}
1077	v.Add("user_id", strconv.Itoa(config.UserID))
1078
1079	if config.UntilDate != 0 {
1080		v.Add("until_date", strconv.FormatInt(config.UntilDate, 10))
1081	}
1082
1083	return v, nil
1084}
1085
1086// RestrictChatMemberConfig contains fields to restrict members of chat
1087type RestrictChatMemberConfig struct {
1088	ChatMemberConfig
1089	UntilDate             int64
1090	CanSendMessages       *bool
1091	CanSendMediaMessages  *bool
1092	CanSendOtherMessages  *bool
1093	CanAddWebPagePreviews *bool
1094}
1095
1096func (config RestrictChatMemberConfig) method() string {
1097	return "restrictChatMember"
1098}
1099
1100func (config RestrictChatMemberConfig) values() (url.Values, error) {
1101	v := url.Values{}
1102
1103	if config.SuperGroupUsername != "" {
1104		v.Add("chat_id", config.SuperGroupUsername)
1105	} else if config.ChannelUsername != "" {
1106		v.Add("chat_id", config.ChannelUsername)
1107	} else {
1108		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1109	}
1110	v.Add("user_id", strconv.Itoa(config.UserID))
1111
1112	if config.CanSendMessages != nil {
1113		v.Add("can_send_messages", strconv.FormatBool(*config.CanSendMessages))
1114	}
1115	if config.CanSendMediaMessages != nil {
1116		v.Add("can_send_media_messages", strconv.FormatBool(*config.CanSendMediaMessages))
1117	}
1118	if config.CanSendOtherMessages != nil {
1119		v.Add("can_send_other_messages", strconv.FormatBool(*config.CanSendOtherMessages))
1120	}
1121	if config.CanAddWebPagePreviews != nil {
1122		v.Add("can_add_web_page_previews", strconv.FormatBool(*config.CanAddWebPagePreviews))
1123	}
1124	if config.UntilDate != 0 {
1125		v.Add("until_date", strconv.FormatInt(config.UntilDate, 10))
1126	}
1127
1128	return v, nil
1129}
1130
1131// PromoteChatMemberConfig contains fields to promote members of chat
1132type PromoteChatMemberConfig struct {
1133	ChatMemberConfig
1134	CanChangeInfo      *bool
1135	CanPostMessages    *bool
1136	CanEditMessages    *bool
1137	CanDeleteMessages  *bool
1138	CanInviteUsers     *bool
1139	CanRestrictMembers *bool
1140	CanPinMessages     *bool
1141	CanPromoteMembers  *bool
1142}
1143
1144func (config PromoteChatMemberConfig) method() string {
1145	return "promoteChatMember"
1146}
1147
1148func (config PromoteChatMemberConfig) values() (url.Values, error) {
1149	v := url.Values{}
1150
1151	if config.SuperGroupUsername != "" {
1152		v.Add("chat_id", config.SuperGroupUsername)
1153	} else if config.ChannelUsername != "" {
1154		v.Add("chat_id", config.ChannelUsername)
1155	} else {
1156		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1157	}
1158	v.Add("user_id", strconv.Itoa(config.UserID))
1159
1160	if config.CanChangeInfo != nil {
1161		v.Add("can_change_info", strconv.FormatBool(*config.CanChangeInfo))
1162	}
1163	if config.CanPostMessages != nil {
1164		v.Add("can_post_messages", strconv.FormatBool(*config.CanPostMessages))
1165	}
1166	if config.CanEditMessages != nil {
1167		v.Add("can_edit_messages", strconv.FormatBool(*config.CanEditMessages))
1168	}
1169	if config.CanDeleteMessages != nil {
1170		v.Add("can_delete_messages", strconv.FormatBool(*config.CanDeleteMessages))
1171	}
1172	if config.CanInviteUsers != nil {
1173		v.Add("can_invite_users", strconv.FormatBool(*config.CanInviteUsers))
1174	}
1175	if config.CanRestrictMembers != nil {
1176		v.Add("can_restrict_members", strconv.FormatBool(*config.CanRestrictMembers))
1177	}
1178	if config.CanPinMessages != nil {
1179		v.Add("can_pin_messages", strconv.FormatBool(*config.CanPinMessages))
1180	}
1181	if config.CanPromoteMembers != nil {
1182		v.Add("can_promote_members", strconv.FormatBool(*config.CanPromoteMembers))
1183	}
1184
1185	return v, nil
1186}
1187
1188// ChatConfig contains information about getting information on a chat.
1189type ChatConfig struct {
1190	ChatID             int64
1191	SuperGroupUsername string
1192}
1193
1194// LeaveChatConfig allows you to leave a chat.
1195type LeaveChatConfig struct {
1196	ChatID          int64
1197	ChannelUsername string
1198}
1199
1200func (config LeaveChatConfig) method() string {
1201	return "leaveChat"
1202}
1203
1204func (config LeaveChatConfig) values() (url.Values, error) {
1205	v := url.Values{}
1206
1207	if config.ChannelUsername == "" {
1208		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1209	} else {
1210		v.Add("chat_id", config.ChannelUsername)
1211	}
1212
1213	return v, nil
1214}
1215
1216// ChatConfigWithUser contains information about getting information on
1217// a specific user within a chat.
1218type ChatConfigWithUser struct {
1219	ChatID             int64
1220	SuperGroupUsername string
1221	UserID             int
1222}
1223
1224// InvoiceConfig contains information for sendInvoice request.
1225type InvoiceConfig struct {
1226	BaseChat
1227	Title               string          // required
1228	Description         string          // required
1229	Payload             string          // required
1230	ProviderToken       string          // required
1231	StartParameter      string          // required
1232	Currency            string          // required
1233	Prices              *[]LabeledPrice // required
1234	PhotoURL            string
1235	PhotoSize           int
1236	PhotoWidth          int
1237	PhotoHeight         int
1238	NeedName            bool
1239	NeedPhoneNumber     bool
1240	NeedEmail           bool
1241	NeedShippingAddress bool
1242	IsFlexible          bool
1243}
1244
1245func (config InvoiceConfig) values() (url.Values, error) {
1246	v, err := config.BaseChat.values()
1247	if err != nil {
1248		return v, err
1249	}
1250	v.Add("title", config.Title)
1251	v.Add("description", config.Description)
1252	v.Add("payload", config.Payload)
1253	v.Add("provider_token", config.ProviderToken)
1254	v.Add("start_parameter", config.StartParameter)
1255	v.Add("currency", config.Currency)
1256	data, err := json.Marshal(config.Prices)
1257	if err != nil {
1258		return v, err
1259	}
1260	v.Add("prices", string(data))
1261	if config.PhotoURL != "" {
1262		v.Add("photo_url", config.PhotoURL)
1263	}
1264	if config.PhotoSize != 0 {
1265		v.Add("photo_size", strconv.Itoa(config.PhotoSize))
1266	}
1267	if config.PhotoWidth != 0 {
1268		v.Add("photo_width", strconv.Itoa(config.PhotoWidth))
1269	}
1270	if config.PhotoHeight != 0 {
1271		v.Add("photo_height", strconv.Itoa(config.PhotoHeight))
1272	}
1273	if config.NeedName != false {
1274		v.Add("need_name", strconv.FormatBool(config.NeedName))
1275	}
1276	if config.NeedPhoneNumber != false {
1277		v.Add("need_phone_number", strconv.FormatBool(config.NeedPhoneNumber))
1278	}
1279	if config.NeedEmail != false {
1280		v.Add("need_email", strconv.FormatBool(config.NeedEmail))
1281	}
1282	if config.NeedShippingAddress != false {
1283		v.Add("need_shipping_address", strconv.FormatBool(config.NeedShippingAddress))
1284	}
1285	if config.IsFlexible != false {
1286		v.Add("is_flexible", strconv.FormatBool(config.IsFlexible))
1287	}
1288
1289	return v, nil
1290}
1291
1292func (config InvoiceConfig) method() string {
1293	return "sendInvoice"
1294}
1295
1296// ShippingConfig contains information for answerShippingQuery request.
1297type ShippingConfig struct {
1298	ShippingQueryID string // required
1299	OK              bool   // required
1300	ShippingOptions *[]ShippingOption
1301	ErrorMessage    string
1302}
1303
1304// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
1305type PreCheckoutConfig struct {
1306	PreCheckoutQueryID string // required
1307	OK                 bool   // required
1308	ErrorMessage       string
1309}
1310
1311// DeleteMessageConfig contains information of a message in a chat to delete.
1312type DeleteMessageConfig struct {
1313	ChatID    int64
1314	MessageID int
1315}
1316
1317func (config DeleteMessageConfig) method() string {
1318	return "deleteMessage"
1319}
1320
1321func (config DeleteMessageConfig) values() (url.Values, error) {
1322	v := url.Values{}
1323
1324	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1325	v.Add("message_id", strconv.Itoa(config.MessageID))
1326
1327	return v, nil
1328}
1329
1330// PinChatMessageConfig contains information of a message in a chat to pin.
1331type PinChatMessageConfig struct {
1332	ChatID              int64
1333	MessageID           int
1334	DisableNotification bool
1335}
1336
1337func (config PinChatMessageConfig) method() string {
1338	return "pinChatMessage"
1339}
1340
1341func (config PinChatMessageConfig) values() (url.Values, error) {
1342	v := url.Values{}
1343
1344	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1345	v.Add("message_id", strconv.Itoa(config.MessageID))
1346	v.Add("disable_notification", strconv.FormatBool(config.DisableNotification))
1347
1348	return v, nil
1349}
1350
1351// UnpinChatMessageConfig contains information of chat to unpin.
1352type UnpinChatMessageConfig struct {
1353	ChatID int64
1354}
1355
1356func (config UnpinChatMessageConfig) method() string {
1357	return "unpinChatMessage"
1358}
1359
1360func (config UnpinChatMessageConfig) values() (url.Values, error) {
1361	v := url.Values{}
1362
1363	v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1364
1365	return v, nil
1366}
1367
1368// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
1369type SetChatPhotoConfig struct {
1370	ChatID          int64
1371	ChannelUsername string
1372
1373	Photo interface{}
1374}
1375
1376func (config SetChatPhotoConfig) method() string {
1377	return "setChatPhoto"
1378}
1379
1380func (config SetChatPhotoConfig) name() string {
1381	return "photo"
1382}
1383
1384func (config SetChatPhotoConfig) values() (url.Values, error) {
1385	v := url.Values{}
1386
1387	if config.ChannelUsername == "" {
1388		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1389	} else {
1390		v.Add("chat_id", config.ChannelUsername)
1391	}
1392
1393	return v, nil
1394}
1395
1396func (config SetChatPhotoConfig) params() map[string]string {
1397	params := make(map[string]string)
1398
1399	if config.ChannelUsername == "" {
1400		params["chat_id"] = strconv.FormatInt(config.ChatID, 10)
1401	} else {
1402		params["chat_id"] = config.ChannelUsername
1403	}
1404
1405	return params
1406}
1407
1408func (config SetChatPhotoConfig) getFile() interface{} {
1409	return config.Photo
1410}
1411
1412func (config SetChatPhotoConfig) useExistingFile() bool {
1413	return false
1414}
1415
1416// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
1417type DeleteChatPhotoConfig struct {
1418	ChatID          int64
1419	ChannelUsername string
1420}
1421
1422func (config DeleteChatPhotoConfig) method() string {
1423	return "deleteChatPhoto"
1424}
1425
1426func (config DeleteChatPhotoConfig) values() (url.Values, error) {
1427	v := url.Values{}
1428
1429	if config.ChannelUsername == "" {
1430		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1431	} else {
1432		v.Add("chat_id", config.ChannelUsername)
1433	}
1434
1435	return v, nil
1436}
1437
1438// SetChatTitleConfig allows you to set the title of something other than a private chat.
1439type SetChatTitleConfig struct {
1440	ChatID          int64
1441	ChannelUsername string
1442
1443	Title string
1444}
1445
1446func (config SetChatTitleConfig) method() string {
1447	return "setChatTitle"
1448}
1449
1450func (config SetChatTitleConfig) values() (url.Values, error) {
1451	v := url.Values{}
1452
1453	if config.ChannelUsername == "" {
1454		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1455	} else {
1456		v.Add("chat_id", config.ChannelUsername)
1457	}
1458
1459	v.Add("title", config.Title)
1460
1461	return v, nil
1462}
1463
1464// SetChatDescriptionConfig allows you to set the description of a supergroup or channel.
1465type SetChatDescriptionConfig struct {
1466	ChatID          int64
1467	ChannelUsername string
1468
1469	Description string
1470}
1471
1472func (config SetChatDescriptionConfig) method() string {
1473	return "setChatDescription"
1474}
1475
1476func (config SetChatDescriptionConfig) values() (url.Values, error) {
1477	v := url.Values{}
1478
1479	if config.ChannelUsername == "" {
1480		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
1481	} else {
1482		v.Add("chat_id", config.ChannelUsername)
1483	}
1484
1485	v.Add("description", config.Description)
1486
1487	return v, nil
1488}
1489
1490// GetStickerSetConfig allows you to get the stickers in a set.
1491type GetStickerSetConfig struct {
1492	Name string
1493}
1494
1495func (config GetStickerSetConfig) method() string {
1496	return "getStickerSet"
1497}
1498
1499func (config GetStickerSetConfig) values() (url.Values, error) {
1500	v := url.Values{}
1501
1502	v.Add("name", config.Name)
1503
1504	return v, nil
1505}
1506
1507// UploadStickerConfig allows you to upload a sticker for use in a set later.
1508type UploadStickerConfig struct {
1509	UserID     int64
1510	PNGSticker interface{}
1511}
1512
1513func (config UploadStickerConfig) method() string {
1514	return "uploadStickerFile"
1515}
1516
1517func (config UploadStickerConfig) values() (url.Values, error) {
1518	v := url.Values{}
1519
1520	v.Add("user_id", strconv.FormatInt(config.UserID, 10))
1521
1522	return v, nil
1523}
1524
1525func (config UploadStickerConfig) params() (map[string]string, error) {
1526	params := make(map[string]string)
1527
1528	params["user_id"] = strconv.FormatInt(config.UserID, 10)
1529
1530	return params, nil
1531}
1532
1533func (config UploadStickerConfig) name() string {
1534	return "png_sticker"
1535}
1536
1537func (config UploadStickerConfig) getFile() interface{} {
1538	return config.PNGSticker
1539}
1540
1541func (config UploadStickerConfig) useExistingFile() bool {
1542	return false
1543}
1544
1545// NewStickerSetConfig allows creating a new sticker set.
1546type NewStickerSetConfig struct {
1547	UserID        int64
1548	Name          string
1549	Title         string
1550	PNGSticker    interface{}
1551	Emojis        string
1552	ContainsMasks bool
1553	MaskPosition  *MaskPosition
1554}
1555
1556func (config NewStickerSetConfig) method() string {
1557	return "createNewStickerSet"
1558}
1559
1560func (config NewStickerSetConfig) values() (url.Values, error) {
1561	v := url.Values{}
1562
1563	v.Add("user_id", strconv.FormatInt(config.UserID, 10))
1564	v.Add("name", config.Name)
1565	v.Add("title", config.Title)
1566	if sticker, ok := config.PNGSticker.(string); ok {
1567		v.Add("png_sticker", sticker)
1568	}
1569	v.Add("emojis", config.Emojis)
1570	if config.ContainsMasks {
1571		v.Add("contains_masks", strconv.FormatBool(config.ContainsMasks))
1572
1573		data, err := json.Marshal(config.MaskPosition)
1574		if err != nil {
1575			return v, err
1576		}
1577
1578		v.Add("mask_position", string(data))
1579	}
1580
1581	return v, nil
1582}
1583
1584func (config NewStickerSetConfig) params() (map[string]string, error) {
1585	params := make(map[string]string)
1586
1587	params["user_id"] = strconv.FormatInt(config.UserID, 10)
1588	params["name"] = config.Name
1589	params["title"] = config.Title
1590	params["emojis"] = config.Emojis
1591	if config.ContainsMasks {
1592		params["contains_masks"] = strconv.FormatBool(config.ContainsMasks)
1593
1594		data, err := json.Marshal(config.MaskPosition)
1595		if err != nil {
1596			return params, err
1597		}
1598
1599		params["mask_position"] = string(data)
1600	}
1601
1602	return params, nil
1603}
1604
1605func (config NewStickerSetConfig) getFile() interface{} {
1606	return config.PNGSticker
1607}
1608
1609func (config NewStickerSetConfig) name() string {
1610	return "png_sticker"
1611}
1612
1613func (config NewStickerSetConfig) useExistingFile() bool {
1614	_, ok := config.PNGSticker.(string)
1615
1616	return ok
1617}
1618
1619// AddStickerConfig allows you to add a sticker to a set.
1620type AddStickerConfig struct {
1621	UserID       int64
1622	Name         string
1623	PNGSticker   interface{}
1624	Emojis       string
1625	MaskPosition *MaskPosition
1626}
1627
1628func (config AddStickerConfig) method() string {
1629	return "addStickerToSet"
1630}
1631
1632func (config AddStickerConfig) values() (url.Values, error) {
1633	v := url.Values{}
1634
1635	v.Add("user_id", strconv.FormatInt(config.UserID, 10))
1636	v.Add("name", config.Name)
1637	if sticker, ok := config.PNGSticker.(string); ok {
1638		v.Add("png_sticker", sticker)
1639	}
1640	v.Add("emojis", config.Emojis)
1641	if config.MaskPosition != nil {
1642		data, err := json.Marshal(config.MaskPosition)
1643		if err != nil {
1644			return v, err
1645		}
1646
1647		v.Add("mask_position", string(data))
1648	}
1649
1650	return v, nil
1651}
1652
1653func (config AddStickerConfig) params() (map[string]string, error) {
1654	params := make(map[string]string)
1655
1656	params["user_id"] = strconv.FormatInt(config.UserID, 10)
1657	params["name"] = config.Name
1658	params["emojis"] = config.Emojis
1659	if config.MaskPosition != nil {
1660		data, err := json.Marshal(config.MaskPosition)
1661		if err != nil {
1662			return params, err
1663		}
1664
1665		params["mask_position"] = string(data)
1666	}
1667
1668	return params, nil
1669}
1670
1671func (config AddStickerConfig) name() string {
1672	return "png_sticker"
1673}
1674
1675func (config AddStickerConfig) getFile() interface{} {
1676	return config.PNGSticker
1677}
1678
1679func (config AddStickerConfig) useExistingFile() bool {
1680	return false
1681}
1682
1683// SetStickerPositionConfig allows you to change the position of a sticker in a set.
1684type SetStickerPositionConfig struct {
1685	Sticker  string
1686	Position int
1687}
1688
1689func (config SetStickerPositionConfig) method() string {
1690	return "setStickerPositionInSet"
1691}
1692
1693func (config SetStickerPositionConfig) values() (url.Values, error) {
1694	v := url.Values{}
1695
1696	v.Add("sticker", config.Sticker)
1697	v.Add("position", strconv.Itoa(config.Position))
1698
1699	return v, nil
1700}
1701
1702// DeleteStickerConfig allows you to delete a sticker from a set.
1703type DeleteStickerConfig struct {
1704	Sticker string
1705}
1706
1707func (config DeleteStickerConfig) method() string {
1708	return "deleteStickerFromSet"
1709}
1710
1711func (config DeleteStickerConfig) values() (url.Values, error) {
1712	v := url.Values{}
1713
1714	v.Add("sticker", config.Sticker)
1715
1716	return v, nil
1717}