mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-06-27 12:19:23 +00:00
Add vk bridge (#1372)
* Add vk bridge * Vk bridge attachments * Vk bridge forwarded messages * Vk bridge sample config and code cleanup * Vk bridge add vendor * Vk bridge message edit * Vk bridge: fix fetching names of other bots * Vk bridge: code cleanup * Vk bridge: fix shadows declaration * Vk bridge: remove UseFileURL
This commit is contained in:
132
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md
generated
vendored
Normal file
132
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
# Bots Long Poll API
|
||||
|
||||
[](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/longpoll-bot)
|
||||
[](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()
|
||||
}
|
||||
|
||||
```
|
12
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/context.go
generated
vendored
Normal file
12
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/context.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
18
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/errors.go
generated
vendored
Normal file
18
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/errors.go
generated
vendored
Normal file
@ -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,
|
||||
)
|
||||
}
|
219
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go
generated
vendored
Normal file
219
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go
generated
vendored
Normal file
@ -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)
|
||||
}
|
Reference in New Issue
Block a user