From 1ae7803be06a7a521004632d8aa02dbc38c068f8 Mon Sep 17 00:00:00 2001 From: Syfaro Date: Fri, 1 Jan 2016 00:10:19 -0600 Subject: [PATCH] Add untested support for Inline Queries. --- bot.go | 45 ++++++++++++++++++-------- configs.go | 17 +++++++--- types.go | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 135 insertions(+), 20 deletions(-) diff --git a/bot.go b/bot.go index 73f5ba1..b7b7024 100644 --- a/bot.go +++ b/bot.go @@ -121,29 +121,31 @@ func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldna buf := bytes.NewBuffer(f.Bytes) ms.WriteReader(fieldname, f.Name, int64(len(f.Bytes)), buf) case FileReader: - if f.Size == -1 { - data, err := ioutil.ReadAll(f.Reader) - if err != nil { - return APIResponse{}, err - } - buf := bytes.NewBuffer(data) - - ms.WriteReader(fieldname, f.Name, int64(len(data)), buf) + if f.Size != -1 { + ms.WriteReader(fieldname, f.Name, f.Size, f.Reader) break } - ms.WriteReader(fieldname, f.Name, f.Size, f.Reader) + data, err := ioutil.ReadAll(f.Reader) + if err != nil { + return APIResponse{}, err + } + + buf := bytes.NewBuffer(data) + + ms.WriteReader(fieldname, f.Name, int64(len(data)), buf) default: return APIResponse{}, errors.New("bad file type") } req, err := http.NewRequest("POST", fmt.Sprintf(APIEndpoint, bot.Token, endpoint), nil) - ms.SetupRequest(req) if err != nil { return APIResponse{}, err } + ms.SetupRequest(req) + res, err := bot.Client.Do(req) if err != nil { return APIResponse{}, err @@ -156,7 +158,7 @@ func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldna } if bot.Debug { - log.Println(string(bytes[:])) + log.Println(string(bytes)) } var apiResp APIResponse @@ -194,9 +196,7 @@ func (bot *BotAPI) GetMe() (User, error) { var user User json.Unmarshal(resp.Result, &user) - if bot.Debug { - log.Printf("getMe: %+v\n", user) - } + bot.debugLog("getMe", nil, user) return user, nil } @@ -451,3 +451,20 @@ func (bot *BotAPI) ListenForWebhook(pattern string) (<-chan Update, http.Handler return updatesChan, handler } + +// AnswerInlineQuery sends a response to an inline query. +func (bot *BotAPI) AnswerInlineQuery(config InlineConfig) (APIResponse, error) { + v := url.Values{} + + v.Add("inline_query_id", config.InlineQueryID) + v.Add("cache_time", strconv.Itoa(config.CacheTime)) + v.Add("is_personal", strconv.FormatBool(config.IsPersonal)) + v.Add("next_offset", config.NextOffset) + data, err := json.Marshal(config.Results) + if err != nil { + return APIResponse{}, err + } + v.Add("results", string(data)) + + return bot.MakeRequest("answerInlineQuery", v) +} diff --git a/configs.go b/configs.go index 00c2830..29a7720 100644 --- a/configs.go +++ b/configs.go @@ -38,13 +38,13 @@ const ( ModeMarkdown = "Markdown" ) -//Chattable represents any event in chat(MessageConfig, PhotoConfig, ChatActionConfig and others) +// Chattable represents any event in chat(MessageConfig, PhotoConfig, ChatActionConfig and others) type Chattable interface { Values() (url.Values, error) Method() string } -//Fileable represents any file event(PhotoConfig, DocumentConfig, AudioConfig, VoiceConfig, VideoConfig, StickerConfig) +// Fileable represents any file event(PhotoConfig, DocumentConfig, AudioConfig, VoiceConfig, VideoConfig, StickerConfig) type Fileable interface { Chattable Params() (map[string]string, error) @@ -53,7 +53,7 @@ type Fileable interface { UseExistingFile() bool } -// BaseChat is base struct for all chat event(Message, Photo and so on) +// BaseChat is base struct for all chat events (Message, Photo and so on) type BaseChat struct { ChatID int ChannelUsername string @@ -86,7 +86,7 @@ func (chat *BaseChat) Values() (url.Values, error) { return v, nil } -// BaseFile is base struct for all file events(PhotoConfig, DocumentConfig, AudioConfig, VoiceConfig, VideoConfig, StickerConfig) +// BaseFile is base struct for all file events (PhotoConfig, DocumentConfig, AudioConfig, VoiceConfig, VideoConfig, StickerConfig) type BaseFile struct { BaseChat FilePath string @@ -505,3 +505,12 @@ type FileReader struct { Reader io.Reader Size int64 } + +// InlineConfig contains information on making an InlineQuery response. +type InlineConfig struct { + InlineQueryID string `json:"inline_query_id"` + Results []InlineQueryResult `json:"results"` + CacheTime int `json:"cache_time"` + IsPersonal bool `json:"is_personal"` + NextOffset string `json:"next_offset"` +} diff --git a/types.go b/types.go index afa1e18..810f72c 100644 --- a/types.go +++ b/types.go @@ -17,8 +17,9 @@ type APIResponse struct { // Update is an update response, from GetUpdates. type Update struct { - UpdateID int `json:"update_id"` - Message Message `json:"message"` + UpdateID int `json:"update_id"` + Message Message `json:"message"` + InlineQuery InlineQuery `json:"inline_query"` } // User is a user, contained in Message and returned by GetSelf. @@ -257,3 +258,91 @@ type ForceReply struct { ForceReply bool `json:"force_reply"` Selective bool `json:"selective"` } + +// InlineQuery is a Query from Telegram for an inline request +type InlineQuery struct { + ID string `json:"id"` + From User `json:"user"` + Query string `json:"query"` + Offset string `json:"offset"` +} + +// InlineQueryResult is the base type that all InlineQuery Results have. +type InlineQueryResult struct { + Type string `json:"type"` // required + ID string `json:"id"` // required +} + +// InlineQueryResultArticle is an inline query response article. +type InlineQueryResultArticle struct { + InlineQueryResult + Title string `json:"title"` // required + MessageText string `json:"message_text"` // required + ParseMode string `json:"parse_mode"` // required + DisableWebPagePreview bool `json:"disable_web_page_preview"` + URL string `json:"url"` + HideURL bool `json:"hide_url"` + Description string `json:"description"` + ThumbURL string `json:"thumb_url"` + ThumbWidth int `json:"thumb_width"` + ThumbHeight int `json:"thumb_height"` +} + +// InlineQueryResultPhoto is an inline query response photo. +type InlineQueryResultPhoto struct { + InlineQueryResult + URL string `json:"photo_url"` // required + MimeType string `json:"mime_type"` + Width int `json:"photo_width"` + Height int `json:"photo_height"` + ThumbURL string `json:"thumb_url"` + Title string `json:"title"` + Description string `json:"description"` + Caption string `json:"caption"` + MessageText string `json:"message_text"` + ParseMode string `json:"parse_mode"` + DisableWebPagePreview bool `json:"disable_web_page_preview"` +} + +// InlineQueryResultGIF is an inline query response GIF. +type InlineQueryResultGIF struct { + InlineQueryResult + URL string `json:"gif_url"` // required + Width int `json:"gif_width"` + Height int `json:"gif_height"` + ThumbURL string `json:"thumb_url"` + Title string `json:"title"` + Caption string `json:"caption"` + MessageText string `json:"message_text"` + ParseMode string `json:"parse_mode"` + DisableWebPagePreview bool `json:"disable_web_page_preview"` +} + +// InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF. +type InlineQueryResultMPEG4GIF struct { + InlineQueryResult + URL string `json:"mpeg4_url"` // required + Width int `json:"mpeg4_width"` + Height int `json:"mpeg4_height"` + ThumbURL string `json:"thumb_url"` + Title string `json:"title"` + Caption string `json:"caption"` + MessageText string `json:"message_text"` + ParseMode string `json:"parse_mode"` + DisableWebPagePreview bool `json:"disable_web_page_preview"` +} + +// InlineQueryResultVideo is an inline query response video. +type InlineQueryResultVideo struct { + InlineQueryResult + URL string `json:"video_url"` // required + MimeType string `json:"mime_type"` // required + MessageText string `json:"message_text"` // required + ParseMode string `json:"parse_mode"` + DisableWebPagePreview bool `json:"disable_web_page_preview"` + Width int `json:"video_width"` + Height int `json:"video_height"` + ThumbURL string `json:"thumb_url"` + Title string `json:"title"` + Description string `json:"description"` +}