2019-08-09 02:16:08 +03:00
|
|
|
//Package tamtam implements TamTam Bot API
|
|
|
|
//Copyright (c) 2019 Alexander Kiryukhin <a.kiryukhin@mail.ru>
|
2019-03-28 17:51:39 +03:00
|
|
|
package tamtam
|
|
|
|
|
2019-03-29 01:55:21 +03:00
|
|
|
import (
|
2019-03-29 17:51:51 +03:00
|
|
|
"context"
|
2019-03-29 01:55:21 +03:00
|
|
|
"encoding/json"
|
|
|
|
"io/ioutil"
|
2019-03-30 22:12:37 +03:00
|
|
|
"log"
|
2019-03-29 01:55:21 +03:00
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"strconv"
|
2019-03-29 17:51:51 +03:00
|
|
|
"time"
|
2019-03-29 01:55:21 +03:00
|
|
|
)
|
|
|
|
|
2019-08-09 02:16:08 +03:00
|
|
|
//Api implements main part of TamTam API
|
2019-03-29 01:55:21 +03:00
|
|
|
type Api struct {
|
2019-08-09 02:02:05 +03:00
|
|
|
Bots *bots
|
|
|
|
Chats *chats
|
|
|
|
Messages *messages
|
|
|
|
Subscriptions *subscriptions
|
|
|
|
Uploads *uploads
|
|
|
|
client *client
|
|
|
|
updates chan UpdateInterface
|
|
|
|
timeout int
|
|
|
|
pause int
|
2019-03-29 01:55:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// New TamTam Api object
|
|
|
|
func New(key string) *Api {
|
|
|
|
u, _ := url.Parse("https://botapi.tamtam.chat/")
|
2019-08-09 02:02:05 +03:00
|
|
|
cl := newClient(key, "0.1.8", u)
|
2019-03-29 01:55:21 +03:00
|
|
|
return &Api{
|
2019-08-09 02:02:05 +03:00
|
|
|
Bots: newBots(cl),
|
|
|
|
Chats: newChats(cl),
|
|
|
|
Uploads: newUploads(cl),
|
|
|
|
Messages: newMessages(cl),
|
|
|
|
Subscriptions: newSubscriptions(cl),
|
|
|
|
client: cl,
|
|
|
|
updates: make(chan UpdateInterface),
|
|
|
|
timeout: 30,
|
|
|
|
pause: 1,
|
2019-03-29 01:55:21 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-09 02:02:05 +03:00
|
|
|
func (a *Api) bytesToProperUpdate(b []byte) UpdateInterface {
|
2019-03-29 17:51:51 +03:00
|
|
|
u := new(Update)
|
|
|
|
_ = json.Unmarshal(b, u)
|
2019-08-09 02:02:05 +03:00
|
|
|
switch u.GetUpdateType() {
|
|
|
|
case TypeMessageCallback:
|
|
|
|
upd := new(MessageCallbackUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeMessageCreated:
|
|
|
|
upd := new(MessageCreatedUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
|
|
|
for _, att := range upd.Message.Body.rawAttachments {
|
2019-03-29 18:52:22 +03:00
|
|
|
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
|
|
|
}
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeMessageRemoved:
|
|
|
|
upd := new(MessageRemovedUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeMessageEdited:
|
|
|
|
upd := new(MessageEditedUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
|
|
|
for _, att := range upd.Message.Body.rawAttachments {
|
2019-03-29 18:52:22 +03:00
|
|
|
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
|
|
|
}
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeBotAdded:
|
|
|
|
upd := new(BotAddedToChatUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeBotRemoved:
|
|
|
|
upd := new(BotRemovedFromChatUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeUserAdded:
|
|
|
|
upd := new(UserAddedToChatUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeUserRemoved:
|
|
|
|
upd := new(UserRemovedFromChatUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeBotStarted:
|
|
|
|
upd := new(BotStartedUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
2019-08-09 02:02:05 +03:00
|
|
|
case TypeChatTitleChanged:
|
|
|
|
upd := new(ChatTitleChangedUpdate)
|
|
|
|
_ = json.Unmarshal(b, upd)
|
2019-03-29 17:51:51 +03:00
|
|
|
return upd
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-09 02:02:05 +03:00
|
|
|
func (a *Api) bytesToProperAttachment(b []byte) AttachmentInterface {
|
2019-03-29 18:52:22 +03:00
|
|
|
attachment := new(Attachment)
|
|
|
|
_ = json.Unmarshal(b, attachment)
|
2019-08-09 02:02:05 +03:00
|
|
|
switch attachment.GetAttachmentType() {
|
2019-03-29 18:52:22 +03:00
|
|
|
case AttachmentAudio:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(AudioAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentContact:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(ContactAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentFile:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(FileAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentImage:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(PhotoAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentKeyboard:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(InlineKeyboardAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentLocation:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(LocationAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentShare:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(ShareAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentSticker:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(StickerAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
case AttachmentVideo:
|
2019-08-09 02:02:05 +03:00
|
|
|
res := new(VideoAttachment)
|
|
|
|
_ = json.Unmarshal(b, res)
|
2019-03-29 18:52:22 +03:00
|
|
|
return res
|
|
|
|
}
|
|
|
|
return attachment
|
|
|
|
}
|
|
|
|
|
2019-08-09 02:02:05 +03:00
|
|
|
func (a *Api) getUpdates(limit int, timeout int, marker int, types []string) (*UpdateList, error) {
|
2019-03-29 01:55:21 +03:00
|
|
|
result := new(UpdateList)
|
|
|
|
values := url.Values{}
|
|
|
|
if limit > 0 {
|
|
|
|
values.Set("limit", strconv.Itoa(limit))
|
|
|
|
}
|
|
|
|
if timeout > 0 {
|
|
|
|
values.Set("timeout", strconv.Itoa(timeout))
|
|
|
|
}
|
|
|
|
if marker > 0 {
|
2019-08-09 02:02:05 +03:00
|
|
|
values.Set("marker", strconv.Itoa(marker))
|
2019-03-29 01:55:21 +03:00
|
|
|
}
|
|
|
|
if len(types) > 0 {
|
|
|
|
for _, t := range types {
|
|
|
|
values.Add("types", t)
|
|
|
|
}
|
|
|
|
}
|
2019-08-09 02:02:05 +03:00
|
|
|
body, err := a.client.request(http.MethodGet, "updates", values, nil)
|
2019-03-29 01:55:21 +03:00
|
|
|
if err != nil {
|
|
|
|
return result, err
|
|
|
|
}
|
2019-08-09 02:02:05 +03:00
|
|
|
defer func() {
|
|
|
|
if err := body.Close(); err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
}
|
|
|
|
}()
|
2019-03-30 22:12:37 +03:00
|
|
|
jb, _ := ioutil.ReadAll(body)
|
|
|
|
return result, json.Unmarshal(jb, result)
|
2019-03-29 01:55:21 +03:00
|
|
|
}
|
|
|
|
|
2019-08-09 02:02:05 +03:00
|
|
|
func (a *Api) UpdatesLoop(ctx context.Context) error {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return nil
|
|
|
|
case <-time.After(time.Duration(a.pause) * time.Second):
|
|
|
|
var marker int
|
|
|
|
for {
|
|
|
|
upds, err := a.getUpdates(50, a.timeout, marker, []string{})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(upds.Updates) == 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
for _, u := range upds.Updates {
|
|
|
|
a.updates <- a.bytesToProperUpdate(u)
|
|
|
|
}
|
|
|
|
marker = *upds.Marker
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 15:06:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-09 02:16:08 +03:00
|
|
|
//GetUpdates returns updates channel
|
2019-08-09 02:02:05 +03:00
|
|
|
func (a *Api) GetUpdates() chan UpdateInterface {
|
|
|
|
return a.updates
|
2019-03-29 01:55:21 +03:00
|
|
|
}
|
|
|
|
|
2019-08-09 02:16:08 +03:00
|
|
|
//GetHandler returns http handler for webhooks
|
2019-08-09 02:02:05 +03:00
|
|
|
func (a *Api) GetHandler(updates chan interface{}) http.HandlerFunc {
|
|
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
defer func() {
|
|
|
|
if err := r.Body.Close(); err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
b, _ := ioutil.ReadAll(r.Body)
|
|
|
|
updates <- a.bytesToProperUpdate(b)
|
|
|
|
}
|
|
|
|
}
|