Cleanup, documentation, bikeshedding.

pull/108/head
Ian Byrd 7 years ago
parent d5e4082eaf
commit 0f1d521167
No known key found for this signature in database
GPG Key ID: 598F598CA3B8055F

@ -318,32 +318,34 @@ func (b *Bot) AnswerCallbackQuery(callback *Callback, response *CallbackResponse
return extractOkResponse(respJSON)
}
// GetFile returns full file object including File.FilePath, which allow you to load file from Telegram
// FileByID returns full file object including File.FilePath, allowing you to
// download the file from the server.
//
// Usually File objects does not contain any FilePath so you need to perform additional request
func (b *Bot) GetFile(fileID string) (*File, error) {
// Usually, Telegram-provided File objects miss FilePath so you might need to
// perform an additional request to fetch them.
func (b *Bot) FileByID(fileID string) (File, error) {
params := map[string]string{
"file_id": fileID,
}
respJSON, err := b.sendCommand("getFile", params)
if err != nil {
return nil, err
return File{}, err
}
var resp struct {
Ok bool
Description string
Result *File
Result File
}
err = json.Unmarshal(respJSON, &resp)
if err != nil {
return nil, errors.Wrap(err, "bad response json")
return File{}, errors.Wrap(err, "bad response json")
}
if !resp.Ok {
return nil, errors.Errorf("api error: %s", resp.Description)
return File{}, errors.Errorf("api error: %s", resp.Description)
}
@ -364,15 +366,15 @@ func (b *Bot) LeaveChat(recipient Recipient) error {
return extractOkResponse(respJSON)
}
// GetChat get up to date information about the chat.
// ChatByID fetches chat info of its ID.
//
// Including 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 (b *Bot) GetChat(recipient Recipient) (*Chat, error) {
func (b *Bot) ChatByID(id string) (*Chat, error) {
params := map[string]string{
"chat_id": recipient.Recipient(),
"chat_id": id,
}
respJSON, err := b.sendCommand("getChat", params)
@ -398,16 +400,15 @@ func (b *Bot) GetChat(recipient Recipient) (*Chat, error) {
return resp.Result, nil
}
// GetChatAdministrators return list of administrators in a chat.
// AdminsOf return a member list of chat admins.
//
// 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 (b *Bot) GetChatAdministrators(recipient Recipient) ([]ChatMember, error) {
func (b *Bot) AdminsOf(chat *Chat) ([]ChatMember, error) {
params := map[string]string{
"chat_id": recipient.Recipient(),
"chat_id": chat.Recipient(),
}
respJSON, err := b.sendCommand("getChatAdministrators", params)
@ -433,12 +434,10 @@ func (b *Bot) GetChatAdministrators(recipient Recipient) ([]ChatMember, error) {
return resp.Result, nil
}
// GetChatMembersCount return the number of members in a chat.
//
// Returns Int on success.
func (b *Bot) GetChatMembersCount(recipient Recipient) (int, error) {
// Len return the number of members in a chat.
func (b *Bot) Len(chat *Chat) (int, error) {
params := map[string]string{
"chat_id": recipient.Recipient(),
"chat_id": chat.Recipient(),
}
respJSON, err := b.sendCommand("getChatMembersCount", params)
@ -464,12 +463,10 @@ func (b *Bot) GetChatMembersCount(recipient Recipient) (int, error) {
return resp.Result, nil
}
// GetUserProfilePhotos return list of profile pictures for a user.
//
// Returns a list[photos][sizes].
func (b *Bot) GetUserProfilePhotos(recipient Recipient) ([][]Photo, error) {
// ProfilePhotosOf return list of profile pictures for a user.
func (b *Bot) ProfilePhotosOf(user *User) ([]Photo, error) {
params := map[string]string{
"user_id": recipient.Recipient(),
"user_id": user.Recipient(),
}
respJSON, err := b.sendCommand("getUserProfilePhotos", params)
@ -480,8 +477,8 @@ func (b *Bot) GetUserProfilePhotos(recipient Recipient) ([][]Photo, error) {
var resp struct {
Ok bool
Result struct {
Count int `json:"total_count"`
Photos [][]Photo `json:"photos"`
Count int `json:"total_count"`
Photos []Photo `json:"photos"`
}
Description string `json:"description"`
@ -502,9 +499,9 @@ func (b *Bot) GetUserProfilePhotos(recipient Recipient) ([][]Photo, error) {
// GetChatMember return information about a member of a chat.
//
// Returns a ChatMember object on success.
func (b *Bot) GetChatMember(recipient Recipient, user User) (ChatMember, error) {
func (b *Bot) GetChatMember(chat *Chat, user *User) (ChatMember, error) {
params := map[string]string{
"chat_id": recipient.Recipient(),
"chat_id": chat.Recipient(),
"user_id": user.Recipient(),
}
@ -533,7 +530,7 @@ func (b *Bot) GetChatMember(recipient Recipient, user User) (ChatMember, error)
// GetFileDirectURL returns direct url for files using FileId which you can get from File object
func (b *Bot) GetFileDirectURL(fileID string) (string, error) {
f, err := b.GetFile(fileID)
f, err := b.FileByID(fileID)
if err != nil {
return "", err
}

@ -10,7 +10,9 @@ package telebot
// could easily implement MessageSig() making
// instances of stored messages editable.
type Editable interface {
// For inline messages, return chatID = 0
// MessageSig is a "message signature".
//
// For inline messages, return chatID = 0.
MessageSig() (messageID int, chatID int64)
}

@ -1,25 +0,0 @@
package telebot
// Default handler prefix.
const Default string = ""
type Context struct {
Bot *Bot
Message Message
}
type Handler func(Context)
func (b *Bot) Handle(prefix string, handler Handler) {
b.tree.Insert(prefix, handler)
}
func (b *Bot) Serve(msg Message) {
request := msg.Text
_, value, _ := b.tree.LongestPrefix(request)
if endpoint, ok := value.(Handler); ok {
go endpoint(Context{b, msg})
}
}

@ -83,8 +83,8 @@ type InlineQueryResults []InlineQueryResult
//
// If ID of some result appears empty, it gets set to a new hash.
// JSON-specific Type gets infered from the actual (specific) IQR type.
func (results *InlineQueryResults) MarshalJSON() ([]byte, error) {
for i, result := range *results {
func (results InlineQueryResults) MarshalJSON() ([]byte, error) {
for i, result := range results {
if result.GetID() == "" {
hash, err := hashstructure.Hash(result, inlineQueryHashOptions)
if err != nil {
@ -101,7 +101,7 @@ func (results *InlineQueryResults) MarshalJSON() ([]byte, error) {
}
}
return json.Marshal([]InlineQueryResult(*results))
return json.Marshal([]InlineQueryResult(results))
}
func inferIQR(result InlineQueryResult) error {
@ -134,8 +134,3 @@ func inferIQR(result InlineQueryResult) error {
return nil
}
// Result is a deprecated type, superseded by InlineQueryResult.
type Result interface {
MarshalJSON() ([]byte, error)
}

@ -1,98 +0,0 @@
package telebot
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
)
// ArticleResult represents a link to an article or web page.
// Deprecated, use InlineQueryResultArticle instead.
type ArticleResult struct {
// [Required!] Title of the result.
Title string
// [Required!] Text of the message to be sent, 1-512 characters.
Text string
// Short description of the result.
Description string
// Markdown, HTML?
Mode ParseMode
// Disables link previews for links in the sent message.
DisableWebPagePreview bool
// Sends the message silently. iOS users will not receive a notification, Android users will receive a notification with no sound.
DisableNotification bool
// URL of the result
URL string
// If true, the URL won't be shown in the message.
HideURL bool
// Result's thumbnail URL.
ThumbURL string
}
func (r ArticleResult) id() string {
sum := md5.Sum([]byte(r.Title + r.Text))
return string(hex.EncodeToString(sum[:]))
}
// MarshalJSON is a serializer.
func (r ArticleResult) MarshalJSON() ([]byte, error) {
var b bytes.Buffer
props := map[string]string{}
props["type"] = "article"
props["id"] = r.id()
props["title"] = r.Title
props["description"] = r.Description
props["message_text"] = r.Text
if r.URL != "" {
props["url"] = r.URL
}
if r.ThumbURL != "" {
props["thumb_url"] = r.ThumbURL
}
if r.HideURL {
props["hide_url"] = "true"
}
if r.DisableWebPagePreview {
props["disable_web_page_preview"] = "true"
}
if r.DisableNotification {
props["disable_notification"] = "true"
}
if r.Mode != ModeDefault {
props["parse_mode"] = string(r.Mode)
}
b.WriteRune('{')
if len(props) > 0 {
const tpl = `"%s":"%s",`
for key, value := range props {
b.WriteString(fmt.Sprintf(tpl, key, value))
}
// the last
b.WriteString(`"":""`)
}
b.WriteRune('}')
return b.Bytes(), nil
}

@ -23,6 +23,12 @@ type Photo struct {
Caption string `json:"caption,omitempty"`
}
// UnmarshalJSON is custom unmarshaller required to abstract
// away the hassle of treating different thumbnail sizes.
// Instead, Telebot chooses the hi-res one and just sticks to
// it.
//
// I really do find it a beautiful solution.
func (p *Photo) UnmarshalJSON(jsonStr []byte) error {
var hq photoSize
@ -125,9 +131,9 @@ type Contact struct {
// Location object represents geographic position.
type Location struct {
// Latitude
Lat float64 `json:"latitude"`
Lat float32 `json:"latitude"`
// Longitude
Lng float64 `json:"longitude"`
Lng float32 `json:"longitude"`
}
// Venue object represents a venue location with name, address and

@ -180,19 +180,19 @@ type MessageEntity struct {
User *User `json:"user,omitempty"`
}
// MessageSig() satisfies Editable interface (see Editable.)
// MessageSig satisfies Editable interface (see Editable.)
func (m *Message) MessageSig() (int, int64) {
return m.ID, m.Chat.ID
}
// Time returns the moment of message creation in local time.
func (m *Message) Time() time.Time {
return time.Unix(int64(m.Unixtime), 0)
return time.Unix(m.Unixtime, 0)
}
// LastEdited returns time.Time of last edit.
func (m *Message) LastEdited() time.Time {
return time.Unix(int64(m.LastEdit), 0)
return time.Unix(m.LastEdit, 0)
}
// IsForwarded says whether message is forwarded copy of another
@ -206,7 +206,7 @@ func (m *Message) IsReply() bool {
return m.ReplyTo != nil
}
// IsPrivate returns true, if it's a personal message.
// Private returns true, if it's a personal message.
func (m *Message) Private() bool {
return m.Chat.Type == ChatPrivate
}

@ -9,16 +9,16 @@ package telebot
type Option int
const (
// SendOptions.DisableWebPagePreview
// NoPreview = SendOptions.DisableWebPagePreview
NoPreview Option = iota
// SendOptions.DisableNotification
// Silent = SendOptions.DisableNotification
Silent
// ReplyMarkup.ForceReply
// ForceReply = ReplyMarkup.ForceReply
ForceReply
// ReplyMarkup.OneTimeKeyboard
// OneTimeKeyboard = ReplyMarkup.OneTimeKeyboard
OneTimeKeyboard
)
@ -50,11 +50,6 @@ type SendOptions struct {
// such as reply keyboard and inline "keyboard" (a grid of buttons as a part
// of the message).
type ReplyMarkup struct {
// ForceReply forces Telegram clients to display
// a reply interface to the user (act as if the user
// has selected the bots message and tapped "Reply").
ForceReply bool `json:"force_reply,omitempty"`
// InlineKeyboard is a grid of InlineButtons displayed in the message.
//
// Note: DO NOT confuse with ReplyKeyboard and other keyboard properties!
@ -65,6 +60,11 @@ type ReplyMarkup struct {
// Note: you don't need to set HideCustomKeyboard field to show custom keyboard.
ReplyKeyboard [][]KeyboardButton `json:"keyboard,omitempty"`
// ForceReply forces Telegram clients to display
// a reply interface to the user (act as if the user
// has selected the bots message and tapped "Reply").
ForceReply bool `json:"force_reply,omitempty"`
// Requests clients to resize the keyboard vertically for optimal fit
// (e.g. make the keyboard smaller if there are just two rows of buttons).
//

@ -18,6 +18,7 @@ type Sendable interface {
Send(*Bot, Recipient, *SendOptions) (*Message, error)
}
// Send delivers media through bot b to recipient.
func (p *Photo) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -37,6 +38,7 @@ func (p *Photo) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
return msg, nil
}
// Send delivers media through bot b to recipient.
func (a *Audio) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -55,6 +57,7 @@ func (a *Audio) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
return msg, nil
}
// Send delivers media through bot b to recipient.
func (d *Document) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -73,6 +76,7 @@ func (d *Document) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error
return msg, nil
}
// Send delivers media through bot b to recipient.
func (s *Sticker) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -90,6 +94,7 @@ func (s *Sticker) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error)
return msg, nil
}
// Send delivers media through bot b to recipient.
func (v *Video) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -108,6 +113,7 @@ func (v *Video) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
return msg, nil
}
// Send delivers media through bot b to recipient.
func (v *Voice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -125,6 +131,7 @@ func (v *Voice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
return msg, nil
}
// Send delivers media through bot b to recipient.
func (v *VideoNote) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -142,6 +149,7 @@ func (v *VideoNote) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, erro
return msg, nil
}
// Send delivers media through bot b to recipient.
func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),
@ -158,6 +166,7 @@ func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error
return extractMsgResponse(respJSON)
}
// Send delivers media through bot b to recipient.
func (v *Venue) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params := map[string]string{
"chat_id": to.Recipient(),

@ -13,5 +13,11 @@ type Sticker struct {
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
}
// MaskPosition describes the position on faces where
// a mask should be placed by default.
type MaskPosition struct {
Feature MaskFeature `json:"point"`
XShift float32 `json:"x_shift"`
YShift float32 `json:"y_shift"`
Scale float32 `json:"scale"`
}

@ -56,14 +56,12 @@ func extractOptions(how []interface{}) *SendOptions {
switch opt := prop.(type) {
case *SendOptions:
opts = opt
break
case *ReplyMarkup:
if opts == nil {
opts = &SendOptions{}
}
opts.ReplyMarkup = opt
break
case Option:
if opts == nil {
@ -73,37 +71,27 @@ func extractOptions(how []interface{}) *SendOptions {
switch opt {
case NoPreview:
opts.DisableWebPagePreview = true
break
case Silent:
opts.DisableNotification = true
break
case ForceReply:
if opts.ReplyMarkup == nil {
opts.ReplyMarkup = &ReplyMarkup{}
}
opts.ReplyMarkup.ForceReply = true
break
case OneTimeKeyboard:
if opts.ReplyMarkup == nil {
opts.ReplyMarkup = &ReplyMarkup{}
}
opts.ReplyMarkup.OneTimeKeyboard = true
break
default:
panic("telebot: unsupported option")
}
break
case ParseMode:
if opts == nil {
opts = &SendOptions{}
}
opts.ParseMode = opt
break
default:
panic(fmt.Sprintf("telebot: %v is not a send-option", opt))

Loading…
Cancel
Save