aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Kiryukhin <alexander@kiryukhin.su>2019-03-29 17:51:51 +0300
committerAlexander Kiryukhin <alexander@kiryukhin.su>2019-03-29 17:52:03 +0300
commit4f343e00669f96451bb5a11b7e83c7ecd8503e5a (patch)
treeb14f524a4ac7418c9df4a0eb790c44caa3200368
parent2c25c4bbfdd9b1c22c9375e8703c4ba0355417d7 (diff)
Api version 1.0.3
GetUpdatesLoop
-rw-r--r--api.go154
-rw-r--r--examples/example_1.go10
-rw-r--r--examples/example_2.go72
-rw-r--r--models.go6
4 files changed, 180 insertions, 62 deletions
diff --git a/api.go b/api.go
index a756231..1ad4611 100644
--- a/api.go
+++ b/api.go
@@ -5,6 +5,7 @@ package tamtam
import (
"bytes"
+ "context"
"encoding/json"
"fmt"
"io"
@@ -12,19 +13,26 @@ import (
"net/http"
"net/url"
"strconv"
+ "time"
)
type Api struct {
- key string
- url *url.URL
+ key string
+ version string
+ url *url.URL
+ timeout int
+ pause int
}
// New TamTam Api object
func New(key string) *Api {
u, _ := url.Parse("https://botapi.tamtam.chat/")
return &Api{
- key: key,
- url: u,
+ key: key,
+ url: u,
+ version: "1.0.3",
+ timeout: 30,
+ pause: 1,
}
}
@@ -53,58 +61,35 @@ func (a *Api) GetUploadURL(uploadType UploadType) (*UploadEndpoint, error) {
return result, json.NewDecoder(body).Decode(result)
}
+func (a *Api) GetUpdatesLoop(ctx context.Context, updates chan interface{}) error {
+ for {
+ select {
+ case <-ctx.Done():
+ return nil
+ case <-time.After(time.Duration(a.pause) * time.Second):
+ var marker int64
+ for {
+ upds, err := a.getUpdates(50, a.timeout, marker, []string{})
+ if err != nil {
+ return err
+ }
+ if len(upds.Updates) == 0 {
+ break
+ }
+ for _, u := range upds.Updates {
+ updates <- a.bytesToProperUpdate(u)
+ }
+ marker = upds.Marker
+ }
+ }
+ }
+}
+
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
- }
+ updates <- a.bytesToProperUpdate(b)
}
}
@@ -346,7 +331,63 @@ func (a *Api) Unsubscribe(subscriptionURL string) (*SimpleQueryResult, error) {
return result, json.NewDecoder(body).Decode(result)
}
-func (a *Api) GetUpdates(limit int, timeout int, marker int64, types []string) (*UpdateList, error) {
+// endregion
+
+// region Internal
+
+func (a *Api) bytesToProperUpdate(b []byte) interface{} {
+ u := new(Update)
+ _ = json.Unmarshal(b, u)
+ switch u.UpdateType {
+ case UpdateTypeMessageCallback:
+ upd := UpdateMessageCallback{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeMessageCreated:
+ upd := UpdateMessageCreated{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeMessageRemoved:
+ upd := UpdateMessageRemoved{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeMessageEdited:
+ upd := UpdateMessageEdited{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeMessageRestored:
+ upd := UpdateMessageRestored{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeBotAdded:
+ upd := UpdateBotAdded{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeBotRemoved:
+ upd := UpdateBotRemoved{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeUserAdded:
+ upd := UpdateUserAdded{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeUserRemoved:
+ upd := UpdateUserRemoved{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeBotStarted:
+ upd := UpdateBotStarted{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ case UpdateTypeChatTitleChanged:
+ upd := UpdateChatTitleChanged{}
+ _ = json.Unmarshal(b, &upd)
+ return upd
+ }
+ return nil
+}
+
+func (a *Api) getUpdates(limit int, timeout int, marker int64, types []string) (*UpdateList, error) {
result := new(UpdateList)
values := url.Values{}
if limit > 0 {
@@ -363,7 +404,7 @@ func (a *Api) GetUpdates(limit int, timeout int, marker int64, types []string) (
values.Add("types", t)
}
}
- body, err := a.request(http.MethodDelete, "updates", values, nil)
+ body, err := a.request(http.MethodGet, "updates", values, nil)
if err != nil {
return result, err
}
@@ -371,15 +412,12 @@ func (a *Api) GetUpdates(limit int, timeout int, marker int64, types []string) (
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)
+ query.Set("v", a.version)
u.RawQuery = query.Encode()
j, err := json.Marshal(body)
if err != nil {
diff --git a/examples/example_1.go b/examples/example_1.go
index 428b99a..a1fb967 100644
--- a/examples/example_1.go
+++ b/examples/example_1.go
@@ -1,5 +1,8 @@
// +build ignore
+/**
+ * Webhook example
+ */
package main
import (
@@ -23,9 +26,12 @@ func main() {
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)
-
+ subs, _ := api.GetSubscriptions()
+ for _, s := range subs.Subscriptions {
+ _, _ = api.Unsubscribe(s.Url)
+ }
subscriptionResp, err := api.Subscribe(&tamtam.SubscriptionRequestBody{
- Url: "https://4940675e.ngrok.io/webhook", // Replace by your webhook!
+ Url: " https://576df2ec.ngrok.io/webhook", // Replace by your webhook!
})
log.Printf("Subscription: %#v %#v", subscriptionResp, err)
diff --git a/examples/example_2.go b/examples/example_2.go
new file mode 100644
index 0000000..74547fa
--- /dev/null
+++ b/examples/example_2.go
@@ -0,0 +1,72 @@
+// +build ignore
+
+/**
+ * Updates loop example
+ */
+package main
+
+import (
+ "context"
+ "fmt"
+ "github.com/neonxp/tamtam"
+ "log"
+ "os"
+ "os/signal"
+)
+
+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)
+ subs, _ := api.GetSubscriptions()
+ for _, s := range subs.Subscriptions {
+ _, _ = api.Unsubscribe(s.Url)
+ }
+ ch := make(chan interface{}, 1) // Channel with updates from TamTam
+
+ ctx, cancel := context.WithCancel(context.Background())
+
+ go func() {
+ for {
+ select {
+ case 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)
+ }
+ case <-ctx.Done():
+ return
+ }
+
+ }
+ }()
+
+ go func() {
+ exit := make(chan os.Signal)
+ signal.Notify(exit, os.Kill, os.Interrupt)
+ select {
+ case <-exit:
+ cancel()
+ case <-ctx.Done():
+ return
+ }
+ }()
+
+ if err := api.GetUpdatesLoop(ctx, ch); err != nil {
+ log.Fatalln(err)
+ }
+
+}
diff --git a/models.go b/models.go
index 1900e44..7ee7888 100644
--- a/models.go
+++ b/models.go
@@ -3,6 +3,8 @@
*/
package tamtam
+import "encoding/json"
+
type ActionRequestBody struct {
Action SenderAction `json:"action"`
}
@@ -373,7 +375,7 @@ type Message struct {
// 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"`
+ Body MessageBody `json:"body"`
}
// Schema representing body of message
@@ -687,7 +689,7 @@ type UpdateUserRemoved struct {
// List of all updates in chats your bot participated in
type UpdateList struct {
// Page of updates
- Updates []Update `json:"updates"`
+ Updates []json.RawMessage `json:"updates"`
// Pointer to the next data page
Marker int64 `json:"marker"`
}