diff options
author | Alexander Kiryukhin <alexander@kiryukhin.su> | 2019-03-29 01:55:21 +0300 |
---|---|---|
committer | Alexander Kiryukhin <alexander@kiryukhin.su> | 2019-03-29 01:55:21 +0300 |
commit | 75679a0cbb631db348cb5a3bbe4a4f8aa5447f60 (patch) | |
tree | 714e1b09b0130cdbe893355cf2a382a5b9ec4330 | |
parent | a5f90182f76a279952f6cfd3dd7beab7391aaf56 (diff) |
Первый рабочий релиз
-rw-r--r-- | .gitignore | 33 | ||||
-rw-r--r-- | README.md | 25 | ||||
-rw-r--r-- | api.go | 403 | ||||
-rw-r--r-- | examples/example_1.go | 50 | ||||
-rw-r--r-- | models.go | 789 | ||||
-rw-r--r-- | types.go | 107 |
6 files changed, 1286 insertions, 121 deletions
@@ -1,15 +1,26 @@ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a *.so -*.dylib -# Test binary, build with `go test -c` -*.test +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* -# Output of the go coverage tool, specifically when used with LiteIDE -*.out +_testmain.go + +*.exe +*.test +*.prof -# IDEA -.idea
\ No newline at end of file +.idea @@ -1,2 +1,23 @@ -# tamtam-go -Go API for TamTam bots +# TamTam Go + +Простая реализация клиента к TamTam Bot API на Go. + +На данном этапе представляет собой 1 в 1 реализованные методы API + HTTPHandler для веб-хуков + сгенерированные модели. + +## Документация + +Её пока нет :) + +Но http://godoc.org/github.com/neonxp/tamtam-go/ может вам помочь. + +## Статус + +API пока крайне неставбильное и обязательно будет меняться в будущем. Учитывайте это! + +## Пример + +Простые примеры использования находятся в директории `examples`. + +## Автор + +Alexander Kiryukhin <a.kiryukhin@mail.ru> @@ -1,3 +1,404 @@ +/* + * TamTam Bot API + */ package tamtam -// TODO methods +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "strconv" +) + +type Api struct { + key string + url *url.URL +} + +// New TamTam Api object +func New(key string) *Api { + u, _ := url.Parse("https://botapi.tamtam.chat/") + return &Api{ + key: key, + url: u, + } +} + +// region Misc methods + +func (a *Api) GetMe() (*UserWithPhoto, error) { + result := new(UserWithPhoto) + values := url.Values{} + body, err := a.request(http.MethodGet, "me", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) GetUploadURL(uploadType UploadType) (*UploadEndpoint, error) { + result := new(UploadEndpoint) + values := url.Values{} + values.Set("type", string(uploadType)) + body, err := a.request(http.MethodPost, "uploads", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) GetHandler(updates chan interface{}) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + u := new(Update) + b, _ := ioutil.ReadAll(r.Body) + _ = json.Unmarshal(b, u) + switch u.UpdateType { + case UpdateTypeMessageCallback: + upd := new(UpdateMessageCallback) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeMessageCreated: + upd := new(UpdateMessageCreated) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeMessageRemoved: + upd := new(UpdateMessageRemoved) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeMessageEdited: + upd := new(UpdateMessageEdited) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeMessageRestored: + upd := new(UpdateMessageRestored) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeBotAdded: + upd := new(UpdateBotAdded) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeBotRemoved: + upd := new(UpdateBotRemoved) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeUserAdded: + upd := new(UpdateUserAdded) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeUserRemoved: + upd := new(UpdateUserRemoved) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeBotStarted: + upd := new(UpdateBotStarted) + _ = json.Unmarshal(b, upd) + updates <- *upd + case UpdateTypeChatTitleChanged: + upd := new(UpdateChatTitleChanged) + _ = json.Unmarshal(b, upd) + updates <- *upd + } + } +} + +// endregion + +// region Chat methods +func (a *Api) GetChats(count, marker int64) (*ChatList, error) { + result := new(ChatList) + values := url.Values{} + if count > 0 { + values.Set("count", strconv.Itoa(int(count))) + } + if marker > 0 { + values.Set("marker", strconv.Itoa(int(marker))) + } + body, err := a.request(http.MethodGet, "chats", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) GetChat(chatID int64) (*Chat, error) { + result := new(Chat) + values := url.Values{} + body, err := a.request(http.MethodGet, fmt.Sprintf("chats/%d", chatID), values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) GetChatMembership(chatID int64) (*ChatMember, error) { + result := new(ChatMember) + values := url.Values{} + body, err := a.request(http.MethodGet, fmt.Sprintf("chats/%d/members/me", chatID), values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) GetChatMembers(chatID, count, marker int64) (*ChatMembersList, error) { + result := new(ChatMembersList) + values := url.Values{} + if count > 0 { + values.Set("count", strconv.Itoa(int(count))) + } + if marker > 0 { + values.Set("marker", strconv.Itoa(int(marker))) + } + body, err := a.request(http.MethodGet, fmt.Sprintf("chats/%d/members", chatID), values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) LeaveChat(chatID int64) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + body, err := a.request(http.MethodDelete, fmt.Sprintf("chats/%d/members/me", chatID), values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) EditChat(chatID int64, update *ChatPatch) (*Chat, error) { + result := new(Chat) + values := url.Values{} + body, err := a.request(http.MethodPatch, fmt.Sprintf("chats/%d", chatID), values, update) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) AddMember(chatID int64, users UserIdsList) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + body, err := a.request(http.MethodPost, fmt.Sprintf("chats/%d/members", chatID), values, users) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) RemoveMember(chatID int64, userID int64) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + values.Set("user_id", strconv.Itoa(int(userID))) + body, err := a.request(http.MethodDelete, fmt.Sprintf("chats/%d/members", chatID), values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) SendAction(chatID int64, action SenderAction) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + body, err := a.request(http.MethodPost, fmt.Sprintf("chats/%d/actions", chatID), values, ActionRequestBody{Action: action}) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +// endregion + +// region Message methods + +func (a *Api) GetMessages(chatID int64, messageIDs []string, from int64, to int64, count int64) (*MessageList, error) { + result := new(MessageList) + values := url.Values{} + if chatID > 0 { + values.Set("chat_id", strconv.Itoa(int(chatID))) + } + if len(messageIDs) > 0 { + for _, mid := range messageIDs { + values.Add("message_ids", mid) + } + } + if from > 0 { + values.Set("from", strconv.Itoa(int(from))) + } + if to > 0 { + values.Set("count", strconv.Itoa(int(to))) + } + if count > 0 { + values.Set("count", strconv.Itoa(int(count))) + } + body, err := a.request(http.MethodGet, "messages", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) SendMessage(chatID int64, userID int64, 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.request(http.MethodPost, "messages", values, message) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) EditMessage(messageID int64, message *NewMessageBody) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + values.Set("message_id", strconv.Itoa(int(messageID))) + body, err := a.request(http.MethodPut, "messages", values, message) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) DeleteMessage(messageID int64) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + values.Set("message_id", strconv.Itoa(int(messageID))) + body, err := a.request(http.MethodDelete, "messages", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) AnswerOnCallback(callbackID int64, callback *CallbackAnswer) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + values.Set("callback_id", strconv.Itoa(int(callbackID))) + body, err := a.request(http.MethodPost, "answers", values, callback) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +// endregion + +// region Subscriptions + +func (a *Api) GetSubscriptions() (*GetSubscriptionsResult, error) { + result := new(GetSubscriptionsResult) + values := url.Values{} + body, err := a.request(http.MethodGet, "subscriptions", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) Subscribe(subscription *SubscriptionRequestBody) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + body, err := a.request(http.MethodPost, "subscriptions", values, subscription) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) Unsubscribe(subscriptionURL string) (*SimpleQueryResult, error) { + result := new(SimpleQueryResult) + values := url.Values{} + values.Set("url", subscriptionURL) + body, err := a.request(http.MethodDelete, "subscriptions", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +func (a *Api) GetUpdates(limit int, timeout int, marker int64, types []string) (*UpdateList, error) { + 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 { + values.Set("marker", strconv.Itoa(int(marker))) + } + if len(types) > 0 { + for _, t := range types { + values.Add("types", t) + } + } + body, err := a.request(http.MethodDelete, "updates", values, nil) + if err != nil { + return result, err + } + defer body.Close() + return result, json.NewDecoder(body).Decode(result) +} + +// endregion + +// region Internal + +func (a *Api) request(method, path string, query url.Values, body interface{}) (io.ReadCloser, error) { + c := http.DefaultClient + u := *a.url + u.Path = path + query.Set("access_token", a.key) + u.RawQuery = query.Encode() + j, err := json.Marshal(body) + if err != nil { + return nil, err + } + req, err := http.NewRequest(method, u.String(), bytes.NewReader(j)) + if err != nil { + return nil, err + } + resp, err := c.Do(req) + if resp.StatusCode != http.StatusOK { + errObj := new(Error) + err = json.NewDecoder(resp.Body).Decode(errObj) + if err != nil { + return nil, err + } + return nil, fmt.Errorf("code=%s message=%s error=%s", errObj.Code, errObj.Message, errObj.Error) + } + return resp.Body, err +} + +// endregion diff --git a/examples/example_1.go b/examples/example_1.go new file mode 100644 index 0000000..bdb496a --- /dev/null +++ b/examples/example_1.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "github.com/neonxp/tamtam-go" + "log" + "net/http" + "os" +) + +func main() { + // Initialisation + api := tamtam.New(os.Getenv("TOKEN")) + + // Some methods demo: + info, err := api.GetMe() + log.Printf("Get me: %#v %#v", info, err) + chats, err := api.GetChats(0, 0) + log.Printf("Get chats: %#v %#v", chats, err) + chat, err := api.GetChat(chats.Chats[0].ChatId) + log.Printf("Get chat: %#v %#v", chat, err) + msgs, err := api.GetMessages(chats.Chats[0].ChatId, nil, 0, 0, 0) + log.Printf("Get messages: %#v %#v", msgs, err) + + subscriptionResp, err := api.Subscribe(&tamtam.SubscriptionRequestBody{ + Url: "https://4940675e.ngrok.io/webhook", // Replace by your webhook! + }) + log.Printf("Subscription: %#v %#v", subscriptionResp, err) + + ch := make(chan interface{}) // Channel with updates from TamTam + + http.HandleFunc("/webhook", api.GetHandler(ch)) + go func() { + for { + upd := <-ch + log.Printf("Received: %#v", upd) + switch upd := upd.(type) { + case tamtam.UpdateMessageCreated: + res, err := api.SendMessage(0, upd.Message.Sender.UserId, &tamtam.NewMessageBody{ + Text: fmt.Sprintf("Hello, %s! Your message: %s", upd.Message.Sender.Name, upd.Message.Body.Text), + }) + log.Printf("Answer: %#v %#v", res, err) + default: + log.Printf("Unknown type: %#v", upd) + } + } + }() + + http.ListenAndServe(":10888", nil) +} diff --git a/models.go b/models.go new file mode 100644 index 0000000..6c50651 --- /dev/null +++ b/models.go @@ -0,0 +1,789 @@ +/* + * TamTam Bot API + * + * Bot API allows bots to interact with TamTam + * + * API version: 0.1.3 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ +package tamtam + +type ActionRequestBody struct { + Action SenderAction `json:"action"` +} + +type AttachmentType string + +const ( + AttachmentImage AttachmentType = "image" + AttachmentVideo = "video" + AttachmentAudio = "audio" + AttachmentFile = "file" + AttachmentContact = "contact" + AttachmentSticker = "sticker" + AttachmentShare = "share" + AttachmentLocation = "location" + AttachmentKeyboard = "inline_keyboard" +) + +// Generic schema representing message attachment +type Attachment struct { + Type AttachmentType `json:"type,omitempty"` +} + +type AttachmentPayload struct { + // Media attachment URL + Url string `json:"url"` +} + +// Request to attach some data to message +type AttachmentRequest struct { + Type string `json:"type,omitempty"` +} + +type AudioAttachment struct { + Type string `json:"type,omitempty"` + Payload AttachmentPayload `json:"payload"` +} + +// Request to attach audio to message. MUST be the only attachment in message +type AudioAttachmentRequest struct { + Type string `json:"type,omitempty"` + Payload UploadedInfo `json:"payload"` +} + +// You will receive this update when bot has been added to chat +type BotAddedToChatUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Chat id where bot was added + ChatId int64 `json:"chat_id"` + // User id who added bot to chat + UserId int64 `json:"user_id"` +} + +// You will receive this update when bot has been removed from chat +type BotRemovedFromChatUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Chat identifier bot removed from + ChatId int64 `json:"chat_id"` + // User id who removed bot from chat + UserId int64 `json:"user_id"` +} + +// Bot gets this type of update as soon as user pressed `Start` button +type BotStartedUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Dialog identifier where event has occurred + ChatId int64 `json:"chat_id"` + // User pressed the 'Start' button + UserId int64 `json:"user_id"` +} + +type Button struct { + Type string `json:"type,omitempty"` + // Visible text of button + Text string `json:"text"` + // Intent of button. Affects clients representation. + Intent Intent `json:"intent"` +} + +// Object sent to bot when user presses button +type Callback struct { + // Unix-time when user pressed the button + Timestamp int64 `json:"timestamp"` + // Current keyboard identifier + CallbackId string `json:"callback_id"` + // Button payload + Payload string `json:"payload"` + // User pressed the button + User User `json:"user"` +} + +// Send this object when your bot wants to react to when a button is pressed +type CallbackAnswer struct { + UserId int64 `json:"user_id,omitempty"` + // Fill this if you want to modify current message + Message NewMessageBody `json:"message,omitempty"` + // Fill this if you just want to send one-time notification to user + Notification string `json:"notification,omitempty"` +} + +// After pressing this type of button client sends to server payload it contains +type CallbackButton struct { + Type string `json:"type,omitempty"` + // Visible text of button + Text string `json:"text"` + // Intent of button. Affects clients representation. + Intent Intent `json:"intent"` + // Button payload + Payload string `json:"payload"` +} + +type Chat struct { + // Chats identifier + ChatId int64 `json:"chat_id"` + // Type of chat. One of: dialog, chat, channel + Type ChatType `json:"type"` + // Chat status. One of: - active: bot is active member of chat - removed: bot was kicked - left: bot intentionally left chat - closed: chat was closed + Status ChatStatus `json:"status"` + // Visible title of chat + Title string `json:"title"` + // Icon of chat + Icon Image `json:"icon"` + // Time of last event occured in chat + LastEventTime int64 `json:"last_event_time"` + // Number of people in chat. Always 2 for `dialog` chat type + ParticipantsCount int32 `json:"participants_count"` + // Identifier of chat owner. Visible only for chat admins + OwnerId int64 `json:"owner_id,omitempty"` + // Participants in chat with time of last activity. Can be *null* when you request list of chats. Visible for chat admins only + Participants map[string]int64 `json:"participants,omitempty"` + // Is current chat publicly available. Always `false` for dialogs + IsPublic bool `json:"is_public"` + // Link on chat if it is public + Link string `json:"link,omitempty"` + // Chat description + Description map[string]interface{} `json:"description"` +} + +// ChatAdminPermission : Chat admin permissions +type ChatAdminPermission string + +// List of ChatAdminPermission +const ( + READ_ALL_MESSAGES ChatAdminPermission = "read_all_messages" + ADD_REMOVE_MEMBERS ChatAdminPermission = "add_remove_members" + ADD_ADMINS ChatAdminPermission = "add_admins" + CHANGE_CHAT_INFO ChatAdminPermission = "change_chat_info" + PIN_MESSAGE ChatAdminPermission = "pin_message" + WRITE ChatAdminPermission = "write" +) + +type ChatList struct { + // List of requested chats + Chats []Chat `json:"chats"` + // Reference to the next page of requested chats + Marker int64 `json:"marker"` +} + +type ChatMember struct { + // Users identifier + UserId int64 `json:"user_id"` + // Users visible name + Name string `json:"name"` + // Unique public user name. Can be `null` if user is not accessible or it is not set + Username string `json:"username"` + // URL of avatar + AvatarUrl string `json:"avatar_url"` + // URL of avatar of a bigger size + FullAvatarUrl string `json:"full_avatar_url"` + LastAccessTime int64 `json:"last_access_time"` + IsOwner bool `json:"is_owner"` + IsAdmin bool `json:"is_admin"` + JoinTime int64 `json:"join_time"` + // Permissions in chat if member is admin. `null` otherwise + Permissions []ChatAdminPermission `json:"permissions"` +} + +type ChatMembersList struct { + // Participants in chat with time of last activity. Visible only for chat admins + Members []ChatMember `json:"members"` + // Pointer to the next data page + Marker int64 `json:"marker"` +} + +type ChatPatch struct { + Icon PhotoAttachmentRequestPayload `json:"icon,omitempty"` + Title string `json:"title,omitempty"` +} + +// ChatStatus : Chat status for current bot +type ChatStatus string + +// List of ChatStatus +const ( + ACTIVE ChatStatus = "active" + REMOVED ChatStatus = "removed" + LEFT ChatStatus = "left" + CLOSED ChatStatus = "closed" + SUSPENDED ChatStatus = "suspended" +) + +// Bot gets this type of update as soon as title has been changed in chat +type ChatTitleChangedUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Chat identifier where event has occurred + ChatId int64 `json:"chat_id"` + // User who changed title + UserId int64 `json:"user_id"` + // New title + Title string `json:"title"` +} + +// ChatType : Type of chat. Dialog (one-on-one), chat or channel +type ChatType string + +// List of ChatType +const ( + DIALOG ChatType = "dialog" + CHAT ChatType = "chat" + CHANNEL ChatType = "channel" +) + +type ContactAttachment struct { + Type string `json:"type,omitempty"` + Payload ContactAttachmentPayload `json:"payload"` +} + +type ContactAttachmentPayload struct { + // User info in VCF format + VcfInfo string `json:"vcfInfo"` + // User info + TamInfo User `json:"tamInfo"` +} + +// Request to attach contact card to message. MUST be the only attachment in message +type ContactAttachmentRequest struct { + Type string `json:"type,omitempty"` + Payload ContactAttachmentRequestPayload `json:"payload"` +} + +type ContactAttachmentRequestPayload struct { + // Contact name + Name string `json:"name"` + // Contact identifier + ContactId int64 `json:"contactId"` + // Full information about contact in VCF format + VcfInfo string `json:"vcfInfo"` + // Contact phone in VCF format + VcfPhone string `json:"vcfPhone"` +} + +// Server returns this if there was an exception to your request +type Error struct { + // Error + Error string `json:"error,omitempty"` + // Error code + Code string `json:"code"` + // Human-readable description + Message string `json:"message"` +} + +type FileAttachment struct { + Type string `json:"type,omitempty"` + Payload AttachmentPayload `json:"payload"` +} + +// Request to attach file to message. MUST be the only attachment in message +type FileAttachmentRequest struct { + Type string `json:"type,omitempty"` + Payload UploadedFileInfo `json:"payload"` +} + +// List of all WebHook subscriptions +type GetSubscriptionsResult struct { + // Current suscriptions + Subscriptions []Subscription `json:"subscriptions"` +} + +// Generic schema describing image object +type Image struct { + // URL of image + Url string `json:"url"` +} + +// Buttons in messages +type InlineKeyboardAttachment struct { + Type string `json:"type,omitempty"` + // Unique identifier of keyboard + CallbackId string `json:"callback_id"` + Payload Keyboard `json:"payload"` +} + +// Request to attach keyboard to message +type InlineKeyboardAttachmentRequest struct { + Type string `json:"type,omitempty"` + Payload InlineKeyboardAttachmentRequestPayload `json:"payload"` +} + +type InlineKeyboardAttachmentRequestPayload struct { + // Two-dimensional array of buttons + Buttons [][]Button `json:"buttons"` +} + +// Intent : Intent of button +type Intent string + +// List of Intent +const ( + POSITIVE Intent = "positive" + NEGATIVE Intent = "negative" + DEFAULT Intent = "default" +) + +// Keyboard is two-dimension array of buttons +type Keyboard struct { + Buttons [][]Button `json:"buttons"` +} + +// After pressing this type of button user follows the link it contains +type LinkButton struct { + Type string `json:"type,omitempty"` + // Visible text of button + Text string `json:"text"` + // Intent of button. Affects clients representation. + Intent Intent `json:"intent"` + Url string `json:"url"` +} + +type LinkedMessage struct { + // Type of linked message + Type MessageLinkType `json:"type"` + // User sent this message + Sender User `json:"sender"` + // Chat where message was originally posted + ChatId int64 `json:"chat_id"` + Message MessageBody `json:"message"` +} + +type LocationAttachment struct { + Type string `json:"type,omitempty"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` +} + +// Request to attach keyboard to message +type LocationAttachmentRequest struct { + Type string `json:"type,omitempty"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` +} + +// Message in chat +type Message struct { + // User that sent this message + Sender User `json:"sender"` + // Message recipient. Could be user or chat + Recipient Recipient `json:"recipient"` + // Unix-time when message was created + Timestamp int64 `json:"timestamp"` + // Forwarder or replied message + Link LinkedMessage `json:"link,omitempty"` + // Body of created message. Text + attachments. Could be null if message contains only forwarded message. + Body MessageBody `json:"message"` +} + +// Schema representing body of message +type MessageBody struct { + // Unique identifier of message + Mid string `json:"mid"` + // Sequence identifier of message in chat + Seq int64 `json:"seq"` + // Message text + Text string `json:"text"` + // Message attachments. Could be one of `Attachment` type. See description of this schema + Attachments []Attachment `json:"attachments"` + // In case this message is repled to, it is the unique identifier of the replied message + ReplyTo string `json:"reply_to,omitempty"` +} + +// You will get this `update` as soon as user presses button +type MessageCallbackUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + Callback Callback `json:"callback"` + // Original message containing inline keyboard. Can be `null` in case it had been deleted by the moment a bot got this update. + Message Message `json:"message"` +} + +// You will get this `update` as soon as message is created +type MessageCreatedUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Newly created message + Message Message `json:"message"` +} + +// You will get this `update` as soon as message is edited +type MessageEditedUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Edited message + Message Message `json:"message"` +} + +// MessageLinkType : Type of linked message +type MessageLinkType string + +// List of MessageLinkType +const ( + FORWARD MessageLinkType = "forward" + REPLY MessageLinkType = "reply" +) + +// Paginated list of messages +type MessageList struct { + // List of messages + Messages []Message `json:"messages"` +} + +// You will get this `update` as soon as message is removed +type MessageRemovedUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Identifier of removed message + MessageId string `json:"message_id"` +} + +// You will get this `update` as soon as message is restored +type MessageRestoredUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Restored message identifier + MessageId string `json:"message_id"` +} + +type NewMessageBody struct { + // Message text + Text string `json:"text"` + // Single message attachment. + Attachment interface{} `json:"attachment,omitempty"` + // Message attachments. See `AttachmentRequest` and it's inheritors for full information. + Attachments []interface{} `json:"attachments,omitempty"` + // If false, chat participants wouldn't be notified + Notify bool `json:"notify,omitempty"` +} + +// Image attachment +type PhotoAttachment struct { + Type string `json:"type,omitempty"` + Payload PhotoAttachmentPayload `json:"payload"` +} + +type PhotoAttachmentPayload struct { + // Unique identifier of this image + PhotoId int64 `json:"photo_id"` + Token string `json:"token"` + // Image URL + Url string `json:"url"` +} + +type PhotoAttachmentRequest struct { + Type string `json:"type,omitempty"` + Payload PhotoAttachmentRequestPayload `json:"payload"` +} + +// Request to attach image. All fields are mutually exclusive. +type PhotoAttachmentRequestPayload struct { + // If specified, given URL will be attached to message as image + Url string `json:"url,omitempty"` + // Token of any existing attachment + Token string `json:"token,omitempty"` + // Tokens were obtained after uploading images + Photos map[string]PhotoToken `json:"photos,omitempty"` +} + +type PhotoToken struct { + // Encoded information of uploaded image + Token string `json:"token"` +} + +// This is information you will recieve as soon as an image uploaded +type PhotoTokens struct { + Photos map[string]PhotoToken `json:"photos"` +} + +// New message recepient. Could be user or chat +type Recipient struct { + // Chat identifier + ChatId int64 `json:"chat_id"` + // Chat type + ChatType ChatType `json:"chat_type"` + // User identifier, if message was sent to user + UserId int64 `json:"user_id"` +} + +// After pressing this type of button client sends new message with attachment of curent user contact +type RequestContactButton struct { + Type string `json:"type,omitempty"` + // Visible text of button + Text string `json:"text"` + // Intent of button. Affects clients representation. + Intent Intent `json:"intent"` +} + +// After pressing this type of button client sends new message with attachment of current user geo location +type RequestGeoLocationButton struct { + Type string `json:"type,omitempty"` + // Visible text of button + Text string `json:"text"` + // Intent of button. Affects clients representation. + Intent Intent `json:"intent"` + // If *true*, sends location without asking user's confirmation + Quick bool `json:"quick,omitempty"` +} + +type SendMessageResult struct { + Message Message `json:"message"` +} + +// SenderAction : Different actions to send to chat members +type SenderAction string + +// List of SenderAction +const ( + TYPING_ON SenderAction = "typing_on" + TYPING_OFF SenderAction = "typing_off" + SENDING_PHOTO SenderAction = "sending_photo" + SENDING_VIDEO SenderAction = "sending_video" + SENDING_AUDIO SenderAction = "sending_audio" + MARK_SEEN SenderAction = "mark_seen" +) + +type ShareAttachment struct { + Type string `json:"type,omitempty"` + Payload AttachmentPayload `json:"payload"` +} + +// Simple response to request +type SimpleQueryResult struct { + // `true` if request was successful. `false` otherwise + Success bool `json:"success"` +} + +type StickerAttachment struct { + Type string `json:"type,omitempty"` + Payload AttachmentPayload `json:"payload"` +} + +// Request to attach sticker. MUST be the only attachment request in message +type StickerAttachmentRequest struct { + Type string `json:"type,omitempty"` + Payload StickerAttachmentRequestPayload `json:"payload"` +} + +type StickerAttachmentRequestPayload struct { + // Sticker code + Code string `json:"code"` +} + +// Schema to describe WebHook subscription +type Subscription struct { + // WebHook URL + Url string `json:"url"` + // Unix-time when subscription was created + Time int64 `json:"time"` + // Update types bot subscribed for + UpdateTypes []string `json:"update_types"` + Version string `json:"version"` +} + +// Request to set up WebHook subscription +type SubscriptionRequestBody struct { + // URL of HTTP(S)-endpoint of your bot + Url string `json:"url"` + // List of update types your bot want to receive. See `Update` object for a complete list of types + UpdateTypes []string `json:"update_types,omitempty"` + // Version of API. Affects model representation + Version string `json:"version,omitempty"` +} + +type UpdateType string + +const ( + UpdateTypeMessageCallback UpdateType = "message_callback" + UpdateTypeMessageCreated = "message_created" + UpdateTypeMessageRemoved = "message_removed" + UpdateTypeMessageEdited = "message_edited" + UpdateTypeMessageRestored = "message_restored" + UpdateTypeBotAdded = "bot_added" + UpdateTypeBotRemoved = "bot_removed" + UpdateTypeUserAdded = "user_added" + UpdateTypeUserRemoved = "user_removed" + UpdateTypeBotStarted = "bot_started" + UpdateTypeChatTitleChanged = "chat_title_changed" +) + +// `Update` object repsesents different types of events that happened in chat. See its inheritors +type Update struct { + UpdateType UpdateType `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` +} + +type UpdateMessageCallback struct { + Update + Callback Callback `json:"callback"` + Message Message `json:"message"` +} + +type UpdateMessageCreated struct { + Update + Message Message `json:"message"` +} + +type UpdateMessageEdited struct { + Update + Message Message `json:"message"` +} + +type UpdateMessageRestored struct { + Update + MessageID string `json:"message_id"` +} + +type UpdateMessageRemoved struct { + Update + MessageID string `json:"message_id"` +} + +type UpdateBotAdded struct { + Update + ChatID int64 `json:"chat_id"` + UserID int64 `json:"user_id"` +} + +type UpdateBotRemoved struct { + Update + ChatID int64 `json:"chat_id"` + UserID int64 `json:"user_id"` +} + +type UpdateBotStarted struct { + Update + ChatID int64 `json:"chat_id"` + UserID int64 `json:"user_id"` +} + +type UpdateChatTitleChanged struct { + Update + ChatID int64 `json:"chat_id"` + UserID int64 `json:"user_id"` + Title string `json:"title"` +} + +type UpdateUserAdded struct { + Update + ChatID int64 `json:"chat_id"` + UserID int64 `json:"user_id"` + InviterID int64 `json:"inviter_id"` +} + +type UpdateUserRemoved struct { + Update + ChatID int64 `json:"chat_id"` + UserID int64 `json:"user_id"` + AdminID int64 `json:"admin_id"` +} + +// List of all updates in chats your bot participated in +type UpdateList struct { + // Page of updates + Updates []Update `json:"updates"` + // Pointer to the next data page + Marker int64 `json:"marker"` +} + +// Endpoint you should upload to your binaries +type UploadEndpoint struct { + // URL to upload + Url string `json:"url"` +} + +// UploadType : Type of file uploading +type UploadType string + +// List of UploadType +const ( + PHOTO UploadType = "photo" + VIDEO UploadType = "video" + AUDIO UploadType = "audio" + FILE UploadType = "file" +) + +// This is information you will recieve as soon as a file is uploaded +type UploadedFileInfo struct { + // Unique file identifier + FileId int64 `json:"fileId"` +} + +// This is information you will recieve as soon as audio/video is uploaded +type UploadedInfo struct { + Id int64 `json:"id"` +} + +type User struct { + // Users identifier + UserId int64 `json:"user_id"` + // Users visible name + Name string `json:"name"` + // Unique public user name. Can be `null` if user is not accessible or it is not set + Username string `json:"username"` +} + +// You will receive this update when user has been added to chat where bot is administrator +type UserAddedToChatUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Chat identifier where event has occured + ChatId int64 `json:"chat_id"` + // User added to chat + UserId int64 `json:"user_id"` + // User who added user to chat + InviterId int64 `json:"inviter_id"` +} + +type UserIdsList struct { + UserIds []int64 `json:"user_ids"` +} + +// You will receive this update when user has been removed from chat where bot is administrator +type UserRemovedFromChatUpdate struct { + UpdateType string `json:"update_type,omitempty"` + // Unix-time when event has occured + Timestamp int64 `json:"timestamp"` + // Chat identifier where event has occured + ChatId int64 `json:"chat_id"` + // User removed from chat + UserId int64 `json:"user_id"` + // Administrator who removed user from chat + AdminId int64 `json:"admin_id"` +} + +type UserWithPhoto struct { + // Users identifier + UserId int64 `json:"user_id"` + // Users visible name + Name string `json:"name"` + // Unique public user name. Can be `null` if user is not accessible or it is not set + Username string `json:"username"` + // URL of avatar + AvatarUrl string `json:"avatar_url"` + // URL of avatar of a bigger size + FullAvatarUrl string `json:"full_avatar_url"` +} + +type VideoAttachment struct { + Type string `json:"type,omitempty"` + Payload AttachmentPayload `json:"payload"` +} + +// Request to attach video to message +type VideoAttachmentRequest struct { + Type string `json:"type,omitempty"` + Payload UploadedInfo `json:"payload"` +} diff --git a/types.go b/types.go deleted file mode 100644 index 1cd88af..0000000 --- a/types.go +++ /dev/null @@ -1,107 +0,0 @@ -package tamtam - -type BotInfo struct { - UserID int64 `json:"user_id"` - Name string `json:"name"` - Username string `json:"username,omitempty"` - AvatarURL string `json:"avatar_url"` - FullAvatarURL string `json:"full_avatar_url"` -} - -type ChatType string - -const ( - TypeDialog ChatType = "dialog" - TypeChat = "chat" - TypeChannel = "channel" -) - -type StatusType string - -const ( - StatusActive StatusType = "active" - StatusRemoved = "removed" - StatusLeft = "left" - StatusClosed = "closed" - StatusSuspended = "suspended" -) - -type Chat struct { - ChatID int64 `json:"chat_id"` - Type ChatType `json:"type"` - Status StatusType `json:"status"` - Title string `json:"title"` - Icon struct { - URL string `json:"url"` - } `json:"icon"` - LastEventTime int64 `json:"last_event_time"` - ParticipantsCount int32 `json:"participants_count"` - OwnerID int64 `json:"owner_id"` - Participants interface{} `json:"participants,omitempty"` - IsPublic bool `json:"is_public"` - Link string `json:"link,omitempty"` - Description string `json:"description,omitempty"` -} - -type Chats struct { - Chats []Chat `json:"chats"` - Marker int `json:"marker"` -} - -type Participant struct { - UserID int64 `json:"user_id"` - Name string `json:"name"` - Username string `json:"username,omitempty"` -} - -type Recipient struct { - ChatID int64 `json:"chat_id"` - ChatType ChatType `json:"chat_type"` - UserID int64 `json:"user_id,omitempty"` -} - -type LinkType string - -const ( - LinkForward = "forward" - LinkReply = "reply" -) - -type Message struct { - Sender Participant `json:"sender"` - Recipient Recipient `json:"recipient"` - Timestamp int64 `json:"timestamp"` - Link struct { - Type LinkType `json:"type"` - Sender Participant `json:"sender"` - ChatID int64 `json:"chat_id"` - Message MessageBody `json:"message"` - } `json:"link"` - Body MessageBody `json:"body"` -} - -type AttachmentType string - -const ( - AttachmentImage AttachmentType = "image" - AttachmentVideo = "video" - AttachmentAudio = "audio" - AttachmentFile = "file" - AttachmentContact = "contact" - AttachmentSticker = "sticker" - AttachmentShare = "share" - AttachmentLocation = "location" - AttachmentKeyboard = "inline_keyboard" -) - -type Attachment struct { - Type AttachmentType `json:"type"` - Payload interface{} `json:"payload"` -} - -type MessageBody struct { - MID string `json:"mid"` - Seq int64 `json:"seq"` - Text string `json:"text,omitempty"` - Attachments []Attachment `json:"attachments"` -} |