diff --git a/api.go b/api.go new file mode 100644 index 0000000..7fc6ea3 --- /dev/null +++ b/api.go @@ -0,0 +1,78 @@ +package telebot + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" +) + +func api_getMe(token string) (User, error) { + request := "https://api.telegram.org/bot" + token + "/getMe" + + resp, err := http.Get(request) + if err != nil { + return User{}, err + } + + defer resp.Body.Close() + me_json, err := ioutil.ReadAll(resp.Body) + if err != nil { + return User{}, err + } + + var bot_info struct { + Ok bool + Result User + Description string + } + + err = json.Unmarshal(me_json, &bot_info) + if err != nil { + return User{}, err + } + + if bot_info.Ok { + return bot_info.Result, nil + } else { + return User{}, AuthError{bot_info.Description} + } +} + +func api_getUpdates(token string, + offset int, + updates chan<- Update) error { + command := fmt.Sprintf("getUpdates?offset=%d", offset) + request := "https://api.telegram.org/bot" + token + "/" + command + + resp, err := http.Get(request) + if err != nil { + return err + } + + defer resp.Body.Close() + updates_json, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + + var updates_recieved struct { + Ok bool + Result []Update + Description string + } + + err = json.Unmarshal(updates_json, &updates_recieved) + + if !updates_recieved.Ok { + log.Println(FetchError{updates_recieved.Description}) + return FetchError{updates_recieved.Description} + } + + for _, update := range updates_recieved.Result { + updates <- update + } + + return nil +} diff --git a/bot.go b/bot.go new file mode 100644 index 0000000..6997cd9 --- /dev/null +++ b/bot.go @@ -0,0 +1,44 @@ +package telebot + +import ( + "time" +) + +type Bot struct { + Token string + + // Bot as `User` on API level. + Identity User + + listeners []Listener +} + +type Listener func(*Bot, Message) + +func (b *Bot) Listen(interval time.Duration) { + updates := make(chan Update, 1000) + var latest_update int + + pulse := time.NewTicker(interval) + go func() { + for range pulse.C { + go api_getUpdates(b.Token, + latest_update+1, + updates) + } + }() + + for update := range updates { + if update.Id > latest_update { + latest_update = update.Id + } + + for _, ear := range b.listeners { + go ear(b, update.Payload) + } + } +} + +func (b *Bot) AddListener(ear Listener) { + b.listeners = append(b.listeners, ear) +} diff --git a/errors.go b/errors.go index ee5ec0d..22b4f6e 100644 --- a/errors.go +++ b/errors.go @@ -5,6 +5,14 @@ type AuthError struct { Payload string } +type FetchError struct { + Payload string +} + func (e AuthError) Error() string { return "AuthError: " + e.Payload } + +func (e FetchError) Error() string { + return "FetchError: " + e.Payload +} diff --git a/message.go b/message.go new file mode 100644 index 0000000..5d5c858 --- /dev/null +++ b/message.go @@ -0,0 +1,9 @@ +package telebot + +type Message struct { + Id int `json:"message_id"` + Sender User `json:"from"` + Unixtime int `json:"date"` + Text string `json:"text"` + // TBA: `chat` +} diff --git a/telebot.go b/telebot.go index 79dda74..9fbd778 100644 --- a/telebot.go +++ b/telebot.go @@ -2,51 +2,15 @@ // with Telegram bots. package telebot -import ( - "encoding/json" - "io/ioutil" - "net/http" -) - -type Bot struct { - Token string - - // Bot as `User` on API level. - Identity User -} - // Attempts to construct a Bot with `token` given. func Create(token string) (Bot, error) { - request := "https://api.telegram.org/bot" + token + "/getMe" - - resp, err := http.Get(request) - if err != nil { - return Bot{}, err - } - - defer resp.Body.Close() - me_json, err := ioutil.ReadAll(resp.Body) - if err != nil { - return Bot{}, err - } - - var bot_info struct { - Ok bool - Result User - Description string - } - - err = json.Unmarshal(me_json, &bot_info) + user, err := api_getMe(token) if err != nil { return Bot{}, err } - if bot_info.Ok { - return Bot{ - Token: token, - Identity: bot_info.Result, - }, nil - } else { - return Bot{}, AuthError{bot_info.Description} - } + return Bot{ + Token: token, + Identity: user, + }, nil } diff --git a/telebot_test.go b/telebot_test.go index eda63c0..efc9fc2 100644 --- a/telebot_test.go +++ b/telebot_test.go @@ -1,6 +1,10 @@ package telebot -import "testing" +import ( + "log" + "testing" + "time" +) const TESTING_TOKEN = "107177593:AAHBJfF3nv3pZXVjXpoowVhv_KSGw56s8zo" @@ -10,3 +14,22 @@ func TestCreate(t *testing.T) { t.Fatal(err) } } + +func TestListen(t *testing.T) { + if testing.Short() { + t.Skip("Skipping test in short mode.") + } + + bot, err := Create(TESTING_TOKEN) + if err != nil { + t.Fatal(err) + } + + bot.AddListener(func(bot *Bot, message Message) { + log.Printf("Recieved a message \"%s\" from user \"%s\"\n", + message.Text, message.Sender.Username) + }) + + log.Println("Listening...") + bot.Listen(1 * time.Second) +} diff --git a/update.go b/update.go new file mode 100644 index 0000000..3b117fa --- /dev/null +++ b/update.go @@ -0,0 +1,6 @@ +package telebot + +type Update struct { + Id int `json:"update_id"` + Payload Message `json:"message"` +}