221 lines
5.5 KiB
Go
221 lines
5.5 KiB
Go
//Package tamtam implements TamTam Bot API.
|
|
//Official documentation: https://dev.tamtam.chat/
|
|
package tamtam
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/neonxp/tamtam/schemes"
|
|
)
|
|
|
|
//Api implements main part of TamTam API
|
|
type Api struct {
|
|
Bots *bots
|
|
Chats *chats
|
|
Messages *messages
|
|
Subscriptions *subscriptions
|
|
Uploads *uploads
|
|
client *client
|
|
timeout int
|
|
pause int
|
|
}
|
|
|
|
// New TamTam Api object
|
|
func New(key string) *Api {
|
|
timeout := 30
|
|
u, _ := url.Parse("https://botapi.tamtam.chat/")
|
|
cl := newClient(key, "0.1.8", u, &http.Client{Timeout: time.Duration(timeout) * time.Second})
|
|
return &Api{
|
|
Bots: newBots(cl),
|
|
Chats: newChats(cl),
|
|
Uploads: newUploads(cl),
|
|
Messages: newMessages(cl),
|
|
Subscriptions: newSubscriptions(cl),
|
|
client: cl,
|
|
timeout: timeout,
|
|
pause: 1,
|
|
}
|
|
}
|
|
|
|
func (a *Api) bytesToProperUpdate(b []byte) schemes.UpdateInterface {
|
|
u := new(schemes.Update)
|
|
_ = json.Unmarshal(b, u)
|
|
switch u.GetUpdateType() {
|
|
case schemes.TypeMessageCallback:
|
|
upd := new(schemes.MessageCallbackUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
case schemes.TypeMessageCreated:
|
|
upd := new(schemes.MessageCreatedUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
for _, att := range upd.Message.Body.RawAttachments {
|
|
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
|
}
|
|
return upd
|
|
case schemes.TypeMessageRemoved:
|
|
upd := new(schemes.MessageRemovedUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
case schemes.TypeMessageEdited:
|
|
upd := new(schemes.MessageEditedUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
for _, att := range upd.Message.Body.RawAttachments {
|
|
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
|
}
|
|
return upd
|
|
case schemes.TypeBotAdded:
|
|
upd := new(schemes.BotAddedToChatUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
case schemes.TypeBotRemoved:
|
|
upd := new(schemes.BotRemovedFromChatUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
case schemes.TypeUserAdded:
|
|
upd := new(schemes.UserAddedToChatUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
case schemes.TypeUserRemoved:
|
|
upd := new(schemes.UserRemovedFromChatUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
case schemes.TypeBotStarted:
|
|
upd := new(schemes.BotStartedUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
case schemes.TypeChatTitleChanged:
|
|
upd := new(schemes.ChatTitleChangedUpdate)
|
|
_ = json.Unmarshal(b, upd)
|
|
return upd
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (a *Api) bytesToProperAttachment(b []byte) schemes.AttachmentInterface {
|
|
attachment := new(schemes.Attachment)
|
|
_ = json.Unmarshal(b, attachment)
|
|
switch attachment.GetAttachmentType() {
|
|
case schemes.AttachmentAudio:
|
|
res := new(schemes.AudioAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentContact:
|
|
res := new(schemes.ContactAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentFile:
|
|
res := new(schemes.FileAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentImage:
|
|
res := new(schemes.PhotoAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentKeyboard:
|
|
res := new(schemes.InlineKeyboardAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentLocation:
|
|
res := new(schemes.LocationAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentShare:
|
|
res := new(schemes.ShareAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentSticker:
|
|
res := new(schemes.StickerAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
case schemes.AttachmentVideo:
|
|
res := new(schemes.VideoAttachment)
|
|
_ = json.Unmarshal(b, res)
|
|
return res
|
|
}
|
|
return attachment
|
|
}
|
|
|
|
func (a *Api) getUpdates(limit int, timeout int, marker int64, types []string) (*schemes.UpdateList, error) {
|
|
result := new(schemes.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 {
|
|
values.Set("marker", strconv.Itoa(int(marker)))
|
|
}
|
|
if len(types) > 0 {
|
|
for _, t := range types {
|
|
values.Add("types", t)
|
|
}
|
|
}
|
|
body, err := a.client.request(http.MethodGet, "updates", values, nil)
|
|
if err != nil {
|
|
if err == errLongPollTimeout {
|
|
return result, nil
|
|
}
|
|
return result, err
|
|
}
|
|
defer func() {
|
|
if err := body.Close(); err != nil {
|
|
log.Println(err)
|
|
}
|
|
}()
|
|
jb, _ := ioutil.ReadAll(body)
|
|
return result, json.Unmarshal(jb, result)
|
|
}
|
|
|
|
//GetUpdates returns updates channel
|
|
func (a *Api) GetUpdates(ctx context.Context) chan schemes.UpdateInterface {
|
|
ch := make(chan schemes.UpdateInterface)
|
|
go func() {
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
close(ch)
|
|
return
|
|
case <-time.After(time.Duration(a.pause) * time.Second):
|
|
var marker int64
|
|
for {
|
|
upds, err := a.getUpdates(50, a.timeout, marker, []string{})
|
|
if err != nil {
|
|
log.Println(err)
|
|
break
|
|
}
|
|
if len(upds.Updates) == 0 {
|
|
break
|
|
}
|
|
for _, u := range upds.Updates {
|
|
ch <- a.bytesToProperUpdate(u)
|
|
}
|
|
marker = *upds.Marker
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
return ch
|
|
}
|
|
|
|
//GetHandler returns http handler for webhooks
|
|
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)
|
|
}
|
|
}
|