Fully refactored high level API
This commit is contained in:
parent
29322bf303
commit
6e4ade909d
14 changed files with 354 additions and 351 deletions
63
README.md
63
README.md
|
@ -19,66 +19,9 @@
|
||||||
|
|
||||||
## Пример
|
## Пример
|
||||||
|
|
||||||
```go
|
* [Пример с отправкой фото](https://github.com/neonxp/tamtam/blob/master/examples/example.go)
|
||||||
package main
|
* [Пример с longpolling](https://github.com/neonxp/tamtam/blob/master/examples/example_longpolling.go)
|
||||||
|
* [Пример с webhook](https://github.com/neonxp/tamtam/blob/master/examples/example_webhook.go)
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
|
|
||||||
"github.com/neonxp/tamtam"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
api := tamtam.New(os.Getenv("TOKEN"))
|
|
||||||
|
|
||||||
info, err := api.Bots.GetBot() // Простой метод
|
|
||||||
log.Printf("Get me: %#v %#v", info, err)
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
go func() {
|
|
||||||
exit := make(chan os.Signal)
|
|
||||||
signal.Notify(exit, os.Kill, os.Interrupt)
|
|
||||||
<-exit
|
|
||||||
cancel()
|
|
||||||
}()
|
|
||||||
for upd := range api.GetUpdates(ctx) { // Чтение из канала с обновлениями
|
|
||||||
log.Printf("Received: %#v", upd)
|
|
||||||
switch upd := upd.(type) { // Определение типа пришедшего обновления
|
|
||||||
case *tamtam.MessageCreatedUpdate:
|
|
||||||
// Создание клавиатуры
|
|
||||||
keyboard := api.Messages.NewKeyboardBuilder()
|
|
||||||
keyboard.
|
|
||||||
AddRow().
|
|
||||||
AddGeolocation("Прислать геолокацию", true).
|
|
||||||
AddContact("Прислать контакт")
|
|
||||||
keyboard.
|
|
||||||
AddRow().
|
|
||||||
AddLink("Библиотека", tamtam.POSITIVE, "https://github.com/neonxp/tamtam").
|
|
||||||
AddCallback("Колбек 1", tamtam.NEGATIVE, "callback_1").
|
|
||||||
AddCallback("Колбек 2", tamtam.NEGATIVE, "callback_2")
|
|
||||||
|
|
||||||
// Отправка сообщения с клавиатурой
|
|
||||||
res, err := api.Messages.SendMessage(0, upd.Message.Sender.UserId, &tamtam.NewMessageBody{
|
|
||||||
Text: fmt.Sprintf("Hello, %s! Your message: %s", upd.Message.Sender.Name, upd.Message.Body.Text),
|
|
||||||
Attachments: []interface{}{
|
|
||||||
tamtam.NewInlineKeyboardAttachmentRequest(keyboard.Build()),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
log.Printf("Answer: %#v %#v", res, err)
|
|
||||||
case *tamtam.MessageCallbackUpdate:
|
|
||||||
res, err := api.Messages.SendMessage(0, upd.Callback.User.UserId, &tamtam.NewMessageBody{
|
|
||||||
Text: "Callback: " + upd.Callback.Payload,
|
|
||||||
})
|
|
||||||
log.Printf("Answer: %#v %#v", res, err)
|
|
||||||
default:
|
|
||||||
log.Printf("Unknown type: %#v", upd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Автор
|
## Автор
|
||||||
|
|
||||||
|
|
94
api.go
94
api.go
|
@ -11,6 +11,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
//Api implements main part of TamTam API
|
//Api implements main part of TamTam API
|
||||||
|
@ -42,106 +44,106 @@ func New(key string) *Api {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Api) bytesToProperUpdate(b []byte) UpdateInterface {
|
func (a *Api) bytesToProperUpdate(b []byte) schemes.UpdateInterface {
|
||||||
u := new(Update)
|
u := new(schemes.Update)
|
||||||
_ = json.Unmarshal(b, u)
|
_ = json.Unmarshal(b, u)
|
||||||
switch u.GetUpdateType() {
|
switch u.GetUpdateType() {
|
||||||
case TypeMessageCallback:
|
case schemes.TypeMessageCallback:
|
||||||
upd := new(MessageCallbackUpdate)
|
upd := new(schemes.MessageCallbackUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
case TypeMessageCreated:
|
case schemes.TypeMessageCreated:
|
||||||
upd := new(MessageCreatedUpdate)
|
upd := new(schemes.MessageCreatedUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
for _, att := range upd.Message.Body.RawAttachments {
|
for _, att := range upd.Message.Body.RawAttachments {
|
||||||
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
||||||
}
|
}
|
||||||
return upd
|
return upd
|
||||||
case TypeMessageRemoved:
|
case schemes.TypeMessageRemoved:
|
||||||
upd := new(MessageRemovedUpdate)
|
upd := new(schemes.MessageRemovedUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
case TypeMessageEdited:
|
case schemes.TypeMessageEdited:
|
||||||
upd := new(MessageEditedUpdate)
|
upd := new(schemes.MessageEditedUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
for _, att := range upd.Message.Body.RawAttachments {
|
for _, att := range upd.Message.Body.RawAttachments {
|
||||||
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
upd.Message.Body.Attachments = append(upd.Message.Body.Attachments, a.bytesToProperAttachment(att))
|
||||||
}
|
}
|
||||||
return upd
|
return upd
|
||||||
case TypeBotAdded:
|
case schemes.TypeBotAdded:
|
||||||
upd := new(BotAddedToChatUpdate)
|
upd := new(schemes.BotAddedToChatUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
case TypeBotRemoved:
|
case schemes.TypeBotRemoved:
|
||||||
upd := new(BotRemovedFromChatUpdate)
|
upd := new(schemes.BotRemovedFromChatUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
case TypeUserAdded:
|
case schemes.TypeUserAdded:
|
||||||
upd := new(UserAddedToChatUpdate)
|
upd := new(schemes.UserAddedToChatUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
case TypeUserRemoved:
|
case schemes.TypeUserRemoved:
|
||||||
upd := new(UserRemovedFromChatUpdate)
|
upd := new(schemes.UserRemovedFromChatUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
case TypeBotStarted:
|
case schemes.TypeBotStarted:
|
||||||
upd := new(BotStartedUpdate)
|
upd := new(schemes.BotStartedUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
case TypeChatTitleChanged:
|
case schemes.TypeChatTitleChanged:
|
||||||
upd := new(ChatTitleChangedUpdate)
|
upd := new(schemes.ChatTitleChangedUpdate)
|
||||||
_ = json.Unmarshal(b, upd)
|
_ = json.Unmarshal(b, upd)
|
||||||
return upd
|
return upd
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Api) bytesToProperAttachment(b []byte) AttachmentInterface {
|
func (a *Api) bytesToProperAttachment(b []byte) schemes.AttachmentInterface {
|
||||||
attachment := new(Attachment)
|
attachment := new(schemes.Attachment)
|
||||||
_ = json.Unmarshal(b, attachment)
|
_ = json.Unmarshal(b, attachment)
|
||||||
switch attachment.GetAttachmentType() {
|
switch attachment.GetAttachmentType() {
|
||||||
case AttachmentAudio:
|
case schemes.AttachmentAudio:
|
||||||
res := new(AudioAttachment)
|
res := new(schemes.AudioAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentContact:
|
case schemes.AttachmentContact:
|
||||||
res := new(ContactAttachment)
|
res := new(schemes.ContactAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentFile:
|
case schemes.AttachmentFile:
|
||||||
res := new(FileAttachment)
|
res := new(schemes.FileAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentImage:
|
case schemes.AttachmentImage:
|
||||||
res := new(PhotoAttachment)
|
res := new(schemes.PhotoAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentKeyboard:
|
case schemes.AttachmentKeyboard:
|
||||||
res := new(InlineKeyboardAttachment)
|
res := new(schemes.InlineKeyboardAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentLocation:
|
case schemes.AttachmentLocation:
|
||||||
res := new(LocationAttachment)
|
res := new(schemes.LocationAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentShare:
|
case schemes.AttachmentShare:
|
||||||
res := new(ShareAttachment)
|
res := new(schemes.ShareAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentSticker:
|
case schemes.AttachmentSticker:
|
||||||
res := new(StickerAttachment)
|
res := new(schemes.StickerAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
case AttachmentVideo:
|
case schemes.AttachmentVideo:
|
||||||
res := new(VideoAttachment)
|
res := new(schemes.VideoAttachment)
|
||||||
_ = json.Unmarshal(b, res)
|
_ = json.Unmarshal(b, res)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
return attachment
|
return attachment
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Api) getUpdates(limit int, timeout int, marker int, types []string) (*UpdateList, error) {
|
func (a *Api) getUpdates(limit int, timeout int, marker int, types []string) (*schemes.UpdateList, error) {
|
||||||
result := new(UpdateList)
|
result := new(schemes.UpdateList)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
if limit > 0 {
|
if limit > 0 {
|
||||||
values.Set("limit", strconv.Itoa(limit))
|
values.Set("limit", strconv.Itoa(limit))
|
||||||
|
@ -171,8 +173,8 @@ func (a *Api) getUpdates(limit int, timeout int, marker int, types []string) (*U
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetUpdates returns updates channel
|
//GetUpdates returns updates channel
|
||||||
func (a *Api) GetUpdates(ctx context.Context) chan UpdateInterface {
|
func (a *Api) GetUpdates(ctx context.Context) chan schemes.UpdateInterface {
|
||||||
ch := make(chan UpdateInterface)
|
ch := make(chan schemes.UpdateInterface)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
|
|
10
bots.go
10
bots.go
|
@ -5,6 +5,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bots struct {
|
type bots struct {
|
||||||
|
@ -16,8 +18,8 @@ func newBots(client *client) *bots {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetBot returns info about current bot. Current bot can be identified by access token. Method returns bot identifier, name and avatar (if any)
|
//GetBot returns info about current bot. Current bot can be identified by access token. Method returns bot identifier, name and avatar (if any)
|
||||||
func (a *bots) GetBot() (*BotInfo, error) {
|
func (a *bots) GetBot() (*schemes.BotInfo, error) {
|
||||||
result := new(BotInfo)
|
result := new(schemes.BotInfo)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodGet, "me", values, nil)
|
body, err := a.client.request(http.MethodGet, "me", values, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,8 +34,8 @@ func (a *bots) GetBot() (*BotInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//PatchBot edits current bot info. Fill only the fields you want to update. All remaining fields will stay untouched
|
//PatchBot edits current bot info. Fill only the fields you want to update. All remaining fields will stay untouched
|
||||||
func (a *bots) PatchBot(patch *BotPatch) (*BotInfo, error) {
|
func (a *bots) PatchBot(patch *schemes.BotPatch) (*schemes.BotInfo, error) {
|
||||||
result := new(BotInfo)
|
result := new(schemes.BotInfo)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodPatch, "me", values, patch)
|
body, err := a.client.request(http.MethodPatch, "me", values, patch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
40
chats.go
40
chats.go
|
@ -7,6 +7,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type chats struct {
|
type chats struct {
|
||||||
|
@ -18,8 +20,8 @@ func newChats(client *client) *chats {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetChats returns information about chats that bot participated in: a result list and marker points to the next page
|
//GetChats returns information about chats that bot participated in: a result list and marker points to the next page
|
||||||
func (a *chats) GetChats(count, marker int) (*ChatList, error) {
|
func (a *chats) GetChats(count, marker int) (*schemes.ChatList, error) {
|
||||||
result := new(ChatList)
|
result := new(schemes.ChatList)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
values.Set("count", strconv.Itoa(int(count)))
|
values.Set("count", strconv.Itoa(int(count)))
|
||||||
|
@ -40,8 +42,8 @@ func (a *chats) GetChats(count, marker int) (*ChatList, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetChat returns info about chat
|
//GetChat returns info about chat
|
||||||
func (a *chats) GetChat(chatID int) (*Chat, error) {
|
func (a *chats) GetChat(chatID int) (*schemes.Chat, error) {
|
||||||
result := new(Chat)
|
result := new(schemes.Chat)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodGet, fmt.Sprintf("chats/%d", chatID), values, nil)
|
body, err := a.client.request(http.MethodGet, fmt.Sprintf("chats/%d", chatID), values, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -56,8 +58,8 @@ func (a *chats) GetChat(chatID int) (*Chat, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetChatMembership returns chat membership info for current bot
|
//GetChatMembership returns chat membership info for current bot
|
||||||
func (a *chats) GetChatMembership(chatID int) (*ChatMember, error) {
|
func (a *chats) GetChatMembership(chatID int) (*schemes.ChatMember, error) {
|
||||||
result := new(ChatMember)
|
result := new(schemes.ChatMember)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodGet, fmt.Sprintf("chats/%d/members/me", chatID), values, nil)
|
body, err := a.client.request(http.MethodGet, fmt.Sprintf("chats/%d/members/me", chatID), values, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -72,8 +74,8 @@ func (a *chats) GetChatMembership(chatID int) (*ChatMember, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetChatMembers returns users participated in chat
|
//GetChatMembers returns users participated in chat
|
||||||
func (a *chats) GetChatMembers(chatID, count, marker int) (*ChatMembersList, error) {
|
func (a *chats) GetChatMembers(chatID, count, marker int) (*schemes.ChatMembersList, error) {
|
||||||
result := new(ChatMembersList)
|
result := new(schemes.ChatMembersList)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
values.Set("count", strconv.Itoa(int(count)))
|
values.Set("count", strconv.Itoa(int(count)))
|
||||||
|
@ -94,8 +96,8 @@ func (a *chats) GetChatMembers(chatID, count, marker int) (*ChatMembersList, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//LeaveChat removes bot from chat members
|
//LeaveChat removes bot from chat members
|
||||||
func (a *chats) LeaveChat(chatID int) (*SimpleQueryResult, error) {
|
func (a *chats) LeaveChat(chatID int) (*schemes.SimpleQueryResult, error) {
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodDelete, fmt.Sprintf("chats/%d/members/me", chatID), values, nil)
|
body, err := a.client.request(http.MethodDelete, fmt.Sprintf("chats/%d/members/me", chatID), values, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -110,8 +112,8 @@ func (a *chats) LeaveChat(chatID int) (*SimpleQueryResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//EditChat edits chat info: title, icon, etc…
|
//EditChat edits chat info: title, icon, etc…
|
||||||
func (a *chats) EditChat(chatID int, update *ChatPatch) (*Chat, error) {
|
func (a *chats) EditChat(chatID int, update *schemes.ChatPatch) (*schemes.Chat, error) {
|
||||||
result := new(Chat)
|
result := new(schemes.Chat)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodPatch, fmt.Sprintf("chats/%d", chatID), values, update)
|
body, err := a.client.request(http.MethodPatch, fmt.Sprintf("chats/%d", chatID), values, update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -126,8 +128,8 @@ func (a *chats) EditChat(chatID int, update *ChatPatch) (*Chat, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddMember adds members to chat. Additional permissions may require.
|
//AddMember adds members to chat. Additional permissions may require.
|
||||||
func (a *chats) AddMember(chatID int, users UserIdsList) (*SimpleQueryResult, error) {
|
func (a *chats) AddMember(chatID int, users schemes.UserIdsList) (*schemes.SimpleQueryResult, error) {
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodPost, fmt.Sprintf("chats/%d/members", chatID), values, users)
|
body, err := a.client.request(http.MethodPost, fmt.Sprintf("chats/%d/members", chatID), values, users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,8 +144,8 @@ func (a *chats) AddMember(chatID int, users UserIdsList) (*SimpleQueryResult, er
|
||||||
}
|
}
|
||||||
|
|
||||||
//RemoveMember removes member from chat. Additional permissions may require.
|
//RemoveMember removes member from chat. Additional permissions may require.
|
||||||
func (a *chats) RemoveMember(chatID int, userID int) (*SimpleQueryResult, error) {
|
func (a *chats) RemoveMember(chatID int, userID int) (*schemes.SimpleQueryResult, error) {
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("user_id", strconv.Itoa(int(userID)))
|
values.Set("user_id", strconv.Itoa(int(userID)))
|
||||||
body, err := a.client.request(http.MethodDelete, fmt.Sprintf("chats/%d/members", chatID), values, nil)
|
body, err := a.client.request(http.MethodDelete, fmt.Sprintf("chats/%d/members", chatID), values, nil)
|
||||||
|
@ -159,10 +161,10 @@ func (a *chats) RemoveMember(chatID int, userID int) (*SimpleQueryResult, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
//SendAction send bot action to chat
|
//SendAction send bot action to chat
|
||||||
func (a *chats) SendAction(chatID int, action SenderAction) (*SimpleQueryResult, error) {
|
func (a *chats) SendAction(chatID int, action schemes.SenderAction) (*schemes.SimpleQueryResult, error) {
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodPost, fmt.Sprintf("chats/%d/actions", chatID), values, ActionRequestBody{Action: action})
|
body, err := a.client.request(http.MethodPost, fmt.Sprintf("chats/%d/actions", chatID), values, schemes.ActionRequestBody{Action: action})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
|
@ -42,7 +44,7 @@ func (cl *client) requestReader(method, path string, query url.Values, body io.R
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
errObj := new(Error)
|
errObj := new(schemes.Error)
|
||||||
err = json.NewDecoder(resp.Body).Decode(errObj)
|
err = json.NewDecoder(resp.Body).Decode(errObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -2,12 +2,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
|
||||||
"github.com/neonxp/tamtam"
|
"github.com/neonxp/tamtam"
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -25,7 +25,7 @@ func main() {
|
||||||
for upd := range api.GetUpdates(ctx) { // Чтение из канала с обновлениями
|
for upd := range api.GetUpdates(ctx) { // Чтение из канала с обновлениями
|
||||||
log.Printf("Received: %#v", upd)
|
log.Printf("Received: %#v", upd)
|
||||||
switch upd := upd.(type) { // Определение типа пришедшего обновления
|
switch upd := upd.(type) { // Определение типа пришедшего обновления
|
||||||
case *tamtam.MessageCreatedUpdate:
|
case *schemes.MessageCreatedUpdate:
|
||||||
// Создание клавиатуры
|
// Создание клавиатуры
|
||||||
keyboard := api.Messages.NewKeyboardBuilder()
|
keyboard := api.Messages.NewKeyboardBuilder()
|
||||||
keyboard.
|
keyboard.
|
||||||
|
@ -34,46 +34,27 @@ func main() {
|
||||||
AddContact("Прислать контакт")
|
AddContact("Прислать контакт")
|
||||||
keyboard.
|
keyboard.
|
||||||
AddRow().
|
AddRow().
|
||||||
AddLink("Библиотека", tamtam.POSITIVE, "https://github.com/neonxp/tamtam").
|
AddLink("Библиотека", schemes.POSITIVE, "https://github.com/neonxp/tamtam").
|
||||||
AddCallback("Колбек 1", tamtam.NEGATIVE, "callback_1").
|
AddCallback("Колбек 1", schemes.NEGATIVE, "callback_1").
|
||||||
AddCallback("Колбек 2", tamtam.NEGATIVE, "callback_2")
|
AddCallback("Колбек 2", schemes.NEGATIVE, "callback_2")
|
||||||
keyboard.
|
keyboard.
|
||||||
AddRow().
|
AddRow().
|
||||||
AddCallback("Картинка", tamtam.POSITIVE, "picture")
|
AddCallback("Картинка", schemes.POSITIVE, "picture")
|
||||||
|
|
||||||
// Отправка сообщения с клавиатурой
|
// Отправка сообщения с клавиатурой
|
||||||
res, err := api.Messages.SendMessage(0, upd.Message.Sender.UserId, &tamtam.NewMessageBody{
|
err := api.Messages.Send(tamtam.NewMessage().SetUser(upd.Message.Sender.UserId).AddKeyboard(keyboard))
|
||||||
Text: fmt.Sprintf("Hello, %s! Your message: %s", upd.Message.Sender.Name, upd.Message.Body.Text),
|
log.Printf("Answer: %#v", err)
|
||||||
Attachments: []interface{}{
|
case *schemes.MessageCallbackUpdate:
|
||||||
tamtam.NewInlineKeyboardAttachmentRequest(keyboard.Build()),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
log.Printf("Answer: %#v %#v", res, err)
|
|
||||||
case *tamtam.MessageCallbackUpdate:
|
|
||||||
// Ответ на коллбек
|
// Ответ на коллбек
|
||||||
attachments := make([]interface{}, 0)
|
|
||||||
if upd.Callback.Payload == "picture" {
|
if upd.Callback.Payload == "picture" {
|
||||||
photo, err := api.Uploads.UploadPhoto("./examples/example.jpg")
|
photo, err := api.Uploads.UploadPhotoFromFile("./examples/example.jpg")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
attachments = append(attachments, tamtam.NewPhotoAttachmentRequest(tamtam.PhotoAttachmentRequestPayload{Photos: photo.Photos}))
|
if err := api.Messages.Send(tamtam.NewMessage().SetUser(upd.Message.Sender.UserId).AddPhoto(photo)); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res, err := api.Messages.AnswerOnCallback(
|
|
||||||
upd.Callback.CallbackID,
|
|
||||||
&tamtam.CallbackAnswer{
|
|
||||||
UserId: upd.Callback.User.UserId,
|
|
||||||
Message: &tamtam.NewMessageBody{
|
|
||||||
Text: "OK!",
|
|
||||||
},
|
|
||||||
Notification: "Callback is ok",
|
|
||||||
})
|
|
||||||
log.Printf("Answer: %#v %#v", res, err)
|
|
||||||
res2, err := api.Messages.SendMessage(0, upd.Callback.User.UserId, &tamtam.NewMessageBody{
|
|
||||||
Text: upd.Callback.Payload + " at " + upd.GetUpdateTime().String(),
|
|
||||||
Attachments: attachments,
|
|
||||||
})
|
|
||||||
log.Printf("Answer: %#v %#v", res2, err)
|
|
||||||
default:
|
default:
|
||||||
log.Printf("Unknown type: %#v", upd)
|
log.Printf("Unknown type: %#v", upd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,11 @@ func main() {
|
||||||
log.Printf("Received: %#v", upd)
|
log.Printf("Received: %#v", upd)
|
||||||
switch upd := upd.(type) {
|
switch upd := upd.(type) {
|
||||||
case *tamtam.MessageCreatedUpdate:
|
case *tamtam.MessageCreatedUpdate:
|
||||||
res, err := api.Messages.SendMessage(0, upd.Message.Sender.UserId, &tamtam.NewMessageBody{
|
err := api.Messages.Send(
|
||||||
Text: fmt.Sprintf("Hello, %s! Your message: %s", upd.Message.Sender.Name, upd.Message.Body.Text),
|
tamtam.NewMessage().
|
||||||
})
|
SetUser(upd.Message.Sender.UserId).
|
||||||
|
SetText(fmt.Sprintf("Hello, %s! Your message: %s", upd.Message.Sender.Name, upd.Message.Body.Text)),
|
||||||
|
)
|
||||||
log.Printf("Answer: %#v %#v", res, err)
|
log.Printf("Answer: %#v %#v", res, err)
|
||||||
default:
|
default:
|
||||||
log.Printf("Unknown type: %#v", upd)
|
log.Printf("Unknown type: %#v", upd)
|
||||||
|
|
|
@ -39,10 +39,12 @@ func main() {
|
||||||
log.Printf("Received: %#v", upd)
|
log.Printf("Received: %#v", upd)
|
||||||
switch upd := upd.(type) {
|
switch upd := upd.(type) {
|
||||||
case tamtam.MessageCreatedUpdate:
|
case tamtam.MessageCreatedUpdate:
|
||||||
res, err := api.Messages.SendMessage(0, upd.Message.Sender.UserId, &tamtam.NewMessageBody{
|
err := api.Messages.Send(
|
||||||
Text: fmt.Sprintf("Hello, %s! Your message: %s", upd.Message.Sender.Name, upd.Message.Body.Text),
|
tamtam.NewMessage().
|
||||||
})
|
SetUser(upd.Message.Sender.UserId).
|
||||||
log.Printf("Answer: %#v %#v", res, err)
|
SetText(fmt.Sprintf("Hello, %s! Your message: %s", upd.Message.Sender.Name, upd.Message.Body.Text)),
|
||||||
|
)
|
||||||
|
log.Printf("Answer: %#v", err)
|
||||||
default:
|
default:
|
||||||
log.Printf("Unknown type: %#v", upd)
|
log.Printf("Unknown type: %#v", upd)
|
||||||
}
|
}
|
||||||
|
|
46
keyboard.go
46
keyboard.go
|
@ -1,43 +1,45 @@
|
||||||
package tamtam
|
package tamtam
|
||||||
|
|
||||||
//KeyboardBuilder implements builder for inline keyboard
|
import "github.com/neonxp/tamtam/schemes"
|
||||||
type KeyboardBuilder struct {
|
|
||||||
|
//Keyboard implements builder for inline keyboard
|
||||||
|
type Keyboard struct {
|
||||||
rows []*KeyboardRow
|
rows []*KeyboardRow
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddRow adds row to inline keyboard
|
//AddRow adds row to inline keyboard
|
||||||
func (k *KeyboardBuilder) AddRow() *KeyboardRow {
|
func (k *Keyboard) AddRow() *KeyboardRow {
|
||||||
kr := &KeyboardRow{}
|
kr := &KeyboardRow{}
|
||||||
k.rows = append(k.rows, kr)
|
k.rows = append(k.rows, kr)
|
||||||
return kr
|
return kr
|
||||||
}
|
}
|
||||||
|
|
||||||
//Build returns result keyboard
|
//Build returns result keyboard
|
||||||
func (k *KeyboardBuilder) Build() Keyboard {
|
func (k *Keyboard) Build() schemes.Keyboard {
|
||||||
buttons := make([][]ButtonInterface, 0, len(k.rows))
|
buttons := make([][]schemes.ButtonInterface, 0, len(k.rows))
|
||||||
for _, r := range k.rows {
|
for _, r := range k.rows {
|
||||||
buttons = append(buttons, r.Build())
|
buttons = append(buttons, r.Build())
|
||||||
}
|
}
|
||||||
return Keyboard{Buttons: buttons}
|
return schemes.Keyboard{Buttons: buttons}
|
||||||
}
|
}
|
||||||
|
|
||||||
//KeyboardRow represents buttons row
|
//KeyboardRow represents buttons row
|
||||||
type KeyboardRow struct {
|
type KeyboardRow struct {
|
||||||
cols []ButtonInterface
|
cols []schemes.ButtonInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
//Build returns result keyboard row
|
//Build returns result keyboard row
|
||||||
func (k *KeyboardRow) Build() []ButtonInterface {
|
func (k *KeyboardRow) Build() []schemes.ButtonInterface {
|
||||||
return k.cols
|
return k.cols
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddLink button
|
//AddLink button
|
||||||
func (k *KeyboardRow) AddLink(text string, intent Intent, url string) *KeyboardRow {
|
func (k *KeyboardRow) AddLink(text string, intent schemes.Intent, url string) *KeyboardRow {
|
||||||
b := LinkButton{
|
b := schemes.LinkButton{
|
||||||
Url: url,
|
Url: url,
|
||||||
Button: Button{
|
Button: schemes.Button{
|
||||||
Text: text,
|
Text: text,
|
||||||
Type: LINK,
|
Type: schemes.LINK,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
k.cols = append(k.cols, b)
|
k.cols = append(k.cols, b)
|
||||||
|
@ -45,13 +47,13 @@ func (k *KeyboardRow) AddLink(text string, intent Intent, url string) *KeyboardR
|
||||||
}
|
}
|
||||||
|
|
||||||
//AddCallback button
|
//AddCallback button
|
||||||
func (k *KeyboardRow) AddCallback(text string, intent Intent, payload string) *KeyboardRow {
|
func (k *KeyboardRow) AddCallback(text string, intent schemes.Intent, payload string) *KeyboardRow {
|
||||||
b := CallbackButton{
|
b := schemes.CallbackButton{
|
||||||
Payload: payload,
|
Payload: payload,
|
||||||
Intent: intent,
|
Intent: intent,
|
||||||
Button: Button{
|
Button: schemes.Button{
|
||||||
Text: text,
|
Text: text,
|
||||||
Type: CALLBACK,
|
Type: schemes.CALLBACK,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
k.cols = append(k.cols, b)
|
k.cols = append(k.cols, b)
|
||||||
|
@ -60,10 +62,10 @@ func (k *KeyboardRow) AddCallback(text string, intent Intent, payload string) *K
|
||||||
|
|
||||||
//AddContact button
|
//AddContact button
|
||||||
func (k *KeyboardRow) AddContact(text string) *KeyboardRow {
|
func (k *KeyboardRow) AddContact(text string) *KeyboardRow {
|
||||||
b := RequestContactButton{
|
b := schemes.RequestContactButton{
|
||||||
Button: Button{
|
Button: schemes.Button{
|
||||||
Text: text,
|
Text: text,
|
||||||
Type: CONTACT,
|
Type: schemes.CONTACT,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
k.cols = append(k.cols, b)
|
k.cols = append(k.cols, b)
|
||||||
|
@ -72,11 +74,11 @@ func (k *KeyboardRow) AddContact(text string) *KeyboardRow {
|
||||||
|
|
||||||
//AddGeolocation button
|
//AddGeolocation button
|
||||||
func (k *KeyboardRow) AddGeolocation(text string, quick bool) *KeyboardRow {
|
func (k *KeyboardRow) AddGeolocation(text string, quick bool) *KeyboardRow {
|
||||||
b := RequestGeoLocationButton{
|
b := schemes.RequestGeoLocationButton{
|
||||||
Quick: quick,
|
Quick: quick,
|
||||||
Button: Button{
|
Button: schemes.Button{
|
||||||
Text: text,
|
Text: text,
|
||||||
Type: GEOLOCATION,
|
Type: schemes.GEOLOCATION,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
k.cols = append(k.cols, b)
|
k.cols = append(k.cols, b)
|
||||||
|
|
81
message.go
Normal file
81
message.go
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
package tamtam
|
||||||
|
|
||||||
|
import "github.com/neonxp/tamtam/schemes"
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
userID int
|
||||||
|
chatID int
|
||||||
|
message *schemes.NewMessageBody
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMessage() *Message {
|
||||||
|
return &Message{userID: 0, chatID: 0, message: &schemes.NewMessageBody{Attachments: []interface{}{}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) SetUser(userID int) *Message {
|
||||||
|
m.userID = userID
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
func (m *Message) SetChat(chatID int) *Message {
|
||||||
|
m.chatID = chatID
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) SetText(text string) *Message {
|
||||||
|
m.message.Text = text
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) SetNotify(notify bool) *Message {
|
||||||
|
m.message.Notify = notify
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddKeyboard(keyboard *Keyboard) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewInlineKeyboardAttachmentRequest(keyboard.Build()))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddPhoto(photo *schemes.PhotoTokens) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewPhotoAttachmentRequest(schemes.PhotoAttachmentRequestPayload{
|
||||||
|
Photos: photo.Photos,
|
||||||
|
}))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddAudio(audio *schemes.UploadedInfo) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewAudioAttachmentRequest(*audio))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddVideo(video *schemes.UploadedInfo) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewVideoAttachmentRequest(*video))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddFile(file *schemes.UploadedInfo) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewFileAttachmentRequest(*file))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddLocation(lat float64, lon float64) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewLocationAttachmentRequest(lat, lon))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddContact(name string, contactID int, vcfInfo string, vcfPhone string) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewContactAttachmentRequest(schemes.ContactAttachmentRequestPayload{
|
||||||
|
Name: name,
|
||||||
|
ContactId: contactID,
|
||||||
|
VcfInfo: vcfInfo,
|
||||||
|
VcfPhone: vcfPhone,
|
||||||
|
}))
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Message) AddSticker(code string) *Message {
|
||||||
|
m.message.Attachments = append(m.message.Attachments, schemes.NewStickerAttachmentRequest(schemes.StickerAttachmentRequestPayload{
|
||||||
|
Code: code,
|
||||||
|
}))
|
||||||
|
return m
|
||||||
|
}
|
102
messages.go
102
messages.go
|
@ -2,10 +2,13 @@ package tamtam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type messages struct {
|
type messages struct {
|
||||||
|
@ -17,8 +20,8 @@ func newMessages(client *client) *messages {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetMessages returns messages in chat: result page and marker referencing to the next page. Messages traversed in reverse direction so the latest message in chat will be first in result array. Therefore if you use from and to parameters, to must be less than from
|
//GetMessages returns messages in chat: result page and marker referencing to the next page. Messages traversed in reverse direction so the latest message in chat will be first in result array. Therefore if you use from and to parameters, to must be less than from
|
||||||
func (a *messages) GetMessages(chatID int, messageIDs []string, from int, to int, count int) (*MessageList, error) {
|
func (a *messages) GetMessages(chatID int, messageIDs []string, from int, to int, count int) (*schemes.MessageList, error) {
|
||||||
result := new(MessageList)
|
result := new(schemes.MessageList)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
if chatID != 0 {
|
if chatID != 0 {
|
||||||
values.Set("chat_id", strconv.Itoa(int(chatID)))
|
values.Set("chat_id", strconv.Itoa(int(chatID)))
|
||||||
|
@ -49,48 +52,21 @@ func (a *messages) GetMessages(chatID int, messageIDs []string, from int, to int
|
||||||
return result, json.NewDecoder(body).Decode(result)
|
return result, json.NewDecoder(body).Decode(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
//SendMessage sends a message to a chat. As a result for this method new message identifier returns.
|
|
||||||
func (a *messages) SendMessage(chatID int, userID int, message *NewMessageBody) (*Message, error) {
|
|
||||||
result := new(Message)
|
|
||||||
values := url.Values{}
|
|
||||||
if chatID != 0 {
|
|
||||||
values.Set("chat_id", strconv.Itoa(int(chatID)))
|
|
||||||
}
|
|
||||||
if userID != 0 {
|
|
||||||
values.Set("user_id", strconv.Itoa(int(userID)))
|
|
||||||
}
|
|
||||||
body, err := a.client.request(http.MethodPost, "messages", values, message)
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := body.Close(); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return result, json.NewDecoder(body).Decode(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
//EditMessage updates message by id
|
//EditMessage updates message by id
|
||||||
func (a *messages) EditMessage(messageID int, message *NewMessageBody) (*SimpleQueryResult, error) {
|
func (a *messages) EditMessage(messageID int, message *Message) error {
|
||||||
result := new(SimpleQueryResult)
|
s, err := a.editMessage(messageID, message.message)
|
||||||
values := url.Values{}
|
|
||||||
values.Set("message_id", strconv.Itoa(int(messageID)))
|
|
||||||
body, err := a.client.request(http.MethodPut, "messages", values, message)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
if !s.Success {
|
||||||
if err := body.Close(); err != nil {
|
return errors.New(s.Message)
|
||||||
log.Println(err)
|
|
||||||
}
|
}
|
||||||
}()
|
return nil
|
||||||
return result, json.NewDecoder(body).Decode(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//DeleteMessage deletes message by id
|
//DeleteMessage deletes message by id
|
||||||
func (a *messages) DeleteMessage(messageID int) (*SimpleQueryResult, error) {
|
func (a *messages) DeleteMessage(messageID int) (*schemes.SimpleQueryResult, error) {
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("message_id", strconv.Itoa(int(messageID)))
|
values.Set("message_id", strconv.Itoa(int(messageID)))
|
||||||
body, err := a.client.request(http.MethodDelete, "messages", values, nil)
|
body, err := a.client.request(http.MethodDelete, "messages", values, nil)
|
||||||
|
@ -106,8 +82,8 @@ func (a *messages) DeleteMessage(messageID int) (*SimpleQueryResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//AnswerOnCallback should be called to send an answer after a user has clicked the button. The answer may be an updated message or/and a one-time user notification.
|
//AnswerOnCallback should be called to send an answer after a user has clicked the button. The answer may be an updated message or/and a one-time user notification.
|
||||||
func (a *messages) AnswerOnCallback(callbackID string, callback *CallbackAnswer) (*SimpleQueryResult, error) {
|
func (a *messages) AnswerOnCallback(callbackID string, callback *schemes.CallbackAnswer) (*schemes.SimpleQueryResult, error) {
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("callback_id", callbackID)
|
values.Set("callback_id", callbackID)
|
||||||
body, err := a.client.request(http.MethodPost, "answers", values, callback)
|
body, err := a.client.request(http.MethodPost, "answers", values, callback)
|
||||||
|
@ -123,8 +99,52 @@ func (a *messages) AnswerOnCallback(callbackID string, callback *CallbackAnswer)
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewKeyboardBuilder returns new keyboard builder helper
|
//NewKeyboardBuilder returns new keyboard builder helper
|
||||||
func (a *messages) NewKeyboardBuilder() *KeyboardBuilder {
|
func (a *messages) NewKeyboardBuilder() *Keyboard {
|
||||||
return &KeyboardBuilder{
|
return &Keyboard{
|
||||||
rows: make([]*KeyboardRow, 0),
|
rows: make([]*KeyboardRow, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Send sends a message to a chat. As a result for this method new message identifier returns.
|
||||||
|
func (a *messages) Send(m *Message) error {
|
||||||
|
return a.sendMessage(m.chatID, m.userID, m.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *messages) sendMessage(chatID int, userID int, message *schemes.NewMessageBody) error {
|
||||||
|
result := new(schemes.Error)
|
||||||
|
values := url.Values{}
|
||||||
|
if chatID != 0 {
|
||||||
|
values.Set("chat_id", strconv.Itoa(int(chatID)))
|
||||||
|
}
|
||||||
|
if userID != 0 {
|
||||||
|
values.Set("user_id", strconv.Itoa(int(userID)))
|
||||||
|
}
|
||||||
|
body, err := a.client.request(http.MethodPost, "messages", values, message)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer body.Close()
|
||||||
|
if err := json.NewDecoder(body).Decode(result); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if result.Code == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *messages) editMessage(messageID int, message *schemes.NewMessageBody) (*schemes.SimpleQueryResult, error) {
|
||||||
|
result := new(schemes.SimpleQueryResult)
|
||||||
|
values := url.Values{}
|
||||||
|
values.Set("message_id", strconv.Itoa(int(messageID)))
|
||||||
|
body, err := a.client.request(http.MethodPut, "messages", values, message)
|
||||||
|
if err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := body.Close(); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return result, json.NewDecoder(body).Decode(result)
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package tamtam
|
package schemes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type subscriptions struct {
|
type subscriptions struct {
|
||||||
|
@ -16,8 +18,8 @@ func newSubscriptions(client *client) *subscriptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetSubscriptions returns list of all subscriptions
|
//GetSubscriptions returns list of all subscriptions
|
||||||
func (a *subscriptions) GetSubscriptions() (*GetSubscriptionsResult, error) {
|
func (a *subscriptions) GetSubscriptions() (*schemes.GetSubscriptionsResult, error) {
|
||||||
result := new(GetSubscriptionsResult)
|
result := new(schemes.GetSubscriptionsResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodGet, "subscriptions", values, nil)
|
body, err := a.client.request(http.MethodGet, "subscriptions", values, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -32,13 +34,13 @@ func (a *subscriptions) GetSubscriptions() (*GetSubscriptionsResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Subscribe subscribes bot to receive updates via WebHook
|
//Subscribe subscribes bot to receive updates via WebHook
|
||||||
func (a *subscriptions) Subscribe(subscribeURL string, updateTypes []string) (*SimpleQueryResult, error) {
|
func (a *subscriptions) Subscribe(subscribeURL string, updateTypes []string) (*schemes.SimpleQueryResult, error) {
|
||||||
subscription := &SubscriptionRequestBody{
|
subscription := &schemes.SubscriptionRequestBody{
|
||||||
Url: subscribeURL,
|
Url: subscribeURL,
|
||||||
UpdateTypes: updateTypes,
|
UpdateTypes: updateTypes,
|
||||||
Version: a.client.version,
|
Version: a.client.version,
|
||||||
}
|
}
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
body, err := a.client.request(http.MethodPost, "subscriptions", values, subscription)
|
body, err := a.client.request(http.MethodPost, "subscriptions", values, subscription)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -53,8 +55,8 @@ func (a *subscriptions) Subscribe(subscribeURL string, updateTypes []string) (*S
|
||||||
}
|
}
|
||||||
|
|
||||||
//Unsubscribe unsubscribes bot from receiving updates via WebHook
|
//Unsubscribe unsubscribes bot from receiving updates via WebHook
|
||||||
func (a *subscriptions) Unsubscribe(subscriptionURL string) (*SimpleQueryResult, error) {
|
func (a *subscriptions) Unsubscribe(subscriptionURL string) (*schemes.SimpleQueryResult, error) {
|
||||||
result := new(SimpleQueryResult)
|
result := new(schemes.SimpleQueryResult)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("url", subscriptionURL)
|
values.Set("url", subscriptionURL)
|
||||||
body, err := a.client.request(http.MethodDelete, "subscriptions", values, nil)
|
body, err := a.client.request(http.MethodDelete, "subscriptions", values, nil)
|
||||||
|
|
182
uploads.go
182
uploads.go
|
@ -9,7 +9,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
|
"github.com/neonxp/tamtam/schemes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type uploads struct {
|
type uploads struct {
|
||||||
|
@ -20,9 +21,61 @@ func newUploads(client *client) *uploads {
|
||||||
return &uploads{client: client}
|
return &uploads{client: client}
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetUploadURL returns url to upload files
|
//UploadMedia uploads file to TamTam server
|
||||||
func (a *uploads) GetUploadURL(uploadType UploadType) (*UploadEndpoint, error) {
|
func (a *uploads) UploadMediaFromFile(uploadType schemes.UploadType, filename string) (*schemes.UploadedInfo, error) {
|
||||||
result := new(UploadEndpoint)
|
fh, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer fh.Close()
|
||||||
|
return a.UploadMediaFromReader(uploadType, fh)
|
||||||
|
}
|
||||||
|
|
||||||
|
//UploadMediaFromUrl uploads file from remote server to TamTam server
|
||||||
|
func (a *uploads) UploadMediaFromUrl(uploadType schemes.UploadType, u url.URL) (*schemes.UploadedInfo, error) {
|
||||||
|
respFile, err := http.Get(u.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer respFile.Body.Close()
|
||||||
|
return a.UploadMediaFromReader(uploadType, respFile.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *uploads) UploadMediaFromReader(uploadType schemes.UploadType, reader io.Reader) (*schemes.UploadedInfo, error) {
|
||||||
|
result := new(schemes.UploadedInfo)
|
||||||
|
return result, a.uploadMediaFromReader(uploadType, reader, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
//UploadPhotoFromFile uploads photos to TamTam server
|
||||||
|
func (a *uploads) UploadPhotoFromFile(filename string) (*schemes.PhotoTokens, error) {
|
||||||
|
fh, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer fh.Close()
|
||||||
|
result := new(schemes.PhotoTokens)
|
||||||
|
return result, a.uploadMediaFromReader(schemes.PHOTO, fh, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
//UploadPhotoFromUrl uploads photo from remote server to TamTam server
|
||||||
|
func (a *uploads) UploadPhotoFromUrl(u url.URL) (*schemes.PhotoTokens, error) {
|
||||||
|
respFile, err := http.Get(u.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer respFile.Body.Close()
|
||||||
|
result := new(schemes.PhotoTokens)
|
||||||
|
return result, a.uploadMediaFromReader(schemes.PHOTO, respFile.Body, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
//UploadPhotoFromReader uploads photo from reader
|
||||||
|
func (a *uploads) UploadPhotoFromReader(reader io.Reader) (*schemes.PhotoTokens, error) {
|
||||||
|
result := new(schemes.PhotoTokens)
|
||||||
|
return result, a.uploadMediaFromReader(schemes.PHOTO, reader, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *uploads) getUploadURL(uploadType schemes.UploadType) (*schemes.UploadEndpoint, error) {
|
||||||
|
result := new(schemes.UploadEndpoint)
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
values.Set("type", string(uploadType))
|
values.Set("type", string(uploadType))
|
||||||
body, err := a.client.request(http.MethodPost, "uploads", values, nil)
|
body, err := a.client.request(http.MethodPost, "uploads", values, nil)
|
||||||
|
@ -37,128 +90,37 @@ func (a *uploads) GetUploadURL(uploadType UploadType) (*UploadEndpoint, error) {
|
||||||
return result, json.NewDecoder(body).Decode(result)
|
return result, json.NewDecoder(body).Decode(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
//UploadMedia uploads file to TamTam server
|
func (a *uploads) uploadMediaFromReader(uploadType schemes.UploadType, reader io.Reader, result interface{}) error {
|
||||||
func (a *uploads) UploadMedia(endpoint *UploadEndpoint, filename string) (*UploadedInfo, error) {
|
endpoint, err := a.getUploadURL(uploadType)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
bodyBuf := &bytes.Buffer{}
|
bodyBuf := &bytes.Buffer{}
|
||||||
bodyWriter := multipart.NewWriter(bodyBuf)
|
bodyWriter := multipart.NewWriter(bodyBuf)
|
||||||
|
fileWriter, err := bodyWriter.CreateFormFile("data", "file")
|
||||||
fileWriter, err := bodyWriter.CreateFormFile("data", filename)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
_, err = io.Copy(fileWriter, reader)
|
||||||
fh, err := os.Open(filename)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := fh.Close(); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
_, err = io.Copy(fileWriter, fh)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bodyWriter.Close(); err != nil {
|
if err := bodyWriter.Close(); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
contentType := bodyWriter.FormDataContentType()
|
contentType := bodyWriter.FormDataContentType()
|
||||||
|
if err := bodyWriter.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
resp, err := http.Post(endpoint.Url, contentType, bodyBuf)
|
resp, err := http.Post(endpoint.Url, contentType, bodyBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := resp.Body.Close(); err != nil {
|
if err := resp.Body.Close(); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
result := new(UploadedInfo)
|
return json.NewDecoder(resp.Body).Decode(result)
|
||||||
return result, json.NewDecoder(resp.Body).Decode(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
//UploadMediaFromUrl uploads file from remote server to TamTam server
|
|
||||||
func (a *uploads) UploadMediaFromUrl(endpoint *UploadEndpoint, u url.URL) (*UploadedInfo, error) {
|
|
||||||
respFile, err := http.Get(u.String())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer respFile.Body.Close()
|
|
||||||
bodyBuf := &bytes.Buffer{}
|
|
||||||
bodyWriter := multipart.NewWriter(bodyBuf)
|
|
||||||
fileWriter, err := bodyWriter.CreateFormFile("data", path.Base(u.Path))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = io.Copy(fileWriter, respFile.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := bodyWriter.Close(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
contentType := bodyWriter.FormDataContentType()
|
|
||||||
if err := bodyWriter.Close(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
resp, err := http.Post(endpoint.Url, contentType, bodyBuf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := resp.Body.Close(); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
result := new(UploadedInfo)
|
|
||||||
return result, json.NewDecoder(resp.Body).Decode(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
//UploadPhoto uploads photos to TamTam server
|
|
||||||
func (a *uploads) UploadPhoto(filename string) (*PhotoTokens, error) {
|
|
||||||
bodyBuf := &bytes.Buffer{}
|
|
||||||
bodyWriter := multipart.NewWriter(bodyBuf)
|
|
||||||
|
|
||||||
fileWriter, err := bodyWriter.CreateFormFile("data", filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fh, err := os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := fh.Close(); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
_, err = io.Copy(fileWriter, fh)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := bodyWriter.Close(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
endpoint, err := a.GetUploadURL(PHOTO)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
contentType := bodyWriter.FormDataContentType()
|
|
||||||
|
|
||||||
resp, err := http.Post(endpoint.Url, contentType, bodyBuf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := resp.Body.Close(); err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
result := new(PhotoTokens)
|
|
||||||
return result, json.NewDecoder(resp.Body).Decode(result)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue