diff --git a/README.md b/README.md index 82bd106..266f4ed 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,10 @@ func main() { updates, err := bot.GetUpdatesChan(u) for update := range updates { + if update.Message == nil { + continue + } + log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text) msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text) diff --git a/bot.go b/bot.go index cf4c0d9..d3f6df7 100644 --- a/bot.go +++ b/bot.go @@ -521,6 +521,117 @@ func (bot *BotAPI) KickChatMember(config ChatMemberConfig) (APIResponse, error) return bot.MakeRequest("kickChatMember", v) } +// LeaveChat makes the bot leave the chat. +func (bot *BotAPI) LeaveChat(config ChatConfig) (APIResponse, error) { + v := url.Values{} + + if config.SuperGroupUsername == "" { + v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) + } else { + v.Add("chat_id", config.SuperGroupUsername) + } + + bot.debugLog("leaveChat", v, nil) + + return bot.MakeRequest("leaveChat", v) +} + +// GetChat gets information about a chat. +func (bot *BotAPI) GetChat(config ChatConfig) (Chat, error) { + v := url.Values{} + + if config.SuperGroupUsername == "" { + v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) + } else { + v.Add("chat_id", config.SuperGroupUsername) + } + + resp, err := bot.MakeRequest("getChat", v) + if err != nil { + return Chat{}, err + } + + var chat Chat + err = json.Unmarshal(resp.Result, &chat) + + bot.debugLog("getChat", v, chat) + + return chat, err +} + +// GetChatAdministrators gets a list of administrators in the chat. +// +// If none have been appointed, only the creator will be returned. +// Bots are not shown, even if they are an administrator. +func (bot *BotAPI) GetChatAdministrators(config ChatConfig) ([]ChatMember, error) { + v := url.Values{} + + if config.SuperGroupUsername == "" { + v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) + } else { + v.Add("chat_id", config.SuperGroupUsername) + } + + resp, err := bot.MakeRequest("getChatAdministrators", v) + if err != nil { + return []ChatMember{}, err + } + + var members []ChatMember + err = json.Unmarshal(resp.Result, &members) + + bot.debugLog("getChatAdministrators", v, members) + + return members, err +} + +// GetChatMembersCount gets the number of users in a chat. +func (bot *BotAPI) GetChatMembersCount(config ChatConfig) (int, error) { + v := url.Values{} + + if config.SuperGroupUsername == "" { + v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) + } else { + v.Add("chat_id", config.SuperGroupUsername) + } + + resp, err := bot.MakeRequest("getChatMembersCount", v) + if err != nil { + return -1, err + } + + var count int + err = json.Unmarshal(resp.Result, &count) + + bot.debugLog("getChatMembersCount", v, count) + + return count, err +} + +// GetChatMember gets a specific chat member. +func (bot *BotAPI) GetChatMember(config ChatConfigWithUser) (ChatMember, error) { + v := url.Values{} + + if config.SuperGroupUsername == "" { + v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) + } else { + v.Add("chat_id", config.SuperGroupUsername) + } + v.Add("user_id", strconv.Itoa(config.UserID)) + + resp, err := bot.MakeRequest("getChatMember", v) + if err != nil { + return ChatMember{}, err + } + + var member ChatMember + err = json.Unmarshal(resp.Result, &member) + + bot.debugLog("getChatMember", v, member) + + return member, err +} + // UnbanChatMember unbans a user from a chat. Note that this only will work // in supergroups, and requires the bot to be an admin. func (bot *BotAPI) UnbanChatMember(config ChatMemberConfig) (APIResponse, error) { diff --git a/bot_test.go b/bot_test.go index dbe40a9..3f84d76 100644 --- a/bot_test.go +++ b/bot_test.go @@ -447,6 +447,10 @@ func ExampleNewBotAPI() { updates, err := bot.GetUpdatesChan(u) for update := range updates { + if update.Message == nil { + continue + } + log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text) msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text) @@ -493,7 +497,7 @@ func ExampleAnswerInlineQuery() { updates, err := bot.GetUpdatesChan(u) for update := range updates { - if update.InlineQuery.Query == "" { // if no inline query, ignore it + if update.InlineQuery == nil { // if no inline query, ignore it continue } diff --git a/configs.go b/configs.go index 85310bf..49fc0c3 100644 --- a/configs.go +++ b/configs.go @@ -675,3 +675,17 @@ type ChatMemberConfig struct { SuperGroupUsername string UserID int } + +// ChatConfig contains information about getting information on a chat. +type ChatConfig struct { + ChatID int64 + SuperGroupUsername string +} + +// ChatConfigWithUser contains information about getting information on +// a specific user within a chat. +type ChatConfigWithUser struct { + ChatID int64 + SuperGroupUsername string + UserID int +} diff --git a/types.go b/types.go index 511d773..1c7b1b0 100644 --- a/types.go +++ b/types.go @@ -70,25 +70,30 @@ type Chat struct { } // IsPrivate returns if the Chat is a private conversation. -func (c *Chat) IsPrivate() bool { +func (c Chat) IsPrivate() bool { return c.Type == "private" } // IsGroup returns if the Chat is a group. -func (c *Chat) IsGroup() bool { +func (c Chat) IsGroup() bool { return c.Type == "group" } // IsSuperGroup returns if the Chat is a supergroup. -func (c *Chat) IsSuperGroup() bool { +func (c Chat) IsSuperGroup() bool { return c.Type == "supergroup" } // IsChannel returns if the Chat is a channel. -func (c *Chat) IsChannel() bool { +func (c Chat) IsChannel() bool { return c.Type == "channel" } +// ChatConfig returns a ChatConfig struct for chat related methods. +func (c Chat) ChatConfig() ChatConfig { + return ChatConfig{ChatID: c.ID} +} + // Message is returned by almost every request, and contains data about // almost anything. type Message struct { @@ -343,6 +348,27 @@ type ForceReply struct { Selective bool `json:"selective"` // optional } +// ChatMember is information about a member in a chat. +type ChatMember struct { + User *User `json:"user"` + Status string `json:"status"` +} + +// IsCreator returns if the ChatMember was the creator of the chat. +func (chat ChatMember) IsCreator() bool { return chat.Status == "creator" } + +// IsAdministrator returns if the ChatMember is a chat administrator. +func (chat ChatMember) IsAdministrator() bool { return chat.Status == "administrator" } + +// IsMember returns if the ChatMember is a current member of the chat. +func (chat ChatMember) IsMember() bool { return chat.Status == "member" } + +// HasLeft returns if the ChatMember left the chat. +func (chat ChatMember) HasLeft() bool { return chat.Status == "left" } + +// WasKicked returns if the ChatMember was kicked from the chat. +func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" } + // InlineQuery is a Query from Telegram for an inline request. type InlineQuery struct { ID string `json:"id"`