initial commit, some api methods and structs for everything

bot-api-6.1
Syfaro 2015-06-25 00:34:05 -05:00
commit 434756c165
2 changed files with 552 additions and 0 deletions

109
bot.go 100644
View File

@ -0,0 +1,109 @@
package main
import (
"encoding/json"
"flag"
"io/ioutil"
"log"
"strconv"
"strings"
"time"
)
type Config struct {
Token string `json:"token"`
}
type Plugin interface {
GetCommand() string
GotCommand(Message, []string)
}
type ColonThree struct {
}
func (plugin *ColonThree) GetCommand() string {
return "/three"
}
func (plugin *ColonThree) GotCommand(message Message, args []string) {
if len(args) > 0 {
n, err := strconv.Atoi(args[0])
if err != nil {
msg := NewMessage(message.Chat.Id, "Bad number!")
msg.ReplyToMessageId = message.MessageId
bot.sendMessage(msg)
return
}
if n > 5 {
msg := NewMessage(message.Chat.Id, "That's a bit much, no?")
msg.ReplyToMessageId = message.MessageId
bot.sendMessage(msg)
return
}
for i := 0; i < n; i++ {
bot.sendMessage(NewMessage(message.Chat.Id, ":3"))
}
} else {
bot.sendMessage(NewMessage(message.Chat.Id, ":3"))
}
}
var bot *BotApi
func main() {
configPath := flag.String("config", "config.json", "path to config.json")
flag.Parse()
data, err := ioutil.ReadFile(*configPath)
if err != nil {
log.Panic(err)
}
var cfg Config
json.Unmarshal(data, &cfg)
bot = NewBotApi(BotConfig{
token: cfg.Token,
debug: true,
})
plugins := []Plugin{&ColonThree{}}
ticker := time.NewTicker(5 * time.Second)
lastUpdate := 0
for range ticker.C {
updates, err := bot.getUpdates(NewUpdate(lastUpdate + 1))
if err != nil {
log.Panic(err)
}
for _, update := range updates {
lastUpdate = update.UpdateId
if update.Message.Text == "" {
continue
}
for _, plugin := range plugins {
parts := strings.Split(update.Message.Text, " ")
if plugin.GetCommand() == parts[0] {
parts = append(parts[:0], parts[1:]...)
plugin.GotCommand(update.Message, parts)
}
}
}
}
}

443
methods.go 100644
View File

@ -0,0 +1,443 @@
package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
)
const (
CHAT_TYPING = "typing"
CHAT_UPLOAD_PHOTO = "upload_photo"
CHAT_RECORD_VIDEO = "record_video"
CHAT_UPLOAD_VIDEO = "upload_video"
CHAT_RECORD_AUDIO = "record_audio"
CHAT_UPLOAD_AUDIO = "upload_audio"
CHAT_UPLOAD_DOCUMENT = "upload_document"
CHAT_FIND_LOCATION = "find_location"
)
type BotConfig struct {
token string
debug bool
}
type BotApi struct {
config BotConfig
}
type ApiResponse struct {
Ok bool `json:"ok"`
Result json.RawMessage `json:"result"`
}
type Update struct {
UpdateId int `json:"update_id"`
Message Message `json:"message"`
}
type User struct {
Id int `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
UserName string `json:"username"`
}
type GroupChat struct {
Id int `json:"id"`
Title string `json:"title"`
}
type UserOrGroupChat struct {
Id int `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
UserName string `json:"username"`
Title string `json:"title"`
}
type Message struct {
MessageId int `json:"message_id"`
From User `json:"from"`
Date int `json:"date"`
Chat UserOrGroupChat `json:"chat"`
ForwardFrom User `json:"forward_from"`
ForwardDate int `json:"forward_date"`
ReplyToMessage *Message `json:"reply_to_message"`
Text string `json:"text"`
Audio Audio `json:"audio"`
Document Document `json:"document"`
Photo []PhotoSize `json:"photo"`
Sticker Sticker `json:"sticker"`
Video Video `json:"video"`
Contact Contact `json:"contact"`
Location Location `json:"location"`
NewChatParticipant User `json:"new_chat_participant"`
LeftChatParticipant User `json:"left_chat_participant"`
NewChatTitle string `json:"new_chat_title"`
NewChatPhoto string `json:"new_chat_photo"`
DeleteChatPhoto bool `json:"delete_chat_photo"`
GroupChatCreated bool `json:"group_chat_created"`
}
type PhotoSize struct {
FileId string `json:"file_id"`
Width int `json:"width"`
Height int `json:"height"`
FileSize int `json:"file_size"`
}
type Audio struct {
FileId string `json:"file_id"`
Duration int `json:"duration"`
MimeType string `json:"mime_type"`
FileSize int `json:"file_size"`
}
type Document struct {
FileId string `json:"file_id"`
Thumb PhotoSize `json:"thumb"`
FileName string `json:"file_name"`
MimeType string `json:"mime_type"`
FileSize int `json:"file_size"`
}
type Sticker struct {
FileId string `json:"file_id"`
Width int `json:"width"`
Height int `json:"height"`
Thumb PhotoSize `json:"thumb"`
FileSize int `json:"file_size"`
}
type Video struct {
FileId string `json:"file_id"`
Width int `json:"width"`
Height int `json:"height"`
Duration int `json:"duration"`
Thumb PhotoSize `json:"thumb"`
MimeType string `json:"mime_type"`
FileSize int `json:"file_size"`
Caption string `json:"caption"`
}
type Contact struct {
PhoneNumber string `json:"phone_number"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
UserId string `json:"user_id"`
}
type Location struct {
Longitude float32 `json:"longitude"`
Latitude float32 `json:"latitude"`
}
type UserProfilePhotos struct {
TotalCount int `json:"total_count"`
Photos []PhotoSize `json:"photos"`
}
type ReplyKeyboardMarkup struct {
Keyboard map[string]map[string]string `json:"keyboard"`
ResizeKeyboard bool `json:"resize_keyboard"`
OneTimeKeyboard bool `json:"one_time_keyboard"`
Selective bool `json:"selective"`
}
type ReplyKeyboardHide struct {
HideKeyboard bool `json:"hide_keyboard"`
Selective bool `json:"selective"`
}
type ForceReply struct {
ForceReply bool `json:"force_reply"`
Selective bool `json:"force_reply"`
}
type UpdateConfig struct {
Offset int
Limit int
Timeout int
}
type MessageConfig struct {
ChatId int
Text string
DisableWebPagePreview bool
ReplyToMessageId int
}
type ForwardConfig struct {
ChatId int
FromChatId int
MessageId int
}
type LocationConfig struct {
ChatId int
Latitude float64
Longitude float64
ReplyToMessageId int
ReplyMarkup interface{}
}
type ChatActionConfig struct {
ChatId int
Action string
}
type UserProfilePhotosConfig struct {
UserId int
Offset int
Limit int
}
func NewBotApi(config BotConfig) *BotApi {
return &BotApi{
config: config,
}
}
func (bot *BotApi) makeRequest(endpoint string, params url.Values) (ApiResponse, error) {
resp, err := http.PostForm("https://api.telegram.org/bot"+bot.config.token+"/"+endpoint, params)
defer resp.Body.Close()
if err != nil {
return ApiResponse{}, err
}
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return ApiResponse{}, nil
}
if bot.config.debug {
log.Println(string(bytes[:]))
}
var apiResp ApiResponse
json.Unmarshal(bytes, &apiResp)
return apiResp, nil
}
func (bot *BotApi) getMe() (User, error) {
resp, err := bot.makeRequest("getMe", nil)
if err != nil {
return User{}, err
}
var user User
json.Unmarshal(resp.Result, &user)
if bot.config.debug {
log.Printf("getMe: %+v\n", user)
}
return user, nil
}
func (bot *BotApi) sendMessage(config MessageConfig) (Message, error) {
v := url.Values{}
v.Add("chat_id", strconv.Itoa(config.ChatId))
v.Add("text", config.Text)
v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
if config.ReplyToMessageId != 0 {
v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
}
resp, err := bot.makeRequest("sendMessage", v)
if err != nil {
return Message{}, err
}
var message Message
json.Unmarshal(resp.Result, &message)
if bot.config.debug {
log.Printf("sendMessage req : %+v\n", v)
log.Printf("sendMessage resp: %+v\n", message)
}
return message, nil
}
func (bot *BotApi) forwardMessage(config ForwardConfig) (Message, error) {
v := url.Values{}
v.Add("chat_id", strconv.Itoa(config.ChatId))
v.Add("from_chat_id", strconv.Itoa(config.FromChatId))
v.Add("message_id", strconv.Itoa(config.MessageId))
resp, err := bot.makeRequest("forwardMessage", v)
if err != nil {
return Message{}, err
}
var message Message
json.Unmarshal(resp.Result, &message)
if bot.config.debug {
log.Printf("forwardMessage req : %+v\n", v)
log.Printf("forwardMessage resp: %+v\n", message)
}
return message, nil
}
func (bot *BotApi) sendLocation(config LocationConfig) (Message, error) {
v := url.Values{}
v.Add("chat_id", strconv.Itoa(config.ChatId))
v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
if config.ReplyToMessageId != 0 {
v.Add("reply_to_message_id", strconv.Itoa(config.ReplyToMessageId))
}
if config.ReplyMarkup != nil {
data, err := json.Marshal(config.ReplyMarkup)
if err != nil {
return Message{}, err
}
v.Add("reply_markup", string(data))
}
resp, err := bot.makeRequest("sendLocation", v)
if err != nil {
return Message{}, err
}
var message Message
json.Unmarshal(resp.Result, &message)
if bot.config.debug {
log.Printf("sendLocation req : %+v\n", v)
log.Printf("sendLocation resp: %+v\n", message)
}
return message, nil
}
func (bot *BotApi) sendChatAction(config ChatActionConfig) error {
v := url.Values{}
v.Add("chat_id", strconv.Itoa(config.ChatId))
v.Add("action", config.Action)
_, err := bot.makeRequest("sendChatAction", v)
if err != nil {
return err
}
return nil
}
func (bot *BotApi) getUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
v := url.Values{}
v.Add("user_id", strconv.Itoa(config.UserId))
if config.Offset != 0 {
v.Add("offset", strconv.Itoa(config.Offset))
}
if config.Limit != 0 {
v.Add("limit", strconv.Itoa(config.Limit))
}
resp, err := bot.makeRequest("getUserProfilePhotos", v)
if err != nil {
return UserProfilePhotos{}, err
}
var profilePhotos UserProfilePhotos
json.Unmarshal(resp.Result, &profilePhotos)
if bot.config.debug {
log.Printf("getUserProfilePhotos req : %+v\n", v)
log.Printf("getUserProfilePhotos resp: %+v\n", profilePhotos)
}
return profilePhotos, nil
}
func (bot *BotApi) getUpdates(config UpdateConfig) ([]Update, error) {
v := url.Values{}
if config.Offset > 0 {
v.Add("offset", strconv.Itoa(config.Offset))
}
if config.Limit > 0 {
v.Add("limit", strconv.Itoa(config.Limit))
}
if config.Timeout > 0 {
v.Add("timeout", strconv.Itoa(config.Timeout))
}
resp, err := bot.makeRequest("getUpdates", v)
if err != nil {
return []Update{}, err
}
var updates []Update
json.Unmarshal(resp.Result, &updates)
if bot.config.debug {
log.Printf("getUpdates: %+v\n", updates)
}
return updates, nil
}
func (bot *BotApi) setWebhook(v url.Values) error {
_, err := bot.makeRequest("setWebhook", v)
return err
}
func NewMessage(chatId int, text string) MessageConfig {
return MessageConfig{
ChatId: chatId,
Text: text,
DisableWebPagePreview: false,
ReplyToMessageId: 0,
}
}
func NewForward(chatId int, fromChatId int, messageId int) ForwardConfig {
return ForwardConfig{
ChatId: chatId,
FromChatId: fromChatId,
MessageId: messageId,
}
}
func NewLocation(chatId int, latitude float64, longitude float64) LocationConfig {
return LocationConfig{
ChatId: chatId,
Latitude: latitude,
Longitude: longitude,
ReplyToMessageId: 0,
ReplyMarkup: nil,
}
}
func NewChatAction(chatId int, action string) ChatActionConfig {
return ChatActionConfig{
ChatId: chatId,
Action: action,
}
}
func NewUserProfilePhotos(userId int) UserProfilePhotosConfig {
return UserProfilePhotosConfig{
UserId: userId,
Offset: 0,
Limit: 0,
}
}
func NewUpdate(offset int) UpdateConfig {
return UpdateConfig{
Offset: offset,
Limit: 0,
Timeout: 0,
}
}