forked from lug/matterbridge
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65c7ac80b5 | ||
|
|
dd3fb32ec7 | ||
|
|
2a3f475ff5 | ||
|
|
7288f71201 | ||
|
|
9c43eff753 | ||
|
|
c8d7fdeedc | ||
|
|
c211152e23 | ||
|
|
ab75d5097e | ||
|
|
c3644c8d3b | ||
|
|
6438a3dba3 | ||
|
|
4b226a6a63 | ||
|
|
4801850013 | ||
|
|
6a7412bf2b | ||
|
|
5a1fd7dadd | ||
|
|
ac06a26809 | ||
|
|
61d56f26f8 | ||
|
|
6aa05b3981 | ||
|
|
aad60c882e | ||
|
|
fecca57507 | ||
|
|
2bcad846c0 | ||
|
|
15ad0165fc | ||
|
|
2e8ab11978 | ||
|
|
9a8ce9b17e | ||
|
|
16ab4c6fed | ||
|
|
e3ee0df7ba | ||
|
|
8f7ab280e2 | ||
|
|
dbedc99421 | ||
|
|
6cb359cb80 | ||
|
|
ae2ad824a9 | ||
|
|
02e3d7852b | ||
|
|
3893a035be | ||
|
|
658bdd9faa | ||
|
|
e1eebcd4e0 | ||
|
|
062b831e88 | ||
|
|
b275efaeff | ||
|
|
80d3033456 | ||
|
|
bd0516f09a | ||
|
|
df4d76e466 | ||
|
|
dcbd7f8cad | ||
|
|
73ec02ab9d | ||
|
|
d1f8347071 | ||
|
|
8601eedada | ||
|
|
9afd33cdfc | ||
|
|
5e1be8e558 | ||
|
|
835dd2635a | ||
|
|
f65b18c2f6 | ||
|
|
b0e7b84f40 | ||
|
|
1635db93c7 | ||
|
|
c4fe462d11 | ||
|
|
b1f403165d | ||
|
|
46e4317b77 | ||
|
|
e3ffbcadd8 | ||
|
|
b7d73077e5 | ||
|
|
77f61ee20a | ||
|
|
8967f02fc9 | ||
|
|
831ff6d0a9 | ||
|
|
2199174def |
22
.github/dependabot.yml
vendored
Normal file
22
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Docs: <https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/customizing-dependency-updates>
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: gomod
|
||||||
|
directory: /
|
||||||
|
schedule: {interval: weekly}
|
||||||
|
reviewers: [42wim]
|
||||||
|
assignees: [42wim]
|
||||||
|
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: /
|
||||||
|
schedule: {interval: weekly}
|
||||||
|
reviewers: [42wim]
|
||||||
|
assignees: [42wim]
|
||||||
|
|
||||||
|
- package-ecosystem: docker
|
||||||
|
directory: /
|
||||||
|
schedule: {interval: weekly}
|
||||||
|
reviewers: [42wim]
|
||||||
|
assignees: [42wim]
|
||||||
6
.github/workflows/development.yml
vendored
6
.github/workflows/development.yml
vendored
@@ -35,9 +35,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p output/{win,lin,arm,mac}
|
mkdir -p output/{win,lin,arm,mac}
|
||||||
VERSION=$(git describe --tags)
|
VERSION=$(git describe --tags)
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o output/lin/matterbridge-$VERSION-linux-amd64
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -X github.com/42wim/matterbridge/version.GitHash=$(git log --pretty=format:'%h' -n 1)" -o output/lin/matterbridge-$VERSION-linux-amd64
|
||||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o output/win/matterbridge-$VERSION-windows-amd64.exe
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags "-s -X github.com/42wim/matterbridge/version.GitHash=$(git log --pretty=format:'%h' -n 1)" -o output/win/matterbridge-$VERSION-windows-amd64.exe
|
||||||
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -X main.githash=$(git log --pretty=format:'%h' -n 1)" -o output/mac/matterbridge-$VERSION-darwin-amd64
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags "-s -X github.com/42wim/matterbridge/version.GitHash=$(git log --pretty=format:'%h' -n 1)" -o output/mac/matterbridge-$VERSION-darwin-amd64
|
||||||
- name: Upload linux 64-bit
|
- name: Upload linux 64-bit
|
||||||
if: startsWith(matrix.go-version,'1.17')
|
if: startsWith(matrix.go-version,'1.17')
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -4,3 +4,6 @@
|
|||||||
|
|
||||||
# Exclude configuration file
|
# Exclude configuration file
|
||||||
matterbridge.toml
|
matterbridge.toml
|
||||||
|
|
||||||
|
# Exclude IDE Files
|
||||||
|
.vscode
|
||||||
|
|||||||
@@ -186,7 +186,24 @@ linters:
|
|||||||
- errorlint
|
- errorlint
|
||||||
- nlreturn
|
- nlreturn
|
||||||
- exhaustivestruct
|
- exhaustivestruct
|
||||||
|
- forbidigo
|
||||||
|
- wrapcheck
|
||||||
|
- varnamelen
|
||||||
|
- ireturn
|
||||||
|
- errorlint
|
||||||
|
- tparallel
|
||||||
|
- wrapcheck
|
||||||
|
- paralleltest
|
||||||
|
- makezero
|
||||||
|
- thelper
|
||||||
|
- cyclop
|
||||||
|
- revive
|
||||||
|
- importas
|
||||||
|
- gomoddirectives
|
||||||
|
- promlinter
|
||||||
|
- tagliatelle
|
||||||
|
- errname
|
||||||
|
- typecheck
|
||||||
# rules to deal with reported isues
|
# rules to deal with reported isues
|
||||||
issues:
|
issues:
|
||||||
# List of regexps of issue texts to exclude, empty list by default.
|
# List of regexps of issue texts to exclude, empty list by default.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ builds:
|
|||||||
- 6
|
- 6
|
||||||
- 7
|
- 7
|
||||||
ldflags:
|
ldflags:
|
||||||
- -s -w -X main.githash={{.ShortCommit}}
|
- -s -w -X github.com/42wim/matterbridge/version.GitHash={{.ShortCommit}}
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
-
|
-
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
FROM alpine:edge AS builder
|
FROM alpine AS builder
|
||||||
|
|
||||||
COPY . /go/src/matterbridge
|
COPY . /go/src/matterbridge
|
||||||
RUN apk --no-cache add go git \
|
RUN apk --no-cache add go git \
|
||||||
&& cd /go/src/matterbridge \
|
&& cd /go/src/matterbridge \
|
||||||
&& CGO_ENABLED=0 go build -mod vendor -ldflags "-X main.githash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge
|
&& CGO_ENABLED=0 go build -mod vendor -ldflags "-X github.com/42wim/matterbridge/version.GitHash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge
|
||||||
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
RUN apk --no-cache add ca-certificates mailcap
|
RUN apk --no-cache add ca-certificates mailcap
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ See <https://github.com/42wim/matterbridge/wiki>
|
|||||||
|
|
||||||
### Binaries
|
### Binaries
|
||||||
|
|
||||||
- Latest stable release [v1.23.0](https://github.com/42wim/matterbridge/releases/latest)
|
- Latest stable release [v1.24.0](https://github.com/42wim/matterbridge/releases/latest)
|
||||||
- Development releases (follows master) can be downloaded [here](https://github.com/42wim/matterbridge/actions) selecting the latest green build and then artifacts.
|
- Development releases (follows master) can be downloaded [here](https://github.com/42wim/matterbridge/actions) selecting the latest green build and then artifacts.
|
||||||
|
|
||||||
To install or upgrade just download the latest [binary](https://github.com/42wim/matterbridge/releases/latest). On \*nix platforms you may need to make the binary executable - you can do this by running `chmod a+x` on the binary (example: `chmod a+x matterbridge-1.20.0-linux-64bit`). After downloading (and making the binary executable, if necessary), follow the instructions on the [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration.
|
To install or upgrade just download the latest [binary](https://github.com/42wim/matterbridge/releases/latest). On \*nix platforms you may need to make the binary executable - you can do this by running `chmod a+x` on the binary (example: `chmod a+x matterbridge-1.20.0-linux-64bit`). After downloading (and making the binary executable, if necessary), follow the instructions on the [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration.
|
||||||
@@ -336,6 +336,7 @@ See [FAQ](https://github.com/42wim/matterbridge/wiki/FAQ)
|
|||||||
- <https://daniele.tech/2019/02/how-to-use-matterbridge-to-connect-2-different-slack-workspaces/>
|
- <https://daniele.tech/2019/02/how-to-use-matterbridge-to-connect-2-different-slack-workspaces/>
|
||||||
- <https://userlinux.net/mattermost-and-matterbridge.html>
|
- <https://userlinux.net/mattermost-and-matterbridge.html>
|
||||||
- <https://nextcloud.com/blog/bridging-chat-services-in-talk/>
|
- <https://nextcloud.com/blog/bridging-chat-services-in-talk/>
|
||||||
|
- <https://minecraftchest1.wordpress.com/2021/06/05/how-to-install-and-setup-matterbridge/>
|
||||||
- Youtube: [whatsapp - telegram bridging](https://www.youtube.com/watch?v=W-VXISoKtNc)
|
- Youtube: [whatsapp - telegram bridging](https://www.youtube.com/watch?v=W-VXISoKtNc)
|
||||||
|
|
||||||
## Thanks
|
## Thanks
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const (
|
|||||||
EventRejoinChannels = "rejoin_channels"
|
EventRejoinChannels = "rejoin_channels"
|
||||||
EventUserAction = "user_action"
|
EventUserAction = "user_action"
|
||||||
EventMsgDelete = "msg_delete"
|
EventMsgDelete = "msg_delete"
|
||||||
|
EventFileDelete = "file_delete"
|
||||||
EventAPIConnected = "api_connected"
|
EventAPIConnected = "api_connected"
|
||||||
EventUserTyping = "user_typing"
|
EventUserTyping = "user_typing"
|
||||||
EventGetChannelMembers = "get_channel_members"
|
EventGetChannelMembers = "get_channel_members"
|
||||||
@@ -63,6 +64,7 @@ type FileInfo struct {
|
|||||||
Size int64
|
Size int64
|
||||||
Avatar bool
|
Avatar bool
|
||||||
SHA string
|
SHA string
|
||||||
|
NativeID string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelInfo struct {
|
type ChannelInfo struct {
|
||||||
@@ -168,7 +170,7 @@ type Protocol struct {
|
|||||||
UseTLS bool // IRC
|
UseTLS bool // IRC
|
||||||
UseDiscriminator bool // discord
|
UseDiscriminator bool // discord
|
||||||
UseFirstName bool // telegram
|
UseFirstName bool // telegram
|
||||||
UseUserName bool // discord, matrix
|
UseUserName bool // discord, matrix, mattermost
|
||||||
UseInsecureURL bool // telegram
|
UseInsecureURL bool // telegram
|
||||||
UserName string // IRC
|
UserName string // IRC
|
||||||
VerboseJoinPart bool // IRC
|
VerboseJoinPart bool // IRC
|
||||||
|
|||||||
@@ -10,10 +10,14 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/discord/transmitter"
|
"github.com/42wim/matterbridge/bridge/discord/transmitter"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/matterbridge/discordgo"
|
"github.com/matterbridge/discordgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MessageLength = 1950
|
const (
|
||||||
|
MessageLength = 1950
|
||||||
|
cFileUpload = "file_upload"
|
||||||
|
)
|
||||||
|
|
||||||
type Bdiscord struct {
|
type Bdiscord struct {
|
||||||
*bridge.Config
|
*bridge.Config
|
||||||
@@ -35,10 +39,20 @@ type Bdiscord struct {
|
|||||||
// Webhook specific logic
|
// Webhook specific logic
|
||||||
useAutoWebhooks bool
|
useAutoWebhooks bool
|
||||||
transmitter *transmitter.Transmitter
|
transmitter *transmitter.Transmitter
|
||||||
|
cache *lru.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *bridge.Config) bridge.Bridger {
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
b := &Bdiscord{Config: cfg}
|
newCache, err := lru.New(5000)
|
||||||
|
if err != nil {
|
||||||
|
cfg.Log.Fatalf("Could not create LRU cache: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b := &Bdiscord{
|
||||||
|
Config: cfg,
|
||||||
|
cache: newCache,
|
||||||
|
}
|
||||||
|
|
||||||
b.userMemberMap = make(map[string]*discordgo.Member)
|
b.userMemberMap = make(map[string]*discordgo.Member)
|
||||||
b.nickMemberMap = make(map[string]*discordgo.Member)
|
b.nickMemberMap = make(map[string]*discordgo.Member)
|
||||||
b.channelInfoMap = make(map[string]*config.ChannelInfo)
|
b.channelInfoMap = make(map[string]*config.ChannelInfo)
|
||||||
@@ -75,6 +89,9 @@ func (b *Bdiscord) Connect() error {
|
|||||||
b.c.AddHandler(b.messageDeleteBulk)
|
b.c.AddHandler(b.messageDeleteBulk)
|
||||||
b.c.AddHandler(b.memberAdd)
|
b.c.AddHandler(b.memberAdd)
|
||||||
b.c.AddHandler(b.memberRemove)
|
b.c.AddHandler(b.memberRemove)
|
||||||
|
if b.GetInt("debuglevel") == 1 {
|
||||||
|
b.c.AddHandler(b.messageEvent)
|
||||||
|
}
|
||||||
// Add privileged intent for guild member tracking. This is needed to track nicks
|
// Add privileged intent for guild member tracking. This is needed to track nicks
|
||||||
// for display names and @mention translation
|
// for display names and @mention translation
|
||||||
b.c.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAllWithoutPrivileged |
|
b.c.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAllWithoutPrivileged |
|
||||||
@@ -153,7 +170,7 @@ func (b *Bdiscord) Connect() error {
|
|||||||
return fmt.Errorf("use of removed WebhookURL setting")
|
return fmt.Errorf("use of removed WebhookURL setting")
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.GetInt("debuglevel") > 0 {
|
if b.GetInt("debuglevel") == 2 {
|
||||||
b.Log.Debug("enabling even more discord debug")
|
b.Log.Debug("enabling even more discord debug")
|
||||||
b.c.Debug = true
|
b.c.Debug = true
|
||||||
}
|
}
|
||||||
@@ -280,6 +297,21 @@ func (b *Bdiscord) handleEventBotUser(msg *config.Message, channelID string) (st
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete a file
|
||||||
|
if msg.Event == config.EventFileDelete {
|
||||||
|
if msg.ID == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi, ok := b.cache.Get(cFileUpload + msg.ID); ok {
|
||||||
|
err := b.c.ChannelMessageDelete(channelID, fi.(string)) // nolint:forcetypeassert
|
||||||
|
b.cache.Remove(cFileUpload + msg.ID)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("file %s not found", msg.ID)
|
||||||
|
}
|
||||||
|
|
||||||
// Upload a file if it exists
|
// Upload a file if it exists
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
for _, rmsg := range helper.HandleExtra(msg, b.General) {
|
for _, rmsg := range helper.HandleExtra(msg, b.General) {
|
||||||
@@ -327,7 +359,6 @@ func (b *Bdiscord) handleEventBotUser(msg *config.Message, channelID string) (st
|
|||||||
|
|
||||||
// handleUploadFile handles native upload of files
|
// handleUploadFile handles native upload of files
|
||||||
func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (string, error) {
|
func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (string, error) {
|
||||||
var err error
|
|
||||||
for _, f := range msg.Extra["file"] {
|
for _, f := range msg.Extra["file"] {
|
||||||
fi := f.(config.FileInfo)
|
fi := f.(config.FileInfo)
|
||||||
file := discordgo.File{
|
file := discordgo.File{
|
||||||
@@ -340,10 +371,15 @@ func (b *Bdiscord) handleUploadFile(msg *config.Message, channelID string) (stri
|
|||||||
Files: []*discordgo.File{&file},
|
Files: []*discordgo.File{&file},
|
||||||
AllowedMentions: b.getAllowedMentions(),
|
AllowedMentions: b.getAllowedMentions(),
|
||||||
}
|
}
|
||||||
_, err = b.c.ChannelMessageSendComplex(channelID, &m)
|
res, err := b.c.ChannelMessageSendComplex(channelID, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("file upload failed: %s", err)
|
return "", fmt.Errorf("file upload failed: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// link file_upload_nativeID (file ID from the original bridge) to our upload id
|
||||||
|
// so that we can remove this later when it eg needs to be deleted
|
||||||
|
b.cache.Add(cFileUpload+fi.NativeID, res.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package bdiscord
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/matterbridge/discordgo"
|
"github.com/matterbridge/discordgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,6 +32,10 @@ func (b *Bdiscord) messageDeleteBulk(s *discordgo.Session, m *discordgo.MessageD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bdiscord) messageEvent(s *discordgo.Session, m *discordgo.Event) {
|
||||||
|
b.Log.Debug(spew.Sdump(m.Struct))
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bdiscord) messageTyping(s *discordgo.Session, m *discordgo.TypingStart) {
|
func (b *Bdiscord) messageTyping(s *discordgo.Session, m *discordgo.TypingStart) {
|
||||||
if !b.GetBool("ShowUserTyping") {
|
if !b.GetBool("ShowUserTyping") {
|
||||||
return
|
return
|
||||||
@@ -82,8 +87,9 @@ func (b *Bdiscord) messageCreate(s *discordgo.Session, m *discordgo.MessageCreat
|
|||||||
|
|
||||||
rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", UserID: m.Author.ID, ID: m.ID}
|
rmsg := config.Message{Account: b.Account, Avatar: "https://cdn.discordapp.com/avatars/" + m.Author.ID + "/" + m.Author.Avatar + ".jpg", UserID: m.Author.ID, ID: m.ID}
|
||||||
|
|
||||||
if m.Content != "" {
|
|
||||||
b.Log.Debugf("== Receiving event %#v", m.Message)
|
b.Log.Debugf("== Receiving event %#v", m.Message)
|
||||||
|
|
||||||
|
if m.Content != "" {
|
||||||
m.Message.Content = b.replaceChannelMentions(m.Message.Content)
|
m.Message.Content = b.replaceChannelMentions(m.Message.Content)
|
||||||
rmsg.Text, err = m.ContentWithMoreMentionsReplaced(b.c)
|
rmsg.Text, err = m.ContentWithMoreMentionsReplaced(b.c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -82,10 +82,8 @@ func (b *Bdiscord) webhookSend(msg *config.Message, channelID string) (*discordg
|
|||||||
ContentType: "",
|
ContentType: "",
|
||||||
Reader: bytes.NewReader(*fi.Data),
|
Reader: bytes.NewReader(*fi.Data),
|
||||||
}
|
}
|
||||||
content := ""
|
content := fi.Comment
|
||||||
if msg.Text == "" {
|
|
||||||
content = fi.Comment
|
|
||||||
}
|
|
||||||
_, e2 := b.transmitter.Send(
|
_, e2 := b.transmitter.Send(
|
||||||
channelID,
|
channelID,
|
||||||
&discordgo.WebhookParams{
|
&discordgo.WebhookParams{
|
||||||
|
|||||||
252
bridge/harmony/harmony.go
Normal file
252
bridge/harmony/harmony.go
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
package harmony
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/harmony-development/shibshib"
|
||||||
|
chatv1 "github.com/harmony-development/shibshib/gen/chat/v1"
|
||||||
|
typesv1 "github.com/harmony-development/shibshib/gen/harmonytypes/v1"
|
||||||
|
profilev1 "github.com/harmony-development/shibshib/gen/profile/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type cachedProfile struct {
|
||||||
|
data *profilev1.GetProfileResponse
|
||||||
|
lastUpdated time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bharmony struct {
|
||||||
|
*bridge.Config
|
||||||
|
|
||||||
|
c *shibshib.Client
|
||||||
|
profileCache map[uint64]cachedProfile
|
||||||
|
}
|
||||||
|
|
||||||
|
func uToStr(in uint64) string {
|
||||||
|
return strconv.FormatUint(in, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func strToU(in string) (uint64, error) {
|
||||||
|
return strconv.ParseUint(in, 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
|
b := &Bharmony{
|
||||||
|
Config: cfg,
|
||||||
|
profileCache: map[uint64]cachedProfile{},
|
||||||
|
}
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) getProfile(u uint64) (*profilev1.GetProfileResponse, error) {
|
||||||
|
if v, ok := b.profileCache[u]; ok && time.Since(v.lastUpdated) < time.Minute*10 {
|
||||||
|
return v.data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := b.c.ProfileKit.GetProfile(&profilev1.GetProfileRequest{
|
||||||
|
UserId: u,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
if v, ok := b.profileCache[u]; ok {
|
||||||
|
return v.data, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
b.profileCache[u] = cachedProfile{
|
||||||
|
data: resp,
|
||||||
|
lastUpdated: time.Now(),
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) avatarFor(m *chatv1.Message) string {
|
||||||
|
if m.Overrides != nil {
|
||||||
|
return m.Overrides.GetAvatar()
|
||||||
|
}
|
||||||
|
|
||||||
|
profi, err := b.getProfile(m.AuthorId)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.c.TransformHMCURL(profi.Profile.GetUserAvatar())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) usernameFor(m *chatv1.Message) string {
|
||||||
|
if m.Overrides != nil {
|
||||||
|
return m.Overrides.GetUsername()
|
||||||
|
}
|
||||||
|
|
||||||
|
profi, err := b.getProfile(m.AuthorId)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return profi.Profile.UserName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) toMessage(msg *shibshib.LocatedMessage) config.Message {
|
||||||
|
message := config.Message{}
|
||||||
|
message.Account = b.Account
|
||||||
|
message.UserID = uToStr(msg.Message.AuthorId)
|
||||||
|
message.Avatar = b.avatarFor(msg.Message)
|
||||||
|
message.Username = b.usernameFor(msg.Message)
|
||||||
|
message.Channel = uToStr(msg.ChannelID)
|
||||||
|
message.ID = uToStr(msg.MessageId)
|
||||||
|
|
||||||
|
switch content := msg.Message.Content.Content.(type) {
|
||||||
|
case *chatv1.Content_EmbedMessage:
|
||||||
|
message.Text = "Embed"
|
||||||
|
case *chatv1.Content_AttachmentMessage:
|
||||||
|
var s strings.Builder
|
||||||
|
for idx, attach := range content.AttachmentMessage.Files {
|
||||||
|
s.WriteString(b.c.TransformHMCURL(attach.Id))
|
||||||
|
if idx < len(content.AttachmentMessage.Files)-1 {
|
||||||
|
s.WriteString(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message.Text = s.String()
|
||||||
|
case *chatv1.Content_PhotoMessage:
|
||||||
|
var s strings.Builder
|
||||||
|
for idx, attach := range content.PhotoMessage.GetPhotos() {
|
||||||
|
s.WriteString(attach.GetCaption().GetText())
|
||||||
|
s.WriteString("\n")
|
||||||
|
s.WriteString(b.c.TransformHMCURL(attach.GetHmc()))
|
||||||
|
if idx < len(content.PhotoMessage.GetPhotos())-1 {
|
||||||
|
s.WriteString("\n\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
message.Text = s.String()
|
||||||
|
case *chatv1.Content_TextMessage:
|
||||||
|
message.Text = content.TextMessage.Content.Text
|
||||||
|
}
|
||||||
|
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) outputMessages() {
|
||||||
|
for {
|
||||||
|
msg := <-b.c.EventsStream()
|
||||||
|
|
||||||
|
if msg.Message.AuthorId == b.c.UserID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
b.Remote <- b.toMessage(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) GetUint64(conf string) uint64 {
|
||||||
|
num, err := strToU(b.GetString(conf))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) Connect() (err error) {
|
||||||
|
b.c, err = shibshib.NewClient(b.GetString("Homeserver"), b.GetString("Token"), b.GetUint64("UserID"))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b.c.SubscribeToGuild(b.GetUint64("Community"))
|
||||||
|
|
||||||
|
go b.outputMessages()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) send(msg config.Message) (id string, err error) {
|
||||||
|
msgChan, err := strToU(msg.Channel)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
retID, err := b.c.ChatKit.SendMessage(&chatv1.SendMessageRequest{
|
||||||
|
GuildId: b.GetUint64("Community"),
|
||||||
|
ChannelId: msgChan,
|
||||||
|
Content: &chatv1.Content{
|
||||||
|
Content: &chatv1.Content_TextMessage{
|
||||||
|
TextMessage: &chatv1.Content_TextContent{
|
||||||
|
Content: &chatv1.FormattedText{
|
||||||
|
Text: msg.Text,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Overrides: &chatv1.Overrides{
|
||||||
|
Username: &msg.Username,
|
||||||
|
Avatar: &msg.Avatar,
|
||||||
|
Reason: &chatv1.Overrides_Bridge{Bridge: &typesv1.Empty{}},
|
||||||
|
},
|
||||||
|
InReplyTo: nil,
|
||||||
|
EchoId: nil,
|
||||||
|
Metadata: nil,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("send: error sending message: %w", err)
|
||||||
|
log.Println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return uToStr(retID.MessageId), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) delete(msg config.Message) (id string, err error) {
|
||||||
|
msgChan, err := strToU(msg.Channel)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
msgID, err := strToU(msg.ID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = b.c.ChatKit.DeleteMessage(&chatv1.DeleteMessageRequest{
|
||||||
|
GuildId: b.GetUint64("Community"),
|
||||||
|
ChannelId: msgChan,
|
||||||
|
MessageId: msgID,
|
||||||
|
})
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) typing(msg config.Message) (id string, err error) {
|
||||||
|
msgChan, err := strToU(msg.Channel)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = b.c.ChatKit.Typing(&chatv1.TypingRequest{
|
||||||
|
GuildId: b.GetUint64("Community"),
|
||||||
|
ChannelId: msgChan,
|
||||||
|
})
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) Send(msg config.Message) (id string, err error) {
|
||||||
|
switch msg.Event {
|
||||||
|
case "":
|
||||||
|
return b.send(msg)
|
||||||
|
case config.EventMsgDelete:
|
||||||
|
return b.delete(msg)
|
||||||
|
case config.EventUserTyping:
|
||||||
|
return b.typing(msg)
|
||||||
|
default:
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) JoinChannel(channel config.ChannelInfo) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bharmony) Disconnect() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -168,6 +168,11 @@ func HandleDownloadSize(logger *logrus.Entry, msg *config.Message, name string,
|
|||||||
|
|
||||||
// HandleDownloadData adds the data for a remote file into a Matterbridge gateway message.
|
// HandleDownloadData adds the data for a remote file into a Matterbridge gateway message.
|
||||||
func HandleDownloadData(logger *logrus.Entry, msg *config.Message, name, comment, url string, data *[]byte, general *config.Protocol) {
|
func HandleDownloadData(logger *logrus.Entry, msg *config.Message, name, comment, url string, data *[]byte, general *config.Protocol) {
|
||||||
|
HandleDownloadData2(logger, msg, name, "", comment, url, data, general)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleDownloadData adds the data for a remote file into a Matterbridge gateway message.
|
||||||
|
func HandleDownloadData2(logger *logrus.Entry, msg *config.Message, name, id, comment, url string, data *[]byte, general *config.Protocol) {
|
||||||
var avatar bool
|
var avatar bool
|
||||||
logger.Debugf("Download OK %#v %#v", name, len(*data))
|
logger.Debugf("Download OK %#v %#v", name, len(*data))
|
||||||
if msg.Event == config.EventAvatarDownload {
|
if msg.Event == config.EventAvatarDownload {
|
||||||
@@ -179,6 +184,7 @@ func HandleDownloadData(logger *logrus.Entry, msg *config.Message, name, comment
|
|||||||
URL: url,
|
URL: url,
|
||||||
Comment: comment,
|
Comment: comment,
|
||||||
Avatar: avatar,
|
Avatar: avatar,
|
||||||
|
NativeID: id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package birc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -72,6 +73,10 @@ func (b *Birc) Command(msg *config.Message) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Birc) Connect() error {
|
func (b *Birc) Connect() error {
|
||||||
|
if b.GetBool("UseSASL") && b.GetString("TLSClientCertificate") != "" {
|
||||||
|
return errors.New("you can't enable SASL and TLSClientCertificate at the same time")
|
||||||
|
}
|
||||||
|
|
||||||
b.Local = make(chan config.Message, b.MessageQueue+10)
|
b.Local = make(chan config.Message, b.MessageQueue+10)
|
||||||
b.Log.Infof("Connecting %s", b.GetString("Server"))
|
b.Log.Infof("Connecting %s", b.GetString("Server"))
|
||||||
|
|
||||||
@@ -300,6 +305,11 @@ func (b *Birc) getClient() (*girc.Client, error) {
|
|||||||
|
|
||||||
b.Log.Debugf("setting pingdelay to %s", pingDelay)
|
b.Log.Debugf("setting pingdelay to %s", pingDelay)
|
||||||
|
|
||||||
|
tlsConfig, err := b.getTLSConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
i := girc.New(girc.Config{
|
i := girc.New(girc.Config{
|
||||||
Server: server,
|
Server: server,
|
||||||
ServerPass: b.GetString("Password"),
|
ServerPass: b.GetString("Password"),
|
||||||
@@ -308,7 +318,8 @@ func (b *Birc) getClient() (*girc.Client, error) {
|
|||||||
User: user,
|
User: user,
|
||||||
Name: realName,
|
Name: realName,
|
||||||
SSL: b.GetBool("UseTLS"),
|
SSL: b.GetBool("UseTLS"),
|
||||||
TLSConfig: &tls.Config{InsecureSkipVerify: b.GetBool("SkipTLSVerify"), ServerName: server}, //nolint:gosec
|
Bind: b.GetString("Bind"),
|
||||||
|
TLSConfig: tlsConfig,
|
||||||
PingDelay: pingDelay,
|
PingDelay: pingDelay,
|
||||||
// skip gIRC internal rate limiting, since we have our own throttling
|
// skip gIRC internal rate limiting, since we have our own throttling
|
||||||
AllowFlood: true,
|
AllowFlood: true,
|
||||||
@@ -380,3 +391,23 @@ func (b *Birc) storeNames(client *girc.Client, event girc.Event) {
|
|||||||
func (b *Birc) formatnicks(nicks []string) string {
|
func (b *Birc) formatnicks(nicks []string) string {
|
||||||
return strings.Join(nicks, ", ") + " currently on IRC"
|
return strings.Join(nicks, ", ") + " currently on IRC"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Birc) getTLSConfig() (*tls.Config, error) {
|
||||||
|
server, _, _ := net.SplitHostPort(b.GetString("server"))
|
||||||
|
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
InsecureSkipVerify: b.GetBool("skiptlsverify"), //nolint:gosec
|
||||||
|
ServerName: server,
|
||||||
|
}
|
||||||
|
|
||||||
|
if filename := b.GetString("TLSClientCertificate"); filename != "" {
|
||||||
|
cert, err := tls.LoadX509KeyPair(filename, filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlsConfig, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ type matrixUsername struct {
|
|||||||
type SubTextMessage struct {
|
type SubTextMessage struct {
|
||||||
MsgType string `json:"msgtype"`
|
MsgType string `json:"msgtype"`
|
||||||
Body string `json:"body"`
|
Body string `json:"body"`
|
||||||
|
FormattedBody string `json:"formatted_body,omitempty"`
|
||||||
|
Format string `json:"format,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageRelation explains how the current message relates to a previous message.
|
// MessageRelation explains how the current message relates to a previous message.
|
||||||
@@ -65,6 +67,19 @@ type EditedMessage struct {
|
|||||||
matrix.TextMessage
|
matrix.TextMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InReplyToRelationContent struct {
|
||||||
|
EventID string `json:"event_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type InReplyToRelation struct {
|
||||||
|
InReplyTo InReplyToRelationContent `json:"m.in_reply_to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReplyMessage struct {
|
||||||
|
RelatedTo InReplyToRelation `json:"m.relates_to"`
|
||||||
|
matrix.TextMessage
|
||||||
|
}
|
||||||
|
|
||||||
func New(cfg *bridge.Config) bridge.Bridger {
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
b := &Bmatrix{Config: cfg}
|
b := &Bmatrix{Config: cfg}
|
||||||
b.RoomMap = make(map[string]string)
|
b.RoomMap = make(map[string]string)
|
||||||
@@ -138,7 +153,13 @@ func (b *Bmatrix) Send(msg config.Message) (string, error) {
|
|||||||
m := matrix.TextMessage{
|
m := matrix.TextMessage{
|
||||||
MsgType: "m.emote",
|
MsgType: "m.emote",
|
||||||
Body: username.plain + msg.Text,
|
Body: username.plain + msg.Text,
|
||||||
FormattedBody: username.formatted + msg.Text,
|
FormattedBody: username.formatted + helper.ParseMarkdown(msg.Text),
|
||||||
|
Format: "org.matrix.custom.html",
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.GetBool("HTMLDisable") {
|
||||||
|
m.Format = ""
|
||||||
|
m.FormattedBody = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
msgID := ""
|
msgID := ""
|
||||||
@@ -201,20 +222,29 @@ func (b *Bmatrix) Send(msg config.Message) (string, error) {
|
|||||||
|
|
||||||
// Edit message if we have an ID
|
// Edit message if we have an ID
|
||||||
if msg.ID != "" {
|
if msg.ID != "" {
|
||||||
rmsg := EditedMessage{TextMessage: matrix.TextMessage{
|
rmsg := EditedMessage{
|
||||||
|
TextMessage: matrix.TextMessage{
|
||||||
Body: username.plain + msg.Text,
|
Body: username.plain + msg.Text,
|
||||||
MsgType: "m.text",
|
MsgType: "m.text",
|
||||||
}}
|
Format: "org.matrix.custom.html",
|
||||||
if b.GetBool("HTMLDisable") {
|
FormattedBody: username.formatted + helper.ParseMarkdown(msg.Text),
|
||||||
rmsg.TextMessage.FormattedBody = username.formatted + "* " + msg.Text
|
},
|
||||||
} else {
|
|
||||||
rmsg.Format = "org.matrix.custom.html"
|
|
||||||
rmsg.TextMessage.FormattedBody = username.formatted + "* " + helper.ParseMarkdown(msg.Text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rmsg.NewContent = SubTextMessage{
|
rmsg.NewContent = SubTextMessage{
|
||||||
Body: rmsg.TextMessage.Body,
|
Body: rmsg.TextMessage.Body,
|
||||||
|
FormattedBody: rmsg.TextMessage.FormattedBody,
|
||||||
|
Format: rmsg.TextMessage.Format,
|
||||||
MsgType: "m.text",
|
MsgType: "m.text",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.GetBool("HTMLDisable") {
|
||||||
|
rmsg.TextMessage.Format = ""
|
||||||
|
rmsg.TextMessage.FormattedBody = ""
|
||||||
|
rmsg.NewContent.Format = ""
|
||||||
|
rmsg.NewContent.FormattedBody = ""
|
||||||
|
}
|
||||||
|
|
||||||
rmsg.RelatedTo = MessageRelation{
|
rmsg.RelatedTo = MessageRelation{
|
||||||
EventID: msg.ID,
|
EventID: msg.ID,
|
||||||
Type: "m.replace",
|
Type: "m.replace",
|
||||||
@@ -238,6 +268,50 @@ func (b *Bmatrix) Send(msg config.Message) (string, error) {
|
|||||||
MsgType: "m.notice",
|
MsgType: "m.notice",
|
||||||
Body: username.plain + msg.Text,
|
Body: username.plain + msg.Text,
|
||||||
FormattedBody: username.formatted + msg.Text,
|
FormattedBody: username.formatted + msg.Text,
|
||||||
|
Format: "org.matrix.custom.html",
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.GetBool("HTMLDisable") {
|
||||||
|
m.Format = ""
|
||||||
|
m.FormattedBody = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
resp *matrix.RespSendEvent
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
err = b.retry(func() error {
|
||||||
|
resp, err = b.mc.SendMessageEvent(channel, "m.room.message", m)
|
||||||
|
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.EventID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.ParentValid() {
|
||||||
|
m := ReplyMessage{
|
||||||
|
TextMessage: matrix.TextMessage{
|
||||||
|
MsgType: "m.text",
|
||||||
|
Body: username.plain + msg.Text,
|
||||||
|
FormattedBody: username.formatted + helper.ParseMarkdown(msg.Text),
|
||||||
|
Format: "org.matrix.custom.html",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.GetBool("HTMLDisable") {
|
||||||
|
m.TextMessage.Format = ""
|
||||||
|
m.TextMessage.FormattedBody = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
m.RelatedTo = InReplyToRelation{
|
||||||
|
InReplyTo: InReplyToRelationContent{
|
||||||
|
EventID: msg.ParentID,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -301,6 +375,9 @@ func (b *Bmatrix) handlematrix() {
|
|||||||
syncer.OnEventType("m.room.member", b.handleMemberChange)
|
syncer.OnEventType("m.room.member", b.handleMemberChange)
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
if b == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if err := b.mc.Sync(); err != nil {
|
if err := b.mc.Sync(); err != nil {
|
||||||
b.Log.Println("Sync() returned ", err)
|
b.Log.Println("Sync() returned ", err)
|
||||||
}
|
}
|
||||||
@@ -338,6 +415,35 @@ func (b *Bmatrix) handleEdit(ev *matrix.Event, rmsg config.Message) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bmatrix) handleReply(ev *matrix.Event, rmsg config.Message) bool {
|
||||||
|
relationInterface, present := ev.Content["m.relates_to"]
|
||||||
|
if !present {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var relation InReplyToRelation
|
||||||
|
if err := interface2Struct(relationInterface, &relation); err != nil {
|
||||||
|
// probably fine
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
body := rmsg.Text
|
||||||
|
for strings.HasPrefix(body, "> ") {
|
||||||
|
lineIdx := strings.IndexRune(body, '\n')
|
||||||
|
if lineIdx == -1 {
|
||||||
|
body = ""
|
||||||
|
} else {
|
||||||
|
body = body[(lineIdx + 1):]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rmsg.Text = body
|
||||||
|
rmsg.ParentID = relation.InReplyTo.EventID
|
||||||
|
b.Remote <- rmsg
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bmatrix) handleMemberChange(ev *matrix.Event) {
|
func (b *Bmatrix) handleMemberChange(ev *matrix.Event) {
|
||||||
// Update the displayname on join messages, according to https://matrix.org/docs/spec/client_server/r0.6.1#events-on-change-of-profile-information
|
// Update the displayname on join messages, according to https://matrix.org/docs/spec/client_server/r0.6.1#events-on-change-of-profile-information
|
||||||
if ev.Content["membership"] == "join" {
|
if ev.Content["membership"] == "join" {
|
||||||
@@ -400,6 +506,11 @@ func (b *Bmatrix) handleEvent(ev *matrix.Event) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is it a reply?
|
||||||
|
if b.handleReply(ev, rmsg) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Do we have attachments
|
// Do we have attachments
|
||||||
if b.containsAttachment(ev.Content) {
|
if b.containsAttachment(ev.Content) {
|
||||||
err := b.handleDownloadFile(&rmsg, ev.Content)
|
err := b.handleDownloadFile(&rmsg, ev.Content)
|
||||||
|
|||||||
@@ -140,9 +140,14 @@ func (b *Bmattermost) handleMatterClient(messages chan *config.Message) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channelName := b.getChannelName(message.Post.ChannelId)
|
||||||
|
if channelName == "" {
|
||||||
|
channelName = message.Channel
|
||||||
|
}
|
||||||
|
|
||||||
// only download avatars if we have a place to upload them (configured mediaserver)
|
// only download avatars if we have a place to upload them (configured mediaserver)
|
||||||
if b.General.MediaServerUpload != "" || b.General.MediaDownloadPath != "" {
|
if b.General.MediaServerUpload != "" || b.General.MediaDownloadPath != "" {
|
||||||
b.handleDownloadAvatar(message.UserID, message.Channel)
|
b.handleDownloadAvatar(message.UserID, channelName)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Log.Debugf("== Receiving event %#v", message)
|
b.Log.Debugf("== Receiving event %#v", message)
|
||||||
@@ -150,7 +155,7 @@ func (b *Bmattermost) handleMatterClient(messages chan *config.Message) {
|
|||||||
rmsg := &config.Message{
|
rmsg := &config.Message{
|
||||||
Username: message.Username,
|
Username: message.Username,
|
||||||
UserID: message.UserID,
|
UserID: message.UserID,
|
||||||
Channel: message.Channel,
|
Channel: channelName,
|
||||||
Text: message.Text,
|
Text: message.Text,
|
||||||
ID: message.Post.Id,
|
ID: message.Post.Id,
|
||||||
ParentID: message.Post.RootId, // ParentID is obsolete with mattermost
|
ParentID: message.Post.RootId, // ParentID is obsolete with mattermost
|
||||||
@@ -177,9 +182,11 @@ func (b *Bmattermost) handleMatterClient(messages chan *config.Message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use nickname instead of username if defined
|
// Use nickname instead of username if defined
|
||||||
|
if !b.GetBool("useusername") {
|
||||||
if nick := b.mc.GetNickName(rmsg.UserID); nick != "" {
|
if nick := b.mc.GetNickName(rmsg.UserID); nick != "" {
|
||||||
rmsg.Username = nick
|
rmsg.Username = nick
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
messages <- rmsg
|
messages <- rmsg
|
||||||
}
|
}
|
||||||
@@ -188,16 +195,21 @@ func (b *Bmattermost) handleMatterClient(messages chan *config.Message) {
|
|||||||
// nolint:cyclop
|
// nolint:cyclop
|
||||||
func (b *Bmattermost) handleMatterClient6(messages chan *config.Message) {
|
func (b *Bmattermost) handleMatterClient6(messages chan *config.Message) {
|
||||||
for message := range b.mc6.MessageChan {
|
for message := range b.mc6.MessageChan {
|
||||||
b.Log.Debugf("%#v", message.Raw.GetData())
|
b.Log.Debugf("%#v %#v", message.Raw.GetData(), message.Raw.EventType())
|
||||||
|
|
||||||
if b.skipMessage6(message) {
|
if b.skipMessage6(message) {
|
||||||
b.Log.Debugf("Skipped message: %#v", message)
|
b.Log.Debugf("Skipped message: %#v", message)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channelName := b.getChannelName(message.Post.ChannelId)
|
||||||
|
if channelName == "" {
|
||||||
|
channelName = message.Channel
|
||||||
|
}
|
||||||
|
|
||||||
// only download avatars if we have a place to upload them (configured mediaserver)
|
// only download avatars if we have a place to upload them (configured mediaserver)
|
||||||
if b.General.MediaServerUpload != "" || b.General.MediaDownloadPath != "" {
|
if b.General.MediaServerUpload != "" || b.General.MediaDownloadPath != "" {
|
||||||
b.handleDownloadAvatar(message.UserID, message.Channel)
|
b.handleDownloadAvatar(message.UserID, channelName)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Log.Debugf("== Receiving event %#v", message)
|
b.Log.Debugf("== Receiving event %#v", message)
|
||||||
@@ -205,7 +217,7 @@ func (b *Bmattermost) handleMatterClient6(messages chan *config.Message) {
|
|||||||
rmsg := &config.Message{
|
rmsg := &config.Message{
|
||||||
Username: message.Username,
|
Username: message.Username,
|
||||||
UserID: message.UserID,
|
UserID: message.UserID,
|
||||||
Channel: message.Channel,
|
Channel: channelName,
|
||||||
Text: message.Text,
|
Text: message.Text,
|
||||||
ID: message.Post.Id,
|
ID: message.Post.Id,
|
||||||
ParentID: message.Post.RootId, // ParentID is obsolete with mattermost
|
ParentID: message.Post.RootId, // ParentID is obsolete with mattermost
|
||||||
@@ -232,9 +244,11 @@ func (b *Bmattermost) handleMatterClient6(messages chan *config.Message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use nickname instead of username if defined
|
// Use nickname instead of username if defined
|
||||||
|
if !b.GetBool("useusername") {
|
||||||
if nick := b.mc6.GetNickName(rmsg.UserID); nick != "" {
|
if nick := b.mc6.GetNickName(rmsg.UserID); nick != "" {
|
||||||
rmsg.Username = nick
|
rmsg.Username = nick
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
messages <- rmsg
|
messages <- rmsg
|
||||||
}
|
}
|
||||||
@@ -244,6 +258,7 @@ func (b *Bmattermost) handleMatterHook(messages chan *config.Message) {
|
|||||||
for {
|
for {
|
||||||
message := b.mh.Receive()
|
message := b.mh.Receive()
|
||||||
b.Log.Debugf("Receiving from matterhook %#v", message)
|
b.Log.Debugf("Receiving from matterhook %#v", message)
|
||||||
|
|
||||||
messages <- &config.Message{
|
messages <- &config.Message{
|
||||||
UserID: message.UserID,
|
UserID: message.UserID,
|
||||||
Username: message.UserName,
|
Username: message.UserName,
|
||||||
@@ -261,7 +276,7 @@ func (b *Bmattermost) handleUploadFile(msg *config.Message) (string, error) {
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
var res, id string
|
var res, id string
|
||||||
channelID := b.mc.GetChannelId(msg.Channel, b.TeamID)
|
channelID := b.getChannelID(msg.Channel)
|
||||||
for _, f := range msg.Extra["file"] {
|
for _, f := range msg.Extra["file"] {
|
||||||
fi := f.(config.FileInfo)
|
fi := f.(config.FileInfo)
|
||||||
id, err = b.mc.UploadFile(*fi.Data, channelID, fi.Name)
|
id, err = b.mc.UploadFile(*fi.Data, channelID, fi.Name)
|
||||||
@@ -281,7 +296,7 @@ func (b *Bmattermost) handleUploadFile(msg *config.Message) (string, error) {
|
|||||||
func (b *Bmattermost) handleUploadFile6(msg *config.Message) (string, error) {
|
func (b *Bmattermost) handleUploadFile6(msg *config.Message) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
var res, id string
|
var res, id string
|
||||||
channelID := b.mc6.GetChannelID(msg.Channel, b.TeamID)
|
channelID := b.getChannelID(msg.Channel)
|
||||||
for _, f := range msg.Extra["file"] {
|
for _, f := range msg.Extra["file"] {
|
||||||
fi := f.(config.FileInfo)
|
fi := f.(config.FileInfo)
|
||||||
id, err = b.mc6.UploadFile(*fi.Data, channelID, fi.Name)
|
id, err = b.mc6.UploadFile(*fi.Data, channelID, fi.Name)
|
||||||
|
|||||||
@@ -241,11 +241,17 @@ func (b *Bmattermost) skipMessage(message *matterclient.Message) bool {
|
|||||||
if b.GetBool("nosendjoinpart") {
|
if b.GetBool("nosendjoinpart") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channelName := b.getChannelName(message.Post.ChannelId)
|
||||||
|
if channelName == "" {
|
||||||
|
channelName = message.Channel
|
||||||
|
}
|
||||||
|
|
||||||
b.Log.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
b.Log.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
||||||
b.Remote <- config.Message{
|
b.Remote <- config.Message{
|
||||||
Username: "system",
|
Username: "system",
|
||||||
Text: message.Text,
|
Text: message.Text,
|
||||||
Channel: message.Channel,
|
Channel: channelName,
|
||||||
Account: b.Account,
|
Account: b.Account,
|
||||||
Event: config.EventJoinLeave,
|
Event: config.EventJoinLeave,
|
||||||
}
|
}
|
||||||
@@ -304,11 +310,17 @@ func (b *Bmattermost) skipMessage6(message *matterclient6.Message) bool {
|
|||||||
if b.GetBool("nosendjoinpart") {
|
if b.GetBool("nosendjoinpart") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channelName := b.getChannelName(message.Post.ChannelId)
|
||||||
|
if channelName == "" {
|
||||||
|
channelName = message.Channel
|
||||||
|
}
|
||||||
|
|
||||||
b.Log.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
b.Log.Debugf("Sending JOIN_LEAVE event from %s to gateway", b.Account)
|
||||||
b.Remote <- config.Message{
|
b.Remote <- config.Message{
|
||||||
Username: "system",
|
Username: "system",
|
||||||
Text: message.Text,
|
Text: message.Text,
|
||||||
Channel: message.Channel,
|
Channel: channelName,
|
||||||
Account: b.Account,
|
Account: b.Account,
|
||||||
Event: config.EventJoinLeave,
|
Event: config.EventJoinLeave,
|
||||||
}
|
}
|
||||||
@@ -329,13 +341,14 @@ func (b *Bmattermost) skipMessage6(message *matterclient6.Message) bool {
|
|||||||
// Ignore messages sent from matterbridge
|
// Ignore messages sent from matterbridge
|
||||||
if message.Post.Props != nil {
|
if message.Post.Props != nil {
|
||||||
if _, ok := message.Post.Props["matterbridge_"+b.uuid].(bool); ok {
|
if _, ok := message.Post.Props["matterbridge_"+b.uuid].(bool); ok {
|
||||||
b.Log.Debugf("sent by matterbridge, ignoring")
|
b.Log.Debug("sent by matterbridge, ignoring")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore messages sent from a user logged in as the bot
|
// Ignore messages sent from a user logged in as the bot
|
||||||
if b.mc6.User.Username == message.Username {
|
if b.mc6.User.Username == message.Username {
|
||||||
|
b.Log.Debug("message from same user as bot, ignoring")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,6 +359,7 @@ func (b *Bmattermost) skipMessage6(message *matterclient6.Message) bool {
|
|||||||
|
|
||||||
// ignore messages from other teams than ours
|
// ignore messages from other teams than ours
|
||||||
if message.Raw.GetData()["team_id"].(string) != b.TeamID {
|
if message.Raw.GetData()["team_id"].(string) != b.TeamID {
|
||||||
|
b.Log.Debug("message from other team, ignoring")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,3 +388,30 @@ func (b *Bmattermost) getVersion() string {
|
|||||||
|
|
||||||
return resp.Header.Get("X-Version-Id")
|
return resp.Header.Get("X-Version-Id")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bmattermost) getChannelID(name string) string {
|
||||||
|
idcheck := strings.Split(name, "ID:")
|
||||||
|
if len(idcheck) > 1 {
|
||||||
|
return idcheck[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.mc6 != nil {
|
||||||
|
return b.mc6.GetChannelID(name, b.TeamID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.mc.GetChannelId(name, b.TeamID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bmattermost) getChannelName(id string) string {
|
||||||
|
b.channelsMutex.RLock()
|
||||||
|
defer b.channelsMutex.RUnlock()
|
||||||
|
|
||||||
|
for _, c := range b.channelInfoMap {
|
||||||
|
if c.Name == "ID:"+id {
|
||||||
|
// if we have ID: specified in our gateway configuration return this
|
||||||
|
return c.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
@@ -23,12 +24,18 @@ type Bmattermost struct {
|
|||||||
TeamID string
|
TeamID string
|
||||||
*bridge.Config
|
*bridge.Config
|
||||||
avatarMap map[string]string
|
avatarMap map[string]string
|
||||||
|
channelsMutex sync.RWMutex
|
||||||
|
channelInfoMap map[string]*config.ChannelInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
const mattermostPlugin = "mattermost.plugin"
|
const mattermostPlugin = "mattermost.plugin"
|
||||||
|
|
||||||
func New(cfg *bridge.Config) bridge.Bridger {
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
b := &Bmattermost{Config: cfg, avatarMap: make(map[string]string)}
|
b := &Bmattermost{
|
||||||
|
Config: cfg,
|
||||||
|
avatarMap: make(map[string]string),
|
||||||
|
channelInfoMap: make(map[string]*config.ChannelInfo),
|
||||||
|
}
|
||||||
|
|
||||||
b.v6 = b.GetBool("v6")
|
b.v6 = b.GetBool("v6")
|
||||||
b.uuid = xid.New().String()
|
b.uuid = xid.New().String()
|
||||||
@@ -113,14 +120,14 @@ func (b *Bmattermost) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
if b.Account == mattermostPlugin {
|
if b.Account == mattermostPlugin {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.channelsMutex.Lock()
|
||||||
|
b.channelInfoMap[channel.ID] = &channel
|
||||||
|
b.channelsMutex.Unlock()
|
||||||
|
|
||||||
// we can only join channels using the API
|
// we can only join channels using the API
|
||||||
if b.GetString("WebhookURL") == "" && b.GetString("WebhookBindAddress") == "" {
|
if b.GetString("WebhookURL") == "" && b.GetString("WebhookBindAddress") == "" {
|
||||||
var id string
|
id := b.getChannelID(channel.Name)
|
||||||
if b.mc6 != nil {
|
|
||||||
id = b.mc6.GetChannelID(channel.Name, b.TeamID)
|
|
||||||
} else {
|
|
||||||
id = b.mc.GetChannelId(channel.Name, b.TeamID)
|
|
||||||
}
|
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return fmt.Errorf("Could not find channel ID for channel %s", channel.Name)
|
return fmt.Errorf("Could not find channel ID for channel %s", channel.Name)
|
||||||
}
|
}
|
||||||
@@ -131,6 +138,7 @@ func (b *Bmattermost) JoinChannel(channel config.ChannelInfo) error {
|
|||||||
|
|
||||||
return b.mc.JoinChannel(id)
|
return b.mc.JoinChannel(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,25 +188,29 @@ func (b *Bmattermost) Send(msg config.Message) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Errorf("getting post %s failed: %s", msg.ParentID, err)
|
b.Log.Errorf("getting post %s failed: %s", msg.ParentID, err)
|
||||||
}
|
}
|
||||||
|
if post.RootId != "" {
|
||||||
msg.ParentID = post.RootId
|
msg.ParentID = post.RootId
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
post, res := b.mc.Client.GetPost(msg.ParentID, "")
|
post, res := b.mc.Client.GetPost(msg.ParentID, "")
|
||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
b.Log.Errorf("getting post %s failed: %s", msg.ParentID, res.Error.DetailedError)
|
b.Log.Errorf("getting post %s failed: %s", msg.ParentID, res.Error.DetailedError)
|
||||||
}
|
}
|
||||||
|
if post.RootId != "" {
|
||||||
msg.ParentID = post.RootId
|
msg.ParentID = post.RootId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Upload a file if it exists
|
// Upload a file if it exists
|
||||||
if msg.Extra != nil {
|
if msg.Extra != nil {
|
||||||
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
if b.mc6 != nil {
|
if b.mc6 != nil {
|
||||||
if _, err := b.mc6.PostMessage(b.mc.GetChannelId(rmsg.Channel, b.TeamID), rmsg.Username+rmsg.Text, msg.ParentID); err != nil {
|
if _, err := b.mc6.PostMessage(b.getChannelID(rmsg.Channel), rmsg.Username+rmsg.Text, msg.ParentID); err != nil {
|
||||||
b.Log.Errorf("PostMessage failed: %s", err)
|
b.Log.Errorf("PostMessage failed: %s", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if _, err := b.mc.PostMessage(b.mc.GetChannelId(rmsg.Channel, b.TeamID), rmsg.Username+rmsg.Text, msg.ParentID); err != nil {
|
if _, err := b.mc.PostMessage(b.getChannelID(rmsg.Channel), rmsg.Username+rmsg.Text, msg.ParentID); err != nil {
|
||||||
b.Log.Errorf("PostMessage failed: %s", err)
|
b.Log.Errorf("PostMessage failed: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,8 +236,8 @@ func (b *Bmattermost) Send(msg config.Message) (string, error) {
|
|||||||
|
|
||||||
// Post normal message
|
// Post normal message
|
||||||
if b.mc6 != nil {
|
if b.mc6 != nil {
|
||||||
return b.mc6.PostMessage(b.mc6.GetChannelID(msg.Channel, b.TeamID), msg.Text, msg.ParentID) // nolint:wrapcheck
|
return b.mc6.PostMessage(b.getChannelID(msg.Channel), msg.Text, msg.ParentID) // nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.mc.PostMessage(b.mc.GetChannelId(msg.Channel, b.TeamID), msg.Text, msg.ParentID)
|
return b.mc.PostMessage(b.getChannelID(msg.Channel), msg.Text, msg.ParentID)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import (
|
|||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultScopes = []string{"openid", "profile", "offline_access", "Group.Read.All", "Group.ReadWrite.All"}
|
var (
|
||||||
var attachRE = regexp.MustCompile(`<attachment id=.*?attachment>`)
|
defaultScopes = []string{"openid", "profile", "offline_access", "Group.Read.All", "Group.ReadWrite.All"}
|
||||||
|
attachRE = regexp.MustCompile(`<attachment id=.*?attachment>`)
|
||||||
|
)
|
||||||
|
|
||||||
type Bmsteams struct {
|
type Bmsteams struct {
|
||||||
gc *msgraph.GraphServiceRequestBuilder
|
gc *msgraph.GraphServiceRequestBuilder
|
||||||
@@ -50,7 +52,7 @@ func (b *Bmsteams) Connect() error {
|
|||||||
b.Log.Errorf("Couldn't save sessionfile in %s: %s", tokenCachePath, err)
|
b.Log.Errorf("Couldn't save sessionfile in %s: %s", tokenCachePath, err)
|
||||||
}
|
}
|
||||||
// make file readable only for matterbridge user
|
// make file readable only for matterbridge user
|
||||||
err = os.Chmod(tokenCachePath, 0600)
|
err = os.Chmod(tokenCachePath, 0o600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Errorf("Couldn't change permissions for %s: %s", tokenCachePath, err)
|
b.Log.Errorf("Couldn't change permissions for %s: %s", tokenCachePath, err)
|
||||||
}
|
}
|
||||||
@@ -168,7 +170,7 @@ func (b *Bmsteams) poll(channelName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// skip non-user message for now.
|
// skip non-user message for now.
|
||||||
if msg.From.User == nil {
|
if msg.From == nil || msg.From.User == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ func (b *Bslack) handleSlack() {
|
|||||||
b.Log.Debug("Start listening for Slack messages")
|
b.Log.Debug("Start listening for Slack messages")
|
||||||
for message := range messages {
|
for message := range messages {
|
||||||
// don't do any action on deleted/typing messages
|
// don't do any action on deleted/typing messages
|
||||||
if message.Event != config.EventUserTyping && message.Event != config.EventMsgDelete {
|
if message.Event != config.EventUserTyping && message.Event != config.EventMsgDelete &&
|
||||||
|
message.Event != config.EventFileDelete {
|
||||||
b.Log.Debugf("<= Sending message from %s on %s to gateway", message.Username, b.Account)
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", message.Username, b.Account)
|
||||||
// cleanup the message
|
// cleanup the message
|
||||||
message.Text = b.replaceMention(message.Text)
|
message.Text = b.replaceMention(message.Text)
|
||||||
@@ -76,6 +77,13 @@ func (b *Bslack) handleSlackClient(messages chan *config.Message) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
messages <- rmsg
|
messages <- rmsg
|
||||||
|
case *slack.FileDeletedEvent:
|
||||||
|
rmsg, err := b.handleFileDeletedEvent(ev)
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("%#v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
messages <- rmsg
|
||||||
case *slack.OutgoingErrorEvent:
|
case *slack.OutgoingErrorEvent:
|
||||||
b.Log.Debugf("%#v", ev.Error())
|
b.Log.Debugf("%#v", ev.Error())
|
||||||
case *slack.ChannelJoinedEvent:
|
case *slack.ChannelJoinedEvent:
|
||||||
@@ -222,6 +230,26 @@ func (b *Bslack) handleMessageEvent(ev *slack.MessageEvent) (*config.Message, er
|
|||||||
return rmsg, nil
|
return rmsg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bslack) handleFileDeletedEvent(ev *slack.FileDeletedEvent) (*config.Message, error) {
|
||||||
|
if rawChannel, ok := b.cache.Get(cfileDownloadChannel + ev.FileID); ok {
|
||||||
|
channel, err := b.channels.getChannelByID(rawChannel.(string))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &config.Message{
|
||||||
|
Event: config.EventFileDelete,
|
||||||
|
Text: config.EventFileDelete,
|
||||||
|
Channel: channel.Name,
|
||||||
|
Account: b.Account,
|
||||||
|
ID: ev.FileID,
|
||||||
|
Protocol: b.Protocol,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("channel ID for file ID %s not found", ev.FileID)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Bslack) handleStatusEvent(ev *slack.MessageEvent, rmsg *config.Message) bool {
|
func (b *Bslack) handleStatusEvent(ev *slack.MessageEvent, rmsg *config.Message) bool {
|
||||||
switch ev.SubType {
|
switch ev.SubType {
|
||||||
case sChannelJoined, sMemberJoined:
|
case sChannelJoined, sMemberJoined:
|
||||||
@@ -281,6 +309,8 @@ func (b *Bslack) handleAttachments(ev *slack.MessageEvent, rmsg *config.Message)
|
|||||||
|
|
||||||
// If we have files attached, download them (in memory) and put a pointer to it in msg.Extra.
|
// If we have files attached, download them (in memory) and put a pointer to it in msg.Extra.
|
||||||
for i := range ev.Files {
|
for i := range ev.Files {
|
||||||
|
// keep reference in cache on which channel we added this file
|
||||||
|
b.cache.Add(cfileDownloadChannel+ev.Files[i].ID, ev.Channel)
|
||||||
if err := b.handleDownloadFile(rmsg, &ev.Files[i], false); err != nil {
|
if err := b.handleDownloadFile(rmsg, &ev.Files[i], false); err != nil {
|
||||||
b.Log.Errorf("Could not download incoming file: %#v", err)
|
b.Log.Errorf("Could not download incoming file: %#v", err)
|
||||||
}
|
}
|
||||||
@@ -330,7 +360,7 @@ func (b *Bslack) handleDownloadFile(rmsg *config.Message, file *slack.File, retr
|
|||||||
// that the comment is not duplicated.
|
// that the comment is not duplicated.
|
||||||
comment := rmsg.Text
|
comment := rmsg.Text
|
||||||
rmsg.Text = ""
|
rmsg.Text = ""
|
||||||
helper.HandleDownloadData(b.Log, rmsg, file.Name, comment, file.URLPrivateDownload, data, b.General)
|
helper.HandleDownloadData2(b.Log, rmsg, file.Name, file.ID, comment, file.URLPrivateDownload, data, b.General)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ const (
|
|||||||
sLatencyReport = "latency_report"
|
sLatencyReport = "latency_report"
|
||||||
sSystemUser = "system"
|
sSystemUser = "system"
|
||||||
sSlackBotUser = "slackbot"
|
sSlackBotUser = "slackbot"
|
||||||
|
cfileDownloadChannel = "file_download_channel"
|
||||||
|
|
||||||
tokenConfig = "Token"
|
tokenConfig = "Token"
|
||||||
incomingWebhookConfig = "WebhookBindAddress"
|
incomingWebhookConfig = "WebhookBindAddress"
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ func (b *channels) populateChannels(wait bool) {
|
|||||||
queryParams := &slack.GetConversationsParameters{
|
queryParams := &slack.GetConversationsParameters{
|
||||||
ExcludeArchived: true,
|
ExcludeArchived: true,
|
||||||
Types: []string{"public_channel,private_channel"},
|
Types: []string{"public_channel,private_channel"},
|
||||||
|
Limit: 1000,
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
channels, nextCursor, err := b.sc.GetConversations(queryParams)
|
channels, nextCursor, err := b.sc.GetConversations(queryParams)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package btelegram
|
package btelegram
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -9,15 +10,28 @@ import (
|
|||||||
|
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Btelegram) handleUpdate(rmsg *config.Message, message, posted, edited *tgbotapi.Message) *tgbotapi.Message {
|
func (b *Btelegram) handleUpdate(rmsg *config.Message, message, posted, edited *tgbotapi.Message) *tgbotapi.Message {
|
||||||
// handle channels
|
// handle channels
|
||||||
if posted != nil {
|
if posted != nil {
|
||||||
|
if posted.Text == "/chatId" {
|
||||||
|
chatID := strconv.FormatInt(posted.Chat.ID, 10)
|
||||||
|
|
||||||
|
_, err := b.Send(config.Message{
|
||||||
|
Channel: chatID,
|
||||||
|
Text: fmt.Sprintf("ID of this chat: %s", chatID),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Warnf("Unable to send chatID to %s", chatID)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
message = posted
|
message = posted
|
||||||
rmsg.Text = message.Text
|
rmsg.Text = message.Text
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// edited channel message
|
// edited channel message
|
||||||
if edited != nil && !b.GetBool("EditDisable") {
|
if edited != nil && !b.GetBool("EditDisable") {
|
||||||
@@ -94,7 +108,7 @@ func (b *Btelegram) handleQuoting(rmsg *config.Message, message *tgbotapi.Messag
|
|||||||
// handleUsername handles the correct setting of the username
|
// handleUsername handles the correct setting of the username
|
||||||
func (b *Btelegram) handleUsername(rmsg *config.Message, message *tgbotapi.Message) {
|
func (b *Btelegram) handleUsername(rmsg *config.Message, message *tgbotapi.Message) {
|
||||||
if message.From != nil {
|
if message.From != nil {
|
||||||
rmsg.UserID = strconv.Itoa(message.From.ID)
|
rmsg.UserID = strconv.FormatInt(message.From.ID, 10)
|
||||||
if b.GetBool("UseFirstName") {
|
if b.GetBool("UseFirstName") {
|
||||||
rmsg.Username = message.From.FirstName
|
rmsg.Username = message.From.FirstName
|
||||||
}
|
}
|
||||||
@@ -110,6 +124,25 @@ func (b *Btelegram) handleUsername(rmsg *config.Message, message *tgbotapi.Messa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if message.SenderChat != nil { //nolint:nestif
|
||||||
|
rmsg.UserID = strconv.FormatInt(message.SenderChat.ID, 10)
|
||||||
|
if b.GetBool("UseFirstName") {
|
||||||
|
rmsg.Username = message.SenderChat.FirstName
|
||||||
|
}
|
||||||
|
|
||||||
|
if rmsg.Username == "" || rmsg.Username == "Channel_Bot" {
|
||||||
|
rmsg.Username = message.SenderChat.UserName
|
||||||
|
|
||||||
|
if rmsg.Username == "" || rmsg.Username == "Channel_Bot" {
|
||||||
|
rmsg.Username = message.SenderChat.FirstName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// only download avatars if we have a place to upload them (configured mediaserver)
|
||||||
|
if b.General.MediaServerUpload != "" || (b.General.MediaServerDownload != "" && b.General.MediaDownloadPath != "") {
|
||||||
|
b.handleDownloadAvatar(message.SenderChat.ID, rmsg.Channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if we really didn't find a username, set it to unknown
|
// if we really didn't find a username, set it to unknown
|
||||||
if rmsg.Username == "" {
|
if rmsg.Username == "" {
|
||||||
rmsg.Username = unknownUser
|
rmsg.Username = unknownUser
|
||||||
@@ -126,6 +159,10 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.GetInt("debuglevel") == 1 {
|
||||||
|
spew.Dump(update.Message)
|
||||||
|
}
|
||||||
|
|
||||||
var message *tgbotapi.Message
|
var message *tgbotapi.Message
|
||||||
|
|
||||||
rmsg := config.Message{Account: b.Account, Extra: make(map[string][]interface{})}
|
rmsg := config.Message{Account: b.Account, Extra: make(map[string][]interface{})}
|
||||||
@@ -167,7 +204,7 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|||||||
rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
||||||
// channels don't have (always?) user information. see #410
|
// channels don't have (always?) user information. see #410
|
||||||
if message.From != nil {
|
if message.From != nil {
|
||||||
rmsg.Avatar = helper.GetAvatar(b.avatarMap, strconv.Itoa(message.From.ID), b.General)
|
rmsg.Avatar = helper.GetAvatar(b.avatarMap, strconv.FormatInt(message.From.ID, 10), b.General)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
||||||
@@ -180,18 +217,21 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|||||||
// handleDownloadAvatar downloads the avatar of userid from channel
|
// handleDownloadAvatar downloads the avatar of userid from channel
|
||||||
// sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful.
|
// sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful.
|
||||||
// logs an error message if it fails
|
// logs an error message if it fails
|
||||||
func (b *Btelegram) handleDownloadAvatar(userid int, channel string) {
|
func (b *Btelegram) handleDownloadAvatar(userid int64, channel string) {
|
||||||
rmsg := config.Message{
|
rmsg := config.Message{
|
||||||
Username: "system",
|
Username: "system",
|
||||||
Text: "avatar",
|
Text: "avatar",
|
||||||
Channel: channel,
|
Channel: channel,
|
||||||
Account: b.Account,
|
Account: b.Account,
|
||||||
UserID: strconv.Itoa(userid),
|
UserID: strconv.FormatInt(userid, 10),
|
||||||
Event: config.EventAvatarDownload,
|
Event: config.EventAvatarDownload,
|
||||||
Extra: make(map[string][]interface{}),
|
Extra: make(map[string][]interface{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := b.avatarMap[strconv.Itoa(userid)]; !ok {
|
if _, ok := b.avatarMap[strconv.FormatInt(userid, 10)]; ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
photos, err := b.c.GetUserProfilePhotos(tgbotapi.UserProfilePhotosConfig{UserID: userid, Limit: 1})
|
photos, err := b.c.GetUserProfilePhotos(tgbotapi.UserProfilePhotosConfig{UserID: userid, Limit: 1})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Errorf("Userprofile download failed for %#v %s", userid, err)
|
b.Log.Errorf("Userprofile download failed for %#v %s", userid, err)
|
||||||
@@ -200,7 +240,7 @@ func (b *Btelegram) handleDownloadAvatar(userid int, channel string) {
|
|||||||
if len(photos.Photos) > 0 {
|
if len(photos.Photos) > 0 {
|
||||||
photo := photos.Photos[0][0]
|
photo := photos.Photos[0][0]
|
||||||
url := b.getFileDirectURL(photo.FileID)
|
url := b.getFileDirectURL(photo.FileID)
|
||||||
name := strconv.Itoa(userid) + ".png"
|
name := strconv.FormatInt(userid, 10) + ".png"
|
||||||
b.Log.Debugf("trying to download %#v fileid %#v with size %#v", name, photo.FileID, photo.FileSize)
|
b.Log.Debugf("trying to download %#v fileid %#v with size %#v", name, photo.FileID, photo.FileSize)
|
||||||
|
|
||||||
err := helper.HandleDownloadSize(b.Log, &rmsg, name, int64(photo.FileSize), b.General)
|
err := helper.HandleDownloadSize(b.Log, &rmsg, name, int64(photo.FileSize), b.General)
|
||||||
@@ -217,7 +257,6 @@ func (b *Btelegram) handleDownloadAvatar(userid int, channel string) {
|
|||||||
b.Remote <- rmsg
|
b.Remote <- rmsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Btelegram) maybeConvertTgs(name *string, data *[]byte) {
|
func (b *Btelegram) maybeConvertTgs(name *string, data *[]byte) {
|
||||||
format := b.GetString("MediaConvertTgs")
|
format := b.GetString("MediaConvertTgs")
|
||||||
@@ -272,7 +311,7 @@ func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Messa
|
|||||||
name = message.Document.FileName
|
name = message.Document.FileName
|
||||||
text = " " + message.Document.FileName + " : " + url
|
text = " " + message.Document.FileName + " : " + url
|
||||||
case message.Photo != nil:
|
case message.Photo != nil:
|
||||||
photos := *message.Photo
|
photos := message.Photo
|
||||||
size = photos[len(photos)-1].FileSize
|
size = photos[len(photos)-1].FileSize
|
||||||
text, name, url = b.getDownloadInfo(photos[len(photos)-1].FileID, "", true)
|
text, name, url = b.getDownloadInfo(photos[len(photos)-1].FileID, "", true)
|
||||||
}
|
}
|
||||||
@@ -331,11 +370,15 @@ func (b *Btelegram) handleDelete(msg *config.Message, chatid int64) (string, err
|
|||||||
if msg.ID == "" {
|
if msg.ID == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
msgid, err := strconv.Atoi(msg.ID)
|
msgid, err := strconv.Atoi(msg.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
_, err = b.c.DeleteMessage(tgbotapi.DeleteMessageConfig{ChatID: chatid, MessageID: msgid})
|
|
||||||
|
cfg := tgbotapi.NewDeleteMessage(chatid, msgid)
|
||||||
|
_, err = b.c.Send(cfg)
|
||||||
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,23 +426,23 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64) string {
|
|||||||
}
|
}
|
||||||
switch filepath.Ext(fi.Name) {
|
switch filepath.Ext(fi.Name) {
|
||||||
case ".jpg", ".jpe", ".png":
|
case ".jpg", ".jpe", ".png":
|
||||||
pc := tgbotapi.NewPhotoUpload(chatid, file)
|
pc := tgbotapi.NewPhoto(chatid, file)
|
||||||
pc.Caption, pc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
pc.Caption, pc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
||||||
c = pc
|
c = pc
|
||||||
case ".mp4", ".m4v":
|
case ".mp4", ".m4v":
|
||||||
vc := tgbotapi.NewVideoUpload(chatid, file)
|
vc := tgbotapi.NewVideo(chatid, file)
|
||||||
vc.Caption, vc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
vc.Caption, vc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
||||||
c = vc
|
c = vc
|
||||||
case ".mp3", ".oga":
|
case ".mp3", ".oga":
|
||||||
ac := tgbotapi.NewAudioUpload(chatid, file)
|
ac := tgbotapi.NewAudio(chatid, file)
|
||||||
ac.Caption, ac.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
ac.Caption, ac.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
||||||
c = ac
|
c = ac
|
||||||
case ".ogg":
|
case ".ogg":
|
||||||
voc := tgbotapi.NewVoiceUpload(chatid, file)
|
voc := tgbotapi.NewVoice(chatid, file)
|
||||||
voc.Caption, voc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
voc.Caption, voc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
||||||
c = voc
|
c = voc
|
||||||
default:
|
default:
|
||||||
dc := tgbotapi.NewDocumentUpload(chatid, file)
|
dc := tgbotapi.NewDocument(chatid, file)
|
||||||
dc.Caption, dc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
dc.Caption, dc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
||||||
c = dc
|
c = dc
|
||||||
}
|
}
|
||||||
@@ -435,8 +478,11 @@ func (b *Btelegram) handleEntities(rmsg *config.Message, message *tgbotapi.Messa
|
|||||||
if message.Entities == nil {
|
if message.Entities == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
indexMovedBy := 0
|
||||||
|
|
||||||
// for now only do URL replacements
|
// for now only do URL replacements
|
||||||
for _, e := range *message.Entities {
|
for _, e := range message.Entities {
|
||||||
if e.Type == "text_link" {
|
if e.Type == "text_link" {
|
||||||
url, err := e.ParseURL()
|
url, err := e.ParseURL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -451,5 +497,17 @@ func (b *Btelegram) handleEntities(rmsg *config.Message, message *tgbotapi.Messa
|
|||||||
link := utf16.Decode(utfEncodedString[e.Offset : e.Offset+e.Length])
|
link := utf16.Decode(utfEncodedString[e.Offset : e.Offset+e.Length])
|
||||||
rmsg.Text = strings.Replace(rmsg.Text, string(link), url.String(), 1)
|
rmsg.Text = strings.Replace(rmsg.Text, string(link), url.String(), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e.Type == "code" {
|
||||||
|
offset := e.Offset + indexMovedBy
|
||||||
|
rmsg.Text = rmsg.Text[:offset] + "`" + rmsg.Text[offset:offset+e.Length] + "`" + rmsg.Text[offset+e.Length:]
|
||||||
|
indexMovedBy += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Type == "pre" {
|
||||||
|
offset := e.Offset + indexMovedBy
|
||||||
|
rmsg.Text = rmsg.Text[:offset] + "```\n" + rmsg.Text[offset:offset+e.Length] + "\n```" + rmsg.Text[offset+e.Length:]
|
||||||
|
indexMovedBy += 8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -49,11 +49,7 @@ func (b *Btelegram) Connect() error {
|
|||||||
}
|
}
|
||||||
u := tgbotapi.NewUpdate(0)
|
u := tgbotapi.NewUpdate(0)
|
||||||
u.Timeout = 60
|
u.Timeout = 60
|
||||||
updates, err := b.c.GetUpdatesChan(u)
|
updates := b.c.GetUpdatesChan(u)
|
||||||
if err != nil {
|
|
||||||
b.Log.Debugf("%#v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b.Log.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
go b.handleRecv(updates)
|
go b.handleRecv(updates)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ type user struct {
|
|||||||
|
|
||||||
type Bvk struct {
|
type Bvk struct {
|
||||||
c *api.VK
|
c *api.VK
|
||||||
|
lp *longpoll.LongPoll
|
||||||
usernamesMap map[int]user // cache of user names and avatar URLs
|
usernamesMap map[int]user // cache of user names and avatar URLs
|
||||||
*bridge.Config
|
*bridge.Config
|
||||||
}
|
}
|
||||||
@@ -45,21 +46,23 @@ func New(cfg *bridge.Config) bridge.Bridger {
|
|||||||
func (b *Bvk) Connect() error {
|
func (b *Bvk) Connect() error {
|
||||||
b.Log.Info("Connecting")
|
b.Log.Info("Connecting")
|
||||||
b.c = api.NewVK(b.GetString("Token"))
|
b.c = api.NewVK(b.GetString("Token"))
|
||||||
lp, err := longpoll.NewLongPoll(b.c, b.GetInt("GroupID"))
|
|
||||||
|
var err error
|
||||||
|
b.lp, err = longpoll.NewLongPollCommunity(b.c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Debugf("%#v", err)
|
b.Log.Debugf("%#v", err)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
lp.MessageNew(func(ctx context.Context, obj events.MessageNewObject) {
|
b.lp.MessageNew(func(ctx context.Context, obj events.MessageNewObject) {
|
||||||
b.handleMessage(obj.Message, false)
|
b.handleMessage(obj.Message, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
b.Log.Info("Connection succeeded")
|
b.Log.Info("Connection succeeded")
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := lp.Run()
|
err := b.lp.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Log.Fatal("Enable longpoll in group management")
|
b.Log.Fatal("Enable longpoll in group management")
|
||||||
}
|
}
|
||||||
@@ -69,6 +72,8 @@ func (b *Bvk) Connect() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bvk) Disconnect() error {
|
func (b *Bvk) Disconnect() error {
|
||||||
|
b.lp.Shutdown()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -293,8 +293,12 @@ func (b *Bwhatsapp) Send(msg config.Message) (string, error) {
|
|||||||
if msg.ID != "" {
|
if msg.ID != "" {
|
||||||
b.Log.Debugf("updating message with id %s", msg.ID)
|
b.Log.Debugf("updating message with id %s", msg.ID)
|
||||||
|
|
||||||
|
if b.GetString("editsuffix") != "" {
|
||||||
|
msg.Text += b.GetString("EditSuffix")
|
||||||
|
} else {
|
||||||
msg.Text += " (edited)"
|
msg.Text += " (edited)"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle Upload a file
|
// Handle Upload a file
|
||||||
if msg.Extra["file"] != nil {
|
if msg.Extra["file"] != nil {
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) {
|
|||||||
var msgReplaceID string
|
var msgReplaceID string
|
||||||
msgID := xid.New().String()
|
msgID := xid.New().String()
|
||||||
if msg.ID != "" {
|
if msg.ID != "" {
|
||||||
msgID = msg.ID
|
|
||||||
msgReplaceID = msg.ID
|
msgReplaceID = msg.ID
|
||||||
}
|
}
|
||||||
b.Log.Debugf("=> Sending message %#v", msg)
|
b.Log.Debugf("=> Sending message %#v", msg)
|
||||||
@@ -284,8 +283,14 @@ func (b *Bxmpp) handleXMPP() error {
|
|||||||
for {
|
for {
|
||||||
m, err := b.xc.Recv()
|
m, err := b.xc.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// An error together with AvatarData is non-fatal
|
||||||
|
switch m.(type) {
|
||||||
|
case xmpp.AvatarData:
|
||||||
|
continue
|
||||||
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch v := m.(type) {
|
switch v := m.(type) {
|
||||||
case xmpp.Chat:
|
case xmpp.Chat:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package bzulip
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge"
|
"github.com/42wim/matterbridge/bridge"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/helper"
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
"github.com/42wim/matterbridge/version"
|
||||||
gzb "github.com/matterbridge/gozulipbot"
|
gzb "github.com/matterbridge/gozulipbot"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,7 +29,7 @@ func New(cfg *bridge.Config) bridge.Bridger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bzulip) Connect() error {
|
func (b *Bzulip) Connect() error {
|
||||||
bot := gzb.Bot{APIKey: b.GetString("token"), APIURL: b.GetString("server") + "/api/v1/", Email: b.GetString("login")}
|
bot := gzb.Bot{APIKey: b.GetString("token"), APIURL: b.GetString("server") + "/api/v1/", Email: b.GetString("login"), UserAgent: fmt.Sprintf("matterbridge/%s", version.Release)}
|
||||||
bot.Init()
|
bot.Init()
|
||||||
q, err := bot.RegisterAll()
|
q, err := bot.RegisterAll()
|
||||||
b.q = q
|
b.q = q
|
||||||
@@ -125,6 +127,7 @@ func (b *Bzulip) handleQueue() error {
|
|||||||
b.Log.Debug("heartbeat received.")
|
b.Log.Debug("heartbeat received.")
|
||||||
default:
|
default:
|
||||||
b.Log.Debugf("receiving error: %#v", err)
|
b.Log.Debugf("receiving error: %#v", err)
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
56
changelog.md
56
changelog.md
@@ -1,3 +1,57 @@
|
|||||||
|
# v1.24.0
|
||||||
|
|
||||||
|
## New features
|
||||||
|
|
||||||
|
- harmony: new protocol added: Add support for Harmony (#1656)
|
||||||
|
- irc: Allow binding to IP on IRC (#1640)
|
||||||
|
- irc: Add support for client certificate (irc) (#1710)
|
||||||
|
- mattermost: Add UseUsername option (mattermost). Fixes #1665 (#1714)
|
||||||
|
- mattermost: Add support for using ID in channel config (mattermost) (#1715)
|
||||||
|
- matrix: Reply support for Matrix (#1664)
|
||||||
|
- telegram: Add Telegram Bot Command /chatId (telegram) (#1703)
|
||||||
|
|
||||||
|
## Enhancements
|
||||||
|
|
||||||
|
- general: Update dependencies/vendor (#1659)
|
||||||
|
- discord: Add more debug options for discord (#1712)
|
||||||
|
- docker: Use Alpine stable again in Dockerfile (#1643)
|
||||||
|
- mattermost: Log eventtype in debug (mattermost) (#1676)
|
||||||
|
- mattermost: Add more ignore debug messages (mattermost) (#1678)
|
||||||
|
- slack: Add support for deleting files from slack to discord. Fixes #1705 (#1709)
|
||||||
|
- telegram: Add support for code blocks in telegram (#1650)
|
||||||
|
- telegram: Update telegram-bot-api to v5 (#1660)
|
||||||
|
- telegram: Add comments to messages (telegram) (#1652)
|
||||||
|
- telegram: Add support for sender_chat (telegram) (#1677)
|
||||||
|
- vk: Remove GroupID (vk) (#1668)
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
|
||||||
|
- mattermost: Use current parentID if rootId is not set (mattermost) (#1675)
|
||||||
|
- matrix: Make HTMLDisable work correct (matrix) (#1716)
|
||||||
|
- whatsapp: Make EditSuffix option actually work (whatsapp). Fixes #1510 (#1728)
|
||||||
|
|
||||||
|
# v1.23.2
|
||||||
|
|
||||||
|
If you're running whatsapp you should update.
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
|
||||||
|
- whatsapp: Update go-whatsapp version (#1630)
|
||||||
|
|
||||||
|
# v1.23.1
|
||||||
|
|
||||||
|
If you're running mattermost 6 you should update.
|
||||||
|
|
||||||
|
## Bugfix
|
||||||
|
|
||||||
|
- mattermost: Do not check cache on deleted messages (mattermost). Fixes #1555 (#1624)
|
||||||
|
- mattermost: Fix crash on users updating info. Update matterclient dep. Fixes #1617
|
||||||
|
- matrix: Keep the logger on a disabled bridge. Fixes #1616 (#1621)
|
||||||
|
- msteams: Fix panic in msteams. Fixes #1588 (#1622)
|
||||||
|
- xmpp: Do not fail on no avatar data (xmpp) #1529 (#1627)
|
||||||
|
- xmpp: Use a new msgID when replacing messages (xmpp). Fixes #1584 (#1623)
|
||||||
|
- zulip: Add better error handling on Zulip (#1589)
|
||||||
|
|
||||||
# v1.23.0
|
# v1.23.0
|
||||||
|
|
||||||
## New features
|
## New features
|
||||||
@@ -24,8 +78,6 @@
|
|||||||
This release couldn't exist without the following contributors:
|
This release couldn't exist without the following contributors:
|
||||||
@powerjungle, @gary-kim, @KingPin, @Benau, @keenan-v1, @tytan652, @KidA001,@minecraftchest1, @irydacea
|
@powerjungle, @gary-kim, @KingPin, @Benau, @keenan-v1, @tytan652, @KidA001,@minecraftchest1, @irydacea
|
||||||
|
|
||||||
##
|
|
||||||
|
|
||||||
# v1.22.3
|
# v1.22.3
|
||||||
|
|
||||||
## Bugfixes
|
## Bugfixes
|
||||||
|
|||||||
12
gateway/bridgemap/bharmony.go
Normal file
12
gateway/bridgemap/bharmony.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
//go:build !noharmony
|
||||||
|
// +build !noharmony
|
||||||
|
|
||||||
|
package bridgemap
|
||||||
|
|
||||||
|
import (
|
||||||
|
bharmony "github.com/42wim/matterbridge/bridge/harmony"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
FullMap["harmony"] = bharmony.New
|
||||||
|
}
|
||||||
@@ -66,7 +66,7 @@ func New(rootLogger *logrus.Logger, cfg *config.Gateway, r *Router) *Gateway {
|
|||||||
func (gw *Gateway) FindCanonicalMsgID(protocol string, mID string) string {
|
func (gw *Gateway) FindCanonicalMsgID(protocol string, mID string) string {
|
||||||
ID := protocol + " " + mID
|
ID := protocol + " " + mID
|
||||||
if gw.Messages.Contains(ID) {
|
if gw.Messages.Contains(ID) {
|
||||||
return mID
|
return ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not keyed, iterate through cache for downstream, and infer upstream.
|
// If not keyed, iterate through cache for downstream, and infer upstream.
|
||||||
@@ -75,7 +75,7 @@ func (gw *Gateway) FindCanonicalMsgID(protocol string, mID string) string {
|
|||||||
ids := v.([]*BrMsgID)
|
ids := v.([]*BrMsgID)
|
||||||
for _, downstreamMsgObj := range ids {
|
for _, downstreamMsgObj := range ids {
|
||||||
if ID == downstreamMsgObj.ID {
|
if ID == downstreamMsgObj.ID {
|
||||||
return strings.Replace(mid.(string), protocol+" ", "", 1)
|
return mid.(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -447,16 +447,19 @@ func (gw *Gateway) SendMessage(
|
|||||||
msg.Avatar = gw.modifyAvatar(rmsg, dest)
|
msg.Avatar = gw.modifyAvatar(rmsg, dest)
|
||||||
msg.Username = gw.modifyUsername(rmsg, dest)
|
msg.Username = gw.modifyUsername(rmsg, dest)
|
||||||
|
|
||||||
|
// exclude file delete event as the msg ID here is the native file ID that needs to be deleted
|
||||||
|
if msg.Event != config.EventFileDelete {
|
||||||
msg.ID = gw.getDestMsgID(rmsg.Protocol+" "+rmsg.ID, dest, channel)
|
msg.ID = gw.getDestMsgID(rmsg.Protocol+" "+rmsg.ID, dest, channel)
|
||||||
|
}
|
||||||
|
|
||||||
// for api we need originchannel as channel
|
// for api we need originchannel as channel
|
||||||
if dest.Protocol == apiProtocol {
|
if dest.Protocol == apiProtocol {
|
||||||
msg.Channel = rmsg.Channel
|
msg.Channel = rmsg.Channel
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.ParentID = gw.getDestMsgID(rmsg.Protocol+" "+canonicalParentMsgID, dest, channel)
|
msg.ParentID = gw.getDestMsgID(canonicalParentMsgID, dest, channel)
|
||||||
if msg.ParentID == "" {
|
if msg.ParentID == "" {
|
||||||
msg.ParentID = canonicalParentMsgID
|
msg.ParentID = strings.Replace(canonicalParentMsgID, dest.Protocol+" ", "", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the parentID is still empty and we have a parentID set in the original message
|
// if the parentID is still empty and we have a parentID set in the original message
|
||||||
|
|||||||
@@ -110,7 +110,9 @@ func (r *Router) disableBridge(br *bridge.Bridge, err error) bool {
|
|||||||
if r.BridgeValues().General.IgnoreFailureOnStart {
|
if r.BridgeValues().General.IgnoreFailureOnStart {
|
||||||
r.logger.Error(err)
|
r.logger.Error(err)
|
||||||
// setting this bridge empty
|
// setting this bridge empty
|
||||||
*br = bridge.Bridge{}
|
*br = bridge.Bridge{
|
||||||
|
Log: br.Log,
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
75
go.mod
75
go.mod
@@ -5,31 +5,32 @@ require (
|
|||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
||||||
github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f
|
github.com/Benau/tgsconverter v0.0.0-20210809170556-99f4a4f6337f
|
||||||
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
||||||
github.com/Rhymen/go-whatsapp v0.1.2-0.20210615184944-2b8a3e9b8aa2
|
github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c
|
||||||
github.com/SevereCloud/vksdk/v2 v2.10.0
|
github.com/SevereCloud/vksdk/v2 v2.13.1
|
||||||
github.com/d5/tengo/v2 v2.8.0
|
github.com/d5/tengo/v2 v2.10.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/fsnotify/fsnotify v1.5.1
|
github.com/fsnotify/fsnotify v1.5.1
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v1.0.1-0.20200524105306-7434b0456e81
|
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
||||||
github.com/gomarkdown/markdown v0.0.0-20210918233619-6c1113f12c4a
|
github.com/gomarkdown/markdown v0.0.0-20211207152620-5d6539fd8bfc
|
||||||
github.com/google/gops v0.3.21
|
github.com/google/gops v0.3.22
|
||||||
github.com/gorilla/schema v1.2.0
|
github.com/gorilla/schema v1.2.0
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
|
github.com/harmony-development/shibshib v0.0.0-20211127182844-512296f7c548
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
github.com/jpillora/backoff v1.0.0
|
github.com/jpillora/backoff v1.0.0
|
||||||
github.com/keybase/go-keybase-chat-bot v0.0.0-20211004153716-fd2ee4d6be11
|
github.com/keybase/go-keybase-chat-bot v0.0.0-20211201215354-ee4b23828b55
|
||||||
github.com/kyokomi/emoji/v2 v2.2.8
|
github.com/kyokomi/emoji/v2 v2.2.8
|
||||||
github.com/labstack/echo/v4 v4.6.1
|
github.com/labstack/echo/v4 v4.6.3
|
||||||
github.com/lrstanley/girc v0.0.0-20210611213246-771323f1624b
|
github.com/lrstanley/girc v0.0.0-20211023233735-147f0ff77566
|
||||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
||||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20211016222428-79310a412696
|
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20211016222428-79310a412696
|
||||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7
|
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7
|
||||||
github.com/matterbridge/go-xmpp v0.0.0-20210731150933-5702291c239f
|
github.com/matterbridge/go-xmpp v0.0.0-20211030125215-791a06c5f1be
|
||||||
github.com/matterbridge/gozulipbot v0.0.0-20200820220548-be5824faa913
|
github.com/matterbridge/gozulipbot v0.0.0-20211023205727-a19d6c1f3b75
|
||||||
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba
|
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba
|
||||||
github.com/matterbridge/matterclient v0.0.0-20211016195328-346acac403d8
|
github.com/matterbridge/matterclient v0.0.0-20211107234719-faca3cd42315
|
||||||
github.com/mattermost/mattermost-server/v5 v5.39.0
|
github.com/mattermost/mattermost-server/v5 v5.39.3
|
||||||
github.com/mattermost/mattermost-server/v6 v6.0.0
|
github.com/mattermost/mattermost-server/v6 v6.3.0
|
||||||
github.com/mattn/godown v0.0.1
|
github.com/mattn/godown v0.0.1
|
||||||
github.com/missdeer/golib v1.0.4
|
github.com/missdeer/golib v1.0.4
|
||||||
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
||||||
@@ -39,15 +40,15 @@ require (
|
|||||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||||
github.com/shazow/ssh-chat v1.10.1
|
github.com/shazow/ssh-chat v1.10.1
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/slack-go/slack v0.9.5
|
github.com/slack-go/slack v0.10.0
|
||||||
github.com/spf13/viper v1.9.0
|
github.com/spf13/viper v1.10.1
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/vincent-petithory/dataurl v0.0.0-20191104211930-d1553a71de50
|
github.com/vincent-petithory/dataurl v1.0.0
|
||||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||||
github.com/yaegashi/msgraph.go v0.1.4
|
github.com/yaegashi/msgraph.go v0.1.4
|
||||||
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
|
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
|
||||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||||
gomod.garykim.dev/nc-talk v0.3.0
|
gomod.garykim.dev/nc-talk v0.3.0
|
||||||
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
||||||
layeh.com/gumble v0.0.0-20200818122324-146f9205029b
|
layeh.com/gumble v0.0.0-20200818122324-146f9205029b
|
||||||
@@ -65,31 +66,32 @@ require (
|
|||||||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/google/uuid v1.2.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/gopackage/ddp v0.0.3 // indirect
|
github.com/gopackage/ddp v0.0.3 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.11 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/kettek/apng v0.0.0-20191108220231-414630eed80f // indirect
|
github.com/kettek/apng v0.0.0-20191108220231-414630eed80f // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.0.6 // indirect
|
github.com/klauspost/compress v1.14.2 // indirect
|
||||||
github.com/labstack/gommon v0.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||||
|
github.com/labstack/gommon v0.3.1 // indirect
|
||||||
github.com/magiconair/properties v1.8.5 // indirect
|
github.com/magiconair/properties v1.8.5 // indirect
|
||||||
github.com/mattermost/go-i18n v1.11.0 // indirect
|
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect
|
||||||
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect
|
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect
|
||||||
github.com/mattermost/logr v1.0.13 // indirect
|
github.com/mattermost/logr v1.0.13 // indirect
|
||||||
github.com/mattermost/logr/v2 v2.0.10 // indirect
|
github.com/mattermost/logr/v2 v2.0.15 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/minio/minio-go/v7 v7.0.11 // indirect
|
github.com/minio/minio-go/v7 v7.0.16 // indirect
|
||||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/monaco-io/request v1.0.5 // indirect
|
github.com/monaco-io/request v1.0.5 // indirect
|
||||||
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d // indirect
|
github.com/mreiferson/go-httpclient v0.0.0-20201222173833-5e475fde3a4d // indirect
|
||||||
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect
|
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect
|
||||||
@@ -109,28 +111,31 @@ require (
|
|||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.2.0 // indirect
|
github.com/subosito/gotenv v1.2.0 // indirect
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
|
||||||
github.com/tinylib/msgp v1.1.6 // indirect
|
github.com/tinylib/msgp v1.1.6 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.1 // indirect
|
github.com/valyala/fasttemplate v1.2.1 // indirect
|
||||||
|
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||||
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
github.com/wiggin77/cfg v1.0.2 // indirect
|
github.com/wiggin77/cfg v1.0.2 // indirect
|
||||||
github.com/wiggin77/merror v1.0.3 // indirect
|
github.com/wiggin77/merror v1.0.3 // indirect
|
||||||
github.com/wiggin77/srslog v1.0.1 // indirect
|
github.com/wiggin77/srslog v1.0.1 // indirect
|
||||||
go.uber.org/atomic v1.8.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.7.0 // indirect
|
go.uber.org/multierr v1.7.0 // indirect
|
||||||
go.uber.org/zap v1.17.0 // indirect
|
go.uber.org/zap v1.17.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect
|
||||||
golang.org/x/net v0.0.0-20210913180222-943fd674d43e // indirect
|
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
|
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/ini.v1 v1.63.2 // indirect
|
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/matrix-org/gomatrix => github.com/matterbridge/gomatrix v0.0.0-20220205235239-607eb9ee6419
|
||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Message for rocketchat outgoing webhook.
|
// Message for rocketchat outgoing webhook.
|
||||||
@@ -68,7 +69,6 @@ func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
msg := Message{}
|
msg := Message{}
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
log.Println(string(body))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
@@ -89,7 +89,11 @@ func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
msg.ChannelName = "#" + msg.ChannelName
|
msg.ChannelName = "#" + msg.ChannelName
|
||||||
if c.Token != "" {
|
if c.Token != "" {
|
||||||
if msg.Token != c.Token {
|
if msg.Token != c.Token {
|
||||||
|
if regexp.MustCompile(`[^a-zA-Z0-9]+`).MatchString(msg.Token) {
|
||||||
log.Println("invalid token " + msg.Token + " from " + r.RemoteAddr)
|
log.Println("invalid token " + msg.Token + " from " + r.RemoteAddr)
|
||||||
|
} else {
|
||||||
|
log.Println("invalid token from " + r.RemoteAddr)
|
||||||
|
}
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,13 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/gateway"
|
"github.com/42wim/matterbridge/gateway"
|
||||||
"github.com/42wim/matterbridge/gateway/bridgemap"
|
"github.com/42wim/matterbridge/gateway/bridgemap"
|
||||||
|
"github.com/42wim/matterbridge/version"
|
||||||
"github.com/google/gops/agent"
|
"github.com/google/gops/agent"
|
||||||
prefixed "github.com/matterbridge/logrus-prefixed-formatter"
|
prefixed "github.com/matterbridge/logrus-prefixed-formatter"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "1.23.0"
|
|
||||||
githash string
|
|
||||||
|
|
||||||
flagConfig = flag.String("conf", "matterbridge.toml", "config file")
|
flagConfig = flag.String("conf", "matterbridge.toml", "config file")
|
||||||
flagDebug = flag.Bool("debug", false, "enable debug")
|
flagDebug = flag.Bool("debug", false, "enable debug")
|
||||||
flagVersion = flag.Bool("version", false, "show version")
|
flagVersion = flag.Bool("version", false, "show version")
|
||||||
@@ -28,7 +26,7 @@ var (
|
|||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *flagVersion {
|
if *flagVersion {
|
||||||
fmt.Printf("version: %s %s\n", version, githash)
|
fmt.Printf("version: %s %s\n", version.Release, version.GitHash)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,8 +41,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Printf("Running version %s %s", version, githash)
|
logger.Printf("Running version %s %s", version.Release, version.GitHash)
|
||||||
if strings.Contains(version, "-dev") {
|
if strings.Contains(version.Release, "-dev") {
|
||||||
logger.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
|
logger.Println("WARNING: THIS IS A DEVELOPMENT VERSION. Things may break.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,13 @@ Password=""
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
UseTLS=false
|
UseTLS=false
|
||||||
|
|
||||||
|
#Use client certificate - see CertFP https://libera.chat/guides/certfp.html
|
||||||
|
#Specify filename which contains private key and cert
|
||||||
|
#OPTIONAL (default "")
|
||||||
|
#
|
||||||
|
#TLSClientCertificate="cert.pem"
|
||||||
|
TLSClientCertificate=""
|
||||||
|
|
||||||
#Enable SASL (PLAIN) authentication. (libera requires this from eg AWS hosts)
|
#Enable SASL (PLAIN) authentication. (libera requires this from eg AWS hosts)
|
||||||
#It uses NickServNick and NickServPassword as login and password
|
#It uses NickServNick and NickServPassword as login and password
|
||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
@@ -34,6 +41,11 @@ UseSASL=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
SkipTLSVerify=true
|
SkipTLSVerify=true
|
||||||
|
|
||||||
|
#Local address to use for server connection
|
||||||
|
#Note that Server and Bind must resolve to addresses of the same family.
|
||||||
|
#OPTIONAL (default "")
|
||||||
|
Bind=""
|
||||||
|
|
||||||
#If you know your charset, you can specify it manually.
|
#If you know your charset, you can specify it manually.
|
||||||
#Otherwise it tries to detect this automatically. Select one below
|
#Otherwise it tries to detect this automatically. Select one below
|
||||||
# "iso-8859-2:1987", "iso-8859-9:1989", "866", "latin9", "iso-8859-10:1992", "iso-ir-109", "hebrew",
|
# "iso-8859-2:1987", "iso-8859-9:1989", "866", "latin9", "iso-8859-10:1992", "iso-ir-109", "hebrew",
|
||||||
@@ -396,6 +408,10 @@ SkipTLSVerify=true
|
|||||||
## RELOADABLE SETTINGS
|
## RELOADABLE SETTINGS
|
||||||
## Settings below can be reloaded by editing the file
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
|
# UseUserName shows the username instead of the server nickname
|
||||||
|
# OPTIONAL (default false)
|
||||||
|
UseUserName=false
|
||||||
|
|
||||||
#how to format the list of IRC nicks when displayed in mattermost.
|
#how to format the list of IRC nicks when displayed in mattermost.
|
||||||
#Possible options are "table" and "plain"
|
#Possible options are "table" and "plain"
|
||||||
#OPTIONAL (default plain)
|
#OPTIONAL (default plain)
|
||||||
@@ -1534,10 +1550,6 @@ MessageClipped="<clipped message>"
|
|||||||
#See https://vk.com/dev/bots_docs
|
#See https://vk.com/dev/bots_docs
|
||||||
Token="Yourtokenhere"
|
Token="Yourtokenhere"
|
||||||
|
|
||||||
#Group ID
|
|
||||||
#For example in URL https://vk.com/public168963511 group ID is 168963511
|
|
||||||
GroupID=123456789
|
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
# WhatsApp
|
# WhatsApp
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -1655,6 +1667,18 @@ StripNick=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowTopicChange=false
|
ShowTopicChange=false
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
# Harmony
|
||||||
|
###################################################################
|
||||||
|
|
||||||
|
[harmony.chat_harmonyapp_io]
|
||||||
|
Homeserver = "https://chat.harmonyapp.io:2289"
|
||||||
|
Token = "your token goes here"
|
||||||
|
UserID = "user id of the bot account"
|
||||||
|
Community = "community id that channels will be located in"
|
||||||
|
UseUserName = true
|
||||||
|
RemoteNickFormat = "{NICK}"
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#API
|
#API
|
||||||
###################################################################
|
###################################################################
|
||||||
@@ -1700,6 +1724,7 @@ RemoteNickFormat="{NICK}"
|
|||||||
|
|
||||||
#RemoteNickFormat defines how remote users appear on this bridge
|
#RemoteNickFormat defines how remote users appear on this bridge
|
||||||
#The string "{NICK}" (case sensitive) will be replaced by the actual nick.
|
#The string "{NICK}" (case sensitive) will be replaced by the actual nick.
|
||||||
|
#The string "{NOPINGNICK}" (case sensitive) will be replaced by the actual nick / username, but with a ZWSP inside the nick, so the irc user with the same nick won't get pinged.
|
||||||
#The string "{USERID}" (case sensitive) will be replaced by the user ID.
|
#The string "{USERID}" (case sensitive) will be replaced by the user ID.
|
||||||
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
||||||
#The string "{LABEL}" (case sensitive) will be replaced by label= field of the sending bridge
|
#The string "{LABEL}" (case sensitive) will be replaced by label= field of the sending bridge
|
||||||
@@ -1872,7 +1897,8 @@ enable=true
|
|||||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||||
# irc | channel | #general | The # symbol is required and should be lowercase!
|
# irc | channel | #general | The # symbol is required and should be lowercase!
|
||||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||||
# mattermost | channel | general | This is the channel name as seen in the URL, not the display name
|
# | channel | general | This is the channel name as seen in the URL, not the display name
|
||||||
|
# mattermost | channel id | ID:oc4wifyuojgw5f3nsuweesmz8w | This is the channel ID (only use if you know what you're doing)
|
||||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||||
# matrix | #channel:server | #yourchannel:matrix.org | Encrypted rooms are not supported in matrix
|
# matrix | #channel:server | #yourchannel:matrix.org | Encrypted rooms are not supported in matrix
|
||||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -1898,7 +1924,7 @@ enable=true
|
|||||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||||
# xmpp | channel | general | The room name
|
# xmpp | channel | general | The room name
|
||||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||||
# zulip | stream/topic:topic | general/off-topic:food | Do not use the # when specifying a topic
|
# zulip | stream/topic:topic | general/topic:food | Do not use the # when specifying a topic
|
||||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1947,6 +1973,10 @@ enable=true
|
|||||||
account="zulip.streamchat"
|
account="zulip.streamchat"
|
||||||
channel="general/topic:mytopic"
|
channel="general/topic:mytopic"
|
||||||
|
|
||||||
|
[[gateway.inout]]
|
||||||
|
account="harmony.chat_harmonyapp_io"
|
||||||
|
channel="channel id goes here"
|
||||||
|
|
||||||
#API example
|
#API example
|
||||||
#[[gateway.inout]]
|
#[[gateway.inout]]
|
||||||
#account="api.local"
|
#account="api.local"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
func (m *MMClient) parseActionPost(rmsg *Message) {
|
func (m *MMClient) parseActionPost(rmsg *Message) {
|
||||||
// add post to cache, if it already exists don't relay this again.
|
// add post to cache, if it already exists don't relay this again.
|
||||||
// this should fix reposts
|
// this should fix reposts
|
||||||
if ok, _ := m.lruCache.ContainsOrAdd(digestString(rmsg.Raw.Data["post"].(string)), true); ok {
|
if ok, _ := m.lruCache.ContainsOrAdd(digestString(rmsg.Raw.Data["post"].(string)), true); ok && rmsg.Raw.Event != model.WEBSOCKET_EVENT_POST_DELETED {
|
||||||
m.logger.Debugf("message %#v in cache, not processing again", rmsg.Raw.Data["post"].(string))
|
m.logger.Debugf("message %#v in cache, not processing again", rmsg.Raw.Data["post"].(string))
|
||||||
rmsg.Text = ""
|
rmsg.Text = ""
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ RUN apk add \
|
|||||||
go \
|
go \
|
||||||
git \
|
git \
|
||||||
&& cd /go/src/matterbridge \
|
&& cd /go/src/matterbridge \
|
||||||
&& go build -mod vendor -ldflags "-X main.githash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge
|
&& CGO_ENABLED=0 go build -mod vendor -ldflags "-X github.com/42wim/matterbridge/version.GitHash=$(git log --pretty=format:'%h' -n 1)" -o /bin/matterbridge
|
||||||
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
RUN apk --no-cache add \
|
RUN apk --no-cache add \
|
||||||
|
|||||||
2
vendor/github.com/Rhymen/go-whatsapp/README.md
generated
vendored
2
vendor/github.com/Rhymen/go-whatsapp/README.md
generated
vendored
@@ -70,7 +70,7 @@ func (myHandler) HandleContactMessage(message whatsapp.ContactMessage) {
|
|||||||
fmt.Println(message)
|
fmt.Println(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (myHandler) HandleBatteryMessage(msg whatsapp.BatteryMessage) {
|
func (myHandler) HandleBatteryMessage(message whatsapp.BatteryMessage) {
|
||||||
fmt.Println(message)
|
fmt.Println(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
vendor/github.com/Rhymen/go-whatsapp/session.go
generated
vendored
4
vendor/github.com/Rhymen/go-whatsapp/session.go
generated
vendored
@@ -18,7 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//represents the WhatsAppWeb client version
|
//represents the WhatsAppWeb client version
|
||||||
var waVersion = []int{2, 2121, 6}
|
var waVersion = []int{2, 2142, 12}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Session contains session individual information. To be able to resume the connection without scanning the qr code
|
Session contains session individual information. To be able to resume the connection without scanning the qr code
|
||||||
@@ -526,5 +526,7 @@ func (wac *Conn) Logout() error {
|
|||||||
return fmt.Errorf("error writing logout: %v\n", err)
|
return fmt.Errorf("error writing logout: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wac.loggedIn = false
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
14
vendor/github.com/SevereCloud/vksdk/v2/.golangci.yml
generated
vendored
14
vendor/github.com/SevereCloud/vksdk/v2/.golangci.yml
generated
vendored
@@ -48,10 +48,18 @@ linters:
|
|||||||
- nilerr
|
- nilerr
|
||||||
- revive
|
- revive
|
||||||
- wastedassign
|
- wastedassign
|
||||||
|
- bidichk
|
||||||
|
- contextcheck
|
||||||
|
- ireturn
|
||||||
|
- nilnil
|
||||||
|
- tenv
|
||||||
|
- nestif
|
||||||
|
- grouper
|
||||||
|
- decorder
|
||||||
|
- containedctx
|
||||||
|
|
||||||
# - wrapcheck # TODO: v3 Fix
|
# - wrapcheck # TODO: v3 Fix
|
||||||
# - testpackage # TODO: Fix testpackage
|
# - testpackage # TODO: Fix testpackage
|
||||||
# - nestif # TODO: Fix nestif
|
|
||||||
# - noctx # TODO: Fix noctx
|
# - noctx # TODO: Fix noctx
|
||||||
|
|
||||||
# don't enable:
|
# don't enable:
|
||||||
@@ -75,6 +83,10 @@ linters:
|
|||||||
# - cyclop
|
# - cyclop
|
||||||
# - promlinter
|
# - promlinter
|
||||||
# - tagliatelle
|
# - tagliatelle
|
||||||
|
# - errname
|
||||||
|
# - varnamelen
|
||||||
|
# - errchkjson
|
||||||
|
# - maintidx
|
||||||
|
|
||||||
# depricated
|
# depricated
|
||||||
# - maligned
|
# - maligned
|
||||||
|
|||||||
1
vendor/github.com/SevereCloud/vksdk/v2/.markdownlint.yml
generated
vendored
1
vendor/github.com/SevereCloud/vksdk/v2/.markdownlint.yml
generated
vendored
@@ -1,2 +1,3 @@
|
|||||||
---
|
---
|
||||||
no-hard-tabs: false
|
no-hard-tabs: false
|
||||||
|
no-duplicate-heading: false
|
||||||
|
|||||||
20
vendor/github.com/SevereCloud/vksdk/v2/.travis.yml
generated
vendored
20
vendor/github.com/SevereCloud/vksdk/v2/.travis.yml
generated
vendored
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
language: go
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.cache/go-build
|
|
||||||
- $HOME/gopath/pkg/mod
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.x
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
|
||||||
- git describe --tags $(git rev-list --tags --max-count=1) --always
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -v -race -coverprofile=coverage.txt -covermode=atomic -p=1 ./...
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
4
vendor/github.com/SevereCloud/vksdk/v2/CONTRIBUTING.md
generated
vendored
4
vendor/github.com/SevereCloud/vksdk/v2/CONTRIBUTING.md
generated
vendored
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
Требования:
|
Требования:
|
||||||
|
|
||||||
- [Go 1.13+](https://golang.org/doc/install)
|
- [Go 1.16+](https://golang.org/doc/install)
|
||||||
- [golangci-lint](https://github.com/golangci/golangci-lint)
|
- [golangci-lint](https://github.com/golangci/golangci-lint)
|
||||||
- [global .gitignore](https://help.github.com/en/articles/ignoring-files#create-a-global-gitignore)
|
- [global .gitignore](https://help.github.com/en/articles/ignoring-files#create-a-global-gitignore)
|
||||||
|
|
||||||
@@ -39,6 +39,7 @@ golangci-lint run
|
|||||||
# CLIENT_SECRET=""
|
# CLIENT_SECRET=""
|
||||||
# USER_TOKEN=""
|
# USER_TOKEN=""
|
||||||
# WIDGET_TOKEN=""
|
# WIDGET_TOKEN=""
|
||||||
|
# MARUSIA_TOKEN=""
|
||||||
# CLIENT_ID="123456"
|
# CLIENT_ID="123456"
|
||||||
# GROUP_ID="123456"
|
# GROUP_ID="123456"
|
||||||
# ACCOUNT_ID="123456"
|
# ACCOUNT_ID="123456"
|
||||||
@@ -56,6 +57,7 @@ go test ./...
|
|||||||
"go.testEnvVars": {
|
"go.testEnvVars": {
|
||||||
"SERVICE_TOKEN": "",
|
"SERVICE_TOKEN": "",
|
||||||
"WIDGET_TOKEN": "",
|
"WIDGET_TOKEN": "",
|
||||||
|
"MARUSIA_TOKEN": "",
|
||||||
"GROUP_TOKEN": "",
|
"GROUP_TOKEN": "",
|
||||||
"CLIENT_SECRET": "",
|
"CLIENT_SECRET": "",
|
||||||
"USER_TOKEN": "",
|
"USER_TOKEN": "",
|
||||||
|
|||||||
8
vendor/github.com/SevereCloud/vksdk/v2/README.md
generated
vendored
8
vendor/github.com/SevereCloud/vksdk/v2/README.md
generated
vendored
@@ -1,6 +1,5 @@
|
|||||||
# VK SDK for Golang
|
# VK SDK for Golang
|
||||||
|
|
||||||
[](https://travis-ci.com/SevereCloud/vksdk)
|
|
||||||
[](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2?tab=subdirectories)
|
[](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2?tab=subdirectories)
|
||||||
[](https://vk.com/dev/)
|
[](https://vk.com/dev/)
|
||||||
[](https://codecov.io/gh/SevereCloud/vksdk)
|
[](https://codecov.io/gh/SevereCloud/vksdk)
|
||||||
@@ -17,11 +16,13 @@
|
|||||||
Version API 5.131.
|
Version API 5.131.
|
||||||
|
|
||||||
- [API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api)
|
- [API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api)
|
||||||
- 400+ methods
|
- 500+ methods
|
||||||
- Ability to change the request handler
|
|
||||||
- Ability to modify HTTP client
|
- Ability to modify HTTP client
|
||||||
- Request Limiter
|
- Request Limiter
|
||||||
|
- Support [zstd](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api#VK.EnableZstd)
|
||||||
|
and [MessagePack](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api#VK.EnableMessagePack)
|
||||||
- Token pool
|
- Token pool
|
||||||
|
- [OAuth](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api/oauth)
|
||||||
- [Callback API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/callback)
|
- [Callback API](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/callback)
|
||||||
- Tracking tool for users activity in your VK communities
|
- Tracking tool for users activity in your VK communities
|
||||||
- Supports all events
|
- Supports all events
|
||||||
@@ -61,6 +62,7 @@ go get github.com/SevereCloud/vksdk/v2@latest
|
|||||||
|
|
||||||
## Use by
|
## Use by
|
||||||
|
|
||||||
|
- A simple chat bridge: <https://github.com/42wim/matterbridge>
|
||||||
- [Joe](https://github.com/go-joe/joe) adapter: <https://github.com/tdakkota/joe-vk-adapter>
|
- [Joe](https://github.com/go-joe/joe) adapter: <https://github.com/tdakkota/joe-vk-adapter>
|
||||||
- [Logrus](https://github.com/sirupsen/logrus) hook: <https://github.com/SevereCloud/vkrus>
|
- [Logrus](https://github.com/sirupsen/logrus) hook: <https://github.com/SevereCloud/vkrus>
|
||||||
|
|
||||||
|
|||||||
50
vendor/github.com/SevereCloud/vksdk/v2/api/README.md
generated
vendored
50
vendor/github.com/SevereCloud/vksdk/v2/api/README.md
generated
vendored
@@ -3,7 +3,7 @@
|
|||||||
[](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api)
|
[](https://pkg.go.dev/github.com/SevereCloud/vksdk/v2/api)
|
||||||
[](https://vk.com/dev/first_guide)
|
[](https://vk.com/dev/first_guide)
|
||||||
|
|
||||||
Данная библиотека поддерживает версию API **5.122**.
|
Данная библиотека поддерживает версию API **5.131**.
|
||||||
|
|
||||||
## Запросы
|
## Запросы
|
||||||
|
|
||||||
@@ -80,6 +80,54 @@ if errors.As(err, &e) {
|
|||||||
|
|
||||||
Для Execute существует отдельная ошибка `ExecuteErrors`
|
Для Execute существует отдельная ошибка `ExecuteErrors`
|
||||||
|
|
||||||
|
### Поддержка MessagePack и zstd
|
||||||
|
|
||||||
|
> Результат перехода с gzip (JSON) на zstd (msgpack):
|
||||||
|
>
|
||||||
|
> - в 7 раз быстрее сжатие (–1 мкс);
|
||||||
|
> - на 10% меньше размер данных (8 Кбайт вместо 9 Кбайт);
|
||||||
|
> - продуктовый эффект не статзначимый :(
|
||||||
|
>
|
||||||
|
> [Как мы отказались от JPEG, JSON, TCP и ускорили ВКонтакте в два раза](https://habr.com/ru/company/vk/blog/594633/)
|
||||||
|
|
||||||
|
VK API способно возвращать ответ в виде [MessagePack](https://msgpack.org/).
|
||||||
|
Это эффективный формат двоичной сериализации, похожий на JSON, только быстрее
|
||||||
|
и меньше по размеру.
|
||||||
|
|
||||||
|
ВНИМАНИЕ, C MessagePack НЕКОТОРЫЕ МЕТОДЫ МОГУТ ВОЗВРАЩАТЬ
|
||||||
|
СЛОМАННУЮ КОДИРОВКУ.
|
||||||
|
|
||||||
|
Для сжатия, вместо классического gzip, можно использовать
|
||||||
|
[zstd](https://github.com/facebook/zstd). Сейчас vksdk поддерживает zstd без
|
||||||
|
словаря. Если кто знает как получать словарь,
|
||||||
|
[отпишитесь сюда](https://github.com/SevereCloud/vksdk/issues/180).
|
||||||
|
|
||||||
|
```go
|
||||||
|
vk := api.NewVK(os.Getenv("USER_TOKEN"))
|
||||||
|
|
||||||
|
method := "store.getStickersKeywords"
|
||||||
|
params := api.Params{
|
||||||
|
"aliases": true,
|
||||||
|
"all_products": true,
|
||||||
|
"need_stickers": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := vk.Request(method, params) // Content-Length: 44758
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Println("json:", len(r)) // json: 814231
|
||||||
|
|
||||||
|
vk.EnableMessagePack() // Включаем поддержку MessagePack
|
||||||
|
vk.EnableZstd() // Включаем поддержку zstd
|
||||||
|
|
||||||
|
r, err = vk.Request(method, params) // Content-Length: 35755
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
log.Println("msgpack:", len(r)) // msgpack: 650775
|
||||||
|
```
|
||||||
|
|
||||||
### Запрос любого метода
|
### Запрос любого метода
|
||||||
|
|
||||||
Пример запроса [users.get](https://vk.com/dev/users.get)
|
Пример запроса [users.get](https://vk.com/dev/users.get)
|
||||||
|
|||||||
21
vendor/github.com/SevereCloud/vksdk/v2/api/ads.go
generated
vendored
21
vendor/github.com/SevereCloud/vksdk/v2/api/ads.go
generated
vendored
@@ -1,9 +1,11 @@
|
|||||||
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/SevereCloud/vksdk/v2/object"
|
"github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AdsAddOfficeUsersItem struct.
|
// AdsAddOfficeUsersItem struct.
|
||||||
@@ -21,6 +23,23 @@ func (r *AdsAddOfficeUsersItem) UnmarshalJSON(data []byte) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack func.
|
||||||
|
func (r *AdsAddOfficeUsersItem) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if msgpack.Unmarshal(data, &r.OK) != nil {
|
||||||
|
d := msgpack.NewDecoder(bytes.NewReader(data))
|
||||||
|
d.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
return d.Decode(&r.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// AdsAddOfficeUsersResponse struct.
|
// AdsAddOfficeUsersResponse struct.
|
||||||
type AdsAddOfficeUsersResponse []AdsAddOfficeUsersItem
|
type AdsAddOfficeUsersResponse []AdsAddOfficeUsersItem
|
||||||
|
|
||||||
@@ -349,7 +368,7 @@ func (vk *VK) AdsGetAdsLayout(params Params) (response AdsGetAdsLayoutResponse,
|
|||||||
|
|
||||||
// AdsGetMusiciansResponse struct.
|
// AdsGetMusiciansResponse struct.
|
||||||
type AdsGetMusiciansResponse struct {
|
type AdsGetMusiciansResponse struct {
|
||||||
Items []object.BaseObjectWithName
|
Items []object.AdsMusician
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdsGetMusicians returns a list of musicians.
|
// AdsGetMusicians returns a list of musicians.
|
||||||
|
|||||||
90
vendor/github.com/SevereCloud/vksdk/v2/api/api.go
generated
vendored
90
vendor/github.com/SevereCloud/vksdk/v2/api/api.go
generated
vendored
@@ -7,9 +7,11 @@ package api // import "github.com/SevereCloud/vksdk/v2/api"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -21,6 +23,8 @@ import (
|
|||||||
"github.com/SevereCloud/vksdk/v2"
|
"github.com/SevereCloud/vksdk/v2"
|
||||||
"github.com/SevereCloud/vksdk/v2/internal"
|
"github.com/SevereCloud/vksdk/v2/internal"
|
||||||
"github.com/SevereCloud/vksdk/v2/object"
|
"github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
"github.com/klauspost/compress/zstd"
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Api constants.
|
// Api constants.
|
||||||
@@ -91,6 +95,9 @@ type VK struct {
|
|||||||
UserAgent string
|
UserAgent string
|
||||||
Handler func(method string, params ...Params) (Response, error)
|
Handler func(method string, params ...Params) (Response, error)
|
||||||
|
|
||||||
|
msgpack bool
|
||||||
|
zstd bool
|
||||||
|
|
||||||
mux sync.Mutex
|
mux sync.Mutex
|
||||||
lastTime time.Time
|
lastTime time.Time
|
||||||
rps int
|
rps int
|
||||||
@@ -98,7 +105,7 @@ type VK struct {
|
|||||||
|
|
||||||
// Response struct.
|
// Response struct.
|
||||||
type Response struct {
|
type Response struct {
|
||||||
Response json.RawMessage `json:"response"`
|
Response object.RawMessage `json:"response"`
|
||||||
Error Error `json:"error"`
|
Error Error `json:"error"`
|
||||||
ExecuteErrors ExecuteErrors `json:"execute_errors"`
|
ExecuteErrors ExecuteErrors `json:"execute_errors"`
|
||||||
}
|
}
|
||||||
@@ -121,7 +128,7 @@ func NewVK(tokens ...string) *VK {
|
|||||||
vk.accessTokens = tokens
|
vk.accessTokens = tokens
|
||||||
vk.Version = Version
|
vk.Version = Version
|
||||||
|
|
||||||
vk.Handler = vk.defaultHandler
|
vk.Handler = vk.DefaultHandler
|
||||||
|
|
||||||
vk.MethodURL = MethodURL
|
vk.MethodURL = MethodURL
|
||||||
vk.Client = http.DefaultClient
|
vk.Client = http.DefaultClient
|
||||||
@@ -207,8 +214,8 @@ func buildQuery(sliceParams ...Params) (context.Context, url.Values) {
|
|||||||
return ctx, query
|
return ctx, query
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultHandler provides access to VK API methods.
|
// DefaultHandler provides access to VK API methods.
|
||||||
func (vk *VK) defaultHandler(method string, sliceParams ...Params) (Response, error) {
|
func (vk *VK) DefaultHandler(method string, sliceParams ...Params) (Response, error) {
|
||||||
u := vk.MethodURL + method
|
u := vk.MethodURL + method
|
||||||
ctx, query := buildQuery(sliceParams...)
|
ctx, query := buildQuery(sliceParams...)
|
||||||
attempt := 0
|
attempt := 0
|
||||||
@@ -243,25 +250,59 @@ func (vk *VK) defaultHandler(method string, sliceParams ...Params) (Response, er
|
|||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acceptEncoding := "gzip"
|
||||||
|
if vk.zstd {
|
||||||
|
acceptEncoding = "zstd"
|
||||||
|
}
|
||||||
|
|
||||||
req.Header.Set("User-Agent", vk.UserAgent)
|
req.Header.Set("User-Agent", vk.UserAgent)
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
req.Header.Set("Accept-Encoding", acceptEncoding)
|
||||||
|
|
||||||
|
var reader io.Reader
|
||||||
|
|
||||||
resp, err := vk.Client.Do(req)
|
resp, err := vk.Client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mediatype, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
switch resp.Header.Get("Content-Encoding") {
|
||||||
if mediatype != "application/json" {
|
case "zstd":
|
||||||
_ = resp.Body.Close()
|
zstdReader, _ := zstd.NewReader(resp.Body)
|
||||||
return response, &InvalidContentType{mediatype}
|
defer zstdReader.Close()
|
||||||
|
|
||||||
|
reader = zstdReader
|
||||||
|
case "gzip":
|
||||||
|
gzipReader, _ := gzip.NewReader(resp.Body)
|
||||||
|
defer gzipReader.Close()
|
||||||
|
|
||||||
|
reader = gzipReader
|
||||||
|
default:
|
||||||
|
reader = resp.Body
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
mediatype, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||||
|
switch mediatype {
|
||||||
|
case "application/json":
|
||||||
|
err = json.NewDecoder(reader).Decode(&response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
case "application/x-msgpack":
|
||||||
|
dec := msgpack.NewDecoder(reader)
|
||||||
|
dec.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
err = dec.Decode(&response)
|
||||||
|
if err != nil {
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
return response, &InvalidContentType{mediatype}
|
||||||
|
}
|
||||||
|
|
||||||
_ = resp.Body.Close()
|
_ = resp.Body.Close()
|
||||||
|
|
||||||
@@ -291,6 +332,10 @@ func (vk *VK) Request(method string, sliceParams ...Params) ([]byte, error) {
|
|||||||
|
|
||||||
sliceParams = append(sliceParams, reqParams)
|
sliceParams = append(sliceParams, reqParams)
|
||||||
|
|
||||||
|
if vk.msgpack {
|
||||||
|
method += ".msgpack"
|
||||||
|
}
|
||||||
|
|
||||||
resp, err := vk.Handler(method, sliceParams...)
|
resp, err := vk.Handler(method, sliceParams...)
|
||||||
|
|
||||||
return resp.Response, err
|
return resp.Response, err
|
||||||
@@ -303,7 +348,32 @@ func (vk *VK) RequestUnmarshal(method string, obj interface{}, sliceParams ...Pa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.Unmarshal(rawResponse, &obj)
|
if vk.msgpack {
|
||||||
|
dec := msgpack.NewDecoder(bytes.NewReader(rawResponse))
|
||||||
|
dec.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
err = dec.Decode(&obj)
|
||||||
|
} else {
|
||||||
|
err = json.Unmarshal(rawResponse, &obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableMessagePack enable using MessagePack instead of JSON.
|
||||||
|
//
|
||||||
|
// THIS IS EXPERIMENTAL FUNCTION! Broken encoding returned in some methods.
|
||||||
|
//
|
||||||
|
// See https://msgpack.org
|
||||||
|
func (vk *VK) EnableMessagePack() {
|
||||||
|
vk.msgpack = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableZstd enable using zstd instead of gzip.
|
||||||
|
//
|
||||||
|
// This not use dict.
|
||||||
|
func (vk *VK) EnableZstd() {
|
||||||
|
vk.zstd = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func fmtReflectValue(value reflect.Value, depth int) string {
|
func fmtReflectValue(value reflect.Value, depth int) string {
|
||||||
|
|||||||
59
vendor/github.com/SevereCloud/vksdk/v2/api/auth.go
generated
vendored
59
vendor/github.com/SevereCloud/vksdk/v2/api/auth.go
generated
vendored
@@ -1,5 +1,9 @@
|
|||||||
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
)
|
||||||
|
|
||||||
// AuthCheckPhone checks a user's phone number for correctness.
|
// AuthCheckPhone checks a user's phone number for correctness.
|
||||||
//
|
//
|
||||||
// https://vk.com/dev/auth.checkPhone
|
// https://vk.com/dev/auth.checkPhone
|
||||||
@@ -24,3 +28,58 @@ func (vk *VK) AuthRestore(params Params) (response AuthRestoreResponse, err erro
|
|||||||
err = vk.RequestUnmarshal("auth.restore", &response, params)
|
err = vk.RequestUnmarshal("auth.restore", &response, params)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthGetProfileInfoBySilentTokenResponse struct.
|
||||||
|
type AuthGetProfileInfoBySilentTokenResponse struct {
|
||||||
|
Success []object.AuthSilentTokenProfile `json:"success"`
|
||||||
|
Errors []AuthSilentTokenError `json:"errors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthGetProfileInfoBySilentToken method.
|
||||||
|
//
|
||||||
|
// https://platform.vk.com/?p=DocsDashboard&docs=tokens_silent-token
|
||||||
|
func (vk *VK) AuthGetProfileInfoBySilentToken(params Params) (response AuthGetProfileInfoBySilentTokenResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("auth.getProfileInfoBySilentToken", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExchangeSilentTokenSource call conditions exchangeSilentToken.
|
||||||
|
//
|
||||||
|
// 0 Unknown
|
||||||
|
// 1 Silent authentication
|
||||||
|
// 2 Auth by login and password
|
||||||
|
// 3 Extended registration
|
||||||
|
// 4 Auth by exchange token
|
||||||
|
// 5 Auth by exchange token on reset password
|
||||||
|
// 6 Auth by exchange token on unblock
|
||||||
|
// 7 Auth by exchange token on reset session
|
||||||
|
// 8 Auth by exchange token on change password
|
||||||
|
// 9 Finish phone validation on authentication
|
||||||
|
// 10 Auth by code
|
||||||
|
// 11 Auth by external oauth
|
||||||
|
// 12 Reactivation
|
||||||
|
// 15 Auth by SDK temporary access-token
|
||||||
|
type ExchangeSilentTokenSource int
|
||||||
|
|
||||||
|
// AuthExchangeSilentAuthTokenResponse struct.
|
||||||
|
type AuthExchangeSilentAuthTokenResponse struct {
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
AccessTokenID string `json:"access_token_id"`
|
||||||
|
UserID int `json:"user_id"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
PhoneValidated interface{} `json:"phone_validated"`
|
||||||
|
IsPartial bool `json:"is_partial"`
|
||||||
|
IsService bool `json:"is_service"`
|
||||||
|
AdditionalSignupRequired bool `json:"additional_signup_required"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
Source ExchangeSilentTokenSource `json:"source"`
|
||||||
|
SourceDescription string `json:"source_description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthExchangeSilentAuthToken method.
|
||||||
|
//
|
||||||
|
// https://platform.vk.com/?p=DocsDashboard&docs=tokens_access-token
|
||||||
|
func (vk *VK) AuthExchangeSilentAuthToken(params Params) (response AuthExchangeSilentAuthTokenResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("auth.exchangeSilentAuthToken", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
82
vendor/github.com/SevereCloud/vksdk/v2/api/errors.go
generated
vendored
82
vendor/github.com/SevereCloud/vksdk/v2/api/errors.go
generated
vendored
@@ -159,6 +159,9 @@ const (
|
|||||||
ErrRateLimit ErrorType = 29
|
ErrRateLimit ErrorType = 29
|
||||||
ErrPrivateProfile ErrorType = 30 // This profile is private
|
ErrPrivateProfile ErrorType = 30 // This profile is private
|
||||||
|
|
||||||
|
// Client version deprecated.
|
||||||
|
ErrClientVersionDeprecated ErrorType = 34
|
||||||
|
|
||||||
// Method execution was interrupted due to timeout.
|
// Method execution was interrupted due to timeout.
|
||||||
ErrExecutionTimeout ErrorType = 36
|
ErrExecutionTimeout ErrorType = 36
|
||||||
|
|
||||||
@@ -177,6 +180,9 @@ const (
|
|||||||
// Additional signup required.
|
// Additional signup required.
|
||||||
ErrAdditionalSignupRequired ErrorType = 41
|
ErrAdditionalSignupRequired ErrorType = 41
|
||||||
|
|
||||||
|
// IP is not allowed.
|
||||||
|
ErrIPNotAllowed ErrorType = 42
|
||||||
|
|
||||||
// One of the parameters specified was missing or invalid
|
// One of the parameters specified was missing or invalid
|
||||||
//
|
//
|
||||||
// Check the required parameters list and their format on a method
|
// Check the required parameters list and their format on a method
|
||||||
@@ -586,6 +592,18 @@ const (
|
|||||||
// Can't send message, reply timed out.
|
// Can't send message, reply timed out.
|
||||||
ErrMessagesReplyTimedOut ErrorType = 950
|
ErrMessagesReplyTimedOut ErrorType = 950
|
||||||
|
|
||||||
|
// You can't access donut chat without subscription.
|
||||||
|
ErrMessagesAccessDonutChat ErrorType = 962
|
||||||
|
|
||||||
|
// This user can't be added to the work chat, as they aren't an employe.
|
||||||
|
ErrMessagesAccessWorkChat ErrorType = 967
|
||||||
|
|
||||||
|
// Message cannot be forwarded.
|
||||||
|
ErrMessagesCantForwarded ErrorType = 969
|
||||||
|
|
||||||
|
// Cannot pin an expiring message.
|
||||||
|
ErrMessagesPinExpiringMessage ErrorType = 970
|
||||||
|
|
||||||
// Invalid phone number.
|
// Invalid phone number.
|
||||||
ErrParamPhone ErrorType = 1000
|
ErrParamPhone ErrorType = 1000
|
||||||
|
|
||||||
@@ -598,6 +616,12 @@ const (
|
|||||||
// Processing.. Try later.
|
// Processing.. Try later.
|
||||||
ErrAuthDelay ErrorType = 1112
|
ErrAuthDelay ErrorType = 1112
|
||||||
|
|
||||||
|
// Anonymous token has expired.
|
||||||
|
ErrAnonymousTokenExpired ErrorType = 1114
|
||||||
|
|
||||||
|
// Anonymous token is invalid.
|
||||||
|
ErrAnonymousTokenInvalid ErrorType = 1116
|
||||||
|
|
||||||
// Invalid document id.
|
// Invalid document id.
|
||||||
ErrParamDocID ErrorType = 1150
|
ErrParamDocID ErrorType = 1150
|
||||||
|
|
||||||
@@ -724,6 +748,9 @@ const (
|
|||||||
// Market was already disabled in this group.
|
// Market was already disabled in this group.
|
||||||
ErrMarketAlreadyDisabled ErrorType = 1432
|
ErrMarketAlreadyDisabled ErrorType = 1432
|
||||||
|
|
||||||
|
// Main album can not be hidden.
|
||||||
|
ErrMainAlbumCantHidden ErrorType = 1446
|
||||||
|
|
||||||
// Story has already expired.
|
// Story has already expired.
|
||||||
ErrStoryExpired ErrorType = 1600
|
ErrStoryExpired ErrorType = 1600
|
||||||
|
|
||||||
@@ -783,6 +810,33 @@ const (
|
|||||||
|
|
||||||
// Can't set AliExpress tag to this type of object.
|
// Can't set AliExpress tag to this type of object.
|
||||||
ErrAliExpressTag ErrorType = 3800
|
ErrAliExpressTag ErrorType = 3800
|
||||||
|
|
||||||
|
// Invalid upload response.
|
||||||
|
ErrInvalidUploadResponse ErrorType = 5701
|
||||||
|
|
||||||
|
// Invalid upload hash.
|
||||||
|
ErrInvalidUploadHash ErrorType = 5702
|
||||||
|
|
||||||
|
// Invalid upload user.
|
||||||
|
ErrInvalidUploadUser ErrorType = 5703
|
||||||
|
|
||||||
|
// Invalid upload group.
|
||||||
|
ErrInvalidUploadGroup ErrorType = 5704
|
||||||
|
|
||||||
|
// Invalid crop data.
|
||||||
|
ErrInvalidCropData ErrorType = 5705
|
||||||
|
|
||||||
|
// To small avatar.
|
||||||
|
ErrToSmallAvatar ErrorType = 5706
|
||||||
|
|
||||||
|
// Photo not found.
|
||||||
|
ErrPhotoNotFound ErrorType = 5708
|
||||||
|
|
||||||
|
// Invalid Photo.
|
||||||
|
ErrInvalidPhoto ErrorType = 5709
|
||||||
|
|
||||||
|
// Invalid hash.
|
||||||
|
ErrInvalidHash ErrorType = 5710
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrorSubtype is the subtype of an error.
|
// ErrorSubtype is the subtype of an error.
|
||||||
@@ -946,3 +1000,31 @@ func (e AdsError) Is(target error) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthSilentTokenError struct.
|
||||||
|
type AuthSilentTokenError struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
Code ErrorType `json:"code"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns the description of a AuthSilentTokenError.
|
||||||
|
func (e AuthSilentTokenError) Error() string {
|
||||||
|
return "api: " + e.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is unwraps its first argument sequentially looking for an error that matches
|
||||||
|
// the second.
|
||||||
|
func (e AuthSilentTokenError) Is(target error) bool {
|
||||||
|
var tError *AuthSilentTokenError
|
||||||
|
if errors.As(target, &tError) {
|
||||||
|
return e.Code == tError.Code && e.Description == tError.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
var tErrorType ErrorType
|
||||||
|
if errors.As(target, &tErrorType) {
|
||||||
|
return e.Code == tErrorType
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
26
vendor/github.com/SevereCloud/vksdk/v2/api/execute.go
generated
vendored
26
vendor/github.com/SevereCloud/vksdk/v2/api/execute.go
generated
vendored
@@ -1,6 +1,11 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import "encoding/json"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
)
|
||||||
|
|
||||||
// ExecuteWithArgs a universal method for calling a sequence of other methods
|
// ExecuteWithArgs a universal method for calling a sequence of other methods
|
||||||
// while saving and filtering interim results.
|
// while saving and filtering interim results.
|
||||||
@@ -22,10 +27,23 @@ func (vk *VK) ExecuteWithArgs(code string, params Params, obj interface{}) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
resp, err := vk.Handler("execute", params, reqParams)
|
resp, err := vk.Handler("execute", params, reqParams)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
jsonErr := json.Unmarshal(resp.Response, &obj)
|
var decoderErr error
|
||||||
if jsonErr != nil {
|
|
||||||
return jsonErr
|
if vk.msgpack {
|
||||||
|
dec := msgpack.NewDecoder(bytes.NewReader(resp.Response))
|
||||||
|
dec.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
decoderErr = dec.Decode(&obj)
|
||||||
|
} else {
|
||||||
|
decoderErr = json.Unmarshal(resp.Response, &obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
if decoderErr != nil {
|
||||||
|
return decoderErr
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.ExecuteErrors != nil {
|
if resp.ExecuteErrors != nil {
|
||||||
|
|||||||
17
vendor/github.com/SevereCloud/vksdk/v2/api/market.go
generated
vendored
17
vendor/github.com/SevereCloud/vksdk/v2/api/market.go
generated
vendored
@@ -20,6 +20,7 @@ func (vk *VK) MarketAdd(params Params) (response MarketAddResponse, err error) {
|
|||||||
// MarketAddAlbumResponse struct.
|
// MarketAddAlbumResponse struct.
|
||||||
type MarketAddAlbumResponse struct {
|
type MarketAddAlbumResponse struct {
|
||||||
MarketAlbumID int `json:"market_album_id"` // Album ID
|
MarketAlbumID int `json:"market_album_id"` // Album ID
|
||||||
|
AlbumsCount int `json:"albums_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarketAddAlbum creates new collection of items.
|
// MarketAddAlbum creates new collection of items.
|
||||||
@@ -318,3 +319,19 @@ func (vk *VK) MarketSearch(params Params) (response MarketSearchResponse, err er
|
|||||||
err = vk.RequestUnmarshal("market.search", &response, params)
|
err = vk.RequestUnmarshal("market.search", &response, params)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarketSearchItemsResponse struct.
|
||||||
|
type MarketSearchItemsResponse struct {
|
||||||
|
Count int `json:"count"`
|
||||||
|
ViewType int `json:"view_type"`
|
||||||
|
Items []object.MarketMarketItem `json:"items"`
|
||||||
|
Groups []object.GroupsGroup `json:"groups,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarketSearchItems method.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/market.searchItems
|
||||||
|
func (vk *VK) MarketSearchItems(params Params) (response MarketSearchItemsResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("market.searchItems", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
103
vendor/github.com/SevereCloud/vksdk/v2/api/marusia.go
generated
vendored
Normal file
103
vendor/github.com/SevereCloud/vksdk/v2/api/marusia.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MarusiaGetPictureUploadLinkResponse struct.
|
||||||
|
type MarusiaGetPictureUploadLinkResponse struct {
|
||||||
|
PictureUploadLink string `json:"picture_upload_link"` // Link
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaGetPictureUploadLink method.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaGetPictureUploadLink(params Params) (response MarusiaGetPictureUploadLinkResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.getPictureUploadLink", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaSavePictureResponse struct.
|
||||||
|
type MarusiaSavePictureResponse struct {
|
||||||
|
AppID int `json:"app_id"`
|
||||||
|
PhotoID int `json:"photo_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaSavePicture method.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaSavePicture(params Params) (response MarusiaSavePictureResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.savePicture", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaGetPicturesResponse struct.
|
||||||
|
type MarusiaGetPicturesResponse struct {
|
||||||
|
Count int `json:"count"`
|
||||||
|
Items []object.MarusiaPicture `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaGetPictures method.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaGetPictures(params Params) (response MarusiaGetPicturesResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.getPictures", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaDeletePicture delete picture.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaDeletePicture(params Params) (response int, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.deletePicture", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaGetAudioUploadLinkResponse struct.
|
||||||
|
type MarusiaGetAudioUploadLinkResponse struct {
|
||||||
|
AudioUploadLink string `json:"audio_upload_link"` // Link
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaGetAudioUploadLink method.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaGetAudioUploadLink(params Params) (response MarusiaGetAudioUploadLinkResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.getAudioUploadLink", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaCreateAudioResponse struct.
|
||||||
|
type MarusiaCreateAudioResponse struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaCreateAudio method.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaCreateAudio(params Params) (response MarusiaCreateAudioResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.createAudio", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaGetAudiosResponse struct.
|
||||||
|
type MarusiaGetAudiosResponse struct {
|
||||||
|
Count int `json:"count"`
|
||||||
|
Audios []object.MarusiaAudio `json:"audios"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaGetAudios method.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaGetAudios(params Params) (response MarusiaGetAudiosResponse, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.getAudios", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaDeleteAudio delete audio.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) MarusiaDeleteAudio(params Params) (response int, err error) {
|
||||||
|
err = vk.RequestUnmarshal("marusia.deleteAudio", &response, params)
|
||||||
|
return
|
||||||
|
}
|
||||||
26
vendor/github.com/SevereCloud/vksdk/v2/api/messages.go
generated
vendored
26
vendor/github.com/SevereCloud/vksdk/v2/api/messages.go
generated
vendored
@@ -1,7 +1,10 @@
|
|||||||
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/SevereCloud/vksdk/v2/object"
|
"github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MessagesAddChatUser adds a new user to a chat.
|
// MessagesAddChatUser adds a new user to a chat.
|
||||||
@@ -31,11 +34,34 @@ func (vk *VK) MessagesCreateChat(params Params) (response int, err error) {
|
|||||||
// MessagesDeleteResponse struct.
|
// MessagesDeleteResponse struct.
|
||||||
type MessagesDeleteResponse map[string]int
|
type MessagesDeleteResponse map[string]int
|
||||||
|
|
||||||
|
// DecodeMsgpack funcion.
|
||||||
|
func (resp *MessagesDeleteResponse) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var respMap map[int]int
|
||||||
|
|
||||||
|
err = msgpack.Unmarshal(data, &respMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*resp = make(MessagesDeleteResponse)
|
||||||
|
for key, val := range respMap {
|
||||||
|
(*resp)[strconv.Itoa(key)] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MessagesDelete deletes one or more messages.
|
// MessagesDelete deletes one or more messages.
|
||||||
//
|
//
|
||||||
// https://vk.com/dev/messages.delete
|
// https://vk.com/dev/messages.delete
|
||||||
func (vk *VK) MessagesDelete(params Params) (response MessagesDeleteResponse, err error) {
|
func (vk *VK) MessagesDelete(params Params) (response MessagesDeleteResponse, err error) {
|
||||||
err = vk.RequestUnmarshal("messages.delete", &response, params)
|
err = vk.RequestUnmarshal("messages.delete", &response, params)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
vendor/github.com/SevereCloud/vksdk/v2/api/photos.go
generated
vendored
7
vendor/github.com/SevereCloud/vksdk/v2/api/photos.go
generated
vendored
@@ -572,9 +572,10 @@ func (vk *VK) PhotosSaveOwnerCoverPhoto(params Params) (response PhotosSaveOwner
|
|||||||
// PhotosSaveOwnerPhotoResponse struct.
|
// PhotosSaveOwnerPhotoResponse struct.
|
||||||
type PhotosSaveOwnerPhotoResponse struct {
|
type PhotosSaveOwnerPhotoResponse struct {
|
||||||
PhotoHash string `json:"photo_hash"`
|
PhotoHash string `json:"photo_hash"`
|
||||||
PhotoSrc string `json:"photo_src"`
|
// BUG(VK): returns false
|
||||||
PhotoSrcBig string `json:"photo_src_big"`
|
// PhotoSrc string `json:"photo_src"`
|
||||||
PhotoSrcSmall string `json:"photo_src_small"`
|
// PhotoSrcBig string `json:"photo_src_big"`
|
||||||
|
// PhotoSrcSmall string `json:"photo_src_small"`
|
||||||
Saved int `json:"saved"`
|
Saved int `json:"saved"`
|
||||||
PostID int `json:"post_id"`
|
PostID int `json:"post_id"`
|
||||||
}
|
}
|
||||||
|
|||||||
54
vendor/github.com/SevereCloud/vksdk/v2/api/upload.go
generated
vendored
54
vendor/github.com/SevereCloud/vksdk/v2/api/upload.go
generated
vendored
@@ -959,3 +959,57 @@ func (vk *VK) UploadGroupImage(imageType string, file io.Reader) (response objec
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UploadMarusiaPicture uploading picture.
|
||||||
|
//
|
||||||
|
// Limits: height not more than 600 px,
|
||||||
|
// aspect ratio of at least 2:1.
|
||||||
|
func (vk *VK) UploadMarusiaPicture(file io.Reader) (response MarusiaSavePictureResponse, err error) {
|
||||||
|
uploadServer, err := vk.MarusiaGetPictureUploadLink(nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyContent, err := vk.UploadFile(uploadServer.PictureUploadLink, file, "photo", "photo.jpg")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var handler object.MarusiaPictureUploadResponse
|
||||||
|
|
||||||
|
err = json.Unmarshal(bodyContent, &handler)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
photo, _ := json.Marshal(handler.Photo)
|
||||||
|
|
||||||
|
response, err = vk.MarusiaSavePicture(Params{
|
||||||
|
"server": handler.Server,
|
||||||
|
"photo": string(photo),
|
||||||
|
"hash": handler.Hash,
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadMarusiaAudio uploading audio.
|
||||||
|
//
|
||||||
|
// https://vk.com/dev/marusia_skill_docs10
|
||||||
|
func (vk *VK) UploadMarusiaAudio(file io.Reader) (response MarusiaCreateAudioResponse, err error) {
|
||||||
|
uploadServer, err := vk.MarusiaGetAudioUploadLink(nil)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyContent, err := vk.UploadFile(uploadServer.AudioUploadLink, file, "file", "audio.mp3")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err = vk.MarusiaCreateAudio(Params{
|
||||||
|
"audio_meta": string(bodyContent),
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
36
vendor/github.com/SevereCloud/vksdk/v2/api/utils.go
generated
vendored
36
vendor/github.com/SevereCloud/vksdk/v2/api/utils.go
generated
vendored
@@ -1,9 +1,8 @@
|
|||||||
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
package api // import "github.com/SevereCloud/vksdk/v2/api"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/SevereCloud/vksdk/v2/object"
|
"github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UtilsCheckLinkResponse struct.
|
// UtilsCheckLinkResponse struct.
|
||||||
@@ -89,17 +88,34 @@ func (vk *VK) UtilsGetShortLink(params Params) (response UtilsGetShortLinkRespon
|
|||||||
// UtilsResolveScreenNameResponse struct.
|
// UtilsResolveScreenNameResponse struct.
|
||||||
type UtilsResolveScreenNameResponse object.UtilsDomainResolved
|
type UtilsResolveScreenNameResponse object.UtilsDomainResolved
|
||||||
|
|
||||||
|
// UnmarshalJSON UtilsResolveScreenNameResponse.
|
||||||
|
//
|
||||||
|
// BUG(VK): UtilsResolveScreenNameResponse return [].
|
||||||
|
func (resp *UtilsResolveScreenNameResponse) UnmarshalJSON(data []byte) error {
|
||||||
|
var p object.UtilsDomainResolved
|
||||||
|
err := p.UnmarshalJSON(data)
|
||||||
|
|
||||||
|
*resp = UtilsResolveScreenNameResponse(p)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack UtilsResolveScreenNameResponse.
|
||||||
|
//
|
||||||
|
// BUG(VK): UtilsResolveScreenNameResponse return [].
|
||||||
|
func (resp *UtilsResolveScreenNameResponse) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
var p object.UtilsDomainResolved
|
||||||
|
err := p.DecodeMsgpack(dec)
|
||||||
|
|
||||||
|
*resp = UtilsResolveScreenNameResponse(p)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// UtilsResolveScreenName detects a type of object (e.g., user, community, application) and its ID by screen name.
|
// UtilsResolveScreenName detects a type of object (e.g., user, community, application) and its ID by screen name.
|
||||||
//
|
//
|
||||||
// https://vk.com/dev/utils.resolveScreenName
|
// https://vk.com/dev/utils.resolveScreenName
|
||||||
func (vk *VK) UtilsResolveScreenName(params Params) (response UtilsResolveScreenNameResponse, err error) {
|
func (vk *VK) UtilsResolveScreenName(params Params) (response UtilsResolveScreenNameResponse, err error) {
|
||||||
rawResponse, err := vk.Request("utils.resolveScreenName", params)
|
err = vk.RequestUnmarshal("utils.resolveScreenName", &response, params)
|
||||||
// Если короткое имя screen_name не занято, то будет возвращён пустой объект.
|
|
||||||
if err != nil || string(rawResponse) == "[]" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(rawResponse, &response)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/github.com/SevereCloud/vksdk/v2/doc.go
generated
vendored
2
vendor/github.com/SevereCloud/vksdk/v2/doc.go
generated
vendored
@@ -7,6 +7,6 @@ package vksdk
|
|||||||
|
|
||||||
// Module constants.
|
// Module constants.
|
||||||
const (
|
const (
|
||||||
Version = "2.10.0"
|
Version = "2.13.1"
|
||||||
API = "5.131"
|
API = "5.131"
|
||||||
)
|
)
|
||||||
|
|||||||
2
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md
generated
vendored
2
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/README.md
generated
vendored
@@ -10,7 +10,7 @@ Long Poll настраивается автоматически. Вам не т
|
|||||||
|
|
||||||
### Версия API
|
### Версия API
|
||||||
|
|
||||||
Данная библиотека поддерживает версию API **5.122**.
|
Данная библиотека поддерживает версию API **5.131**.
|
||||||
|
|
||||||
### Инициализация
|
### Инициализация
|
||||||
|
|
||||||
|
|||||||
58
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go
generated
vendored
58
vendor/github.com/SevereCloud/vksdk/v2/longpoll-bot/longpoll.go
generated
vendored
@@ -8,8 +8,11 @@ package longpoll // import "github.com/SevereCloud/vksdk/v2/longpoll-bot"
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/SevereCloud/vksdk/v2"
|
"github.com/SevereCloud/vksdk/v2"
|
||||||
"github.com/SevereCloud/vksdk/v2/api"
|
"github.com/SevereCloud/vksdk/v2/api"
|
||||||
@@ -117,7 +120,7 @@ func (lp *LongPoll) check(ctx context.Context) (response Response, err error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
response, err = parseResponse(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
@@ -127,6 +130,59 @@ func (lp *LongPoll) check(ctx context.Context) (response Response, err error) {
|
|||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseResponse(reader io.Reader) (response Response, err error) {
|
||||||
|
decoder := json.NewDecoder(reader)
|
||||||
|
for decoder.More() {
|
||||||
|
token, err := decoder.Token()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t, ok := token.(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t {
|
||||||
|
case "failed":
|
||||||
|
raw, err := decoder.Token()
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Failed = int(raw.(float64))
|
||||||
|
case "updates":
|
||||||
|
var updates []events.GroupEvent
|
||||||
|
|
||||||
|
err = decoder.Decode(&updates)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response.Updates = updates
|
||||||
|
case "ts":
|
||||||
|
// can be a number in the response with "failed" field: {"ts":8,"failed":1}
|
||||||
|
// or string, e.g. {"ts":"8","updates":[]}
|
||||||
|
rawTs, err := decoder.Token()
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ts, isNumber := rawTs.(float64); isNumber {
|
||||||
|
response.Ts = strconv.Itoa(int(ts))
|
||||||
|
} else {
|
||||||
|
response.Ts = rawTs.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
func (lp *LongPoll) checkResponse(response Response) (err error) {
|
func (lp *LongPoll) checkResponse(response Response) (err error) {
|
||||||
switch response.Failed {
|
switch response.Failed {
|
||||||
case 0:
|
case 0:
|
||||||
|
|||||||
4
vendor/github.com/SevereCloud/vksdk/v2/object/account.go
generated
vendored
4
vendor/github.com/SevereCloud/vksdk/v2/object/account.go
generated
vendored
@@ -77,6 +77,9 @@ type AccountAccountCounters struct {
|
|||||||
MenuClipsBadge int `json:"menu_clips_badge"` // New menu clips badge number
|
MenuClipsBadge int `json:"menu_clips_badge"` // New menu clips badge number
|
||||||
Videos int `json:"videos"` // New video tags number
|
Videos int `json:"videos"` // New video tags number
|
||||||
Faves int `json:"faves"` // New faves number
|
Faves int `json:"faves"` // New faves number
|
||||||
|
Calls int `json:"calls"` // New calls number
|
||||||
|
MenuSuperappFriendsBadge int `json:"menu_superapp_friends_badge"`
|
||||||
|
MenuNewClipsBadge int `json:"menu_new_clips_badge"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountInfo struct.
|
// AccountInfo struct.
|
||||||
@@ -107,6 +110,7 @@ type AccountInfo struct {
|
|||||||
IsLiveStreamingEnabled BaseBoolInt `json:"is_live_streaming_enabled"`
|
IsLiveStreamingEnabled BaseBoolInt `json:"is_live_streaming_enabled"`
|
||||||
IsNewLiveStreamingEnabled BaseBoolInt `json:"is_new_live_streaming_enabled"`
|
IsNewLiveStreamingEnabled BaseBoolInt `json:"is_new_live_streaming_enabled"`
|
||||||
LinkRedirects map[string]string `json:"link_redirects"`
|
LinkRedirects map[string]string `json:"link_redirects"`
|
||||||
|
VkPayEndpointV2 string `json:"vk_pay_endpoint_v2"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountPushSettings struct.
|
// AccountPushSettings struct.
|
||||||
|
|||||||
8
vendor/github.com/SevereCloud/vksdk/v2/object/ads.go
generated
vendored
8
vendor/github.com/SevereCloud/vksdk/v2/object/ads.go
generated
vendored
@@ -13,6 +13,7 @@ type AdsAccount struct {
|
|||||||
AccountName string `json:"account_name"`
|
AccountName string `json:"account_name"`
|
||||||
AccountStatus BaseBoolInt `json:"account_status"` // Information whether account is active
|
AccountStatus BaseBoolInt `json:"account_status"` // Information whether account is active
|
||||||
CanViewBudget BaseBoolInt `json:"can_view_budget"`
|
CanViewBudget BaseBoolInt `json:"can_view_budget"`
|
||||||
|
AdNetworkAllowedPotentially BaseBoolInt `json:"ad_network_allowed_potentially"`
|
||||||
AccountType string `json:"account_type"`
|
AccountType string `json:"account_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,3 +319,10 @@ type AdsPromotedPostReach struct {
|
|||||||
VideoViews75p int `json:"video_views_75p"` // Video views for 75 percent
|
VideoViews75p int `json:"video_views_75p"` // Video views for 75 percent
|
||||||
VideoViewsStart int `json:"video_views_start"` // Video starts
|
VideoViewsStart int `json:"video_views_start"` // Video starts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdsMusician struct.
|
||||||
|
type AdsMusician struct {
|
||||||
|
ID int `json:"id"` // Targeting music artist ID
|
||||||
|
Name string `json:"name"` // Music artist name
|
||||||
|
Avatar string `json:"avatar,omitempty"` // Music artist photo.
|
||||||
|
}
|
||||||
|
|||||||
3
vendor/github.com/SevereCloud/vksdk/v2/object/apps.go
generated
vendored
3
vendor/github.com/SevereCloud/vksdk/v2/object/apps.go
generated
vendored
@@ -60,6 +60,7 @@ type AppsApp struct {
|
|||||||
IsNew BaseBoolInt `json:"is_new"`
|
IsNew BaseBoolInt `json:"is_new"`
|
||||||
New BaseBoolInt `json:"new"`
|
New BaseBoolInt `json:"new"`
|
||||||
IsInstalled BaseBoolInt `json:"is_installed"`
|
IsInstalled BaseBoolInt `json:"is_installed"`
|
||||||
|
HasVkConnect BaseBoolInt `json:"has_vk_connect"`
|
||||||
LeaderboardType int `json:"leaderboard_type"`
|
LeaderboardType int `json:"leaderboard_type"`
|
||||||
MembersCount int `json:"members_count"` // Members number
|
MembersCount int `json:"members_count"` // Members number
|
||||||
PlatformID int `json:"platform_id"` // Application ID in store
|
PlatformID int `json:"platform_id"` // Application ID in store
|
||||||
@@ -78,7 +79,7 @@ type AppsApp struct {
|
|||||||
|
|
||||||
// mobile_controls_type = 0 - прозрачный элемент управления поверх области с игрой;
|
// mobile_controls_type = 0 - прозрачный элемент управления поверх области с игрой;
|
||||||
// mobile_controls_type = 1 - чёрная полоска над областью с игрой;
|
// mobile_controls_type = 1 - чёрная полоска над областью с игрой;
|
||||||
// mobile_controls_type = 2 - только для vk apps, без контроллов.
|
// mobile_controls_type = 2 - только для vk apps, без элементов управления'.
|
||||||
MobileControlsType int `json:"mobile_controls_type"`
|
MobileControlsType int `json:"mobile_controls_type"`
|
||||||
|
|
||||||
// mobile_view_support_type = 0 - игра не использует нижнюю часть экрана на iPhoneX, черная полоса есть.
|
// mobile_view_support_type = 0 - игра не использует нижнюю часть экрана на iPhoneX, черная полоса есть.
|
||||||
|
|||||||
17
vendor/github.com/SevereCloud/vksdk/v2/object/auth.go
generated
vendored
Normal file
17
vendor/github.com/SevereCloud/vksdk/v2/object/auth.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
|
||||||
|
// AuthSilentTokenProfile struct.
|
||||||
|
type AuthSilentTokenProfile struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
Expires int `json:"expires"`
|
||||||
|
FirstName string `json:"first_name"`
|
||||||
|
LastName string `json:"last_name"`
|
||||||
|
Photo50 string `json:"photo_50"`
|
||||||
|
Photo100 string `json:"photo_100"`
|
||||||
|
Photo200 string `json:"photo_200"`
|
||||||
|
Phone string `json:"phone"`
|
||||||
|
PhoneValidated interface{} `json:"phone_validated"` // int | bool
|
||||||
|
UserID int `json:"user_id"`
|
||||||
|
IsPartial BaseBoolInt `json:"is_partial"`
|
||||||
|
IsService BaseBoolInt `json:"is_service"`
|
||||||
|
}
|
||||||
6
vendor/github.com/SevereCloud/vksdk/v2/object/database.go
generated
vendored
6
vendor/github.com/SevereCloud/vksdk/v2/object/database.go
generated
vendored
@@ -4,9 +4,9 @@ package object // import "github.com/SevereCloud/vksdk/v2/object"
|
|||||||
type DatabaseCity struct {
|
type DatabaseCity struct {
|
||||||
ID int `json:"id"` // City ID
|
ID int `json:"id"` // City ID
|
||||||
Title string `json:"title"` // City title
|
Title string `json:"title"` // City title
|
||||||
Area string `json:"area"`
|
Area string `json:"area,omitempty"`
|
||||||
Region string `json:"region"`
|
Region string `json:"region,omitempty"`
|
||||||
Important BaseBoolInt `json:"important"`
|
Important BaseBoolInt `json:"important,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DatabaseMetroStation struct.
|
// DatabaseMetroStation struct.
|
||||||
|
|||||||
305
vendor/github.com/SevereCloud/vksdk/v2/object/groups.go
generated
vendored
305
vendor/github.com/SevereCloud/vksdk/v2/object/groups.go
generated
vendored
@@ -1,9 +1,13 @@
|
|||||||
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
"github.com/vmihailenco/msgpack/v5/msgpcode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GroupsAddress WorkInfoStatus of information about timetable.
|
// GroupsAddress WorkInfoStatus of information about timetable.
|
||||||
@@ -110,112 +114,113 @@ const (
|
|||||||
|
|
||||||
// GroupsGroup struct.
|
// GroupsGroup struct.
|
||||||
type GroupsGroup struct {
|
type GroupsGroup struct {
|
||||||
AdminLevel int `json:"admin_level"`
|
|
||||||
Deactivated string `json:"deactivated"` // Information whether community is banned
|
|
||||||
FinishDate int `json:"finish_date"` // Finish date in Unixtime format
|
|
||||||
ID int `json:"id"` // Community ID
|
ID int `json:"id"` // Community ID
|
||||||
Name string `json:"name"` // Community name
|
Name string `json:"name"` // Community name
|
||||||
Photo100 string `json:"photo_100"` // URL of square photo of the community with 100 pixels in width
|
|
||||||
Photo200 string `json:"photo_200"` // URL of square photo of the community with 200 pixels in width
|
|
||||||
Photo50 string `json:"photo_50"` // URL of square photo of the community with 50 pixels in width
|
|
||||||
ScreenName string `json:"screen_name"` // Domain of the community page
|
ScreenName string `json:"screen_name"` // Domain of the community page
|
||||||
StartDate int `json:"start_date"` // Start date in Unixtime format
|
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Market GroupsMarketInfo `json:"market"`
|
|
||||||
MemberStatus int `json:"member_status"` // Current user's member status
|
|
||||||
IsClosed int `json:"is_closed"`
|
IsClosed int `json:"is_closed"`
|
||||||
City BaseObject `json:"city"`
|
AdminLevel int `json:"admin_level,omitempty"`
|
||||||
Country BaseCountry `json:"country"`
|
Deactivated string `json:"deactivated,omitempty"` // Information whether community is banned
|
||||||
|
FinishDate int `json:"finish_date,omitempty"` // Finish date in Unixtime format
|
||||||
|
Photo100 string `json:"photo_100,omitempty"` // URL of square photo of the community with 100 pixels in width
|
||||||
|
Photo200 string `json:"photo_200,omitempty"` // URL of square photo of the community with 200 pixels in width
|
||||||
|
Photo50 string `json:"photo_50,omitempty"` // URL of square photo of the community with 50 pixels in width
|
||||||
|
StartDate int `json:"start_date,omitempty"` // Start date in Unixtime format
|
||||||
|
Market GroupsMarketInfo `json:"market,omitempty"`
|
||||||
|
MemberStatus int `json:"member_status,omitempty"` // Current user's member status
|
||||||
|
City BaseObject `json:"city,omitempty"`
|
||||||
|
Country BaseCountry `json:"country,omitempty"`
|
||||||
|
|
||||||
// Information whether current user is administrator.
|
// Information whether current user is administrator.
|
||||||
IsAdmin BaseBoolInt `json:"is_admin"`
|
IsAdmin BaseBoolInt `json:"is_admin"`
|
||||||
|
|
||||||
// Information whether current user is advertiser.
|
// Information whether current user is advertiser.
|
||||||
IsAdvertiser BaseBoolInt `json:"is_advertiser"`
|
IsAdvertiser BaseBoolInt `json:"is_advertiser,omitempty"`
|
||||||
|
|
||||||
// Information whether current user is member.
|
// Information whether current user is member.
|
||||||
IsMember BaseBoolInt `json:"is_member"`
|
IsMember BaseBoolInt `json:"is_member,omitempty"`
|
||||||
|
|
||||||
// Information whether community is in faves.
|
// Information whether community is in faves.
|
||||||
IsFavorite BaseBoolInt `json:"is_favorite"`
|
IsFavorite BaseBoolInt `json:"is_favorite,omitempty"`
|
||||||
|
|
||||||
// Information whether community is adult.
|
// Information whether community is adult.
|
||||||
IsAdult BaseBoolInt `json:"is_adult"`
|
IsAdult BaseBoolInt `json:"is_adult,omitempty"`
|
||||||
|
|
||||||
// Information whether current user is subscribed.
|
// Information whether current user is subscribed.
|
||||||
IsSubscribed BaseBoolInt `json:"is_subscribed"`
|
IsSubscribed BaseBoolInt `json:"is_subscribed,omitempty"`
|
||||||
|
|
||||||
// Information whether current user can post on community's wall.
|
// Information whether current user can post on community's wall.
|
||||||
CanPost BaseBoolInt `json:"can_post"`
|
CanPost BaseBoolInt `json:"can_post,omitempty"`
|
||||||
|
|
||||||
// Information whether current user can see all posts on community's wall.
|
// Information whether current user can see all posts on community's wall.
|
||||||
CanSeeAllPosts BaseBoolInt `json:"can_see_all_posts"`
|
CanSeeAllPosts BaseBoolInt `json:"can_see_all_posts,omitempty"`
|
||||||
|
|
||||||
// Information whether current user can create topic.
|
// Information whether current user can create topic.
|
||||||
CanCreateTopic BaseBoolInt `json:"can_create_topic"`
|
CanCreateTopic BaseBoolInt `json:"can_create_topic,omitempty"`
|
||||||
|
|
||||||
// Information whether current user can upload video.
|
// Information whether current user can upload video.
|
||||||
CanUploadVideo BaseBoolInt `json:"can_upload_video"`
|
CanUploadVideo BaseBoolInt `json:"can_upload_video,omitempty"`
|
||||||
|
|
||||||
// Information whether current user can upload doc.
|
// Information whether current user can upload doc.
|
||||||
CanUploadDoc BaseBoolInt `json:"can_upload_doc"`
|
CanUploadDoc BaseBoolInt `json:"can_upload_doc,omitempty"`
|
||||||
|
|
||||||
// Information whether community has photo.
|
// Information whether community has photo.
|
||||||
HasPhoto BaseBoolInt `json:"has_photo"`
|
HasPhoto BaseBoolInt `json:"has_photo,omitempty"`
|
||||||
|
|
||||||
// Information whether current user can send a message to community.
|
// Information whether current user can send a message to community.
|
||||||
CanMessage BaseBoolInt `json:"can_message"`
|
CanMessage BaseBoolInt `json:"can_message,omitempty"`
|
||||||
|
|
||||||
// Information whether community can send a message to current user.
|
// Information whether community can send a message to current user.
|
||||||
IsMessagesBlocked BaseBoolInt `json:"is_messages_blocked"`
|
IsMessagesBlocked BaseBoolInt `json:"is_messages_blocked,omitempty"`
|
||||||
|
|
||||||
// Information whether community can send notifications by phone number to current user.
|
// Information whether community can send notifications by phone number to current user.
|
||||||
CanSendNotify BaseBoolInt `json:"can_send_notify"`
|
CanSendNotify BaseBoolInt `json:"can_send_notify,omitempty"`
|
||||||
|
|
||||||
// Information whether current user is subscribed to podcasts.
|
// Information whether current user is subscribed to podcasts.
|
||||||
IsSubscribedPodcasts BaseBoolInt `json:"is_subscribed_podcasts"`
|
IsSubscribedPodcasts BaseBoolInt `json:"is_subscribed_podcasts,omitempty"`
|
||||||
|
|
||||||
// Owner in whitelist or not.
|
// Owner in whitelist or not.
|
||||||
CanSubscribePodcasts BaseBoolInt `json:"can_subscribe_podcasts"`
|
CanSubscribePodcasts BaseBoolInt `json:"can_subscribe_podcasts,omitempty"`
|
||||||
|
|
||||||
// Can subscribe to wall.
|
// Can subscribe to wall.
|
||||||
CanSubscribePosts BaseBoolInt `json:"can_subscribe_posts"`
|
CanSubscribePosts BaseBoolInt `json:"can_subscribe_posts,omitempty"`
|
||||||
|
|
||||||
// Information whether community has market app.
|
// Information whether community has market app.
|
||||||
HasMarketApp BaseBoolInt `json:"has_market_app"`
|
HasMarketApp BaseBoolInt `json:"has_market_app,omitempty"`
|
||||||
IsHiddenFromFeed BaseBoolInt `json:"is_hidden_from_feed"`
|
IsHiddenFromFeed BaseBoolInt `json:"is_hidden_from_feed,omitempty"`
|
||||||
IsMarketCartEnabled BaseBoolInt `json:"is_market_cart_enabled"`
|
IsMarketCartEnabled BaseBoolInt `json:"is_market_cart_enabled,omitempty"`
|
||||||
Verified BaseBoolInt `json:"verified"` // Information whether community is verified
|
Verified BaseBoolInt `json:"verified,omitempty"` // Information whether community is verified
|
||||||
|
|
||||||
// Information whether the community has a fire pictogram.
|
// Information whether the community has a fire pictogram.
|
||||||
Trending BaseBoolInt `json:"trending"`
|
Trending BaseBoolInt `json:"trending,omitempty"`
|
||||||
Description string `json:"description"` // Community description
|
Description string `json:"description,omitempty"` // Community description
|
||||||
WikiPage string `json:"wiki_page"` // Community's main wiki page title
|
WikiPage string `json:"wiki_page,omitempty"` // Community's main wiki page title
|
||||||
MembersCount int `json:"members_count"` // Community members number
|
MembersCount int `json:"members_count,omitempty"` // Community members number
|
||||||
Counters GroupsCountersGroup `json:"counters"`
|
Counters GroupsCountersGroup `json:"counters,omitempty"`
|
||||||
Cover GroupsCover `json:"cover"`
|
Cover GroupsCover `json:"cover,omitempty"`
|
||||||
|
|
||||||
// Type of group, start date of event or category of public page.
|
// Type of group, start date of event or category of public page.
|
||||||
Activity string `json:"activity"`
|
Activity string `json:"activity,omitempty"`
|
||||||
FixedPost int `json:"fixed_post"` // Fixed post ID
|
FixedPost int `json:"fixed_post,omitempty"` // Fixed post ID
|
||||||
Status string `json:"status"` // Community status
|
Status string `json:"status,omitempty"` // Community status
|
||||||
MainAlbumID int `json:"main_album_id"` // Community's main photo album ID
|
MainAlbumID int `json:"main_album_id,omitempty"` // Community's main photo album ID
|
||||||
Links []GroupsLinksItem `json:"links"`
|
Links []GroupsLinksItem `json:"links,omitempty"`
|
||||||
Contacts []GroupsContactsItem `json:"contacts"`
|
Contacts []GroupsContactsItem `json:"contacts,omitempty"`
|
||||||
Site string `json:"site"` // Community's website
|
Site string `json:"site,omitempty"` // Community's website
|
||||||
MainSection int `json:"main_section"`
|
MainSection int `json:"main_section,omitempty"`
|
||||||
OnlineStatus GroupsOnlineStatus `json:"online_status"` // Status of replies in community messages
|
OnlineStatus GroupsOnlineStatus `json:"online_status,omitempty"` // Status of replies in community messages
|
||||||
AgeLimits int `json:"age_limits"` // Information whether age limit
|
AgeLimits int `json:"age_limits,omitempty"` // Information whether age limit
|
||||||
BanInfo GroupsGroupBanInfo `json:"ban_info"` // User ban info
|
BanInfo GroupsGroupBanInfo `json:"ban_info,omitempty"` // User ban info
|
||||||
Addresses GroupsAddressesInfo `json:"addresses"` // Info about addresses in Groups
|
Addresses GroupsAddressesInfo `json:"addresses,omitempty"` // Info about addresses in Groups
|
||||||
LiveCovers GroupsLiveCovers `json:"live_covers"`
|
LiveCovers GroupsLiveCovers `json:"live_covers,omitempty"`
|
||||||
CropPhoto UsersCropPhoto `json:"crop_photo"`
|
CropPhoto UsersCropPhoto `json:"crop_photo,omitempty"`
|
||||||
Wall int `json:"wall"`
|
Wall int `json:"wall,omitempty"`
|
||||||
ActionButton GroupsActionButton `json:"action_button"`
|
ActionButton GroupsActionButton `json:"action_button,omitempty"`
|
||||||
TrackCode string `json:"track_code"`
|
TrackCode string `json:"track_code,omitempty"`
|
||||||
PublicDateLabel string `json:"public_date_label"`
|
PublicDateLabel string `json:"public_date_label,omitempty"`
|
||||||
AuthorID int `json:"author_id"`
|
AuthorID int `json:"author_id,omitempty"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone,omitempty"`
|
||||||
|
Like GroupsGroupLike `json:"like"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToMention return mention.
|
// ToMention return mention.
|
||||||
@@ -223,6 +228,18 @@ func (group GroupsGroup) ToMention() string {
|
|||||||
return fmt.Sprintf("[club%d|%s]", group.ID, group.Name)
|
return fmt.Sprintf("[club%d|%s]", group.ID, group.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GroupsGroupLike struct.
|
||||||
|
type GroupsGroupLike struct {
|
||||||
|
IsLiked BaseBoolInt `json:"is_liked"`
|
||||||
|
Friends GroupsGroupLikeFriends `json:"friends"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsGroupLikeFriends struct.
|
||||||
|
type GroupsGroupLikeFriends struct {
|
||||||
|
Count int `json:"count"`
|
||||||
|
Preview []int `json:"preview"`
|
||||||
|
}
|
||||||
|
|
||||||
// GroupsLiveCovers struct.
|
// GroupsLiveCovers struct.
|
||||||
type GroupsLiveCovers struct {
|
type GroupsLiveCovers struct {
|
||||||
IsEnabled BaseBoolInt `json:"is_enabled"`
|
IsEnabled BaseBoolInt `json:"is_enabled"`
|
||||||
@@ -285,6 +302,60 @@ type GroupsCountersGroup struct {
|
|||||||
Topics int `json:"topics"` // Topics number
|
Topics int `json:"topics"` // Topics number
|
||||||
Videos int `json:"videos"` // Videos number
|
Videos int `json:"videos"` // Videos number
|
||||||
Narratives int `json:"narratives"` // Narratives number
|
Narratives int `json:"narratives"` // Narratives number
|
||||||
|
Clips int `json:"clips"` // Clips number
|
||||||
|
ClipsFollowers int `json:"clips_followers"` // Clips followers number
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON GroupsCountersGroup.
|
||||||
|
//
|
||||||
|
// BUG(VK): GroupsCountersGroup return [].
|
||||||
|
func (personal *GroupsCountersGroup) UnmarshalJSON(data []byte) error {
|
||||||
|
if bytes.Equal(data, []byte("[]")) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type renamedGroupsCountersGroup GroupsCountersGroup
|
||||||
|
|
||||||
|
var r renamedGroupsCountersGroup
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, &r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*personal = GroupsCountersGroup(r)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack GroupsCountersGroup.
|
||||||
|
//
|
||||||
|
// BUG(VK): GroupsCountersGroup return [].
|
||||||
|
func (personal *GroupsCountersGroup) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(data, []byte{msgpcode.FixedArrayLow}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type renamedGroupsCountersGroup GroupsCountersGroup
|
||||||
|
|
||||||
|
var r renamedGroupsCountersGroup
|
||||||
|
|
||||||
|
d := msgpack.NewDecoder(bytes.NewReader(data))
|
||||||
|
d.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
err = d.Decode(&r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*personal = GroupsCountersGroup(r)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupsCover struct.
|
// GroupsCover struct.
|
||||||
@@ -479,6 +550,70 @@ type GroupsGroupSettings struct {
|
|||||||
SecondarySection int `json:"secondary_section"`
|
SecondarySection int `json:"secondary_section"`
|
||||||
ActionButton GroupsActionButton `json:"action_button"`
|
ActionButton GroupsActionButton `json:"action_button"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
|
|
||||||
|
RecognizePhoto int `json:"recognize_photo"`
|
||||||
|
|
||||||
|
MarketServices GroupsMarketServices `json:"market_services"`
|
||||||
|
Narratives int `json:"narratives"`
|
||||||
|
Clips int `json:"clips"`
|
||||||
|
Textlives int `json:"textlives"`
|
||||||
|
Youla GroupsYoula `json:"youla"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsMarketServices struct.
|
||||||
|
type GroupsMarketServices struct {
|
||||||
|
Enabled BaseBoolInt `json:"enabled"`
|
||||||
|
CanMessage BaseBoolInt `json:"can_message"`
|
||||||
|
CommentsEnabled BaseBoolInt `json:"comments_enabled"`
|
||||||
|
ContactID int `json:"contact_id"`
|
||||||
|
Currency MarketCurrency `json:"currency"`
|
||||||
|
ViewType GroupsSelectedItems `json:"view_type"`
|
||||||
|
BlockName GroupsSelectedItems `json:"block_name"`
|
||||||
|
ButtonLabel GroupsSelectedItems `json:"button_label"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsSelectedItems struct.
|
||||||
|
type GroupsSelectedItems struct {
|
||||||
|
SelectedItemID int64 `json:"selected_item_id"`
|
||||||
|
Items []BaseObjectWithName `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsYoula struct.
|
||||||
|
type GroupsYoula struct {
|
||||||
|
CategoryTree GroupsYoulaCategory `json:"category_tree"`
|
||||||
|
GroupSettings GroupsYoulaSettings `json:"group_settings"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsYoulaCategory struct.
|
||||||
|
type GroupsYoulaCategory struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Subcategories []GroupsYoulaSubcategory `json:"subcategories"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsYoulaSubcategory struct.
|
||||||
|
type GroupsYoulaSubcategory struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
ParentID int `json:"parent_id"`
|
||||||
|
Subcategories []GroupsYoulaSubcategory `json:"subcategories"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GroupsYoulaSettings struct.
|
||||||
|
type GroupsYoulaSettings struct {
|
||||||
|
IsActive BaseBoolInt `json:"is_active"`
|
||||||
|
IsModerated BaseBoolInt `json:"is_moderated"`
|
||||||
|
ShowModerationSetting BaseBoolInt `json:"show_moderation_setting"`
|
||||||
|
ModerationStatus int `json:"moderation_status"`
|
||||||
|
DeclineReason string `json:"decline_reason"`
|
||||||
|
GroupMode int `json:"group_mode"`
|
||||||
|
SelectedCategoryIDS []int `json:"selected_category_ids"`
|
||||||
|
Lat float64 `json:"lat"`
|
||||||
|
Long float64 `json:"long"`
|
||||||
|
Radius float64 `json:"radius"`
|
||||||
|
RadiusArea string `json:"radius_area"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Radiuses []float64 `json:"radiuses"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupsSectionsList struct.
|
// GroupsSectionsList struct.
|
||||||
@@ -532,6 +667,53 @@ func (g *GroupsSectionsList) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack need for decode dynamic array (Example: [1, "Фотографии"]) to struct.
|
||||||
|
func (g *GroupsSectionsList) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var alias []interface{}
|
||||||
|
|
||||||
|
err = msgpack.Unmarshal(data, &alias)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(alias) != 2 {
|
||||||
|
return &json.UnmarshalTypeError{
|
||||||
|
Value: string(data),
|
||||||
|
Type: reflect.TypeOf((*GroupsSectionsList)(nil)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id, ok := alias[0].(int8)
|
||||||
|
if !ok {
|
||||||
|
return &json.UnmarshalTypeError{
|
||||||
|
Value: string(data),
|
||||||
|
Type: reflect.TypeOf((*GroupsSectionsList)(nil)),
|
||||||
|
Struct: "GroupsSectionsList",
|
||||||
|
Field: "ID",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name, ok := alias[1].(string)
|
||||||
|
if !ok {
|
||||||
|
return &json.UnmarshalTypeError{
|
||||||
|
Value: string(data),
|
||||||
|
Type: reflect.TypeOf((*GroupsSectionsList)(nil)),
|
||||||
|
Struct: "GroupsSectionsList",
|
||||||
|
Field: "Name",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g.ID = int(id)
|
||||||
|
g.Name = name
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GroupsActionType for action_button in groups.
|
// GroupsActionType for action_button in groups.
|
||||||
type GroupsActionType string
|
type GroupsActionType string
|
||||||
|
|
||||||
@@ -685,7 +867,10 @@ type GroupsLongPollServer struct {
|
|||||||
Ts string `json:"ts"` // Number of the last event
|
Ts string `json:"ts"` // Number of the last event
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: func (g GroupsLongPollServer) GetURL() string {
|
// GetURL return link.
|
||||||
|
func (lp GroupsLongPollServer) GetURL(wait int) string {
|
||||||
|
return fmt.Sprintf("%s?act=a_check&key=%s&ts=%s&wait=%d", lp.Server, lp.Key, lp.Ts, wait)
|
||||||
|
}
|
||||||
|
|
||||||
// GroupsLongPollSettings struct.
|
// GroupsLongPollSettings struct.
|
||||||
type GroupsLongPollSettings struct {
|
type GroupsLongPollSettings struct {
|
||||||
@@ -714,12 +899,14 @@ type GroupsMarketInfo struct {
|
|||||||
Enabled BaseBoolInt `json:"enabled"` // Information whether the market is enabled
|
Enabled BaseBoolInt `json:"enabled"` // Information whether the market is enabled
|
||||||
CommentsEnabled BaseBoolInt `json:"comments_enabled,omitempty"`
|
CommentsEnabled BaseBoolInt `json:"comments_enabled,omitempty"`
|
||||||
CanMessage BaseBoolInt `json:"can_message,omitempty"`
|
CanMessage BaseBoolInt `json:"can_message,omitempty"`
|
||||||
|
IsHsEnabled BaseBoolInt `json:"is_hs_enabled,omitempty"`
|
||||||
MainAlbumID int `json:"main_album_id,omitempty"` // Main market album ID
|
MainAlbumID int `json:"main_album_id,omitempty"` // Main market album ID
|
||||||
PriceMax string `json:"price_max,omitempty"` // Maximum price
|
PriceMax string `json:"price_max,omitempty"` // Maximum price
|
||||||
PriceMin string `json:"price_min,omitempty"` // Minimum price
|
PriceMin string `json:"price_min,omitempty"` // Minimum price
|
||||||
Wiki PagesWikipageFull `json:"wiki,omitempty"`
|
Wiki PagesWikipageFull `json:"wiki,omitempty"`
|
||||||
CityIDs []int `json:"city_ids"`
|
CityIDs []int `json:"city_ids"`
|
||||||
CountryIDs []int `json:"country_ids,omitempty"`
|
CountryIDs []int `json:"country_ids,omitempty"`
|
||||||
|
MinOrderPrice MarketPrice `json:"min_order_price,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupsGroupRole Role type.
|
// GroupsGroupRole Role type.
|
||||||
|
|||||||
65
vendor/github.com/SevereCloud/vksdk/v2/object/market.go
generated
vendored
65
vendor/github.com/SevereCloud/vksdk/v2/object/market.go
generated
vendored
@@ -4,6 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
"github.com/vmihailenco/msgpack/v5/msgpcode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Information whether the MarketMarketItem is available.
|
// Information whether the MarketMarketItem is available.
|
||||||
@@ -28,6 +31,8 @@ type MarketMarketAlbum struct {
|
|||||||
Photo PhotosPhoto `json:"photo"`
|
Photo PhotosPhoto `json:"photo"`
|
||||||
Title string `json:"title"` // Market album title
|
Title string `json:"title"` // Market album title
|
||||||
UpdatedTime int `json:"updated_time"` // Date when album has been updated last time in Unixtime
|
UpdatedTime int `json:"updated_time"` // Date when album has been updated last time in Unixtime
|
||||||
|
IsMain BaseBoolInt `json:"is_main"`
|
||||||
|
IsHidden BaseBoolInt `json:"is_hidden"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToAttachment return attachment format.
|
// ToAttachment return attachment format.
|
||||||
@@ -98,6 +103,36 @@ func (market *MarketMarketItem) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack MarketMarketItem.
|
||||||
|
//
|
||||||
|
// BUG(VK): https://github.com/SevereCloud/vksdk/issues/147
|
||||||
|
func (market *MarketMarketItem) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(data, []byte{msgpcode.False}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type renamedMarketMarketItem MarketMarketItem
|
||||||
|
|
||||||
|
var r renamedMarketMarketItem
|
||||||
|
|
||||||
|
d := msgpack.NewDecoder(bytes.NewReader(data))
|
||||||
|
d.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
err = d.Decode(&r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*market = MarketMarketItem(r)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarketMarketItemProperty struct.
|
// MarketMarketItemProperty struct.
|
||||||
type MarketMarketItemProperty struct {
|
type MarketMarketItemProperty struct {
|
||||||
VariantID int `json:"variant_id"`
|
VariantID int `json:"variant_id"`
|
||||||
@@ -149,6 +184,36 @@ func (m *MarketPrice) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack MarketPrice.
|
||||||
|
//
|
||||||
|
// BUG(VK): unavailable product, in fave.get return [].
|
||||||
|
func (m *MarketPrice) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(data, []byte{msgpcode.FixedArrayLow}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type renamedMarketPrice MarketPrice
|
||||||
|
|
||||||
|
var r renamedMarketPrice
|
||||||
|
|
||||||
|
d := msgpack.NewDecoder(bytes.NewReader(data))
|
||||||
|
d.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
err = d.Decode(&r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*m = MarketPrice(r)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarketSection struct.
|
// MarketSection struct.
|
||||||
type MarketSection struct {
|
type MarketSection struct {
|
||||||
ID int `json:"id"` // Section ID
|
ID int `json:"id"` // Section ID
|
||||||
|
|||||||
52
vendor/github.com/SevereCloud/vksdk/v2/object/marusia.go
generated
vendored
Normal file
52
vendor/github.com/SevereCloud/vksdk/v2/object/marusia.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MarusiaPicture struct.
|
||||||
|
type MarusiaPicture struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
OwnerID int `json:"owner_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaPictureUploadResponse struct.
|
||||||
|
type MarusiaPictureUploadResponse struct {
|
||||||
|
Hash string `json:"hash"` // Uploading hash
|
||||||
|
Photo json.RawMessage `json:"photo"` // Uploaded photo data
|
||||||
|
Server int `json:"server"` // Upload server number
|
||||||
|
AID int `json:"aid"`
|
||||||
|
MessageCode int `json:"message_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaAudio struct.
|
||||||
|
type MarusiaAudio struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
OwnerID int `json:"owner_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaAudioUploadResponse struct.
|
||||||
|
type MarusiaAudioUploadResponse struct {
|
||||||
|
Sha string `json:"sha"`
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
Meta MarusiaAudioMeta `json:"meta"`
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
Server string `json:"server"`
|
||||||
|
UserID int `json:"user_id"`
|
||||||
|
RequestID string `json:"request_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarusiaAudioMeta struct.
|
||||||
|
type MarusiaAudioMeta struct {
|
||||||
|
Album string `json:"album"`
|
||||||
|
Artist string `json:"artist"`
|
||||||
|
Bitrate string `json:"bitrate"`
|
||||||
|
Duration string `json:"duration"`
|
||||||
|
Genre string `json:"genre"`
|
||||||
|
Kad string `json:"kad"`
|
||||||
|
Md5 string `json:"md5"`
|
||||||
|
Md5DataSize string `json:"md5_data_size"`
|
||||||
|
Samplerate string `json:"samplerate"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
}
|
||||||
27
vendor/github.com/SevereCloud/vksdk/v2/object/messages.go
generated
vendored
27
vendor/github.com/SevereCloud/vksdk/v2/object/messages.go
generated
vendored
@@ -79,6 +79,7 @@ type MessagesMessage struct {
|
|||||||
UpdateTime int `json:"update_time"` // Date when the message has been updated in Unixtime
|
UpdateTime int `json:"update_time"` // Date when the message has been updated in Unixtime
|
||||||
MembersCount int `json:"members_count"` // Members number
|
MembersCount int `json:"members_count"` // Members number
|
||||||
ExpireTTL int `json:"expire_ttl"`
|
ExpireTTL int `json:"expire_ttl"`
|
||||||
|
MessageTag string `json:"message_tag"` // for https://notify.mail.ru/
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessagesBasePayload struct.
|
// MessagesBasePayload struct.
|
||||||
@@ -375,17 +376,18 @@ type MessagesTemplateElement struct {
|
|||||||
|
|
||||||
// MessagesTemplateElementCarousel struct.
|
// MessagesTemplateElementCarousel struct.
|
||||||
type MessagesTemplateElementCarousel struct {
|
type MessagesTemplateElementCarousel struct {
|
||||||
Title string `json:"title"`
|
Title string `json:"title,omitempty"`
|
||||||
Action MessagesTemplateElementCarouselAction `json:"action"`
|
Action MessagesTemplateElementCarouselAction `json:"action,omitempty"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description,omitempty"`
|
||||||
Photo PhotosPhoto `json:"photo"`
|
Photo *PhotosPhoto `json:"photo,omitempty"` // Only read
|
||||||
Buttons []MessagesKeyboardButton `json:"buttons"`
|
PhotoID string `json:"photo_id,omitempty"` // Only for send
|
||||||
|
Buttons []MessagesKeyboardButton `json:"buttons,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessagesTemplateElementCarouselAction struct.
|
// MessagesTemplateElementCarouselAction struct.
|
||||||
type MessagesTemplateElementCarouselAction struct {
|
type MessagesTemplateElementCarouselAction struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Link string `json:"link"`
|
Link string `json:"link,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessageContentSourceMessage ...
|
// MessageContentSourceMessage ...
|
||||||
@@ -443,6 +445,7 @@ type MessagesChat struct {
|
|||||||
AdminID int `json:"admin_id"` // Chat creator ID
|
AdminID int `json:"admin_id"` // Chat creator ID
|
||||||
ID int `json:"id"` // Chat ID
|
ID int `json:"id"` // Chat ID
|
||||||
IsDefaultPhoto BaseBoolInt `json:"is_default_photo"`
|
IsDefaultPhoto BaseBoolInt `json:"is_default_photo"`
|
||||||
|
IsGroupChannel BaseBoolInt `json:"is_group_channel"`
|
||||||
Photo100 string `json:"photo_100"` // URL of the preview image with 100 px in width
|
Photo100 string `json:"photo_100"` // URL of the preview image with 100 px in width
|
||||||
Photo200 string `json:"photo_200"` // URL of the preview image with 200 px in width
|
Photo200 string `json:"photo_200"` // URL of the preview image with 200 px in width
|
||||||
Photo50 string `json:"photo_50"` // URL of the preview image with 50 px in width
|
Photo50 string `json:"photo_50"` // URL of the preview image with 50 px in width
|
||||||
@@ -477,6 +480,7 @@ type MessagesChatSettingsPhoto struct {
|
|||||||
Photo200 string `json:"photo_200"`
|
Photo200 string `json:"photo_200"`
|
||||||
Photo50 string `json:"photo_50"`
|
Photo50 string `json:"photo_50"`
|
||||||
IsDefaultPhoto BaseBoolInt `json:"is_default_photo"`
|
IsDefaultPhoto BaseBoolInt `json:"is_default_photo"`
|
||||||
|
IsDefaultCallPhoto bool `json:"is_default_call_photo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessagesConversation struct.
|
// MessagesConversation struct.
|
||||||
@@ -487,6 +491,9 @@ type MessagesConversation struct {
|
|||||||
LastMessageID int `json:"last_message_id"` // ID of the last message in conversation
|
LastMessageID int `json:"last_message_id"` // ID of the last message in conversation
|
||||||
Mentions []int `json:"mentions"` // IDs of messages with mentions
|
Mentions []int `json:"mentions"` // IDs of messages with mentions
|
||||||
MessageRequest string `json:"message_request"`
|
MessageRequest string `json:"message_request"`
|
||||||
|
LastConversationMessageID int `json:"last_conversation_message_id"`
|
||||||
|
InReadCMID int `json:"in_read_cmid"`
|
||||||
|
OutReadCMID int `json:"out_read_cmid"`
|
||||||
|
|
||||||
// Last outcoming message have been read by the opponent.
|
// Last outcoming message have been read by the opponent.
|
||||||
OutRead int `json:"out_read"`
|
OutRead int `json:"out_read"`
|
||||||
@@ -495,6 +502,10 @@ type MessagesConversation struct {
|
|||||||
Important BaseBoolInt `json:"important"`
|
Important BaseBoolInt `json:"important"`
|
||||||
Unanswered BaseBoolInt `json:"unanswered"`
|
Unanswered BaseBoolInt `json:"unanswered"`
|
||||||
IsMarkedUnread BaseBoolInt `json:"is_marked_unread"`
|
IsMarkedUnread BaseBoolInt `json:"is_marked_unread"`
|
||||||
|
CanSendMoney BaseBoolInt `json:"can_send_money"`
|
||||||
|
CanReceiveMoney BaseBoolInt `json:"can_receive_money"`
|
||||||
|
IsNew BaseBoolInt `json:"is_new"`
|
||||||
|
IsArchived BaseBoolInt `json:"is_archived"`
|
||||||
UnreadCount int `json:"unread_count"` // Unread messages number
|
UnreadCount int `json:"unread_count"` // Unread messages number
|
||||||
CurrentKeyboard MessagesKeyboard `json:"current_keyboard"`
|
CurrentKeyboard MessagesKeyboard `json:"current_keyboard"`
|
||||||
SortID struct {
|
SortID struct {
|
||||||
@@ -530,6 +541,7 @@ type MessagesConversationChatSettings struct {
|
|||||||
CanCall BaseBoolInt `json:"can_call"`
|
CanCall BaseBoolInt `json:"can_call"`
|
||||||
CanUseMassMentions BaseBoolInt `json:"can_use_mass_mentions"`
|
CanUseMassMentions BaseBoolInt `json:"can_use_mass_mentions"`
|
||||||
CanChangeServiceType BaseBoolInt `json:"can_change_service_type"`
|
CanChangeServiceType BaseBoolInt `json:"can_change_service_type"`
|
||||||
|
CanChangeStyle BaseBoolInt `json:"can_change_style"`
|
||||||
} `json:"acl"`
|
} `json:"acl"`
|
||||||
IsGroupChannel BaseBoolInt `json:"is_group_channel"`
|
IsGroupChannel BaseBoolInt `json:"is_group_channel"`
|
||||||
IsDisappearing BaseBoolInt `json:"is_disappearing"`
|
IsDisappearing BaseBoolInt `json:"is_disappearing"`
|
||||||
@@ -559,6 +571,7 @@ type MessagesChatPermissions struct {
|
|||||||
SeeInviteLink MessagesChatPermission `json:"see_invite_link"`
|
SeeInviteLink MessagesChatPermission `json:"see_invite_link"`
|
||||||
Call MessagesChatPermission `json:"call"`
|
Call MessagesChatPermission `json:"call"`
|
||||||
ChangeAdmins MessagesChatPermission `json:"change_admins"`
|
ChangeAdmins MessagesChatPermission `json:"change_admins"`
|
||||||
|
ChangeStyle MessagesChatPermission `json:"change_style"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessagesConversationPeer struct.
|
// MessagesConversationPeer struct.
|
||||||
@@ -573,6 +586,8 @@ type MessagesConversationPushSettings struct {
|
|||||||
DisabledUntil int `json:"disabled_until"`
|
DisabledUntil int `json:"disabled_until"`
|
||||||
DisabledForever BaseBoolInt `json:"disabled_forever"`
|
DisabledForever BaseBoolInt `json:"disabled_forever"`
|
||||||
NoSound BaseBoolInt `json:"no_sound"`
|
NoSound BaseBoolInt `json:"no_sound"`
|
||||||
|
DisabledMentions BaseBoolInt `json:"disabled_mentions"`
|
||||||
|
DisabledMassMentions BaseBoolInt `json:"disabled_mass_mentions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MessagesConversationWithMessage struct.
|
// MessagesConversationWithMessage struct.
|
||||||
|
|||||||
6
vendor/github.com/SevereCloud/vksdk/v2/object/notifications.go
generated
vendored
6
vendor/github.com/SevereCloud/vksdk/v2/object/notifications.go
generated
vendored
@@ -1,7 +1,5 @@
|
|||||||
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
|
||||||
import "encoding/json"
|
|
||||||
|
|
||||||
// NotificationsFeedback struct.
|
// NotificationsFeedback struct.
|
||||||
type NotificationsFeedback struct {
|
type NotificationsFeedback struct {
|
||||||
Attachments []WallWallpostAttachment `json:"attachments"`
|
Attachments []WallWallpostAttachment `json:"attachments"`
|
||||||
@@ -16,8 +14,8 @@ type NotificationsFeedback struct {
|
|||||||
// NotificationsNotification struct.
|
// NotificationsNotification struct.
|
||||||
type NotificationsNotification struct {
|
type NotificationsNotification struct {
|
||||||
Date int `json:"date"` // Date when the event has been occurred
|
Date int `json:"date"` // Date when the event has been occurred
|
||||||
Feedback json.RawMessage `json:"feedback"`
|
Feedback RawMessage `json:"feedback"`
|
||||||
Parent json.RawMessage `json:"parent"`
|
Parent RawMessage `json:"parent"`
|
||||||
Reply NotificationsReply `json:"reply"`
|
Reply NotificationsReply `json:"reply"`
|
||||||
Type string `json:"type"` // Notification type
|
Type string `json:"type"` // Notification type
|
||||||
}
|
}
|
||||||
|
|||||||
69
vendor/github.com/SevereCloud/vksdk/v2/object/object.go
generated
vendored
69
vendor/github.com/SevereCloud/vksdk/v2/object/object.go
generated
vendored
@@ -9,6 +9,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attachment interface.
|
// Attachment interface.
|
||||||
@@ -42,6 +44,44 @@ func (b *BaseBoolInt) UnmarshalJSON(data []byte) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack func.
|
||||||
|
func (b *BaseBoolInt) DecodeMsgpack(dec *msgpack.Decoder) (err error) {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
valueInt int
|
||||||
|
valueBool bool
|
||||||
|
)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case msgpack.Unmarshal(data, &valueBool) == nil:
|
||||||
|
*b = BaseBoolInt(valueBool)
|
||||||
|
case msgpack.Unmarshal(data, &valueInt) == nil:
|
||||||
|
if valueInt == 1 {
|
||||||
|
*b = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if valueInt == 0 {
|
||||||
|
*b = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
// return msgpack error
|
||||||
|
err = &json.UnmarshalTypeError{
|
||||||
|
Value: string(data),
|
||||||
|
Type: reflect.TypeOf((*BaseBoolInt)(nil)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// BaseCountry struct.
|
// BaseCountry struct.
|
||||||
type BaseCountry struct {
|
type BaseCountry struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
@@ -151,6 +191,33 @@ func (obj *BaseImage) UnmarshalJSON(data []byte) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack is required to support images with `src` field.
|
||||||
|
func (obj *BaseImage) DecodeMsgpack(dec *msgpack.Decoder) (err error) {
|
||||||
|
type renamedBaseImage struct {
|
||||||
|
Height float64 `msgpack:"height"`
|
||||||
|
URL string `msgpack:"url"`
|
||||||
|
Src string `msgpack:"src"`
|
||||||
|
Width float64 `msgpack:"width"`
|
||||||
|
Type string `msgpack:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var renamedObj renamedBaseImage
|
||||||
|
|
||||||
|
err = dec.Decode(&renamedObj)
|
||||||
|
|
||||||
|
obj.Height = renamedObj.Height
|
||||||
|
obj.Width = renamedObj.Width
|
||||||
|
obj.Type = renamedObj.Type
|
||||||
|
|
||||||
|
if renamedObj.Src == "" {
|
||||||
|
obj.URL = renamedObj.URL
|
||||||
|
} else {
|
||||||
|
obj.URL = renamedObj.Src
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// BaseLikes struct.
|
// BaseLikes struct.
|
||||||
type BaseLikes struct {
|
type BaseLikes struct {
|
||||||
UserLikes BaseBoolInt `json:"user_likes"` // Information whether current user likes
|
UserLikes BaseBoolInt `json:"user_likes"` // Information whether current user likes
|
||||||
@@ -347,8 +414,10 @@ type Privacy struct {
|
|||||||
Category PrivacyCategory `json:"category,omitempty"`
|
Category PrivacyCategory `json:"category,omitempty"`
|
||||||
Lists struct {
|
Lists struct {
|
||||||
Allowed []int `json:"allowed"`
|
Allowed []int `json:"allowed"`
|
||||||
|
Excluded []int `json:"excluded"`
|
||||||
} `json:"lists,omitempty"`
|
} `json:"lists,omitempty"`
|
||||||
Owners struct {
|
Owners struct {
|
||||||
|
Allowed []int `json:"allowed"`
|
||||||
Excluded []int `json:"excluded"`
|
Excluded []int `json:"excluded"`
|
||||||
} `json:"owners,omitempty"`
|
} `json:"owners,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/SevereCloud/vksdk/v2/object/photos.go
generated
vendored
1
vendor/github.com/SevereCloud/vksdk/v2/object/photos.go
generated
vendored
@@ -239,6 +239,7 @@ type PhotosPhotoFull struct {
|
|||||||
Photo1280 string `json:"photo_1280"` // URL of image with 1280 px width
|
Photo1280 string `json:"photo_1280"` // URL of image with 1280 px width
|
||||||
Photo2560 string `json:"photo_2560"` // URL of image with 2560 px width
|
Photo2560 string `json:"photo_2560"` // URL of image with 2560 px width
|
||||||
Sizes []PhotosPhotoSizes `json:"sizes"`
|
Sizes []PhotosPhotoSizes `json:"sizes"`
|
||||||
|
OrigPhoto PhotosPhotoSizes `json:"orig_photo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToAttachment return attachment format.
|
// ToAttachment return attachment format.
|
||||||
|
|||||||
39
vendor/github.com/SevereCloud/vksdk/v2/object/raw.go
generated
vendored
Normal file
39
vendor/github.com/SevereCloud/vksdk/v2/object/raw.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
|
||||||
|
import "github.com/vmihailenco/msgpack/v5"
|
||||||
|
|
||||||
|
// RawMessage is a raw encoded JSON or MessagePack value.
|
||||||
|
type RawMessage []byte
|
||||||
|
|
||||||
|
// MarshalJSON returns m as the JSON encoding of m.
|
||||||
|
func (m RawMessage) MarshalJSON() ([]byte, error) {
|
||||||
|
if m == nil {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON sets *m to a copy of data.
|
||||||
|
func (m *RawMessage) UnmarshalJSON(data []byte) error {
|
||||||
|
*m = append((*m)[0:0], data...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeMsgpack write m as the MessagePack encoding of m.
|
||||||
|
func (m RawMessage) EncodeMsgpack(enc *msgpack.Encoder) error {
|
||||||
|
_, err := enc.Writer().Write(m)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack sets *m to a copy of data.
|
||||||
|
func (m *RawMessage) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
msg, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*m = RawMessage(msg)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
33
vendor/github.com/SevereCloud/vksdk/v2/object/stories.go
generated
vendored
33
vendor/github.com/SevereCloud/vksdk/v2/object/stories.go
generated
vendored
@@ -127,6 +127,7 @@ type StoriesStory struct {
|
|||||||
Seen BaseBoolInt `json:"seen"`
|
Seen BaseBoolInt `json:"seen"`
|
||||||
IsOwnerPinned BaseBoolInt `json:"is_owner_pinned"`
|
IsOwnerPinned BaseBoolInt `json:"is_owner_pinned"`
|
||||||
IsOneTime BaseBoolInt `json:"is_one_time"`
|
IsOneTime BaseBoolInt `json:"is_one_time"`
|
||||||
|
IsAdvice BaseBoolInt `json:"is_advice,omitempty"`
|
||||||
NeedMute BaseBoolInt `json:"need_mute"`
|
NeedMute BaseBoolInt `json:"need_mute"`
|
||||||
MuteReply BaseBoolInt `json:"mute_reply"`
|
MuteReply BaseBoolInt `json:"mute_reply"`
|
||||||
CanLike BaseBoolInt `json:"can_like"`
|
CanLike BaseBoolInt `json:"can_like"`
|
||||||
@@ -152,6 +153,7 @@ type StoriesStory struct {
|
|||||||
NarrativesCount int `json:"narratives_count"`
|
NarrativesCount int `json:"narratives_count"`
|
||||||
FirstNarrativeTitle string `json:"first_narrative_title"`
|
FirstNarrativeTitle string `json:"first_narrative_title"`
|
||||||
Questions StoriesQuestions `json:"questions"`
|
Questions StoriesQuestions `json:"questions"`
|
||||||
|
ReactionSetID string `json:"reaction_set_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StoriesFeedItemType type.
|
// StoriesFeedItemType type.
|
||||||
@@ -251,8 +253,10 @@ type StoriesClickableSticker struct { // nolint: maligned
|
|||||||
StickerID int `json:"sticker_id,omitempty"`
|
StickerID int `json:"sticker_id,omitempty"`
|
||||||
StickerPackID int `json:"sticker_pack_id,omitempty"`
|
StickerPackID int `json:"sticker_pack_id,omitempty"`
|
||||||
|
|
||||||
// type=place
|
// type=place or geo
|
||||||
PlaceID int `json:"place_id,omitempty"`
|
PlaceID int `json:"place_id,omitempty"`
|
||||||
|
// Title
|
||||||
|
CategoryID int `json:"category_id,omitempty"`
|
||||||
|
|
||||||
// type=question
|
// type=question
|
||||||
Question string `json:"question,omitempty"`
|
Question string `json:"question,omitempty"`
|
||||||
@@ -269,6 +273,12 @@ type StoriesClickableSticker struct { // nolint: maligned
|
|||||||
// type=link
|
// type=link
|
||||||
LinkObject BaseLink `json:"link_object,omitempty"`
|
LinkObject BaseLink `json:"link_object,omitempty"`
|
||||||
TooltipText string `json:"tooltip_text,omitempty"`
|
TooltipText string `json:"tooltip_text,omitempty"`
|
||||||
|
TooltipTextKey string `json:"tooltip_text_key,omitempty"`
|
||||||
|
|
||||||
|
// type=time
|
||||||
|
TimestampMs int64 `json:"timestamp_ms,omitempty"`
|
||||||
|
Date string `json:"date,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
|
||||||
// type=market_item
|
// type=market_item
|
||||||
Subtype string `json:"subtype,omitempty"`
|
Subtype string `json:"subtype,omitempty"`
|
||||||
@@ -290,10 +300,19 @@ type StoriesClickableSticker struct { // nolint: maligned
|
|||||||
AudioStartTime int `json:"audio_start_time,omitempty"`
|
AudioStartTime int `json:"audio_start_time,omitempty"`
|
||||||
|
|
||||||
// type=app
|
// type=app
|
||||||
App AppsApp `json:"app"`
|
App AppsApp `json:"app,omitempty"`
|
||||||
AppContext string `json:"app_context"`
|
AppContext string `json:"app_context,omitempty"`
|
||||||
HasNewInteractions BaseBoolInt `json:"has_new_interactions"`
|
HasNewInteractions BaseBoolInt `json:"has_new_interactions,omitempty"`
|
||||||
IsBroadcastNotifyAllowed BaseBoolInt `json:"is_broadcast_notify_allowed"`
|
IsBroadcastNotifyAllowed BaseBoolInt `json:"is_broadcast_notify_allowed,omitempty"`
|
||||||
|
|
||||||
|
// type=emoji
|
||||||
|
Emoji string `json:"emoji,omitempty"`
|
||||||
|
|
||||||
|
// type=text
|
||||||
|
Text string `json:"text,omitempty"`
|
||||||
|
BackgroundStyle string `json:"background_style,omitempty"`
|
||||||
|
Alignment string `json:"alignment,omitempty"`
|
||||||
|
SelectionColor string `json:"selection_color,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: сделать несколько структур для кликабельного стикера
|
// TODO: сделать несколько структур для кликабельного стикера
|
||||||
@@ -313,6 +332,10 @@ const (
|
|||||||
ClickableStickerPoll = "poll"
|
ClickableStickerPoll = "poll"
|
||||||
ClickableStickerMusic = "music"
|
ClickableStickerMusic = "music"
|
||||||
ClickableStickerApp = "app"
|
ClickableStickerApp = "app"
|
||||||
|
ClickableStickerTime = "time"
|
||||||
|
ClickableStickerEmoji = "emoji"
|
||||||
|
ClickableStickerGeo = "geo"
|
||||||
|
ClickableStickerText = "text"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Subtype of clickable sticker.
|
// Subtype of clickable sticker.
|
||||||
|
|||||||
33
vendor/github.com/SevereCloud/vksdk/v2/object/users.go
generated
vendored
33
vendor/github.com/SevereCloud/vksdk/v2/object/users.go
generated
vendored
@@ -4,6 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
"github.com/vmihailenco/msgpack/v5/msgpcode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User relationship status.
|
// User relationship status.
|
||||||
@@ -258,6 +261,36 @@ func (personal *UsersPersonal) UnmarshalJSON(data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack UsersPersonal.
|
||||||
|
//
|
||||||
|
// BUG(VK): UsersPersonal return [].
|
||||||
|
func (personal *UsersPersonal) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(data, []byte{msgpcode.FixedArrayLow}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type renamedUsersPersonal UsersPersonal
|
||||||
|
|
||||||
|
var r renamedUsersPersonal
|
||||||
|
|
||||||
|
d := msgpack.NewDecoder(bytes.NewReader(data))
|
||||||
|
d.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
err = d.Decode(&r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*personal = UsersPersonal(r)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UsersRelative struct.
|
// UsersRelative struct.
|
||||||
type UsersRelative struct {
|
type UsersRelative struct {
|
||||||
BirthDate string `json:"birth_date"` // Date of child birthday (format dd.mm.yyyy)
|
BirthDate string `json:"birth_date"` // Date of child birthday (format dd.mm.yyyy)
|
||||||
|
|||||||
60
vendor/github.com/SevereCloud/vksdk/v2/object/utils.go
generated
vendored
60
vendor/github.com/SevereCloud/vksdk/v2/object/utils.go
generated
vendored
@@ -1,5 +1,13 @@
|
|||||||
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
package object // import "github.com/SevereCloud/vksdk/v2/object"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
|
"github.com/vmihailenco/msgpack/v5/msgpcode"
|
||||||
|
)
|
||||||
|
|
||||||
// UtilsDomainResolvedType object type.
|
// UtilsDomainResolvedType object type.
|
||||||
const (
|
const (
|
||||||
UtilsDomainResolvedTypeUser = "user"
|
UtilsDomainResolvedTypeUser = "user"
|
||||||
@@ -15,6 +23,58 @@ type UtilsDomainResolved struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON UtilsDomainResolved.
|
||||||
|
//
|
||||||
|
// BUG(VK): UtilsDomainResolved return [].
|
||||||
|
func (link *UtilsDomainResolved) UnmarshalJSON(data []byte) error {
|
||||||
|
if bytes.Equal(data, []byte("[]")) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type renamedUtilsDomainResolved UtilsDomainResolved
|
||||||
|
|
||||||
|
var r renamedUtilsDomainResolved
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, &r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*link = UtilsDomainResolved(r)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeMsgpack UtilsDomainResolved.
|
||||||
|
//
|
||||||
|
// BUG(VK): UtilsDomainResolved return [].
|
||||||
|
func (link *UtilsDomainResolved) DecodeMsgpack(dec *msgpack.Decoder) error {
|
||||||
|
data, err := dec.DecodeRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(data, []byte{msgpcode.FixedArrayLow}) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type renamedUtilsDomainResolved UtilsDomainResolved
|
||||||
|
|
||||||
|
var r renamedUtilsDomainResolved
|
||||||
|
|
||||||
|
d := msgpack.NewDecoder(bytes.NewReader(data))
|
||||||
|
d.SetCustomStructTag("json")
|
||||||
|
|
||||||
|
err = d.Decode(&r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*link = UtilsDomainResolved(r)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UtilsLastShortenedLink struct.
|
// UtilsLastShortenedLink struct.
|
||||||
type UtilsLastShortenedLink struct {
|
type UtilsLastShortenedLink struct {
|
||||||
AccessKey string `json:"access_key"` // Access key for private stats
|
AccessKey string `json:"access_key"` // Access key for private stats
|
||||||
|
|||||||
39
vendor/github.com/SevereCloud/vksdk/v2/object/video.go
generated
vendored
39
vendor/github.com/SevereCloud/vksdk/v2/object/video.go
generated
vendored
@@ -12,6 +12,9 @@ type VideoVideo struct {
|
|||||||
// Date when the video has been added in Unixtime.
|
// Date when the video has been added in Unixtime.
|
||||||
AddingDate int `json:"adding_date"`
|
AddingDate int `json:"adding_date"`
|
||||||
|
|
||||||
|
// Date when the video has been released in Unixtime.
|
||||||
|
ReleaseDate int `json:"release_date"`
|
||||||
|
|
||||||
// Information whether current user can add the video.
|
// Information whether current user can add the video.
|
||||||
CanAdd BaseBoolInt `json:"can_add"`
|
CanAdd BaseBoolInt `json:"can_add"`
|
||||||
|
|
||||||
@@ -27,12 +30,17 @@ type VideoVideo struct {
|
|||||||
// Information whether current user can like the video.
|
// Information whether current user can like the video.
|
||||||
CanLike BaseBoolInt `json:"can_like"`
|
CanLike BaseBoolInt `json:"can_like"`
|
||||||
|
|
||||||
|
// Information whether current user can download the video.
|
||||||
|
CanDownload BaseBoolInt `json:"can_download"`
|
||||||
|
|
||||||
// Information whether current user can repost this video.
|
// Information whether current user can repost this video.
|
||||||
CanRepost BaseBoolInt `json:"can_repost"`
|
CanRepost BaseBoolInt `json:"can_repost"`
|
||||||
CanSubscribe BaseBoolInt `json:"can_subscribe"`
|
CanSubscribe BaseBoolInt `json:"can_subscribe"`
|
||||||
CanAttachLink BaseBoolInt `json:"can_attach_link"`
|
CanAttachLink BaseBoolInt `json:"can_attach_link"`
|
||||||
IsFavorite BaseBoolInt `json:"is_favorite"`
|
IsFavorite BaseBoolInt `json:"is_favorite"`
|
||||||
IsPrivate BaseBoolInt `json:"is_private"`
|
IsPrivate BaseBoolInt `json:"is_private"`
|
||||||
|
IsExplicit BaseBoolInt `json:"is_explicit"`
|
||||||
|
IsSubscribed BaseBoolInt `json:"is_subscribed"`
|
||||||
Added BaseBoolInt `json:"added"`
|
Added BaseBoolInt `json:"added"`
|
||||||
Repeat BaseBoolInt `json:"repeat"` // Information whether the video is repeated
|
Repeat BaseBoolInt `json:"repeat"` // Information whether the video is repeated
|
||||||
ContentRestricted int `json:"content_restricted"`
|
ContentRestricted int `json:"content_restricted"`
|
||||||
@@ -43,6 +51,7 @@ type VideoVideo struct {
|
|||||||
Description string `json:"description"` // Video description
|
Description string `json:"description"` // Video description
|
||||||
Duration int `json:"duration"` // Video duration in seconds
|
Duration int `json:"duration"` // Video duration in seconds
|
||||||
Files VideoVideoFiles `json:"files"`
|
Files VideoVideoFiles `json:"files"`
|
||||||
|
Trailer VideoVideoFiles `json:"trailer,omitempty"`
|
||||||
FirstFrame []VideoVideoImage `json:"first_frame"`
|
FirstFrame []VideoVideoImage `json:"first_frame"`
|
||||||
Image []VideoVideoImage `json:"image"`
|
Image []VideoVideoImage `json:"image"`
|
||||||
Height int `json:"height"` // Video height
|
Height int `json:"height"` // Video height
|
||||||
@@ -59,6 +68,7 @@ type VideoVideo struct {
|
|||||||
Player string `json:"player"`
|
Player string `json:"player"`
|
||||||
Processing int `json:"processing"` // Returns if the video is processing
|
Processing int `json:"processing"` // Returns if the video is processing
|
||||||
Title string `json:"title"` // Video title
|
Title string `json:"title"` // Video title
|
||||||
|
Subtitle string `json:"subtitle"` // Video subtitle
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Views int `json:"views"` // Number of views
|
Views int `json:"views"` // Number of views
|
||||||
Width int `json:"width"` // Video width
|
Width int `json:"width"` // Video width
|
||||||
@@ -72,6 +82,10 @@ type VideoVideo struct {
|
|||||||
ActionButton VideoActionButton `json:"action_button"`
|
ActionButton VideoActionButton `json:"action_button"`
|
||||||
Restriction VideoRestriction `json:"restriction"`
|
Restriction VideoRestriction `json:"restriction"`
|
||||||
ContentRestrictedMessage string `json:"content_restricted_message"`
|
ContentRestrictedMessage string `json:"content_restricted_message"`
|
||||||
|
MainArtists []AudioAudioArtist `json:"main_artists"`
|
||||||
|
FeaturedArtists []AudioAudioArtist `json:"featured_artists"`
|
||||||
|
Genres []BaseObjectWithName `json:"genres"`
|
||||||
|
OvID string `json:"ov_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToAttachment return attachment format.
|
// ToAttachment return attachment format.
|
||||||
@@ -112,16 +126,20 @@ type VideoSnippet struct {
|
|||||||
|
|
||||||
// VideoVideoFiles struct.
|
// VideoVideoFiles struct.
|
||||||
type VideoVideoFiles struct {
|
type VideoVideoFiles struct {
|
||||||
External string `json:"external"` // URL of the external player
|
External string `json:"external,omitempty"` // URL of the external player
|
||||||
Mp4_1080 string `json:"mp4_1080"` // URL of the mpeg4 file with 1080p quality
|
Mp4_1080 string `json:"mp4_1080,omitempty"` // URL of the mpeg4 file with 1080p quality
|
||||||
Mp4_1440 string `json:"mp4_1440"` // URL of the mpeg4 file with 2k quality
|
Mp4_1440 string `json:"mp4_1440,omitempty"` // URL of the mpeg4 file with 2k quality
|
||||||
Mp4_2160 string `json:"mp4_2160"` // URL of the mpeg4 file with 4k quality
|
Mp4_2160 string `json:"mp4_2160,omitempty"` // URL of the mpeg4 file with 4k quality
|
||||||
Mp4_240 string `json:"mp4_240"` // URL of the mpeg4 file with 240p quality
|
Mp4_240 string `json:"mp4_240,omitempty"` // URL of the mpeg4 file with 240p quality
|
||||||
Mp4_360 string `json:"mp4_360"` // URL of the mpeg4 file with 360p quality
|
Mp4_360 string `json:"mp4_360,omitempty"` // URL of the mpeg4 file with 360p quality
|
||||||
Mp4_480 string `json:"mp4_480"` // URL of the mpeg4 file with 480p quality
|
Mp4_480 string `json:"mp4_480,omitempty"` // URL of the mpeg4 file with 480p quality
|
||||||
Mp4_720 string `json:"mp4_720"` // URL of the mpeg4 file with 720p quality
|
Mp4_720 string `json:"mp4_720,omitempty"` // URL of the mpeg4 file with 720p quality
|
||||||
Live string `json:"live"`
|
Live string `json:"live,omitempty"`
|
||||||
HLS string `json:"hls"`
|
HLS string `json:"hls,omitempty"`
|
||||||
|
DashUni string `json:"dash_uni,omitempty"`
|
||||||
|
DashSep string `json:"dash_sep,omitempty"`
|
||||||
|
DashWebm string `json:"dash_webm,omitempty"`
|
||||||
|
FailoverHost string `json:"failover_host,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// VideoCatBlock struct.
|
// VideoCatBlock struct.
|
||||||
@@ -213,6 +231,7 @@ type VideoVideoFull struct {
|
|||||||
Description string `json:"description"` // Video description
|
Description string `json:"description"` // Video description
|
||||||
Duration int `json:"duration"` // Video duration in seconds
|
Duration int `json:"duration"` // Video duration in seconds
|
||||||
Files VideoVideoFiles `json:"files"`
|
Files VideoVideoFiles `json:"files"`
|
||||||
|
Trailer VideoVideoFiles `json:"trailer"`
|
||||||
ID int `json:"id"` // Video ID
|
ID int `json:"id"` // Video ID
|
||||||
Likes BaseLikes `json:"likes"`
|
Likes BaseLikes `json:"likes"`
|
||||||
Live int `json:"live"` // Returns if the video is live translation
|
Live int `json:"live"` // Returns if the video is live translation
|
||||||
|
|||||||
21
vendor/github.com/SevereCloud/vksdk/v2/object/wall.go
generated
vendored
21
vendor/github.com/SevereCloud/vksdk/v2/object/wall.go
generated
vendored
@@ -156,14 +156,17 @@ type WallWallpost struct {
|
|||||||
IsPinned BaseBoolInt `json:"is_pinned"`
|
IsPinned BaseBoolInt `json:"is_pinned"`
|
||||||
IsFavorite BaseBoolInt `json:"is_favorite"` // Information whether the post in favorites list
|
IsFavorite BaseBoolInt `json:"is_favorite"` // Information whether the post in favorites list
|
||||||
IsArchived BaseBoolInt `json:"is_archived"` // Is post archived, only for post owners
|
IsArchived BaseBoolInt `json:"is_archived"` // Is post archived, only for post owners
|
||||||
|
IsDeleted BaseBoolInt `json:"is_deleted"`
|
||||||
MarkedAsAds BaseBoolInt `json:"marked_as_ads"`
|
MarkedAsAds BaseBoolInt `json:"marked_as_ads"`
|
||||||
Edited int `json:"edited"` // Date of editing in Unixtime
|
Edited int `json:"edited"` // Date of editing in Unixtime
|
||||||
Copyright WallPostCopyright `json:"copyright"`
|
Copyright WallPostCopyright `json:"copyright"`
|
||||||
PostID int `json:"post_id"`
|
PostID int `json:"post_id"`
|
||||||
ParentsStack []int `json:"parents_stack"`
|
ParentsStack []int `json:"parents_stack"`
|
||||||
Donut WallWallpostDonut `json:"donut"` // need api v5.125
|
Donut WallWallpostDonut `json:"donut"`
|
||||||
ShortTextRate float64 `json:"short_text_rate"`
|
ShortTextRate float64 `json:"short_text_rate"`
|
||||||
CarouselOffset int `json:"carousel_offset"`
|
CarouselOffset int `json:"carousel_offset"`
|
||||||
|
Header WallWallpostHeader `json:"header"`
|
||||||
|
Hash string `json:"hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attachment type.
|
// Attachment type.
|
||||||
@@ -235,8 +238,10 @@ type WallWallpostToID struct {
|
|||||||
IsFavorite BaseBoolInt `json:"is_favorite"` // Information whether the post in favorites list
|
IsFavorite BaseBoolInt `json:"is_favorite"` // Information whether the post in favorites list
|
||||||
MarkedAsAds BaseBoolInt `json:"marked_as_ads"`
|
MarkedAsAds BaseBoolInt `json:"marked_as_ads"`
|
||||||
ParentsStack []int `json:"parents_stack"`
|
ParentsStack []int `json:"parents_stack"`
|
||||||
Donut WallWallpostDonut `json:"donut"` // need api v5.125
|
Donut WallWallpostDonut `json:"donut"`
|
||||||
ShortTextRate float64 `json:"short_text_rate"`
|
ShortTextRate float64 `json:"short_text_rate"`
|
||||||
|
Views WallViews `json:"views"` // Count of views
|
||||||
|
Header WallWallpostHeader `json:"header"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// WallWallpostDonut info about VK Donut.
|
// WallWallpostDonut info about VK Donut.
|
||||||
@@ -255,3 +260,15 @@ type WallPostCopyright struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WallWallpostHeader struct.
|
||||||
|
type WallWallpostHeader struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
CustomDescription WallWallpostHeaderCustomDescription `json:"custom_description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WallWallpostHeaderCustomDescription struct.
|
||||||
|
type WallWallpostHeaderCustomDescription struct {
|
||||||
|
SourceID int `json:"source_id"`
|
||||||
|
Date int `json:"date"`
|
||||||
|
}
|
||||||
|
|||||||
3
vendor/github.com/SevereCloud/vksdk/v2/object/widgets.go
generated
vendored
3
vendor/github.com/SevereCloud/vksdk/v2/object/widgets.go
generated
vendored
@@ -45,6 +45,9 @@ type WidgetsWidgetComment struct {
|
|||||||
Views struct {
|
Views struct {
|
||||||
Count int `json:"count"`
|
Count int `json:"count"`
|
||||||
} `json:"views"`
|
} `json:"views"`
|
||||||
|
Donut WallWallpostDonut `json:"donut"`
|
||||||
|
ShortTextRate float64 `json:"short_text_rate"`
|
||||||
|
Header WallWallpostHeader `json:"header"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// WidgetsWidgetLikes struct.
|
// WidgetsWidgetLikes struct.
|
||||||
|
|||||||
4
vendor/github.com/d5/tengo/v2/README.md
generated
vendored
4
vendor/github.com/d5/tengo/v2/README.md
generated
vendored
@@ -1,7 +1,3 @@
|
|||||||
<p align="center">
|
|
||||||
<img src="https://raw.githubusercontent.com/d5/tengolang-share/master/logo_400.png" width="200" height="200">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
# The Tengo Language
|
# The Tengo Language
|
||||||
|
|
||||||
[](https://godoc.org/github.com/d5/tengo/v2)
|
[](https://godoc.org/github.com/d5/tengo/v2)
|
||||||
|
|||||||
70
vendor/github.com/d5/tengo/v2/compiler.go
generated
vendored
70
vendor/github.com/d5/tengo/v2/compiler.go
generated
vendored
@@ -1,9 +1,11 @@
|
|||||||
package tengo
|
package tengo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -45,11 +47,12 @@ type Compiler struct {
|
|||||||
parent *Compiler
|
parent *Compiler
|
||||||
modulePath string
|
modulePath string
|
||||||
importDir string
|
importDir string
|
||||||
|
importFileExt []string
|
||||||
constants []Object
|
constants []Object
|
||||||
symbolTable *SymbolTable
|
symbolTable *SymbolTable
|
||||||
scopes []compilationScope
|
scopes []compilationScope
|
||||||
scopeIndex int
|
scopeIndex int
|
||||||
modules *ModuleMap
|
modules ModuleGetter
|
||||||
compiledModules map[string]*CompiledFunction
|
compiledModules map[string]*CompiledFunction
|
||||||
allowFileImport bool
|
allowFileImport bool
|
||||||
loops []*loop
|
loops []*loop
|
||||||
@@ -63,7 +66,7 @@ func NewCompiler(
|
|||||||
file *parser.SourceFile,
|
file *parser.SourceFile,
|
||||||
symbolTable *SymbolTable,
|
symbolTable *SymbolTable,
|
||||||
constants []Object,
|
constants []Object,
|
||||||
modules *ModuleMap,
|
modules ModuleGetter,
|
||||||
trace io.Writer,
|
trace io.Writer,
|
||||||
) *Compiler {
|
) *Compiler {
|
||||||
mainScope := compilationScope{
|
mainScope := compilationScope{
|
||||||
@@ -96,6 +99,7 @@ func NewCompiler(
|
|||||||
trace: trace,
|
trace: trace,
|
||||||
modules: modules,
|
modules: modules,
|
||||||
compiledModules: make(map[string]*CompiledFunction),
|
compiledModules: make(map[string]*CompiledFunction),
|
||||||
|
importFileExt: []string{SourceFileExtDefault},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,12 +542,8 @@ func (c *Compiler) Compile(node parser.Node) error {
|
|||||||
}
|
}
|
||||||
} else if c.allowFileImport {
|
} else if c.allowFileImport {
|
||||||
moduleName := node.ModuleName
|
moduleName := node.ModuleName
|
||||||
if !strings.HasSuffix(moduleName, ".tengo") {
|
|
||||||
moduleName += ".tengo"
|
|
||||||
}
|
|
||||||
|
|
||||||
modulePath, err := filepath.Abs(
|
modulePath, err := c.getPathModule(moduleName)
|
||||||
filepath.Join(c.importDir, moduleName))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.errorf(node, "module file path error: %s",
|
return c.errorf(node, "module file path error: %s",
|
||||||
err.Error())
|
err.Error())
|
||||||
@@ -640,6 +640,39 @@ func (c *Compiler) SetImportDir(dir string) {
|
|||||||
c.importDir = dir
|
c.importDir = dir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetImportFileExt sets the extension name of the source file for loading
|
||||||
|
// local module files.
|
||||||
|
//
|
||||||
|
// Use this method if you want other source file extension than ".tengo".
|
||||||
|
//
|
||||||
|
// // this will search for *.tengo, *.foo, *.bar
|
||||||
|
// err := c.SetImportFileExt(".tengo", ".foo", ".bar")
|
||||||
|
//
|
||||||
|
// This function requires at least one argument, since it will replace the
|
||||||
|
// current list of extension name.
|
||||||
|
func (c *Compiler) SetImportFileExt(exts ...string) error {
|
||||||
|
if len(exts) == 0 {
|
||||||
|
return fmt.Errorf("missing arg: at least one argument is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ext := range exts {
|
||||||
|
if ext != filepath.Ext(ext) || ext == "" {
|
||||||
|
return fmt.Errorf("invalid file extension: %s", ext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.importFileExt = exts // Replace the hole current extension list
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetImportFileExt returns the current list of extension name.
|
||||||
|
// Thease are the complementary suffix of the source file to search and load
|
||||||
|
// local module files.
|
||||||
|
func (c *Compiler) GetImportFileExt() []string {
|
||||||
|
return c.importFileExt
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Compiler) compileAssign(
|
func (c *Compiler) compileAssign(
|
||||||
node parser.Node,
|
node parser.Node,
|
||||||
lhs, rhs []parser.Expr,
|
lhs, rhs []parser.Expr,
|
||||||
@@ -1098,6 +1131,7 @@ func (c *Compiler) fork(
|
|||||||
child.parent = c // parent to set to current compiler
|
child.parent = c // parent to set to current compiler
|
||||||
child.allowFileImport = c.allowFileImport
|
child.allowFileImport = c.allowFileImport
|
||||||
child.importDir = c.importDir
|
child.importDir = c.importDir
|
||||||
|
child.importFileExt = c.importFileExt
|
||||||
if isFile && c.importDir != "" {
|
if isFile && c.importDir != "" {
|
||||||
child.importDir = filepath.Dir(modulePath)
|
child.importDir = filepath.Dir(modulePath)
|
||||||
}
|
}
|
||||||
@@ -1287,6 +1321,28 @@ func (c *Compiler) printTrace(a ...interface{}) {
|
|||||||
_, _ = fmt.Fprintln(c.trace, a...)
|
_, _ = fmt.Fprintln(c.trace, a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Compiler) getPathModule(moduleName string) (pathFile string, err error) {
|
||||||
|
for _, ext := range c.importFileExt {
|
||||||
|
nameFile := moduleName
|
||||||
|
|
||||||
|
if !strings.HasSuffix(nameFile, ext) {
|
||||||
|
nameFile += ext
|
||||||
|
}
|
||||||
|
|
||||||
|
pathFile, err = filepath.Abs(filepath.Join(c.importDir, nameFile))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if file exists
|
||||||
|
if _, err := os.Stat(pathFile); !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return pathFile, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("module '%s' not found at: %s", moduleName, pathFile)
|
||||||
|
}
|
||||||
|
|
||||||
func resolveAssignLHS(
|
func resolveAssignLHS(
|
||||||
expr parser.Expr,
|
expr parser.Expr,
|
||||||
) (name string, selectors []parser.Expr) {
|
) (name string, selectors []parser.Expr) {
|
||||||
|
|||||||
5
vendor/github.com/d5/tengo/v2/modules.go
generated
vendored
5
vendor/github.com/d5/tengo/v2/modules.go
generated
vendored
@@ -6,6 +6,11 @@ type Importable interface {
|
|||||||
Import(moduleName string) (interface{}, error)
|
Import(moduleName string) (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ModuleGetter enables implementing dynamic module loading.
|
||||||
|
type ModuleGetter interface {
|
||||||
|
Get(name string) Importable
|
||||||
|
}
|
||||||
|
|
||||||
// ModuleMap represents a set of named modules. Use NewModuleMap to create a
|
// ModuleMap represents a set of named modules. Use NewModuleMap to create a
|
||||||
// new module map.
|
// new module map.
|
||||||
type ModuleMap struct {
|
type ModuleMap struct {
|
||||||
|
|||||||
16
vendor/github.com/d5/tengo/v2/script.go
generated
vendored
16
vendor/github.com/d5/tengo/v2/script.go
generated
vendored
@@ -12,7 +12,7 @@ import (
|
|||||||
// Script can simplify compilation and execution of embedded scripts.
|
// Script can simplify compilation and execution of embedded scripts.
|
||||||
type Script struct {
|
type Script struct {
|
||||||
variables map[string]*Variable
|
variables map[string]*Variable
|
||||||
modules *ModuleMap
|
modules ModuleGetter
|
||||||
input []byte
|
input []byte
|
||||||
maxAllocs int64
|
maxAllocs int64
|
||||||
maxConstObjects int
|
maxConstObjects int
|
||||||
@@ -54,7 +54,7 @@ func (s *Script) Remove(name string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetImports sets import modules.
|
// SetImports sets import modules.
|
||||||
func (s *Script) SetImports(modules *ModuleMap) {
|
func (s *Script) SetImports(modules ModuleGetter) {
|
||||||
s.modules = modules
|
s.modules = modules
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,6 +219,18 @@ func (c *Compiled) RunContext(ctx context.Context) (err error) {
|
|||||||
v := NewVM(c.bytecode, c.globals, c.maxAllocs)
|
v := NewVM(c.bytecode, c.globals, c.maxAllocs)
|
||||||
ch := make(chan error, 1)
|
ch := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
switch e := r.(type) {
|
||||||
|
case string:
|
||||||
|
ch <- fmt.Errorf(e)
|
||||||
|
case error:
|
||||||
|
ch <- e
|
||||||
|
default:
|
||||||
|
ch <- fmt.Errorf("unknown panic: %v", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
ch <- v.Run()
|
ch <- v.Run()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
3
vendor/github.com/d5/tengo/v2/tengo.go
generated
vendored
3
vendor/github.com/d5/tengo/v2/tengo.go
generated
vendored
@@ -26,6 +26,9 @@ const (
|
|||||||
|
|
||||||
// MaxFrames is the maximum number of function frames for a VM.
|
// MaxFrames is the maximum number of function frames for a VM.
|
||||||
MaxFrames = 1024
|
MaxFrames = 1024
|
||||||
|
|
||||||
|
// SourceFileExtDefault is the default extension for source files.
|
||||||
|
SourceFileExtDefault = ".tengo"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CallableFunc is a function signature for the callable functions.
|
// CallableFunc is a function signature for the callable functions.
|
||||||
|
|||||||
2
vendor/github.com/d5/tengo/v2/vm.go
generated
vendored
2
vendor/github.com/d5/tengo/v2/vm.go
generated
vendored
@@ -293,7 +293,7 @@ func (v *VM) run() {
|
|||||||
case parser.OpMap:
|
case parser.OpMap:
|
||||||
v.ip += 2
|
v.ip += 2
|
||||||
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
numElements := int(v.curInsts[v.ip]) | int(v.curInsts[v.ip-1])<<8
|
||||||
kv := make(map[string]Object)
|
kv := make(map[string]Object, numElements)
|
||||||
for i := v.sp - numElements; i < v.sp; i += 2 {
|
for i := v.sp - numElements; i < v.sp; i += 2 {
|
||||||
key := v.stack[i]
|
key := v.stack[i]
|
||||||
value := v.stack[i+1]
|
value := v.stack[i+1]
|
||||||
|
|||||||
8
vendor/github.com/go-telegram-bot-api/telegram-bot-api/.travis.yml
generated
vendored
8
vendor/github.com/go-telegram-bot-api/telegram-bot-api/.travis.yml
generated
vendored
@@ -1,8 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- '1.10'
|
|
||||||
- '1.11'
|
|
||||||
- '1.12'
|
|
||||||
- '1.13'
|
|
||||||
- tip
|
|
||||||
1014
vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go
generated
vendored
1014
vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1279
vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go
generated
vendored
1279
vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go
generated
vendored
File diff suppressed because it is too large
Load Diff
990
vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go
generated
vendored
990
vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go
generated
vendored
@@ -1,990 +0,0 @@
|
|||||||
package tgbotapi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIResponse is a response from the Telegram API with the result
|
|
||||||
// stored raw.
|
|
||||||
type APIResponse struct {
|
|
||||||
Ok bool `json:"ok"`
|
|
||||||
Result json.RawMessage `json:"result"`
|
|
||||||
ErrorCode int `json:"error_code"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Parameters *ResponseParameters `json:"parameters"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResponseParameters are various errors that can be returned in APIResponse.
|
|
||||||
type ResponseParameters struct {
|
|
||||||
MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional
|
|
||||||
RetryAfter int `json:"retry_after"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is an update response, from GetUpdates.
|
|
||||||
type Update struct {
|
|
||||||
UpdateID int `json:"update_id"`
|
|
||||||
Message *Message `json:"message"`
|
|
||||||
EditedMessage *Message `json:"edited_message"`
|
|
||||||
ChannelPost *Message `json:"channel_post"`
|
|
||||||
EditedChannelPost *Message `json:"edited_channel_post"`
|
|
||||||
InlineQuery *InlineQuery `json:"inline_query"`
|
|
||||||
ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"`
|
|
||||||
CallbackQuery *CallbackQuery `json:"callback_query"`
|
|
||||||
ShippingQuery *ShippingQuery `json:"shipping_query"`
|
|
||||||
PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdatesChannel is the channel for getting updates.
|
|
||||||
type UpdatesChannel <-chan Update
|
|
||||||
|
|
||||||
// Clear discards all unprocessed incoming updates.
|
|
||||||
func (ch UpdatesChannel) Clear() {
|
|
||||||
for len(ch) != 0 {
|
|
||||||
<-ch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// User is a user on Telegram.
|
|
||||||
type User struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
FirstName string `json:"first_name"`
|
|
||||||
LastName string `json:"last_name"` // optional
|
|
||||||
UserName string `json:"username"` // optional
|
|
||||||
LanguageCode string `json:"language_code"` // optional
|
|
||||||
IsBot bool `json:"is_bot"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// String displays a simple text version of a user.
|
|
||||||
//
|
|
||||||
// It is normally a user's username, but falls back to a first/last
|
|
||||||
// name as available.
|
|
||||||
func (u *User) String() string {
|
|
||||||
if u == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if u.UserName != "" {
|
|
||||||
return u.UserName
|
|
||||||
}
|
|
||||||
|
|
||||||
name := u.FirstName
|
|
||||||
if u.LastName != "" {
|
|
||||||
name += " " + u.LastName
|
|
||||||
}
|
|
||||||
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
// GroupChat is a group chat.
|
|
||||||
type GroupChat struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChatPhoto represents a chat photo.
|
|
||||||
type ChatPhoto struct {
|
|
||||||
SmallFileID string `json:"small_file_id"`
|
|
||||||
BigFileID string `json:"big_file_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chat contains information about the place a message was sent.
|
|
||||||
type Chat struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Title string `json:"title"` // optional
|
|
||||||
UserName string `json:"username"` // optional
|
|
||||||
FirstName string `json:"first_name"` // optional
|
|
||||||
LastName string `json:"last_name"` // optional
|
|
||||||
AllMembersAreAdmins bool `json:"all_members_are_administrators"` // optional
|
|
||||||
Photo *ChatPhoto `json:"photo"`
|
|
||||||
Description string `json:"description,omitempty"` // optional
|
|
||||||
InviteLink string `json:"invite_link,omitempty"` // optional
|
|
||||||
PinnedMessage *Message `json:"pinned_message"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPrivate returns if the Chat is a private conversation.
|
|
||||||
func (c Chat) IsPrivate() bool {
|
|
||||||
return c.Type == "private"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsGroup returns if the Chat is a group.
|
|
||||||
func (c Chat) IsGroup() bool {
|
|
||||||
return c.Type == "group"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSuperGroup returns if the Chat is a supergroup.
|
|
||||||
func (c Chat) IsSuperGroup() bool {
|
|
||||||
return c.Type == "supergroup"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsChannel returns if the Chat is a channel.
|
|
||||||
func (c Chat) IsChannel() bool {
|
|
||||||
return c.Type == "channel"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChatConfig returns a ChatConfig struct for chat related methods.
|
|
||||||
func (c Chat) ChatConfig() ChatConfig {
|
|
||||||
return ChatConfig{ChatID: c.ID}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message is returned by almost every request, and contains data about
|
|
||||||
// almost anything.
|
|
||||||
type Message struct {
|
|
||||||
MessageID int `json:"message_id"`
|
|
||||||
From *User `json:"from"` // optional
|
|
||||||
Date int `json:"date"`
|
|
||||||
Chat *Chat `json:"chat"`
|
|
||||||
ForwardFrom *User `json:"forward_from"` // optional
|
|
||||||
ForwardFromChat *Chat `json:"forward_from_chat"` // optional
|
|
||||||
ForwardFromMessageID int `json:"forward_from_message_id"` // optional
|
|
||||||
ForwardDate int `json:"forward_date"` // optional
|
|
||||||
ReplyToMessage *Message `json:"reply_to_message"` // optional
|
|
||||||
EditDate int `json:"edit_date"` // optional
|
|
||||||
Text string `json:"text"` // optional
|
|
||||||
Entities *[]MessageEntity `json:"entities"` // optional
|
|
||||||
CaptionEntities *[]MessageEntity `json:"caption_entities"` // optional
|
|
||||||
Audio *Audio `json:"audio"` // optional
|
|
||||||
Document *Document `json:"document"` // optional
|
|
||||||
Animation *ChatAnimation `json:"animation"` // optional
|
|
||||||
Game *Game `json:"game"` // optional
|
|
||||||
Photo *[]PhotoSize `json:"photo"` // optional
|
|
||||||
Sticker *Sticker `json:"sticker"` // optional
|
|
||||||
Video *Video `json:"video"` // optional
|
|
||||||
VideoNote *VideoNote `json:"video_note"` // optional
|
|
||||||
Voice *Voice `json:"voice"` // optional
|
|
||||||
Caption string `json:"caption"` // optional
|
|
||||||
Contact *Contact `json:"contact"` // optional
|
|
||||||
Location *Location `json:"location"` // optional
|
|
||||||
Venue *Venue `json:"venue"` // optional
|
|
||||||
NewChatMembers *[]User `json:"new_chat_members"` // optional
|
|
||||||
LeftChatMember *User `json:"left_chat_member"` // optional
|
|
||||||
NewChatTitle string `json:"new_chat_title"` // optional
|
|
||||||
NewChatPhoto *[]PhotoSize `json:"new_chat_photo"` // optional
|
|
||||||
DeleteChatPhoto bool `json:"delete_chat_photo"` // optional
|
|
||||||
GroupChatCreated bool `json:"group_chat_created"` // optional
|
|
||||||
SuperGroupChatCreated bool `json:"supergroup_chat_created"` // optional
|
|
||||||
ChannelChatCreated bool `json:"channel_chat_created"` // optional
|
|
||||||
MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional
|
|
||||||
MigrateFromChatID int64 `json:"migrate_from_chat_id"` // optional
|
|
||||||
PinnedMessage *Message `json:"pinned_message"` // optional
|
|
||||||
Invoice *Invoice `json:"invoice"` // optional
|
|
||||||
SuccessfulPayment *SuccessfulPayment `json:"successful_payment"` // optional
|
|
||||||
PassportData *PassportData `json:"passport_data,omitempty"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time converts the message timestamp into a Time.
|
|
||||||
func (m *Message) Time() time.Time {
|
|
||||||
return time.Unix(int64(m.Date), 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCommand returns true if message starts with a "bot_command" entity.
|
|
||||||
func (m *Message) IsCommand() bool {
|
|
||||||
if m.Entities == nil || len(*m.Entities) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
entity := (*m.Entities)[0]
|
|
||||||
return entity.Offset == 0 && entity.IsCommand()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command checks if the message was a command and if it was, returns the
|
|
||||||
// command. If the Message was not a command, it returns an empty string.
|
|
||||||
//
|
|
||||||
// If the command contains the at name syntax, it is removed. Use
|
|
||||||
// CommandWithAt() if you do not want that.
|
|
||||||
func (m *Message) Command() string {
|
|
||||||
command := m.CommandWithAt()
|
|
||||||
|
|
||||||
if i := strings.Index(command, "@"); i != -1 {
|
|
||||||
command = command[:i]
|
|
||||||
}
|
|
||||||
|
|
||||||
return command
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommandWithAt checks if the message was a command and if it was, returns the
|
|
||||||
// command. If the Message was not a command, it returns an empty string.
|
|
||||||
//
|
|
||||||
// If the command contains the at name syntax, it is not removed. Use Command()
|
|
||||||
// if you want that.
|
|
||||||
func (m *Message) CommandWithAt() string {
|
|
||||||
if !m.IsCommand() {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCommand() checks that the message begins with a bot_command entity
|
|
||||||
entity := (*m.Entities)[0]
|
|
||||||
return m.Text[1:entity.Length]
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommandArguments checks if the message was a command and if it was,
|
|
||||||
// returns all text after the command name. If the Message was not a
|
|
||||||
// command, it returns an empty string.
|
|
||||||
//
|
|
||||||
// Note: The first character after the command name is omitted:
|
|
||||||
// - "/foo bar baz" yields "bar baz", not " bar baz"
|
|
||||||
// - "/foo-bar baz" yields "bar baz", too
|
|
||||||
// Even though the latter is not a command conforming to the spec, the API
|
|
||||||
// marks "/foo" as command entity.
|
|
||||||
func (m *Message) CommandArguments() string {
|
|
||||||
if !m.IsCommand() {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCommand() checks that the message begins with a bot_command entity
|
|
||||||
entity := (*m.Entities)[0]
|
|
||||||
if len(m.Text) == entity.Length {
|
|
||||||
return "" // The command makes up the whole message
|
|
||||||
}
|
|
||||||
|
|
||||||
return m.Text[entity.Length+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// MessageEntity contains information about data in a Message.
|
|
||||||
type MessageEntity struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Length int `json:"length"`
|
|
||||||
URL string `json:"url"` // optional
|
|
||||||
User *User `json:"user"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseURL attempts to parse a URL contained within a MessageEntity.
|
|
||||||
func (e MessageEntity) ParseURL() (*url.URL, error) {
|
|
||||||
if e.URL == "" {
|
|
||||||
return nil, errors.New(ErrBadURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.Parse(e.URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMention returns true if the type of the message entity is "mention" (@username).
|
|
||||||
func (e MessageEntity) IsMention() bool {
|
|
||||||
return e.Type == "mention"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsHashtag returns true if the type of the message entity is "hashtag".
|
|
||||||
func (e MessageEntity) IsHashtag() bool {
|
|
||||||
return e.Type == "hashtag"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCommand returns true if the type of the message entity is "bot_command".
|
|
||||||
func (e MessageEntity) IsCommand() bool {
|
|
||||||
return e.Type == "bot_command"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUrl returns true if the type of the message entity is "url".
|
|
||||||
func (e MessageEntity) IsUrl() bool {
|
|
||||||
return e.Type == "url"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEmail returns true if the type of the message entity is "email".
|
|
||||||
func (e MessageEntity) IsEmail() bool {
|
|
||||||
return e.Type == "email"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsBold returns true if the type of the message entity is "bold" (bold text).
|
|
||||||
func (e MessageEntity) IsBold() bool {
|
|
||||||
return e.Type == "bold"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsItalic returns true if the type of the message entity is "italic" (italic text).
|
|
||||||
func (e MessageEntity) IsItalic() bool {
|
|
||||||
return e.Type == "italic"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCode returns true if the type of the message entity is "code" (monowidth string).
|
|
||||||
func (e MessageEntity) IsCode() bool {
|
|
||||||
return e.Type == "code"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPre returns true if the type of the message entity is "pre" (monowidth block).
|
|
||||||
func (e MessageEntity) IsPre() bool {
|
|
||||||
return e.Type == "pre"
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsTextLink returns true if the type of the message entity is "text_link" (clickable text URL).
|
|
||||||
func (e MessageEntity) IsTextLink() bool {
|
|
||||||
return e.Type == "text_link"
|
|
||||||
}
|
|
||||||
|
|
||||||
// PhotoSize contains information about photos.
|
|
||||||
type PhotoSize struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Width int `json:"width"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio contains information about audio.
|
|
||||||
type Audio struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Duration int `json:"duration"`
|
|
||||||
Performer string `json:"performer"` // optional
|
|
||||||
Title string `json:"title"` // optional
|
|
||||||
MimeType string `json:"mime_type"` // optional
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Document contains information about a document.
|
|
||||||
type Document struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Thumbnail *PhotoSize `json:"thumb"` // optional
|
|
||||||
FileName string `json:"file_name"` // optional
|
|
||||||
MimeType string `json:"mime_type"` // optional
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sticker contains information about a sticker.
|
|
||||||
type Sticker struct {
|
|
||||||
FileUniqueID string `json:"file_unique_id"`
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Width int `json:"width"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
Thumbnail *PhotoSize `json:"thumb"` // optional
|
|
||||||
Emoji string `json:"emoji"` // optional
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
SetName string `json:"set_name"` // optional
|
|
||||||
IsAnimated bool `json:"is_animated"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
type StickerSet struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
IsAnimated bool `json:"is_animated"`
|
|
||||||
ContainsMasks bool `json:"contains_masks"`
|
|
||||||
Stickers []Sticker `json:"stickers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChatAnimation contains information about an animation.
|
|
||||||
type ChatAnimation struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Width int `json:"width"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
Duration int `json:"duration"`
|
|
||||||
Thumbnail *PhotoSize `json:"thumb"` // optional
|
|
||||||
FileName string `json:"file_name"` // optional
|
|
||||||
MimeType string `json:"mime_type"` // optional
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Video contains information about a video.
|
|
||||||
type Video struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Width int `json:"width"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
Duration int `json:"duration"`
|
|
||||||
Thumbnail *PhotoSize `json:"thumb"` // optional
|
|
||||||
MimeType string `json:"mime_type"` // optional
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// VideoNote contains information about a video.
|
|
||||||
type VideoNote struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Length int `json:"length"`
|
|
||||||
Duration int `json:"duration"`
|
|
||||||
Thumbnail *PhotoSize `json:"thumb"` // optional
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Voice contains information about a voice.
|
|
||||||
type Voice struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Duration int `json:"duration"`
|
|
||||||
MimeType string `json:"mime_type"` // optional
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contact contains information about a contact.
|
|
||||||
//
|
|
||||||
// Note that LastName and UserID may be empty.
|
|
||||||
type Contact struct {
|
|
||||||
PhoneNumber string `json:"phone_number"`
|
|
||||||
FirstName string `json:"first_name"`
|
|
||||||
LastName string `json:"last_name"` // optional
|
|
||||||
UserID int `json:"user_id"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Location contains information about a place.
|
|
||||||
type Location struct {
|
|
||||||
Longitude float64 `json:"longitude"`
|
|
||||||
Latitude float64 `json:"latitude"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Venue contains information about a venue, including its Location.
|
|
||||||
type Venue struct {
|
|
||||||
Location Location `json:"location"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Address string `json:"address"`
|
|
||||||
FoursquareID string `json:"foursquare_id"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserProfilePhotos contains a set of user profile photos.
|
|
||||||
type UserProfilePhotos struct {
|
|
||||||
TotalCount int `json:"total_count"`
|
|
||||||
Photos [][]PhotoSize `json:"photos"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// File contains information about a file to download from Telegram.
|
|
||||||
type File struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
FileSize int `json:"file_size"` // optional
|
|
||||||
FilePath string `json:"file_path"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// Link returns a full path to the download URL for a File.
|
|
||||||
//
|
|
||||||
// It requires the Bot Token to create the link.
|
|
||||||
func (f *File) Link(token string) string {
|
|
||||||
return fmt.Sprintf(FileEndpoint, token, f.FilePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplyKeyboardMarkup allows the Bot to set a custom keyboard.
|
|
||||||
type ReplyKeyboardMarkup struct {
|
|
||||||
Keyboard [][]KeyboardButton `json:"keyboard"`
|
|
||||||
ResizeKeyboard bool `json:"resize_keyboard"` // optional
|
|
||||||
OneTimeKeyboard bool `json:"one_time_keyboard"` // optional
|
|
||||||
Selective bool `json:"selective"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyboardButton is a button within a custom keyboard.
|
|
||||||
type KeyboardButton struct {
|
|
||||||
Text string `json:"text"`
|
|
||||||
RequestContact bool `json:"request_contact"`
|
|
||||||
RequestLocation bool `json:"request_location"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplyKeyboardHide allows the Bot to hide a custom keyboard.
|
|
||||||
type ReplyKeyboardHide struct {
|
|
||||||
HideKeyboard bool `json:"hide_keyboard"`
|
|
||||||
Selective bool `json:"selective"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReplyKeyboardRemove allows the Bot to hide a custom keyboard.
|
|
||||||
type ReplyKeyboardRemove struct {
|
|
||||||
RemoveKeyboard bool `json:"remove_keyboard"`
|
|
||||||
Selective bool `json:"selective"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineKeyboardMarkup is a custom keyboard presented for an inline bot.
|
|
||||||
type InlineKeyboardMarkup struct {
|
|
||||||
InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineKeyboardButton is a button within a custom keyboard for
|
|
||||||
// inline query responses.
|
|
||||||
//
|
|
||||||
// Note that some values are references as even an empty string
|
|
||||||
// will change behavior.
|
|
||||||
//
|
|
||||||
// CallbackGame, if set, MUST be first button in first row.
|
|
||||||
type InlineKeyboardButton struct {
|
|
||||||
Text string `json:"text"`
|
|
||||||
URL *string `json:"url,omitempty"` // optional
|
|
||||||
CallbackData *string `json:"callback_data,omitempty"` // optional
|
|
||||||
SwitchInlineQuery *string `json:"switch_inline_query,omitempty"` // optional
|
|
||||||
SwitchInlineQueryCurrentChat *string `json:"switch_inline_query_current_chat,omitempty"` // optional
|
|
||||||
CallbackGame *CallbackGame `json:"callback_game,omitempty"` // optional
|
|
||||||
Pay bool `json:"pay,omitempty"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// CallbackQuery is data sent when a keyboard button with callback data
|
|
||||||
// is clicked.
|
|
||||||
type CallbackQuery struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
From *User `json:"from"`
|
|
||||||
Message *Message `json:"message"` // optional
|
|
||||||
InlineMessageID string `json:"inline_message_id"` // optional
|
|
||||||
ChatInstance string `json:"chat_instance"`
|
|
||||||
Data string `json:"data"` // optional
|
|
||||||
GameShortName string `json:"game_short_name"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForceReply allows the Bot to have users directly reply to it without
|
|
||||||
// additional interaction.
|
|
||||||
type ForceReply struct {
|
|
||||||
ForceReply bool `json:"force_reply"`
|
|
||||||
Selective bool `json:"selective"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChatMember is information about a member in a chat.
|
|
||||||
type ChatMember struct {
|
|
||||||
User *User `json:"user"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
UntilDate int64 `json:"until_date,omitempty"` // optional
|
|
||||||
CanBeEdited bool `json:"can_be_edited,omitempty"` // optional
|
|
||||||
CanChangeInfo bool `json:"can_change_info,omitempty"` // optional
|
|
||||||
CanPostMessages bool `json:"can_post_messages,omitempty"` // optional
|
|
||||||
CanEditMessages bool `json:"can_edit_messages,omitempty"` // optional
|
|
||||||
CanDeleteMessages bool `json:"can_delete_messages,omitempty"` // optional
|
|
||||||
CanInviteUsers bool `json:"can_invite_users,omitempty"` // optional
|
|
||||||
CanRestrictMembers bool `json:"can_restrict_members,omitempty"` // optional
|
|
||||||
CanPinMessages bool `json:"can_pin_messages,omitempty"` // optional
|
|
||||||
CanPromoteMembers bool `json:"can_promote_members,omitempty"` // optional
|
|
||||||
CanSendMessages bool `json:"can_send_messages,omitempty"` // optional
|
|
||||||
CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"` // optional
|
|
||||||
CanSendOtherMessages bool `json:"can_send_other_messages,omitempty"` // optional
|
|
||||||
CanAddWebPagePreviews bool `json:"can_add_web_page_previews,omitempty"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsCreator returns if the ChatMember was the creator of the chat.
|
|
||||||
func (chat ChatMember) IsCreator() bool { return chat.Status == "creator" }
|
|
||||||
|
|
||||||
// IsAdministrator returns if the ChatMember is a chat administrator.
|
|
||||||
func (chat ChatMember) IsAdministrator() bool { return chat.Status == "administrator" }
|
|
||||||
|
|
||||||
// IsMember returns if the ChatMember is a current member of the chat.
|
|
||||||
func (chat ChatMember) IsMember() bool { return chat.Status == "member" }
|
|
||||||
|
|
||||||
// HasLeft returns if the ChatMember left the chat.
|
|
||||||
func (chat ChatMember) HasLeft() bool { return chat.Status == "left" }
|
|
||||||
|
|
||||||
// WasKicked returns if the ChatMember was kicked from the chat.
|
|
||||||
func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" }
|
|
||||||
|
|
||||||
// Game is a game within Telegram.
|
|
||||||
type Game struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Photo []PhotoSize `json:"photo"`
|
|
||||||
Text string `json:"text"`
|
|
||||||
TextEntities []MessageEntity `json:"text_entities"`
|
|
||||||
Animation Animation `json:"animation"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Animation is a GIF animation demonstrating the game.
|
|
||||||
type Animation struct {
|
|
||||||
FileID string `json:"file_id"`
|
|
||||||
Thumb PhotoSize `json:"thumb"`
|
|
||||||
FileName string `json:"file_name"`
|
|
||||||
MimeType string `json:"mime_type"`
|
|
||||||
FileSize int `json:"file_size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GameHighScore is a user's score and position on the leaderboard.
|
|
||||||
type GameHighScore struct {
|
|
||||||
Position int `json:"position"`
|
|
||||||
User User `json:"user"`
|
|
||||||
Score int `json:"score"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CallbackGame is for starting a game in an inline keyboard button.
|
|
||||||
type CallbackGame struct{}
|
|
||||||
|
|
||||||
// WebhookInfo is information about a currently set webhook.
|
|
||||||
type WebhookInfo struct {
|
|
||||||
URL string `json:"url"`
|
|
||||||
HasCustomCertificate bool `json:"has_custom_certificate"`
|
|
||||||
PendingUpdateCount int `json:"pending_update_count"`
|
|
||||||
LastErrorDate int `json:"last_error_date"` // optional
|
|
||||||
LastErrorMessage string `json:"last_error_message"` // optional
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSet returns true if a webhook is currently set.
|
|
||||||
func (info WebhookInfo) IsSet() bool {
|
|
||||||
return info.URL != ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputMediaPhoto contains a photo for displaying as part of a media group.
|
|
||||||
type InputMediaPhoto struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Media string `json:"media"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputMediaVideo contains a video for displaying as part of a media group.
|
|
||||||
type InputMediaVideo struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Media string `json:"media"`
|
|
||||||
// thumb intentionally missing as it is not currently compatible
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
Width int `json:"width"`
|
|
||||||
Height int `json:"height"`
|
|
||||||
Duration int `json:"duration"`
|
|
||||||
SupportsStreaming bool `json:"supports_streaming"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQuery is a Query from Telegram for an inline request.
|
|
||||||
type InlineQuery struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
From *User `json:"from"`
|
|
||||||
Location *Location `json:"location"` // optional
|
|
||||||
Query string `json:"query"`
|
|
||||||
Offset string `json:"offset"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultArticle is an inline query response article.
|
|
||||||
type InlineQueryResultArticle struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"` // required
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
HideURL bool `json:"hide_url"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
ThumbURL string `json:"thumb_url"`
|
|
||||||
ThumbWidth int `json:"thumb_width"`
|
|
||||||
ThumbHeight int `json:"thumb_height"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultPhoto is an inline query response photo.
|
|
||||||
type InlineQueryResultPhoto struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
URL string `json:"photo_url"` // required
|
|
||||||
MimeType string `json:"mime_type"`
|
|
||||||
Width int `json:"photo_width"`
|
|
||||||
Height int `json:"photo_height"`
|
|
||||||
ThumbURL string `json:"thumb_url"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultCachedPhoto is an inline query response with cached photo.
|
|
||||||
type InlineQueryResultCachedPhoto struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
PhotoID string `json:"photo_file_id"` // required
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultGIF is an inline query response GIF.
|
|
||||||
type InlineQueryResultGIF struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
URL string `json:"gif_url"` // required
|
|
||||||
ThumbURL string `json:"thumb_url"` // required
|
|
||||||
Width int `json:"gif_width,omitempty"`
|
|
||||||
Height int `json:"gif_height,omitempty"`
|
|
||||||
Duration int `json:"gif_duration,omitempty"`
|
|
||||||
Title string `json:"title,omitempty"`
|
|
||||||
Caption string `json:"caption,omitempty"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultCachedGIF is an inline query response with cached gif.
|
|
||||||
type InlineQueryResultCachedGIF struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
GifID string `json:"gif_file_id"` // required
|
|
||||||
Title string `json:"title"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF.
|
|
||||||
type InlineQueryResultMPEG4GIF struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
URL string `json:"mpeg4_url"` // required
|
|
||||||
Width int `json:"mpeg4_width"`
|
|
||||||
Height int `json:"mpeg4_height"`
|
|
||||||
Duration int `json:"mpeg4_duration"`
|
|
||||||
ThumbURL string `json:"thumb_url"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultCachedMpeg4Gif is an inline query response with cached
|
|
||||||
// H.264/MPEG-4 AVC video without sound gif.
|
|
||||||
type InlineQueryResultCachedMpeg4Gif struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
MGifID string `json:"mpeg4_file_id"` // required
|
|
||||||
Title string `json:"title"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultVideo is an inline query response video.
|
|
||||||
type InlineQueryResultVideo struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
URL string `json:"video_url"` // required
|
|
||||||
MimeType string `json:"mime_type"` // required
|
|
||||||
ThumbURL string `json:"thumb_url"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
Width int `json:"video_width"`
|
|
||||||
Height int `json:"video_height"`
|
|
||||||
Duration int `json:"video_duration"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultCachedVideo is an inline query response with cached video.
|
|
||||||
type InlineQueryResultCachedVideo struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
VideoID string `json:"video_file_id"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
Description string `json:"description"`
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultAudio is an inline query response audio.
|
|
||||||
type InlineQueryResultAudio struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
URL string `json:"audio_url"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
Performer string `json:"performer"`
|
|
||||||
Duration int `json:"audio_duration"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultCachedAudio is an inline query response with cached audio.
|
|
||||||
type InlineQueryResultCachedAudio struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
AudioID string `json:"audio_file_id"` // required
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultVoice is an inline query response voice.
|
|
||||||
type InlineQueryResultVoice struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
URL string `json:"voice_url"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
Duration int `json:"voice_duration"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultCachedVoice is an inline query response with cached voice.
|
|
||||||
type InlineQueryResultCachedVoice struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
VoiceID string `json:"voice_file_id"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultDocument is an inline query response document.
|
|
||||||
type InlineQueryResultDocument struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
URL string `json:"document_url"` // required
|
|
||||||
MimeType string `json:"mime_type"` // required
|
|
||||||
Description string `json:"description"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
ThumbURL string `json:"thumb_url"`
|
|
||||||
ThumbWidth int `json:"thumb_width"`
|
|
||||||
ThumbHeight int `json:"thumb_height"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultCachedDocument is an inline query response with cached document.
|
|
||||||
type InlineQueryResultCachedDocument struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
DocumentID string `json:"document_file_id"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
Caption string `json:"caption"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultLocation is an inline query response location.
|
|
||||||
type InlineQueryResultLocation struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
Latitude float64 `json:"latitude"` // required
|
|
||||||
Longitude float64 `json:"longitude"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
ThumbURL string `json:"thumb_url"`
|
|
||||||
ThumbWidth int `json:"thumb_width"`
|
|
||||||
ThumbHeight int `json:"thumb_height"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultVenue is an inline query response venue.
|
|
||||||
type InlineQueryResultVenue struct {
|
|
||||||
Type string `json:"type"` // required
|
|
||||||
ID string `json:"id"` // required
|
|
||||||
Latitude float64 `json:"latitude"` // required
|
|
||||||
Longitude float64 `json:"longitude"` // required
|
|
||||||
Title string `json:"title"` // required
|
|
||||||
Address string `json:"address"` // required
|
|
||||||
FoursquareID string `json:"foursquare_id"`
|
|
||||||
FoursquareType string `json:"foursquare_type"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
|
||||||
ThumbURL string `json:"thumb_url"`
|
|
||||||
ThumbWidth int `json:"thumb_width"`
|
|
||||||
ThumbHeight int `json:"thumb_height"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InlineQueryResultGame is an inline query response game.
|
|
||||||
type InlineQueryResultGame struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
ID string `json:"id"`
|
|
||||||
GameShortName string `json:"game_short_name"`
|
|
||||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChosenInlineResult is an inline query result chosen by a User
|
|
||||||
type ChosenInlineResult struct {
|
|
||||||
ResultID string `json:"result_id"`
|
|
||||||
From *User `json:"from"`
|
|
||||||
Location *Location `json:"location"`
|
|
||||||
InlineMessageID string `json:"inline_message_id"`
|
|
||||||
Query string `json:"query"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputTextMessageContent contains text for displaying
|
|
||||||
// as an inline query result.
|
|
||||||
type InputTextMessageContent struct {
|
|
||||||
Text string `json:"message_text"`
|
|
||||||
ParseMode string `json:"parse_mode"`
|
|
||||||
DisableWebPagePreview bool `json:"disable_web_page_preview"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputLocationMessageContent contains a location for displaying
|
|
||||||
// as an inline query result.
|
|
||||||
type InputLocationMessageContent struct {
|
|
||||||
Latitude float64 `json:"latitude"`
|
|
||||||
Longitude float64 `json:"longitude"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputVenueMessageContent contains a venue for displaying
|
|
||||||
// as an inline query result.
|
|
||||||
type InputVenueMessageContent struct {
|
|
||||||
Latitude float64 `json:"latitude"`
|
|
||||||
Longitude float64 `json:"longitude"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Address string `json:"address"`
|
|
||||||
FoursquareID string `json:"foursquare_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// InputContactMessageContent contains a contact for displaying
|
|
||||||
// as an inline query result.
|
|
||||||
type InputContactMessageContent struct {
|
|
||||||
PhoneNumber string `json:"phone_number"`
|
|
||||||
FirstName string `json:"first_name"`
|
|
||||||
LastName string `json:"last_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoice contains basic information about an invoice.
|
|
||||||
type Invoice struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
StartParameter string `json:"start_parameter"`
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
TotalAmount int `json:"total_amount"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// LabeledPrice represents a portion of the price for goods or services.
|
|
||||||
type LabeledPrice struct {
|
|
||||||
Label string `json:"label"`
|
|
||||||
Amount int `json:"amount"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShippingAddress represents a shipping address.
|
|
||||||
type ShippingAddress struct {
|
|
||||||
CountryCode string `json:"country_code"`
|
|
||||||
State string `json:"state"`
|
|
||||||
City string `json:"city"`
|
|
||||||
StreetLine1 string `json:"street_line1"`
|
|
||||||
StreetLine2 string `json:"street_line2"`
|
|
||||||
PostCode string `json:"post_code"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// OrderInfo represents information about an order.
|
|
||||||
type OrderInfo struct {
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
PhoneNumber string `json:"phone_number,omitempty"`
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShippingOption represents one shipping option.
|
|
||||||
type ShippingOption struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Prices *[]LabeledPrice `json:"prices"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SuccessfulPayment contains basic information about a successful payment.
|
|
||||||
type SuccessfulPayment struct {
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
TotalAmount int `json:"total_amount"`
|
|
||||||
InvoicePayload string `json:"invoice_payload"`
|
|
||||||
ShippingOptionID string `json:"shipping_option_id,omitempty"`
|
|
||||||
OrderInfo *OrderInfo `json:"order_info,omitempty"`
|
|
||||||
TelegramPaymentChargeID string `json:"telegram_payment_charge_id"`
|
|
||||||
ProviderPaymentChargeID string `json:"provider_payment_charge_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShippingQuery contains information about an incoming shipping query.
|
|
||||||
type ShippingQuery struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
From *User `json:"from"`
|
|
||||||
InvoicePayload string `json:"invoice_payload"`
|
|
||||||
ShippingAddress *ShippingAddress `json:"shipping_address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PreCheckoutQuery contains information about an incoming pre-checkout query.
|
|
||||||
type PreCheckoutQuery struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
From *User `json:"from"`
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
TotalAmount int `json:"total_amount"`
|
|
||||||
InvoicePayload string `json:"invoice_payload"`
|
|
||||||
ShippingOptionID string `json:"shipping_option_id,omitempty"`
|
|
||||||
OrderInfo *OrderInfo `json:"order_info,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error is an error containing extra information returned by the Telegram API.
|
|
||||||
type Error struct {
|
|
||||||
Code int
|
|
||||||
Message string
|
|
||||||
ResponseParameters
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e Error) Error() string {
|
|
||||||
return e.Message
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
.idea/
|
.idea/
|
||||||
coverage.out
|
coverage.out
|
||||||
tmp/
|
tmp/
|
||||||
|
book/
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
# Golang bindings for the Telegram Bot API
|
# Golang bindings for the Telegram Bot API
|
||||||
|
|
||||||
[](http://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api)
|
[](https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5)
|
||||||
[](https://travis-ci.org/go-telegram-bot-api/telegram-bot-api)
|
[](https://github.com/go-telegram-bot-api/telegram-bot-api/actions/workflows/test.yml)
|
||||||
|
|
||||||
All methods are fairly self explanatory, and reading the [godoc](http://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api) page should
|
All methods are fairly self-explanatory, and reading the [godoc](https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5) page should
|
||||||
explain everything. If something isn't clear, open an issue or submit
|
explain everything. If something isn't clear, open an issue or submit
|
||||||
a pull request.
|
a pull request.
|
||||||
|
|
||||||
|
There are more tutorials and high-level information on the website, [go-telegram-bot-api.dev](https://go-telegram-bot-api.dev).
|
||||||
|
|
||||||
The scope of this project is just to provide a wrapper around the API
|
The scope of this project is just to provide a wrapper around the API
|
||||||
without any additional features. There are other projects for creating
|
without any additional features. There are other projects for creating
|
||||||
something with plugins and command handlers without having to design
|
something with plugins and command handlers without having to design
|
||||||
@@ -18,7 +20,7 @@ you want to ask questions or discuss development.
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
First, ensure the library is installed and up to date by running
|
First, ensure the library is installed and up to date by running
|
||||||
`go get -u github.com/go-telegram-bot-api/telegram-bot-api`.
|
`go get -u github.com/go-telegram-bot-api/telegram-bot-api/v5`.
|
||||||
|
|
||||||
This is a very simple bot that just displays any gotten updates,
|
This is a very simple bot that just displays any gotten updates,
|
||||||
then replies it to that chat.
|
then replies it to that chat.
|
||||||
@@ -29,7 +31,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -45,13 +47,10 @@ func main() {
|
|||||||
u := tgbotapi.NewUpdate(0)
|
u := tgbotapi.NewUpdate(0)
|
||||||
u.Timeout = 60
|
u.Timeout = 60
|
||||||
|
|
||||||
updates, err := bot.GetUpdatesChan(u)
|
updates := bot.GetUpdatesChan(u)
|
||||||
|
|
||||||
for update := range updates {
|
for update := range updates {
|
||||||
if update.Message == nil { // ignore any non-Message Updates
|
if update.Message != nil { // If we got a message
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
|
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
|
||||||
|
|
||||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
|
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
|
||||||
@@ -60,13 +59,9 @@ func main() {
|
|||||||
bot.Send(msg)
|
bot.Send(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
There are more examples on the [wiki](https://github.com/go-telegram-bot-api/telegram-bot-api/wiki)
|
|
||||||
with detailed information on how to do many different kinds of things.
|
|
||||||
It's a great place to get started on using keyboards, commands, or other
|
|
||||||
kinds of reply markup.
|
|
||||||
|
|
||||||
If you need to use webhooks (if you wish to run on Google App Engine),
|
If you need to use webhooks (if you wish to run on Google App Engine),
|
||||||
you may use a slightly different method.
|
you may use a slightly different method.
|
||||||
|
|
||||||
@@ -77,7 +72,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -90,17 +85,22 @@ func main() {
|
|||||||
|
|
||||||
log.Printf("Authorized on account %s", bot.Self.UserName)
|
log.Printf("Authorized on account %s", bot.Self.UserName)
|
||||||
|
|
||||||
_, err = bot.SetWebhook(tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem"))
|
wh, _ := tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem")
|
||||||
|
|
||||||
|
_, err = bot.SetWebhook(wh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := bot.GetWebhookInfo()
|
info, err := bot.GetWebhookInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.LastErrorDate != 0 {
|
if info.LastErrorDate != 0 {
|
||||||
log.Printf("Telegram callback failed: %s", info.LastErrorMessage)
|
log.Printf("Telegram callback failed: %s", info.LastErrorMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
updates := bot.ListenForWebhook("/" + bot.Token)
|
updates := bot.ListenForWebhook("/" + bot.Token)
|
||||||
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
|
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you need, you may generate a self signed certficate, as this requires
|
If you need, you may generate a self-signed certificate, as this requires
|
||||||
HTTPS / TLS. The above example tells Telegram that this is your
|
HTTPS / TLS. The above example tells Telegram that this is your
|
||||||
certificate and that it should be trusted, even though it is not
|
certificate and that it should be trusted, even though it is not
|
||||||
properly signed.
|
properly signed.
|
||||||
9
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/book.toml
generated
vendored
Normal file
9
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/book.toml
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[book]
|
||||||
|
authors = ["Syfaro"]
|
||||||
|
language = "en"
|
||||||
|
multilingual = false
|
||||||
|
src = "docs"
|
||||||
|
title = "Go Telegram Bot API"
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
git-repository-url = "https://github.com/go-telegram-bot-api/telegram-bot-api"
|
||||||
726
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/bot.go
generated
vendored
Normal file
726
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/bot.go
generated
vendored
Normal file
@@ -0,0 +1,726 @@
|
|||||||
|
// Package tgbotapi has functions and types used for interacting with
|
||||||
|
// the Telegram Bot API.
|
||||||
|
package tgbotapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HTTPClient is the type needed for the bot to perform HTTP requests.
|
||||||
|
type HTTPClient interface {
|
||||||
|
Do(req *http.Request) (*http.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BotAPI allows you to interact with the Telegram Bot API.
|
||||||
|
type BotAPI struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
Debug bool `json:"debug"`
|
||||||
|
Buffer int `json:"buffer"`
|
||||||
|
|
||||||
|
Self User `json:"-"`
|
||||||
|
Client HTTPClient `json:"-"`
|
||||||
|
shutdownChannel chan interface{}
|
||||||
|
|
||||||
|
apiEndpoint string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotAPI creates a new BotAPI instance.
|
||||||
|
//
|
||||||
|
// It requires a token, provided by @BotFather on Telegram.
|
||||||
|
func NewBotAPI(token string) (*BotAPI, error) {
|
||||||
|
return NewBotAPIWithClient(token, APIEndpoint, &http.Client{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotAPIWithAPIEndpoint creates a new BotAPI instance
|
||||||
|
// and allows you to pass API endpoint.
|
||||||
|
//
|
||||||
|
// It requires a token, provided by @BotFather on Telegram and API endpoint.
|
||||||
|
func NewBotAPIWithAPIEndpoint(token, apiEndpoint string) (*BotAPI, error) {
|
||||||
|
return NewBotAPIWithClient(token, apiEndpoint, &http.Client{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotAPIWithClient creates a new BotAPI instance
|
||||||
|
// and allows you to pass a http.Client.
|
||||||
|
//
|
||||||
|
// It requires a token, provided by @BotFather on Telegram and API endpoint.
|
||||||
|
func NewBotAPIWithClient(token, apiEndpoint string, client HTTPClient) (*BotAPI, error) {
|
||||||
|
bot := &BotAPI{
|
||||||
|
Token: token,
|
||||||
|
Client: client,
|
||||||
|
Buffer: 100,
|
||||||
|
shutdownChannel: make(chan interface{}),
|
||||||
|
|
||||||
|
apiEndpoint: apiEndpoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
self, err := bot.GetMe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bot.Self = self
|
||||||
|
|
||||||
|
return bot, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAPIEndpoint changes the Telegram Bot API endpoint used by the instance.
|
||||||
|
func (bot *BotAPI) SetAPIEndpoint(apiEndpoint string) {
|
||||||
|
bot.apiEndpoint = apiEndpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildParams(in Params) url.Values {
|
||||||
|
if in == nil {
|
||||||
|
return url.Values{}
|
||||||
|
}
|
||||||
|
|
||||||
|
out := url.Values{}
|
||||||
|
|
||||||
|
for key, value := range in {
|
||||||
|
out.Set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeRequest makes a request to a specific endpoint with our token.
|
||||||
|
func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, error) {
|
||||||
|
if bot.Debug {
|
||||||
|
log.Printf("Endpoint: %s, params: %v\n", endpoint, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint)
|
||||||
|
|
||||||
|
values := buildParams(params)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", method, strings.NewReader(values.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return &APIResponse{}, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
resp, err := bot.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var apiResp APIResponse
|
||||||
|
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
|
||||||
|
if err != nil {
|
||||||
|
return &apiResp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bot.Debug {
|
||||||
|
log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !apiResp.Ok {
|
||||||
|
var parameters ResponseParameters
|
||||||
|
|
||||||
|
if apiResp.Parameters != nil {
|
||||||
|
parameters = *apiResp.Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apiResp, &Error{
|
||||||
|
Code: apiResp.ErrorCode,
|
||||||
|
Message: apiResp.Description,
|
||||||
|
ResponseParameters: parameters,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apiResp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeAPIResponse decode response and return slice of bytes if debug enabled.
|
||||||
|
// If debug disabled, just decode http.Response.Body stream to APIResponse struct
|
||||||
|
// for efficient memory usage
|
||||||
|
func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse) ([]byte, error) {
|
||||||
|
if !bot.Debug {
|
||||||
|
dec := json.NewDecoder(responseBody)
|
||||||
|
err := dec.Decode(resp)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if debug, read response body
|
||||||
|
data, err := ioutil.ReadAll(responseBody)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(data, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadFiles makes a request to the API with files.
|
||||||
|
func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFile) (*APIResponse, error) {
|
||||||
|
r, w := io.Pipe()
|
||||||
|
m := multipart.NewWriter(w)
|
||||||
|
|
||||||
|
// This code modified from the very helpful @HirbodBehnam
|
||||||
|
// https://github.com/go-telegram-bot-api/telegram-bot-api/issues/354#issuecomment-663856473
|
||||||
|
go func() {
|
||||||
|
defer w.Close()
|
||||||
|
defer m.Close()
|
||||||
|
|
||||||
|
for field, value := range params {
|
||||||
|
if err := m.WriteField(field, value); err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if file.Data.NeedsUpload() {
|
||||||
|
name, reader, err := file.Data.UploadData()
|
||||||
|
if err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
part, err := m.CreateFormFile(file.Name, name)
|
||||||
|
if err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(part, reader); err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if closer, ok := reader.(io.ReadCloser); ok {
|
||||||
|
if err = closer.Close(); err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value := file.Data.SendData()
|
||||||
|
|
||||||
|
if err := m.WriteField(file.Name, value); err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if bot.Debug {
|
||||||
|
log.Printf("Endpoint: %s, params: %v, with %d files\n", endpoint, params, len(files))
|
||||||
|
}
|
||||||
|
|
||||||
|
method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint)
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", method, r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", m.FormDataContentType())
|
||||||
|
|
||||||
|
resp, err := bot.Client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
var apiResp APIResponse
|
||||||
|
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
|
||||||
|
if err != nil {
|
||||||
|
return &apiResp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if bot.Debug {
|
||||||
|
log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !apiResp.Ok {
|
||||||
|
var parameters ResponseParameters
|
||||||
|
|
||||||
|
if apiResp.Parameters != nil {
|
||||||
|
parameters = *apiResp.Parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apiResp, &Error{
|
||||||
|
Message: apiResp.Description,
|
||||||
|
ResponseParameters: parameters,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &apiResp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFileDirectURL returns direct URL to file
|
||||||
|
//
|
||||||
|
// It requires the FileID.
|
||||||
|
func (bot *BotAPI) GetFileDirectURL(fileID string) (string, error) {
|
||||||
|
file, err := bot.GetFile(FileConfig{fileID})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return file.Link(bot.Token), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMe fetches the currently authenticated bot.
|
||||||
|
//
|
||||||
|
// This method is called upon creation to validate the token,
|
||||||
|
// and so you may get this data from BotAPI.Self without the need for
|
||||||
|
// another request.
|
||||||
|
func (bot *BotAPI) GetMe() (User, error) {
|
||||||
|
resp, err := bot.MakeRequest("getMe", nil)
|
||||||
|
if err != nil {
|
||||||
|
return User{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var user User
|
||||||
|
err = json.Unmarshal(resp.Result, &user)
|
||||||
|
|
||||||
|
return user, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMessageToMe returns true if message directed to this bot.
|
||||||
|
//
|
||||||
|
// It requires the Message.
|
||||||
|
func (bot *BotAPI) IsMessageToMe(message Message) bool {
|
||||||
|
return strings.Contains(message.Text, "@"+bot.Self.UserName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasFilesNeedingUpload(files []RequestFile) bool {
|
||||||
|
for _, file := range files {
|
||||||
|
if file.Data.NeedsUpload() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request sends a Chattable to Telegram, and returns the APIResponse.
|
||||||
|
func (bot *BotAPI) Request(c Chattable) (*APIResponse, error) {
|
||||||
|
params, err := c.params()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, ok := c.(Fileable); ok {
|
||||||
|
files := t.files()
|
||||||
|
|
||||||
|
// If we have files that need to be uploaded, we should delegate the
|
||||||
|
// request to UploadFile.
|
||||||
|
if hasFilesNeedingUpload(files) {
|
||||||
|
return bot.UploadFiles(t.method(), params, files)
|
||||||
|
}
|
||||||
|
|
||||||
|
// However, if there are no files to be uploaded, there's likely things
|
||||||
|
// that need to be turned into params instead.
|
||||||
|
for _, file := range files {
|
||||||
|
params[file.Name] = file.Data.SendData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bot.MakeRequest(c.method(), params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send will send a Chattable item to Telegram and provides the
|
||||||
|
// returned Message.
|
||||||
|
func (bot *BotAPI) Send(c Chattable) (Message, error) {
|
||||||
|
resp, err := bot.Request(c)
|
||||||
|
if err != nil {
|
||||||
|
return Message{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var message Message
|
||||||
|
err = json.Unmarshal(resp.Result, &message)
|
||||||
|
|
||||||
|
return message, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendMediaGroup sends a media group and returns the resulting messages.
|
||||||
|
func (bot *BotAPI) SendMediaGroup(config MediaGroupConfig) ([]Message, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var messages []Message
|
||||||
|
err = json.Unmarshal(resp.Result, &messages)
|
||||||
|
|
||||||
|
return messages, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserProfilePhotos gets a user's profile photos.
|
||||||
|
//
|
||||||
|
// It requires UserID.
|
||||||
|
// Offset and Limit are optional.
|
||||||
|
func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return UserProfilePhotos{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var profilePhotos UserProfilePhotos
|
||||||
|
err = json.Unmarshal(resp.Result, &profilePhotos)
|
||||||
|
|
||||||
|
return profilePhotos, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFile returns a File which can download a file from Telegram.
|
||||||
|
//
|
||||||
|
// Requires FileID.
|
||||||
|
func (bot *BotAPI) GetFile(config FileConfig) (File, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return File{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var file File
|
||||||
|
err = json.Unmarshal(resp.Result, &file)
|
||||||
|
|
||||||
|
return file, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUpdates fetches updates.
|
||||||
|
// If a WebHook is set, this will not return any data!
|
||||||
|
//
|
||||||
|
// Offset, Limit, Timeout, and AllowedUpdates are optional.
|
||||||
|
// To avoid stale items, set Offset to one higher than the previous item.
|
||||||
|
// Set Timeout to a large number to reduce requests, so you can get updates
|
||||||
|
// instantly instead of having to wait between requests.
|
||||||
|
func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return []Update{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var updates []Update
|
||||||
|
err = json.Unmarshal(resp.Result, &updates)
|
||||||
|
|
||||||
|
return updates, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebhookInfo allows you to fetch information about a webhook and if
|
||||||
|
// one currently is set, along with pending update count and error messages.
|
||||||
|
func (bot *BotAPI) GetWebhookInfo() (WebhookInfo, error) {
|
||||||
|
resp, err := bot.MakeRequest("getWebhookInfo", nil)
|
||||||
|
if err != nil {
|
||||||
|
return WebhookInfo{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var info WebhookInfo
|
||||||
|
err = json.Unmarshal(resp.Result, &info)
|
||||||
|
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUpdatesChan starts and returns a channel for getting updates.
|
||||||
|
func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) UpdatesChannel {
|
||||||
|
ch := make(chan Update, bot.Buffer)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-bot.shutdownChannel:
|
||||||
|
close(ch)
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
updates, err := bot.GetUpdates(config)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
log.Println("Failed to get updates, retrying in 3 seconds...")
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, update := range updates {
|
||||||
|
if update.UpdateID >= config.Offset {
|
||||||
|
config.Offset = update.UpdateID + 1
|
||||||
|
ch <- update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopReceivingUpdates stops the go routine which receives updates
|
||||||
|
func (bot *BotAPI) StopReceivingUpdates() {
|
||||||
|
if bot.Debug {
|
||||||
|
log.Println("Stopping the update receiver routine...")
|
||||||
|
}
|
||||||
|
close(bot.shutdownChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenForWebhook registers a http handler for a webhook.
|
||||||
|
func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel {
|
||||||
|
ch := make(chan Update, bot.Buffer)
|
||||||
|
|
||||||
|
http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
update, err := bot.HandleUpdate(r)
|
||||||
|
if err != nil {
|
||||||
|
errMsg, _ := json.Marshal(map[string]string{"error": err.Error()})
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write(errMsg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ch <- *update
|
||||||
|
})
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenForWebhookRespReqFormat registers a http handler for a single incoming webhook.
|
||||||
|
func (bot *BotAPI) ListenForWebhookRespReqFormat(w http.ResponseWriter, r *http.Request) UpdatesChannel {
|
||||||
|
ch := make(chan Update, bot.Buffer)
|
||||||
|
|
||||||
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
update, err := bot.HandleUpdate(r)
|
||||||
|
if err != nil {
|
||||||
|
errMsg, _ := json.Marshal(map[string]string{"error": err.Error()})
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, _ = w.Write(errMsg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ch <- *update
|
||||||
|
close(ch)
|
||||||
|
}(w, r)
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleUpdate parses and returns update received via webhook
|
||||||
|
func (bot *BotAPI) HandleUpdate(r *http.Request) (*Update, error) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
err := errors.New("wrong HTTP method required POST")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var update Update
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&update)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &update, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteToHTTPResponse writes the request to the HTTP ResponseWriter.
|
||||||
|
//
|
||||||
|
// It doesn't support uploading files.
|
||||||
|
//
|
||||||
|
// See https://core.telegram.org/bots/api#making-requests-when-getting-updates
|
||||||
|
// for details.
|
||||||
|
func WriteToHTTPResponse(w http.ResponseWriter, c Chattable) error {
|
||||||
|
params, err := c.params()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if t, ok := c.(Fileable); ok {
|
||||||
|
if hasFilesNeedingUpload(t.files()) {
|
||||||
|
return errors.New("unable to use http response to upload files")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
values := buildParams(params)
|
||||||
|
values.Set("method", c.method())
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
_, err = w.Write([]byte(values.Encode()))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChat gets information about a chat.
|
||||||
|
func (bot *BotAPI) GetChat(config ChatInfoConfig) (Chat, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return Chat{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var chat Chat
|
||||||
|
err = json.Unmarshal(resp.Result, &chat)
|
||||||
|
|
||||||
|
return chat, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChatAdministrators gets a list of administrators in the chat.
|
||||||
|
//
|
||||||
|
// If none have been appointed, only the creator will be returned.
|
||||||
|
// Bots are not shown, even if they are an administrator.
|
||||||
|
func (bot *BotAPI) GetChatAdministrators(config ChatAdministratorsConfig) ([]ChatMember, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return []ChatMember{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var members []ChatMember
|
||||||
|
err = json.Unmarshal(resp.Result, &members)
|
||||||
|
|
||||||
|
return members, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChatMembersCount gets the number of users in a chat.
|
||||||
|
func (bot *BotAPI) GetChatMembersCount(config ChatMemberCountConfig) (int, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int
|
||||||
|
err = json.Unmarshal(resp.Result, &count)
|
||||||
|
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChatMember gets a specific chat member.
|
||||||
|
func (bot *BotAPI) GetChatMember(config GetChatMemberConfig) (ChatMember, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return ChatMember{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var member ChatMember
|
||||||
|
err = json.Unmarshal(resp.Result, &member)
|
||||||
|
|
||||||
|
return member, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGameHighScores allows you to get the high scores for a game.
|
||||||
|
func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return []GameHighScore{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var highScores []GameHighScore
|
||||||
|
err = json.Unmarshal(resp.Result, &highScores)
|
||||||
|
|
||||||
|
return highScores, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInviteLink get InviteLink for a chat
|
||||||
|
func (bot *BotAPI) GetInviteLink(config ChatInviteLinkConfig) (string, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var inviteLink string
|
||||||
|
err = json.Unmarshal(resp.Result, &inviteLink)
|
||||||
|
|
||||||
|
return inviteLink, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStickerSet returns a StickerSet.
|
||||||
|
func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return StickerSet{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var stickers StickerSet
|
||||||
|
err = json.Unmarshal(resp.Result, &stickers)
|
||||||
|
|
||||||
|
return stickers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopPoll stops a poll and returns the result.
|
||||||
|
func (bot *BotAPI) StopPoll(config StopPollConfig) (Poll, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return Poll{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var poll Poll
|
||||||
|
err = json.Unmarshal(resp.Result, &poll)
|
||||||
|
|
||||||
|
return poll, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyCommands gets the currently registered commands.
|
||||||
|
func (bot *BotAPI) GetMyCommands() ([]BotCommand, error) {
|
||||||
|
return bot.GetMyCommandsWithConfig(GetMyCommandsConfig{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyCommandsWithConfig gets the currently registered commands with a config.
|
||||||
|
func (bot *BotAPI) GetMyCommandsWithConfig(config GetMyCommandsConfig) ([]BotCommand, error) {
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var commands []BotCommand
|
||||||
|
err = json.Unmarshal(resp.Result, &commands)
|
||||||
|
|
||||||
|
return commands, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CopyMessage copy messages of any kind. The method is analogous to the method
|
||||||
|
// forwardMessage, but the copied message doesn't have a link to the original
|
||||||
|
// message. Returns the MessageID of the sent message on success.
|
||||||
|
func (bot *BotAPI) CopyMessage(config CopyMessageConfig) (MessageID, error) {
|
||||||
|
params, err := config.params()
|
||||||
|
if err != nil {
|
||||||
|
return MessageID{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := bot.MakeRequest(config.method(), params)
|
||||||
|
if err != nil {
|
||||||
|
return MessageID{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var messageID MessageID
|
||||||
|
err = json.Unmarshal(resp.Result, &messageID)
|
||||||
|
|
||||||
|
return messageID, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EscapeText takes an input text and escape Telegram markup symbols.
|
||||||
|
// In this way we can send a text without being afraid of having to escape the characters manually.
|
||||||
|
// Note that you don't have to include the formatting style in the input text, or it will be escaped too.
|
||||||
|
// If there is an error, an empty string will be returned.
|
||||||
|
//
|
||||||
|
// parseMode is the text formatting mode (ModeMarkdown, ModeMarkdownV2 or ModeHTML)
|
||||||
|
// text is the input string that will be escaped
|
||||||
|
func EscapeText(parseMode string, text string) string {
|
||||||
|
var replacer *strings.Replacer
|
||||||
|
|
||||||
|
if parseMode == ModeHTML {
|
||||||
|
replacer = strings.NewReplacer("<", "<", ">", ">", "&", "&")
|
||||||
|
} else if parseMode == ModeMarkdown {
|
||||||
|
replacer = strings.NewReplacer("_", "\\_", "*", "\\*", "`", "\\`", "[", "\\[")
|
||||||
|
} else if parseMode == ModeMarkdownV2 {
|
||||||
|
replacer = strings.NewReplacer(
|
||||||
|
"_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(",
|
||||||
|
"\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>",
|
||||||
|
"#", "\\#", "+", "\\+", "-", "\\-", "=", "\\=", "|",
|
||||||
|
"\\|", "{", "\\{", "}", "\\}", ".", "\\.", "!", "\\!",
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacer.Replace(text)
|
||||||
|
}
|
||||||
2468
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/configs.go
generated
vendored
Normal file
2468
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/configs.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -52,241 +52,117 @@ func NewForward(chatID int64, fromChatID int64, messageID int) ForwardConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPhotoUpload creates a new photo uploader.
|
// NewCopyMessage creates a new copy message.
|
||||||
|
//
|
||||||
|
// chatID is where to send it, fromChatID is the source chat,
|
||||||
|
// and messageID is the ID of the original message.
|
||||||
|
func NewCopyMessage(chatID int64, fromChatID int64, messageID int) CopyMessageConfig {
|
||||||
|
return CopyMessageConfig{
|
||||||
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
|
FromChatID: fromChatID,
|
||||||
|
MessageID: messageID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPhoto creates a new sendPhoto request.
|
||||||
//
|
//
|
||||||
// chatID is where to send it, file is a string path to the file,
|
// chatID is where to send it, file is a string path to the file,
|
||||||
// FileReader, or FileBytes.
|
// FileReader, or FileBytes.
|
||||||
//
|
//
|
||||||
// Note that you must send animated GIFs as a document.
|
// Note that you must send animated GIFs as a document.
|
||||||
func NewPhotoUpload(chatID int64, file interface{}) PhotoConfig {
|
func NewPhoto(chatID int64, file RequestFileData) PhotoConfig {
|
||||||
return PhotoConfig{
|
return PhotoConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPhotoShare shares an existing photo.
|
// NewPhotoToChannel creates a new photo uploader to send a photo to a channel.
|
||||||
// You may use this to reshare an existing photo without reuploading it.
|
|
||||||
//
|
//
|
||||||
// chatID is where to send it, fileID is the ID of the file
|
// Note that you must send animated GIFs as a document.
|
||||||
// already uploaded.
|
func NewPhotoToChannel(username string, file RequestFileData) PhotoConfig {
|
||||||
func NewPhotoShare(chatID int64, fileID string) PhotoConfig {
|
|
||||||
return PhotoConfig{
|
return PhotoConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{
|
||||||
FileID: fileID,
|
ChannelUsername: username,
|
||||||
UseExisting: true,
|
},
|
||||||
|
File: file,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAudioUpload creates a new audio uploader.
|
// NewAudio creates a new sendAudio request.
|
||||||
//
|
func NewAudio(chatID int64, file RequestFileData) AudioConfig {
|
||||||
// chatID is where to send it, file is a string path to the file,
|
|
||||||
// FileReader, or FileBytes.
|
|
||||||
func NewAudioUpload(chatID int64, file interface{}) AudioConfig {
|
|
||||||
return AudioConfig{
|
return AudioConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAudioShare shares an existing audio file.
|
// NewDocument creates a new sendDocument request.
|
||||||
// You may use this to reshare an existing audio file without
|
func NewDocument(chatID int64, file RequestFileData) DocumentConfig {
|
||||||
// reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the audio
|
|
||||||
// already uploaded.
|
|
||||||
func NewAudioShare(chatID int64, fileID string) AudioConfig {
|
|
||||||
return AudioConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDocumentUpload creates a new document uploader.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, file is a string path to the file,
|
|
||||||
// FileReader, or FileBytes.
|
|
||||||
func NewDocumentUpload(chatID int64, file interface{}) DocumentConfig {
|
|
||||||
return DocumentConfig{
|
return DocumentConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDocumentShare shares an existing document.
|
// NewSticker creates a new sendSticker request.
|
||||||
// You may use this to reshare an existing document without
|
func NewSticker(chatID int64, file RequestFileData) StickerConfig {
|
||||||
// reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the document
|
|
||||||
// already uploaded.
|
|
||||||
func NewDocumentShare(chatID int64, fileID string) DocumentConfig {
|
|
||||||
return DocumentConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewStickerUpload creates a new sticker uploader.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, file is a string path to the file,
|
|
||||||
// FileReader, or FileBytes.
|
|
||||||
func NewStickerUpload(chatID int64, file interface{}) StickerConfig {
|
|
||||||
return StickerConfig{
|
return StickerConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStickerShare shares an existing sticker.
|
// NewVideo creates a new sendVideo request.
|
||||||
// You may use this to reshare an existing sticker without
|
func NewVideo(chatID int64, file RequestFileData) VideoConfig {
|
||||||
// reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the sticker
|
|
||||||
// already uploaded.
|
|
||||||
func NewStickerShare(chatID int64, fileID string) StickerConfig {
|
|
||||||
return StickerConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVideoUpload creates a new video uploader.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, file is a string path to the file,
|
|
||||||
// FileReader, or FileBytes.
|
|
||||||
func NewVideoUpload(chatID int64, file interface{}) VideoConfig {
|
|
||||||
return VideoConfig{
|
return VideoConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVideoShare shares an existing video.
|
// NewAnimation creates a new sendAnimation request.
|
||||||
// You may use this to reshare an existing video without reuploading it.
|
func NewAnimation(chatID int64, file RequestFileData) AnimationConfig {
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the video
|
|
||||||
// already uploaded.
|
|
||||||
func NewVideoShare(chatID int64, fileID string) VideoConfig {
|
|
||||||
return VideoConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAnimationUpload creates a new animation uploader.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, file is a string path to the file,
|
|
||||||
// FileReader, or FileBytes.
|
|
||||||
func NewAnimationUpload(chatID int64, file interface{}) AnimationConfig {
|
|
||||||
return AnimationConfig{
|
return AnimationConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAnimationShare shares an existing animation.
|
// NewVideoNote creates a new sendVideoNote request.
|
||||||
// You may use this to reshare an existing animation without reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the animation
|
|
||||||
// already uploaded.
|
|
||||||
func NewAnimationShare(chatID int64, fileID string) AnimationConfig {
|
|
||||||
return AnimationConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVideoNoteUpload creates a new video note uploader.
|
|
||||||
//
|
//
|
||||||
// chatID is where to send it, file is a string path to the file,
|
// chatID is where to send it, file is a string path to the file,
|
||||||
// FileReader, or FileBytes.
|
// FileReader, or FileBytes.
|
||||||
func NewVideoNoteUpload(chatID int64, length int, file interface{}) VideoNoteConfig {
|
func NewVideoNote(chatID int64, length int, file RequestFileData) VideoNoteConfig {
|
||||||
return VideoNoteConfig{
|
return VideoNoteConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
Length: length,
|
Length: length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVideoNoteShare shares an existing video.
|
// NewVoice creates a new sendVoice request.
|
||||||
// You may use this to reshare an existing video without reuploading it.
|
func NewVoice(chatID int64, file RequestFileData) VoiceConfig {
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the video
|
|
||||||
// already uploaded.
|
|
||||||
func NewVideoNoteShare(chatID int64, length int, fileID string) VideoNoteConfig {
|
|
||||||
return VideoNoteConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
Length: length,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVoiceUpload creates a new voice uploader.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, file is a string path to the file,
|
|
||||||
// FileReader, or FileBytes.
|
|
||||||
func NewVoiceUpload(chatID int64, file interface{}) VoiceConfig {
|
|
||||||
return VoiceConfig{
|
return VoiceConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVoiceShare shares an existing voice.
|
|
||||||
// You may use this to reshare an existing voice without reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the video
|
|
||||||
// already uploaded.
|
|
||||||
func NewVoiceShare(chatID int64, fileID string) VoiceConfig {
|
|
||||||
return VoiceConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,26 +171,58 @@ func NewVoiceShare(chatID int64, fileID string) VoiceConfig {
|
|||||||
// two to ten InputMediaPhoto or InputMediaVideo.
|
// two to ten InputMediaPhoto or InputMediaVideo.
|
||||||
func NewMediaGroup(chatID int64, files []interface{}) MediaGroupConfig {
|
func NewMediaGroup(chatID int64, files []interface{}) MediaGroupConfig {
|
||||||
return MediaGroupConfig{
|
return MediaGroupConfig{
|
||||||
BaseChat: BaseChat{
|
|
||||||
ChatID: chatID,
|
ChatID: chatID,
|
||||||
},
|
Media: files,
|
||||||
InputMedia: files,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInputMediaPhoto creates a new InputMediaPhoto.
|
// NewInputMediaPhoto creates a new InputMediaPhoto.
|
||||||
func NewInputMediaPhoto(media string) InputMediaPhoto {
|
func NewInputMediaPhoto(media RequestFileData) InputMediaPhoto {
|
||||||
return InputMediaPhoto{
|
return InputMediaPhoto{
|
||||||
|
BaseInputMedia{
|
||||||
Type: "photo",
|
Type: "photo",
|
||||||
Media: media,
|
Media: media,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInputMediaVideo creates a new InputMediaVideo.
|
// NewInputMediaVideo creates a new InputMediaVideo.
|
||||||
func NewInputMediaVideo(media string) InputMediaVideo {
|
func NewInputMediaVideo(media RequestFileData) InputMediaVideo {
|
||||||
return InputMediaVideo{
|
return InputMediaVideo{
|
||||||
|
BaseInputMedia: BaseInputMedia{
|
||||||
Type: "video",
|
Type: "video",
|
||||||
Media: media,
|
Media: media,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInputMediaAnimation creates a new InputMediaAnimation.
|
||||||
|
func NewInputMediaAnimation(media RequestFileData) InputMediaAnimation {
|
||||||
|
return InputMediaAnimation{
|
||||||
|
BaseInputMedia: BaseInputMedia{
|
||||||
|
Type: "animation",
|
||||||
|
Media: media,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInputMediaAudio creates a new InputMediaAudio.
|
||||||
|
func NewInputMediaAudio(media RequestFileData) InputMediaAudio {
|
||||||
|
return InputMediaAudio{
|
||||||
|
BaseInputMedia: BaseInputMedia{
|
||||||
|
Type: "audio",
|
||||||
|
Media: media,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInputMediaDocument creates a new InputMediaDocument.
|
||||||
|
func NewInputMediaDocument(media RequestFileData) InputMediaDocument {
|
||||||
|
return InputMediaDocument{
|
||||||
|
BaseInputMedia: BaseInputMedia{
|
||||||
|
Type: "document",
|
||||||
|
Media: media,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,7 +277,7 @@ func NewChatAction(chatID int64, action string) ChatActionConfig {
|
|||||||
// NewUserProfilePhotos gets user profile photos.
|
// NewUserProfilePhotos gets user profile photos.
|
||||||
//
|
//
|
||||||
// userID is the ID of the user you wish to get profile photos from.
|
// userID is the ID of the user you wish to get profile photos from.
|
||||||
func NewUserProfilePhotos(userID int) UserProfilePhotosConfig {
|
func NewUserProfilePhotos(userID int64) UserProfilePhotosConfig {
|
||||||
return UserProfilePhotosConfig{
|
return UserProfilePhotosConfig{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Offset: 0,
|
Offset: 0,
|
||||||
@@ -392,25 +300,33 @@ func NewUpdate(offset int) UpdateConfig {
|
|||||||
// NewWebhook creates a new webhook.
|
// NewWebhook creates a new webhook.
|
||||||
//
|
//
|
||||||
// link is the url parsable link you wish to get the updates.
|
// link is the url parsable link you wish to get the updates.
|
||||||
func NewWebhook(link string) WebhookConfig {
|
func NewWebhook(link string) (WebhookConfig, error) {
|
||||||
u, _ := url.Parse(link)
|
u, err := url.Parse(link)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return WebhookConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return WebhookConfig{
|
return WebhookConfig{
|
||||||
URL: u,
|
URL: u,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebhookWithCert creates a new webhook with a certificate.
|
// NewWebhookWithCert creates a new webhook with a certificate.
|
||||||
//
|
//
|
||||||
// link is the url you wish to get webhooks,
|
// link is the url you wish to get webhooks,
|
||||||
// file contains a string to a file, FileReader, or FileBytes.
|
// file contains a string to a file, FileReader, or FileBytes.
|
||||||
func NewWebhookWithCert(link string, file interface{}) WebhookConfig {
|
func NewWebhookWithCert(link string, file RequestFileData) (WebhookConfig, error) {
|
||||||
u, _ := url.Parse(link)
|
u, err := url.Parse(link)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return WebhookConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
return WebhookConfig{
|
return WebhookConfig{
|
||||||
URL: u,
|
URL: u,
|
||||||
Certificate: file,
|
Certificate: file,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInlineQueryResultArticle creates a new inline query article.
|
// NewInlineQueryResultArticle creates a new inline query article.
|
||||||
@@ -438,6 +354,19 @@ func NewInlineQueryResultArticleMarkdown(id, title, messageText string) InlineQu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewInlineQueryResultArticleMarkdownV2 creates a new inline query article with MarkdownV2 parsing.
|
||||||
|
func NewInlineQueryResultArticleMarkdownV2(id, title, messageText string) InlineQueryResultArticle {
|
||||||
|
return InlineQueryResultArticle{
|
||||||
|
Type: "article",
|
||||||
|
ID: id,
|
||||||
|
Title: title,
|
||||||
|
InputMessageContent: InputTextMessageContent{
|
||||||
|
Text: messageText,
|
||||||
|
ParseMode: "MarkdownV2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewInlineQueryResultArticleHTML creates a new inline query article with HTML parsing.
|
// NewInlineQueryResultArticleHTML creates a new inline query article with HTML parsing.
|
||||||
func NewInlineQueryResultArticleHTML(id, title, messageText string) InlineQueryResultArticle {
|
func NewInlineQueryResultArticleHTML(id, title, messageText string) InlineQueryResultArticle {
|
||||||
return InlineQueryResultArticle{
|
return InlineQueryResultArticle{
|
||||||
@@ -465,7 +394,7 @@ func NewInlineQueryResultCachedGIF(id, gifID string) InlineQueryResultCachedGIF
|
|||||||
return InlineQueryResultCachedGIF{
|
return InlineQueryResultCachedGIF{
|
||||||
Type: "gif",
|
Type: "gif",
|
||||||
ID: id,
|
ID: id,
|
||||||
GifID: gifID,
|
GIFID: gifID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,12 +407,12 @@ func NewInlineQueryResultMPEG4GIF(id, url string) InlineQueryResultMPEG4GIF {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInlineQueryResultCachedPhoto create a new inline query with cached photo.
|
// NewInlineQueryResultCachedMPEG4GIF create a new inline query with cached MPEG4 GIF.
|
||||||
func NewInlineQueryResultCachedMPEG4GIF(id, MPEG4GifID string) InlineQueryResultCachedMpeg4Gif {
|
func NewInlineQueryResultCachedMPEG4GIF(id, MPEG4GIFID string) InlineQueryResultCachedMPEG4GIF {
|
||||||
return InlineQueryResultCachedMpeg4Gif{
|
return InlineQueryResultCachedMPEG4GIF{
|
||||||
Type: "mpeg4_gif",
|
Type: "mpeg4_gif",
|
||||||
ID: id,
|
ID: id,
|
||||||
MGifID: MPEG4GifID,
|
MPEG4FileID: MPEG4GIFID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,6 +463,16 @@ func NewInlineQueryResultCachedVideo(id, videoID, title string) InlineQueryResul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewInlineQueryResultCachedSticker create a new inline query with cached sticker.
|
||||||
|
func NewInlineQueryResultCachedSticker(id, stickerID, title string) InlineQueryResultCachedSticker {
|
||||||
|
return InlineQueryResultCachedSticker{
|
||||||
|
Type: "sticker",
|
||||||
|
ID: id,
|
||||||
|
StickerID: stickerID,
|
||||||
|
Title: title,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewInlineQueryResultAudio creates a new inline query audio.
|
// NewInlineQueryResultAudio creates a new inline query audio.
|
||||||
func NewInlineQueryResultAudio(id, url, title string) InlineQueryResultAudio {
|
func NewInlineQueryResultAudio(id, url, title string) InlineQueryResultAudio {
|
||||||
return InlineQueryResultAudio{
|
return InlineQueryResultAudio{
|
||||||
@@ -628,6 +567,18 @@ func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewEditMessageTextAndMarkup allows you to edit the text and replymarkup of a message.
|
||||||
|
func NewEditMessageTextAndMarkup(chatID int64, messageID int, text string, replyMarkup InlineKeyboardMarkup) EditMessageTextConfig {
|
||||||
|
return EditMessageTextConfig{
|
||||||
|
BaseEdit: BaseEdit{
|
||||||
|
ChatID: chatID,
|
||||||
|
MessageID: messageID,
|
||||||
|
ReplyMarkup: &replyMarkup,
|
||||||
|
},
|
||||||
|
Text: text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewEditMessageCaption allows you to edit the caption of a message.
|
// NewEditMessageCaption allows you to edit the caption of a message.
|
||||||
func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMessageCaptionConfig {
|
func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMessageCaptionConfig {
|
||||||
return EditMessageCaptionConfig{
|
return EditMessageCaptionConfig{
|
||||||
@@ -651,17 +602,6 @@ func NewEditMessageReplyMarkup(chatID int64, messageID int, replyMarkup InlineKe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHideKeyboard hides the keyboard, with the option for being selective
|
|
||||||
// or hiding for everyone.
|
|
||||||
func NewHideKeyboard(selective bool) ReplyKeyboardHide {
|
|
||||||
log.Println("NewHideKeyboard is deprecated, please use NewRemoveKeyboard")
|
|
||||||
|
|
||||||
return ReplyKeyboardHide{
|
|
||||||
HideKeyboard: true,
|
|
||||||
Selective: selective,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRemoveKeyboard hides the keyboard, with the option for being selective
|
// NewRemoveKeyboard hides the keyboard, with the option for being selective
|
||||||
// or hiding for everyone.
|
// or hiding for everyone.
|
||||||
func NewRemoveKeyboard(selective bool) ReplyKeyboardRemove {
|
func NewRemoveKeyboard(selective bool) ReplyKeyboardRemove {
|
||||||
@@ -717,6 +657,13 @@ func NewReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewOneTimeReplyKeyboard creates a new one time keyboard.
|
||||||
|
func NewOneTimeReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup {
|
||||||
|
markup := NewReplyKeyboard(rows...)
|
||||||
|
markup.OneTimeKeyboard = true
|
||||||
|
return markup
|
||||||
|
}
|
||||||
|
|
||||||
// NewInlineKeyboardButtonData creates an inline keyboard button with text
|
// NewInlineKeyboardButtonData creates an inline keyboard button with text
|
||||||
// and data for a callback.
|
// and data for a callback.
|
||||||
func NewInlineKeyboardButtonData(text, data string) InlineKeyboardButton {
|
func NewInlineKeyboardButtonData(text, data string) InlineKeyboardButton {
|
||||||
@@ -726,6 +673,15 @@ func NewInlineKeyboardButtonData(text, data string) InlineKeyboardButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewInlineKeyboardButtonLoginURL creates an inline keyboard button with text
|
||||||
|
// which goes to a LoginURL.
|
||||||
|
func NewInlineKeyboardButtonLoginURL(text string, loginURL LoginURL) InlineKeyboardButton {
|
||||||
|
return InlineKeyboardButton{
|
||||||
|
Text: text,
|
||||||
|
LoginURL: &loginURL,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewInlineKeyboardButtonURL creates an inline keyboard button with text
|
// NewInlineKeyboardButtonURL creates an inline keyboard button with text
|
||||||
// which goes to a URL.
|
// which goes to a URL.
|
||||||
func NewInlineKeyboardButtonURL(text, url string) InlineKeyboardButton {
|
func NewInlineKeyboardButtonURL(text, url string) InlineKeyboardButton {
|
||||||
@@ -784,7 +740,7 @@ func NewCallbackWithAlert(id, text string) CallbackConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewInvoice creates a new Invoice request to the user.
|
// NewInvoice creates a new Invoice request to the user.
|
||||||
func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices *[]LabeledPrice) InvoiceConfig {
|
func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices []LabeledPrice) InvoiceConfig {
|
||||||
return InvoiceConfig{
|
return InvoiceConfig{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
Title: title,
|
Title: title,
|
||||||
@@ -796,33 +752,176 @@ func NewInvoice(chatID int64, title, description, payload, providerToken, startP
|
|||||||
Prices: prices}
|
Prices: prices}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSetChatPhotoUpload creates a new chat photo uploader.
|
// NewChatTitle allows you to update the title of a chat.
|
||||||
//
|
func NewChatTitle(chatID int64, title string) SetChatTitleConfig {
|
||||||
// chatID is where to send it, file is a string path to the file,
|
return SetChatTitleConfig{
|
||||||
// FileReader, or FileBytes.
|
ChatID: chatID,
|
||||||
//
|
Title: title,
|
||||||
// Note that you must send animated GIFs as a document.
|
}
|
||||||
func NewSetChatPhotoUpload(chatID int64, file interface{}) SetChatPhotoConfig {
|
}
|
||||||
|
|
||||||
|
// NewChatDescription allows you to update the description of a chat.
|
||||||
|
func NewChatDescription(chatID int64, description string) SetChatDescriptionConfig {
|
||||||
|
return SetChatDescriptionConfig{
|
||||||
|
ChatID: chatID,
|
||||||
|
Description: description,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewChatPhoto allows you to update the photo for a chat.
|
||||||
|
func NewChatPhoto(chatID int64, photo RequestFileData) SetChatPhotoConfig {
|
||||||
return SetChatPhotoConfig{
|
return SetChatPhotoConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{
|
||||||
File: file,
|
ChatID: chatID,
|
||||||
UseExisting: false,
|
},
|
||||||
|
File: photo,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSetChatPhotoShare shares an existing photo.
|
// NewDeleteChatPhoto allows you to delete the photo for a chat.
|
||||||
// You may use this to reshare an existing photo without reuploading it.
|
func NewDeleteChatPhoto(chatID int64) DeleteChatPhotoConfig {
|
||||||
//
|
return DeleteChatPhotoConfig{
|
||||||
// chatID is where to send it, fileID is the ID of the file
|
ChatID: chatID,
|
||||||
// already uploaded.
|
}
|
||||||
func NewSetChatPhotoShare(chatID int64, fileID string) SetChatPhotoConfig {
|
}
|
||||||
return SetChatPhotoConfig{
|
|
||||||
BaseFile: BaseFile{
|
// NewPoll allows you to create a new poll.
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
func NewPoll(chatID int64, question string, options ...string) SendPollConfig {
|
||||||
FileID: fileID,
|
return SendPollConfig{
|
||||||
UseExisting: true,
|
BaseChat: BaseChat{
|
||||||
|
ChatID: chatID,
|
||||||
|
},
|
||||||
|
Question: question,
|
||||||
|
Options: options,
|
||||||
|
IsAnonymous: true, // This is Telegram's default.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStopPoll allows you to stop a poll.
|
||||||
|
func NewStopPoll(chatID int64, messageID int) StopPollConfig {
|
||||||
|
return StopPollConfig{
|
||||||
|
BaseEdit{
|
||||||
|
ChatID: chatID,
|
||||||
|
MessageID: messageID,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDice allows you to send a random dice roll.
|
||||||
|
func NewDice(chatID int64) DiceConfig {
|
||||||
|
return DiceConfig{
|
||||||
|
BaseChat: BaseChat{
|
||||||
|
ChatID: chatID,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDiceWithEmoji allows you to send a random roll of one of many types.
|
||||||
|
//
|
||||||
|
// Emoji may be 🎲 (1-6), 🎯 (1-6), or 🏀 (1-5).
|
||||||
|
func NewDiceWithEmoji(chatID int64, emoji string) DiceConfig {
|
||||||
|
return DiceConfig{
|
||||||
|
BaseChat: BaseChat{
|
||||||
|
ChatID: chatID,
|
||||||
|
},
|
||||||
|
Emoji: emoji,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotCommandScopeDefault represents the default scope of bot commands.
|
||||||
|
func NewBotCommandScopeDefault() BotCommandScope {
|
||||||
|
return BotCommandScope{Type: "default"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotCommandScopeAllPrivateChats represents the scope of bot commands,
|
||||||
|
// covering all private chats.
|
||||||
|
func NewBotCommandScopeAllPrivateChats() BotCommandScope {
|
||||||
|
return BotCommandScope{Type: "all_private_chats"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotCommandScopeAllGroupChats represents the scope of bot commands,
|
||||||
|
// covering all group and supergroup chats.
|
||||||
|
func NewBotCommandScopeAllGroupChats() BotCommandScope {
|
||||||
|
return BotCommandScope{Type: "all_group_chats"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotCommandScopeAllChatAdministrators represents the scope of bot commands,
|
||||||
|
// covering all group and supergroup chat administrators.
|
||||||
|
func NewBotCommandScopeAllChatAdministrators() BotCommandScope {
|
||||||
|
return BotCommandScope{Type: "all_chat_administrators"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotCommandScopeChat represents the scope of bot commands, covering a
|
||||||
|
// specific chat.
|
||||||
|
func NewBotCommandScopeChat(chatID int64) BotCommandScope {
|
||||||
|
return BotCommandScope{
|
||||||
|
Type: "chat",
|
||||||
|
ChatID: chatID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotCommandScopeChatAdministrators represents the scope of bot commands,
|
||||||
|
// covering all administrators of a specific group or supergroup chat.
|
||||||
|
func NewBotCommandScopeChatAdministrators(chatID int64) BotCommandScope {
|
||||||
|
return BotCommandScope{
|
||||||
|
Type: "chat_administrators",
|
||||||
|
ChatID: chatID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBotCommandScopeChatMember represents the scope of bot commands, covering a
|
||||||
|
// specific member of a group or supergroup chat.
|
||||||
|
func NewBotCommandScopeChatMember(chatID, userID int64) BotCommandScope {
|
||||||
|
return BotCommandScope{
|
||||||
|
Type: "chat_member",
|
||||||
|
ChatID: chatID,
|
||||||
|
UserID: userID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetMyCommandsWithScope allows you to set the registered commands for a
|
||||||
|
// given scope.
|
||||||
|
func NewGetMyCommandsWithScope(scope BotCommandScope) GetMyCommandsConfig {
|
||||||
|
return GetMyCommandsConfig{Scope: &scope}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetMyCommandsWithScopeAndLanguage allows you to set the registered
|
||||||
|
// commands for a given scope and language code.
|
||||||
|
func NewGetMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string) GetMyCommandsConfig {
|
||||||
|
return GetMyCommandsConfig{Scope: &scope, LanguageCode: languageCode}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetMyCommands allows you to set the registered commands.
|
||||||
|
func NewSetMyCommands(commands ...BotCommand) SetMyCommandsConfig {
|
||||||
|
return SetMyCommandsConfig{Commands: commands}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetMyCommandsWithScope allows you to set the registered commands for a given scope.
|
||||||
|
func NewSetMyCommandsWithScope(scope BotCommandScope, commands ...BotCommand) SetMyCommandsConfig {
|
||||||
|
return SetMyCommandsConfig{Commands: commands, Scope: &scope}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetMyCommandsWithScopeAndLanguage allows you to set the registered commands for a given scope
|
||||||
|
// and language code.
|
||||||
|
func NewSetMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string, commands ...BotCommand) SetMyCommandsConfig {
|
||||||
|
return SetMyCommandsConfig{Commands: commands, Scope: &scope, LanguageCode: languageCode}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeleteMyCommands allows you to delete the registered commands.
|
||||||
|
func NewDeleteMyCommands() DeleteMyCommandsConfig {
|
||||||
|
return DeleteMyCommandsConfig{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeleteMyCommandsWithScope allows you to delete the registered commands for a given
|
||||||
|
// scope.
|
||||||
|
func NewDeleteMyCommandsWithScope(scope BotCommandScope) DeleteMyCommandsConfig {
|
||||||
|
return DeleteMyCommandsConfig{Scope: &scope}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDeleteMyCommandsWithScopeAndLanguage allows you to delete the registered commands for a given
|
||||||
|
// scope and language code.
|
||||||
|
func NewDeleteMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string) DeleteMyCommandsConfig {
|
||||||
|
return DeleteMyCommandsConfig{Scope: &scope, LanguageCode: languageCode}
|
||||||
|
}
|
||||||
97
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/params.go
generated
vendored
Normal file
97
vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/params.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package tgbotapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Params represents a set of parameters that gets passed to a request.
|
||||||
|
type Params map[string]string
|
||||||
|
|
||||||
|
// AddNonEmpty adds a value if it not an empty string.
|
||||||
|
func (p Params) AddNonEmpty(key, value string) {
|
||||||
|
if value != "" {
|
||||||
|
p[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNonZero adds a value if it is not zero.
|
||||||
|
func (p Params) AddNonZero(key string, value int) {
|
||||||
|
if value != 0 {
|
||||||
|
p[key] = strconv.Itoa(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNonZero64 is the same as AddNonZero except uses an int64.
|
||||||
|
func (p Params) AddNonZero64(key string, value int64) {
|
||||||
|
if value != 0 {
|
||||||
|
p[key] = strconv.FormatInt(value, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddBool adds a value of a bool if it is true.
|
||||||
|
func (p Params) AddBool(key string, value bool) {
|
||||||
|
if value {
|
||||||
|
p[key] = strconv.FormatBool(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNonZeroFloat adds a floating point value that is not zero.
|
||||||
|
func (p Params) AddNonZeroFloat(key string, value float64) {
|
||||||
|
if value != 0 {
|
||||||
|
p[key] = strconv.FormatFloat(value, 'f', 6, 64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddInterface adds an interface if it is not nil and can be JSON marshalled.
|
||||||
|
func (p Params) AddInterface(key string, value interface{}) error {
|
||||||
|
if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p[key] = string(b)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFirstValid attempts to add the first item that is not a default value.
|
||||||
|
//
|
||||||
|
// For example, AddFirstValid(0, "", "test") would add "test".
|
||||||
|
func (p Params) AddFirstValid(key string, args ...interface{}) error {
|
||||||
|
for _, arg := range args {
|
||||||
|
switch v := arg.(type) {
|
||||||
|
case int:
|
||||||
|
if v != 0 {
|
||||||
|
p[key] = strconv.Itoa(v)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case int64:
|
||||||
|
if v != 0 {
|
||||||
|
p[key] = strconv.FormatInt(v, 10)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
if v != "" {
|
||||||
|
p[key] = v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case nil:
|
||||||
|
default:
|
||||||
|
b, err := json.Marshal(arg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p[key] = string(b)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -54,13 +54,15 @@ type (
|
|||||||
Credentials *EncryptedCredentials `json:"credentials"`
|
Credentials *EncryptedCredentials `json:"credentials"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PassportFile represents a file uploaded to Telegram Passport. Currently all
|
// PassportFile represents a file uploaded to Telegram Passport. Currently, all
|
||||||
// Telegram Passport files are in JPEG format when decrypted and don't exceed
|
// Telegram Passport files are in JPEG format when decrypted and don't exceed
|
||||||
// 10MB.
|
// 10MB.
|
||||||
PassportFile struct {
|
PassportFile struct {
|
||||||
// Unique identifier for this file
|
// Unique identifier for this file
|
||||||
FileID string `json:"file_id"`
|
FileID string `json:"file_id"`
|
||||||
|
|
||||||
|
FileUniqueID string `json:"file_unique_id"`
|
||||||
|
|
||||||
// File size
|
// File size
|
||||||
FileSize int `json:"file_size"`
|
FileSize int `json:"file_size"`
|
||||||
|
|
||||||
@@ -212,7 +214,7 @@ type (
|
|||||||
// PassportElementErrorFile represents an issue with a document scan. The
|
// PassportElementErrorFile represents an issue with a document scan. The
|
||||||
// error is considered resolved when the file with the document scan changes.
|
// error is considered resolved when the file with the document scan changes.
|
||||||
PassportElementErrorFile struct {
|
PassportElementErrorFile struct {
|
||||||
// Error source, must be file
|
// Error source, must be a file
|
||||||
Source string `json:"source"`
|
Source string `json:"source"`
|
||||||
|
|
||||||
// The section of the user's Telegram Passport which has the issue, one
|
// The section of the user's Telegram Passport which has the issue, one
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user