summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot')
-rw-r--r--vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md132
-rw-r--r--vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/context.go12
-rw-r--r--vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/errors.go18
-rw-r--r--vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go219
4 files changed, 381 insertions, 0 deletions
diff --git a/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md
new file mode 100644
index 00000000..94d87dba
--- /dev/null
+++ b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md
@@ -0,0 +1,132 @@
+# Bots Long Poll API
+
+[![PkgGoDev](https://pkg.go.dev/badge/github.com/SevereCloud/vksdk/v2/longpoll-bot)](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/longpoll-bot)
+[![VK](https://img.shields.io/badge/developers-%234a76a8.svg?logo=VK&logoColor=white)](https://vk.com/dev/bots_longpoll)
+
+## Подключение Bots Long Poll API
+
+Long Poll настраивается автоматически. Вам не требуется заходить в настройки
+сообщества.
+
+### Версия API
+
+Данная библиотека поддерживает версию API **5.122**.
+
+### Инициализация
+
+Модуль можно использовать с ключом доступа пользователя, полученным в
+Standalone-приложении через Implicit Flow(требуются права доступа: **groups**)
+или с ключом доступа сообщества(требуются права доступа: **manage**).
+
+В начале необходимо инициализировать api:
+
+```go
+vk := api.NewVK("<TOKEN>")
+```
+
+А потом сам longpoll
+
+```go
+lp, err := longpoll.NewLongPoll(vk api.VK, groupID int)
+// По умолчанию Wait = 25
+// lp.Wait = 90
+// lp.Ts = "123"
+```
+
+### HTTP client
+
+В модуле реализована возможность изменять HTTP клиент - `lp.Client`
+
+Пример прокси
+
+```go
+dialer, _ := proxy.SOCKS5("tcp", "127.0.0.1:9050", nil, proxy.Direct)
+httpTransport := &http.Transport{
+ Dial: dialer.Dial,
+ // DisableKeepAlives: true,
+}
+httpTransport.Dial = dialer.Dial
+lp.Client.Transport = httpTransport
+```
+
+### Обработчик событий
+
+Для каждого события существует отдельный обработчик, который передает функции
+`ctx` и `object`.
+
+Пример для события `message_new`
+
+```go
+lp.MessageNew(func(ctx context.Context, obj events.MessageNewObject) {
+ ...
+})
+```
+
+Если вы хотите получать полный ответ от Long Poll(например для сохранения `ts`
+или специальной обработки `failed`), можно воспользоваться следующим обработчиком.
+
+```go
+lp.FullResponse(func(resp object.LongPollBotResponse) {
+ ...
+})
+```
+
+Полный список событий Вы найдёте [в документации](https://vk.com/dev/groups_events)
+
+### Контекст
+
+Поля `groupID`, `ts` и `eventID` передаются в `ctx`. Чтобы получить их, можно
+воспользоваться следующими функциями:
+
+```go
+groupID := events.GroupIDFromContext(ctx)
+eventID := events.EventIDFromContext(ctx)
+ts := longpoll.TsFromContext(ctx)
+```
+
+### Запуск и остановка
+
+```go
+// Запуск
+if err := lp.Run(); err != nil {
+ log.Fatal(err)
+}
+
+// Безопасное завершение
+// Ждет пока соединение закроется и события обработаются
+lp.Shutdown()
+
+// Закрыть соединение
+// Требует lp.Client.Transport = &http.Transport{DisableKeepAlives: true}
+lp.Client.CloseIdleConnections()
+```
+
+## Пример
+
+```go
+package main
+
+import (
+ "log"
+
+ "github.com/SevereCloud/vksdk/v2/api"
+
+ longpoll "github.com/SevereCloud/vksdk/v2/longpoll-bot"
+ "github.com/SevereCloud/vksdk/v2/events"
+)
+
+func main() {
+ vk := api.NewVK("<TOKEN>")
+ lp, err := longpoll.NewLongPoll(vk, 12345678)
+ if err != nil {
+ panic(err)
+ }
+
+ lp.MessageNew(func(ctx context.Context, obj events.MessageNewObject) {
+ log.Print(obj.Message.Text)
+ })
+
+ lp.Run()
+}
+
+```
diff --git a/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/context.go b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/context.go
new file mode 100644
index 00000000..cfc4fd90
--- /dev/null
+++ b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/context.go
@@ -0,0 +1,12 @@
+package longpoll // import "github.com/SevereCloud/vksdk/v2/longpoll-bot"
+
+import (
+ "context"
+
+ "github.com/SevereCloud/vksdk/v2/internal"
+)
+
+// TsFromContext returns the ts from context.
+func TsFromContext(ctx context.Context) int {
+ return ctx.Value(internal.LongPollTsKey).(int)
+}
diff --git a/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/errors.go b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/errors.go
new file mode 100644
index 00000000..58d97c96
--- /dev/null
+++ b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/errors.go
@@ -0,0 +1,18 @@
+package longpoll
+
+import (
+ "fmt"
+)
+
+// Failed struct.
+type Failed struct {
+ Code int
+}
+
+// Error returns the message of a Failed.
+func (e Failed) Error() string {
+ return fmt.Sprintf(
+ "longpoll: failed code %d",
+ e.Code,
+ )
+}
diff --git a/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go
new file mode 100644
index 00000000..b230c4c1
--- /dev/null
+++ b/vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go
@@ -0,0 +1,219 @@
+/*
+Package longpoll implements Bots Long Poll API.
+
+See more https://vk.com/dev/bots_longpoll
+*/
+package longpoll // import "github.com/SevereCloud/vksdk/v2/longpoll-bot"
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+
+ "github.com/SevereCloud/vksdk/v2"
+ "github.com/SevereCloud/vksdk/v2/api"
+ "github.com/SevereCloud/vksdk/v2/events"
+ "github.com/SevereCloud/vksdk/v2/internal"
+)
+
+// Response struct.
+type Response struct {
+ Ts string `json:"ts"`
+ Updates []events.GroupEvent `json:"updates"`
+ Failed int `json:"failed"`
+}
+
+// LongPoll struct.
+type LongPoll struct {
+ GroupID int
+ Server string
+ Key string
+ Ts string
+ Wait int
+ VK *api.VK
+ Client *http.Client
+ cancel context.CancelFunc
+
+ funcFullResponseList []func(Response)
+
+ events.FuncList
+}
+
+// NewLongPoll returns a new LongPoll.
+//
+// The LongPoll will use the http.DefaultClient.
+// This means that if the http.DefaultClient is modified by other components
+// of your application the modifications will be picked up by the SDK as well.
+func NewLongPoll(vk *api.VK, groupID int) (*LongPoll, error) {
+ lp := &LongPoll{
+ VK: vk,
+ GroupID: groupID,
+ Wait: 25,
+ Client: http.DefaultClient,
+ }
+ lp.FuncList = *events.NewFuncList()
+
+ err := lp.updateServer(true)
+
+ return lp, err
+}
+
+// NewLongPollCommunity returns a new LongPoll for community token.
+//
+// The LongPoll will use the http.DefaultClient.
+// This means that if the http.DefaultClient is modified by other components
+// of your application the modifications will be picked up by the SDK as well.
+func NewLongPollCommunity(vk *api.VK) (*LongPoll, error) {
+ resp, err := vk.GroupsGetByID(nil)
+ if err != nil {
+ return nil, err
+ }
+
+ lp := &LongPoll{
+ VK: vk,
+ GroupID: resp[0].ID,
+ Wait: 25,
+ Client: http.DefaultClient,
+ }
+ lp.FuncList = *events.NewFuncList()
+
+ err = lp.updateServer(true)
+
+ return lp, err
+}
+
+func (lp *LongPoll) updateServer(updateTs bool) error {
+ params := api.Params{
+ "group_id": lp.GroupID,
+ }
+
+ serverSetting, err := lp.VK.GroupsGetLongPollServer(params)
+ if err != nil {
+ return err
+ }
+
+ lp.Key = serverSetting.Key
+ lp.Server = serverSetting.Server
+
+ if updateTs {
+ lp.Ts = serverSetting.Ts
+ }
+
+ return nil
+}
+
+func (lp *LongPoll) check(ctx context.Context) (response Response, err error) {
+ u := fmt.Sprintf("%s?act=a_check&key=%s&ts=%s&wait=%d", lp.Server, lp.Key, lp.Ts, lp.Wait)
+
+ req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
+ if err != nil {
+ return response, err
+ }
+
+ resp, err := lp.Client.Do(req)
+ if err != nil {
+ return response, err
+ }
+ defer resp.Body.Close()
+
+ err = json.NewDecoder(resp.Body).Decode(&response)
+ if err != nil {
+ return response, err
+ }
+
+ err = lp.checkResponse(response)
+
+ return response, err
+}
+
+func (lp *LongPoll) checkResponse(response Response) (err error) {
+ switch response.Failed {
+ case 0:
+ lp.Ts = response.Ts
+ case 1:
+ lp.Ts = response.Ts
+ case 2:
+ err = lp.updateServer(false)
+ case 3:
+ err = lp.updateServer(true)
+ default:
+ err = &Failed{response.Failed}
+ }
+
+ return
+}
+
+func (lp *LongPoll) autoSetting(ctx context.Context) error {
+ params := api.Params{
+ "group_id": lp.GroupID,
+ "enabled": true,
+ "api_version": vksdk.API,
+ }.WithContext(ctx)
+ for _, event := range lp.ListEvents() {
+ params[string(event)] = true
+ }
+
+ // Updating LongPoll settings
+ _, err := lp.VK.GroupsSetLongPollSettings(params)
+
+ return err
+}
+
+// Run handler.
+func (lp *LongPoll) Run() error {
+ return lp.RunWithContext(context.Background())
+}
+
+// RunWithContext handler.
+func (lp *LongPoll) RunWithContext(ctx context.Context) error {
+ return lp.run(ctx)
+}
+
+func (lp *LongPoll) run(ctx context.Context) error {
+ ctx, lp.cancel = context.WithCancel(ctx)
+
+ err := lp.autoSetting(ctx)
+ if err != nil {
+ return err
+ }
+
+ for {
+ select {
+ case _, ok := <-ctx.Done():
+ if !ok {
+ return nil
+ }
+ default:
+ resp, err := lp.check(ctx)
+ if err != nil {
+ return err
+ }
+
+ ctx = context.WithValue(ctx, internal.LongPollTsKey, resp.Ts)
+
+ for _, event := range resp.Updates {
+ err = lp.Handler(ctx, event)
+ if err != nil {
+ return err
+ }
+ }
+
+ for _, f := range lp.funcFullResponseList {
+ f(resp)
+ }
+ }
+ }
+}
+
+// Shutdown gracefully shuts down the longpoll without interrupting any active connections.
+func (lp *LongPoll) Shutdown() {
+ if lp.cancel != nil {
+ lp.cancel()
+ }
+}
+
+// FullResponse handler.
+func (lp *LongPoll) FullResponse(f func(Response)) {
+ lp.funcFullResponseList = append(lp.funcFullResponseList, f)
+}