mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-23 19:22:03 -08:00
Add support for Telegram topics (telegram) (#1942)
Topics are surfaced by appending /<topic-id> to the channel setting for the gateway. An example for the topic with ID of 16 would be: ``` [[gateway.inout]] account="telegram.mytelegram" channel="-100xxxxxxxxxx/16" ```
This commit is contained in:
parent
c2b8e298d8
commit
601f48a50e
@ -11,7 +11,7 @@ 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"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
tgbotapi "github.com/matterbridge/telegram-bot-api/v6"
|
||||||
)
|
)
|
||||||
|
|
||||||
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 {
|
||||||
@ -20,6 +20,11 @@ func (b *Btelegram) handleUpdate(rmsg *config.Message, message, posted, edited *
|
|||||||
if posted.Text == "/chatId" {
|
if posted.Text == "/chatId" {
|
||||||
chatID := strconv.FormatInt(posted.Chat.ID, 10)
|
chatID := strconv.FormatInt(posted.Chat.ID, 10)
|
||||||
|
|
||||||
|
// Handle chat topics
|
||||||
|
if posted.IsTopicMessage {
|
||||||
|
chatID = chatID + "/" + strconv.Itoa(posted.MessageThreadID)
|
||||||
|
}
|
||||||
|
|
||||||
_, err := b.Send(config.Message{
|
_, err := b.Send(config.Message{
|
||||||
Channel: chatID,
|
Channel: chatID,
|
||||||
Text: fmt.Sprintf("ID of this chat: %s", chatID),
|
Text: fmt.Sprintf("ID of this chat: %s", chatID),
|
||||||
@ -91,7 +96,8 @@ func (b *Btelegram) handleForwarded(rmsg *config.Message, message *tgbotapi.Mess
|
|||||||
|
|
||||||
// handleQuoting handles quoting of previous messages
|
// handleQuoting handles quoting of previous messages
|
||||||
func (b *Btelegram) handleQuoting(rmsg *config.Message, message *tgbotapi.Message) {
|
func (b *Btelegram) handleQuoting(rmsg *config.Message, message *tgbotapi.Message) {
|
||||||
if message.ReplyToMessage != nil {
|
// Used to check if the message was a reply to the root topic
|
||||||
|
if message.ReplyToMessage != nil && !(message.ReplyToMessage.MessageID == message.MessageThreadID) { //nolint:nestif
|
||||||
usernameReply := ""
|
usernameReply := ""
|
||||||
if message.ReplyToMessage.From != nil {
|
if message.ReplyToMessage.From != nil {
|
||||||
if b.GetBool("UseFirstName") {
|
if b.GetBool("UseFirstName") {
|
||||||
@ -211,9 +217,14 @@ func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|||||||
// set the ID's from the channel or group message
|
// set the ID's from the channel or group message
|
||||||
rmsg.ID = strconv.Itoa(message.MessageID)
|
rmsg.ID = strconv.Itoa(message.MessageID)
|
||||||
rmsg.Channel = strconv.FormatInt(message.Chat.ID, 10)
|
rmsg.Channel = strconv.FormatInt(message.Chat.ID, 10)
|
||||||
|
if message.MessageThreadID != 0 {
|
||||||
|
rmsg.Channel += "/" + strconv.Itoa(message.MessageThreadID)
|
||||||
|
}
|
||||||
|
|
||||||
// preserve threading from telegram reply
|
// preserve threading from telegram reply
|
||||||
if message.ReplyToMessage != nil {
|
if message.ReplyToMessage != nil &&
|
||||||
|
// Used to check if the message was a reply to the root topic
|
||||||
|
!(message.ReplyToMessage.MessageID == message.MessageThreadID) {
|
||||||
rmsg.ParentID = strconv.Itoa(message.ReplyToMessage.MessageID)
|
rmsg.ParentID = strconv.Itoa(message.ReplyToMessage.MessageID)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,12 +337,12 @@ func (b *Btelegram) maybeConvertWebp(name *string, data *[]byte) {
|
|||||||
|
|
||||||
// handleDownloadFile handles file download
|
// handleDownloadFile handles file download
|
||||||
func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Message) error {
|
func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Message) error {
|
||||||
size := 0
|
size := int64(0)
|
||||||
var url, name, text string
|
var url, name, text string
|
||||||
switch {
|
switch {
|
||||||
case message.Sticker != nil:
|
case message.Sticker != nil:
|
||||||
text, name, url = b.getDownloadInfo(message.Sticker.FileID, ".webp", true)
|
text, name, url = b.getDownloadInfo(message.Sticker.FileID, ".webp", true)
|
||||||
size = message.Sticker.FileSize
|
size = int64(message.Sticker.FileSize)
|
||||||
case message.Voice != nil:
|
case message.Voice != nil:
|
||||||
text, name, url = b.getDownloadInfo(message.Voice.FileID, ".ogg", true)
|
text, name, url = b.getDownloadInfo(message.Voice.FileID, ".ogg", true)
|
||||||
size = message.Voice.FileSize
|
size = message.Voice.FileSize
|
||||||
@ -348,7 +359,7 @@ func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Messa
|
|||||||
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 = int64(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)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,7 +463,7 @@ func (b *Btelegram) handleEdit(msg *config.Message, chatid int64) (string, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handleUploadFile handles native upload of files
|
// handleUploadFile handles native upload of files
|
||||||
func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, parentID int) (string, error) {
|
func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, threadid int, parentID int) (string, error) {
|
||||||
var media []interface{}
|
var media []interface{}
|
||||||
for _, f := range msg.Extra["file"] {
|
for _, f := range msg.Extra["file"] {
|
||||||
fi := f.(config.FileInfo)
|
fi := f.(config.FileInfo)
|
||||||
@ -502,7 +513,7 @@ func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64, parentID
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.sendMediaFiles(msg, chatid, parentID, media)
|
return b.sendMediaFiles(msg, chatid, threadid, parentID, media)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) handleQuote(message, quoteNick, quoteMessage string) string {
|
func (b *Btelegram) handleQuote(message, quoteNick, quoteMessage string) string {
|
||||||
|
@ -10,7 +10,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/v5"
|
tgbotapi "github.com/matterbridge/telegram-bot-api/v6"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -86,11 +86,41 @@ func TGGetParseMode(b *Btelegram, username string, text string) (textout string,
|
|||||||
return textout, parsemode
|
return textout, parsemode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Btelegram) getIds(channel string) (int64, int, error) {
|
||||||
|
var chatid int64
|
||||||
|
topicid := 0
|
||||||
|
|
||||||
|
// get the chatid
|
||||||
|
if strings.Contains(channel, "/") { //nolint:nestif
|
||||||
|
s := strings.Split(channel, "/")
|
||||||
|
if len(s) < 2 {
|
||||||
|
b.Log.Errorf("Invalid channel format: %#v\n", channel)
|
||||||
|
return 0, 0, nil
|
||||||
|
}
|
||||||
|
id, err := strconv.ParseInt(s[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
chatid = id
|
||||||
|
tid, err := strconv.Atoi(s[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
topicid = tid
|
||||||
|
} else {
|
||||||
|
id, err := strconv.ParseInt(channel, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
chatid = id
|
||||||
|
}
|
||||||
|
return chatid, topicid, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Btelegram) Send(msg config.Message) (string, error) {
|
func (b *Btelegram) Send(msg config.Message) (string, error) {
|
||||||
b.Log.Debugf("=> Receiving %#v", msg)
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
// get the chatid
|
chatid, topicid, err := b.getIds(msg.Channel)
|
||||||
chatid, err := strconv.ParseInt(msg.Channel, 10, 64)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -123,13 +153,13 @@ func (b *Btelegram) Send(msg config.Message) (string, error) {
|
|||||||
// 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 _, msgErr := b.sendMessage(chatid, rmsg.Username, rmsg.Text, parentID); msgErr != nil {
|
if _, msgErr := b.sendMessage(chatid, topicid, rmsg.Username, rmsg.Text, parentID); msgErr != nil {
|
||||||
b.Log.Errorf("sendMessage failed: %s", msgErr)
|
b.Log.Errorf("sendMessage failed: %s", msgErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if we have files to upload (from slack, telegram or mattermost)
|
// check if we have files to upload (from slack, telegram or mattermost)
|
||||||
if len(msg.Extra["file"]) > 0 {
|
if len(msg.Extra["file"]) > 0 {
|
||||||
return b.handleUploadFile(&msg, chatid, parentID)
|
return b.handleUploadFile(&msg, chatid, topicid, parentID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +173,7 @@ func (b *Btelegram) Send(msg config.Message) (string, error) {
|
|||||||
// Ignore empty text field needs for prevent double messages from whatsapp to telegram
|
// Ignore empty text field needs for prevent double messages from whatsapp to telegram
|
||||||
// when sending media with text caption
|
// when sending media with text caption
|
||||||
if msg.Text != "" {
|
if msg.Text != "" {
|
||||||
return b.sendMessage(chatid, msg.Username, msg.Text, parentID)
|
return b.sendMessage(chatid, topicid, msg.Username, msg.Text, parentID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", nil
|
return "", nil
|
||||||
@ -157,9 +187,12 @@ func (b *Btelegram) getFileDirectURL(id string) string {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Btelegram) sendMessage(chatid int64, username, text string, parentID int) (string, error) {
|
func (b *Btelegram) sendMessage(chatid int64, topicid int, username, text string, parentID int) (string, error) {
|
||||||
m := tgbotapi.NewMessage(chatid, "")
|
m := tgbotapi.NewMessage(chatid, "")
|
||||||
m.Text, m.ParseMode = TGGetParseMode(b, username, text)
|
m.Text, m.ParseMode = TGGetParseMode(b, username, text)
|
||||||
|
if topicid != 0 {
|
||||||
|
m.BaseChat.MessageThreadID = topicid
|
||||||
|
}
|
||||||
m.ReplyToMessageID = parentID
|
m.ReplyToMessageID = parentID
|
||||||
m.DisableWebPagePreview = b.GetBool("DisableWebPagePreview")
|
m.DisableWebPagePreview = b.GetBool("DisableWebPagePreview")
|
||||||
|
|
||||||
@ -171,11 +204,19 @@ func (b *Btelegram) sendMessage(chatid int64, username, text string, parentID in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sendMediaFiles native upload media files via media group
|
// sendMediaFiles native upload media files via media group
|
||||||
func (b *Btelegram) sendMediaFiles(msg *config.Message, chatid int64, parentID int, media []interface{}) (string, error) {
|
func (b *Btelegram) sendMediaFiles(msg *config.Message, chatid int64, threadid int, parentID int, media []interface{}) (string, error) {
|
||||||
if len(media) == 0 {
|
if len(media) == 0 {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
mg := tgbotapi.MediaGroupConfig{ChatID: chatid, ChannelUsername: msg.Username, Media: media, ReplyToMessageID: parentID}
|
mg := tgbotapi.MediaGroupConfig{
|
||||||
|
BaseChat: tgbotapi.BaseChat{
|
||||||
|
ChatID: chatid,
|
||||||
|
MessageThreadID: threadid,
|
||||||
|
ChannelUsername: msg.Username,
|
||||||
|
ReplyToMessageID: parentID,
|
||||||
|
},
|
||||||
|
Media: media,
|
||||||
|
}
|
||||||
messages, err := b.c.SendMediaGroup(mg)
|
messages, err := b.c.SendMediaGroup(mg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
2
go.mod
2
go.mod
@ -11,7 +11,6 @@ require (
|
|||||||
github.com/d5/tengo/v2 v2.13.0
|
github.com/d5/tengo/v2 v2.13.0
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
|
||||||
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c
|
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c
|
||||||
github.com/google/gops v0.3.27
|
github.com/google/gops v0.3.27
|
||||||
github.com/gorilla/schema v1.2.0
|
github.com/gorilla/schema v1.2.0
|
||||||
@ -29,6 +28,7 @@ require (
|
|||||||
github.com/matterbridge/gozulipbot v0.0.0-20211023205727-a19d6c1f3b75
|
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-20221106190440-8bcf49695e0d
|
github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d
|
||||||
|
github.com/matterbridge/telegram-bot-api/v6 v6.5.0
|
||||||
github.com/mattermost/mattermost-server/v5 v5.39.3
|
github.com/mattermost/mattermost-server/v5 v5.39.3
|
||||||
github.com/mattermost/mattermost-server/v6 v6.7.2
|
github.com/mattermost/mattermost-server/v6 v6.7.2
|
||||||
github.com/mattn/godown v0.0.1
|
github.com/mattn/godown v0.0.1
|
||||||
|
4
go.sum
4
go.sum
@ -607,8 +607,6 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
|||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
|
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=
|
|
||||||
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
|
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
|
||||||
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||||
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
|
||||||
@ -1085,6 +1083,8 @@ github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d97130
|
|||||||
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba/go.mod h1:iXGEotOvwI1R1SjLxRc+BF5rUORTMtE0iMZBT2lxqAU=
|
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba/go.mod h1:iXGEotOvwI1R1SjLxRc+BF5rUORTMtE0iMZBT2lxqAU=
|
||||||
github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d h1:aI0ANEzy3dMv3vEAMQ80AItNie0fBR9ZxE2sAedORmM=
|
github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d h1:aI0ANEzy3dMv3vEAMQ80AItNie0fBR9ZxE2sAedORmM=
|
||||||
github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d/go.mod h1:Zg8PH1P/1CNUxozQ8blnjAV9PA4Qn2qWf33cX5yNKGM=
|
github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d/go.mod h1:Zg8PH1P/1CNUxozQ8blnjAV9PA4Qn2qWf33cX5yNKGM=
|
||||||
|
github.com/matterbridge/telegram-bot-api/v6 v6.5.0 h1:wCnHWvt4WGhfognQsuu2OnHyqENBdJRf2mReYTCXggQ=
|
||||||
|
github.com/matterbridge/telegram-bot-api/v6 v6.5.0/go.mod h1:/hSLrs8h/xNsQglQXjwXJ92iZU8XfTGkYUQ7KVDWEVo=
|
||||||
github.com/mattermost/go-i18n v1.11.0/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34=
|
github.com/mattermost/go-i18n v1.11.0/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34=
|
||||||
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG1cHc4Cz5ef9n3XVCxRWpAKUtqg9PJl5+y8=
|
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG1cHc4Cz5ef9n3XVCxRWpAKUtqg9PJl5+y8=
|
||||||
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34=
|
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34=
|
||||||
|
@ -2,3 +2,4 @@
|
|||||||
coverage.out
|
coverage.out
|
||||||
tmp/
|
tmp/
|
||||||
book/
|
book/
|
||||||
|
.vscode/
|
@ -85,9 +85,9 @@ func main() {
|
|||||||
|
|
||||||
log.Printf("Authorized on account %s", bot.Self.UserName)
|
log.Printf("Authorized on account %s", bot.Self.UserName)
|
||||||
|
|
||||||
wh, _ := tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem")
|
wh, _ := tgbotapi.NewWebhookWithCert("https://www.example.com:8443/"+bot.Token, "cert.pem")
|
||||||
|
|
||||||
_, err = bot.SetWebhook(wh)
|
_, err = bot.Request(wh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
@ -7,7 +7,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -151,7 +150,7 @@ func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if debug, read response body
|
// if debug, read response body
|
||||||
data, err := ioutil.ReadAll(responseBody)
|
data, err := io.ReadAll(responseBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -494,6 +493,8 @@ func (bot *BotAPI) ListenForWebhookRespReqFormat(w http.ResponseWriter, r *http.
|
|||||||
ch := make(chan Update, bot.Buffer)
|
ch := make(chan Update, bot.Buffer)
|
||||||
|
|
||||||
func(w http.ResponseWriter, r *http.Request) {
|
func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer close(ch)
|
||||||
|
|
||||||
update, err := bot.HandleUpdate(r)
|
update, err := bot.HandleUpdate(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errMsg, _ := json.Marshal(map[string]string{"error": err.Error()})
|
errMsg, _ := json.Marshal(map[string]string{"error": err.Error()})
|
||||||
@ -504,7 +505,6 @@ func (bot *BotAPI) ListenForWebhookRespReqFormat(w http.ResponseWriter, r *http.
|
|||||||
}
|
}
|
||||||
|
|
||||||
ch <- *update
|
ch <- *update
|
||||||
close(ch)
|
|
||||||
}(w, r)
|
}(w, r)
|
||||||
|
|
||||||
return ch
|
return ch
|
||||||
@ -681,12 +681,7 @@ func (bot *BotAPI) GetMyCommandsWithConfig(config GetMyCommandsConfig) ([]BotCom
|
|||||||
// forwardMessage, but the copied message doesn't have a link to the original
|
// forwardMessage, but the copied message doesn't have a link to the original
|
||||||
// message. Returns the MessageID of the sent message on success.
|
// message. Returns the MessageID of the sent message on success.
|
||||||
func (bot *BotAPI) CopyMessage(config CopyMessageConfig) (MessageID, error) {
|
func (bot *BotAPI) CopyMessage(config CopyMessageConfig) (MessageID, error) {
|
||||||
params, err := config.params()
|
resp, err := bot.Request(config)
|
||||||
if err != nil {
|
|
||||||
return MessageID{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return MessageID{}, err
|
return MessageID{}, err
|
||||||
}
|
}
|
||||||
@ -697,6 +692,33 @@ func (bot *BotAPI) CopyMessage(config CopyMessageConfig) (MessageID, error) {
|
|||||||
return messageID, err
|
return messageID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AnswerWebAppQuery sets the result of an interaction with a Web App and send a
|
||||||
|
// corresponding message on behalf of the user to the chat from which the query originated.
|
||||||
|
func (bot *BotAPI) AnswerWebAppQuery(config AnswerWebAppQueryConfig) (SentWebAppMessage, error) {
|
||||||
|
var sentWebAppMessage SentWebAppMessage
|
||||||
|
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return sentWebAppMessage, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(resp.Result, &sentWebAppMessage)
|
||||||
|
return sentWebAppMessage, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMyDefaultAdministratorRights gets the current default administrator rights of the bot.
|
||||||
|
func (bot *BotAPI) GetMyDefaultAdministratorRights(config GetMyDefaultAdministratorRightsConfig) (ChatAdministratorRights, error) {
|
||||||
|
var rights ChatAdministratorRights
|
||||||
|
|
||||||
|
resp, err := bot.Request(config)
|
||||||
|
if err != nil {
|
||||||
|
return rights, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(resp.Result, &rights)
|
||||||
|
return rights, err
|
||||||
|
}
|
||||||
|
|
||||||
// EscapeText takes an input text and escape Telegram markup symbols.
|
// 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.
|
// 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.
|
// Note that you don't have to include the formatting style in the input text, or it will be escaped too.
|
@ -265,7 +265,9 @@ func (CloseConfig) params() (Params, error) {
|
|||||||
// BaseChat is base type for all chat config types.
|
// BaseChat is base type for all chat config types.
|
||||||
type BaseChat struct {
|
type BaseChat struct {
|
||||||
ChatID int64 // required
|
ChatID int64 // required
|
||||||
|
MessageThreadID int
|
||||||
ChannelUsername string
|
ChannelUsername string
|
||||||
|
ProtectContent bool
|
||||||
ReplyToMessageID int
|
ReplyToMessageID int
|
||||||
ReplyMarkup interface{}
|
ReplyMarkup interface{}
|
||||||
DisableNotification bool
|
DisableNotification bool
|
||||||
@ -276,9 +278,11 @@ func (chat *BaseChat) params() (Params, error) {
|
|||||||
params := make(Params)
|
params := make(Params)
|
||||||
|
|
||||||
params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername)
|
params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername)
|
||||||
|
params.AddNonZero("message_thread_id", chat.MessageThreadID)
|
||||||
params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID)
|
params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID)
|
||||||
params.AddBool("disable_notification", chat.DisableNotification)
|
params.AddBool("disable_notification", chat.DisableNotification)
|
||||||
params.AddBool("allow_sending_without_reply", chat.AllowSendingWithoutReply)
|
params.AddBool("allow_sending_without_reply", chat.AllowSendingWithoutReply)
|
||||||
|
params.AddBool("protect_content", chat.ProtectContent)
|
||||||
|
|
||||||
err := params.AddInterface("reply_markup", chat.ReplyMarkup)
|
err := params.AddInterface("reply_markup", chat.ReplyMarkup)
|
||||||
|
|
||||||
@ -319,6 +323,21 @@ func (edit BaseEdit) params() (Params, error) {
|
|||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BaseSpoiler is base type of structures with spoilers.
|
||||||
|
type BaseSpoiler struct {
|
||||||
|
HasSpoiler bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (spoiler BaseSpoiler) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
if spoiler.HasSpoiler {
|
||||||
|
params.AddBool("has_spoiler", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
// MessageConfig contains information about a SendMessage request.
|
// MessageConfig contains information about a SendMessage request.
|
||||||
type MessageConfig struct {
|
type MessageConfig struct {
|
||||||
BaseChat
|
BaseChat
|
||||||
@ -403,6 +422,7 @@ func (config CopyMessageConfig) method() string {
|
|||||||
// PhotoConfig contains information about a SendPhoto request.
|
// PhotoConfig contains information about a SendPhoto request.
|
||||||
type PhotoConfig struct {
|
type PhotoConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
BaseSpoiler
|
||||||
Thumb RequestFileData
|
Thumb RequestFileData
|
||||||
Caption string
|
Caption string
|
||||||
ParseMode string
|
ParseMode string
|
||||||
@ -418,6 +438,15 @@ func (config PhotoConfig) params() (Params, error) {
|
|||||||
params.AddNonEmpty("caption", config.Caption)
|
params.AddNonEmpty("caption", config.Caption)
|
||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
||||||
|
if err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p1, err := config.BaseSpoiler.params()
|
||||||
|
if err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
@ -553,6 +582,7 @@ func (config StickerConfig) files() []RequestFile {
|
|||||||
// VideoConfig contains information about a SendVideo request.
|
// VideoConfig contains information about a SendVideo request.
|
||||||
type VideoConfig struct {
|
type VideoConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
BaseSpoiler
|
||||||
Thumb RequestFileData
|
Thumb RequestFileData
|
||||||
Duration int
|
Duration int
|
||||||
Caption string
|
Caption string
|
||||||
@ -572,6 +602,15 @@ func (config VideoConfig) params() (Params, error) {
|
|||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
params.AddBool("supports_streaming", config.SupportsStreaming)
|
params.AddBool("supports_streaming", config.SupportsStreaming)
|
||||||
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
||||||
|
if err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p1, err := config.BaseSpoiler.params()
|
||||||
|
if err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
@ -599,6 +638,7 @@ func (config VideoConfig) files() []RequestFile {
|
|||||||
// AnimationConfig contains information about a SendAnimation request.
|
// AnimationConfig contains information about a SendAnimation request.
|
||||||
type AnimationConfig struct {
|
type AnimationConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
BaseSpoiler
|
||||||
Duration int
|
Duration int
|
||||||
Thumb RequestFileData
|
Thumb RequestFileData
|
||||||
Caption string
|
Caption string
|
||||||
@ -616,6 +656,15 @@ func (config AnimationConfig) params() (Params, error) {
|
|||||||
params.AddNonEmpty("caption", config.Caption)
|
params.AddNonEmpty("caption", config.Caption)
|
||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
||||||
|
if err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p1, err := config.BaseSpoiler.params()
|
||||||
|
if err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
@ -972,13 +1021,15 @@ func (config GetGameHighScoresConfig) method() string {
|
|||||||
// ChatActionConfig contains information about a SendChatAction request.
|
// ChatActionConfig contains information about a SendChatAction request.
|
||||||
type ChatActionConfig struct {
|
type ChatActionConfig struct {
|
||||||
BaseChat
|
BaseChat
|
||||||
Action string // required
|
MessageThreadID int
|
||||||
|
Action string // required
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config ChatActionConfig) params() (Params, error) {
|
func (config ChatActionConfig) params() (Params, error) {
|
||||||
params, err := config.BaseChat.params()
|
params, err := config.BaseChat.params()
|
||||||
|
|
||||||
params["action"] = config.Action
|
params["action"] = config.Action
|
||||||
|
params.AddNonZero("message_thread_id", config.MessageThreadID)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
@ -1162,6 +1213,7 @@ type WebhookConfig struct {
|
|||||||
MaxConnections int
|
MaxConnections int
|
||||||
AllowedUpdates []string
|
AllowedUpdates []string
|
||||||
DropPendingUpdates bool
|
DropPendingUpdates bool
|
||||||
|
SecretToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config WebhookConfig) method() string {
|
func (config WebhookConfig) method() string {
|
||||||
@ -1179,6 +1231,7 @@ func (config WebhookConfig) params() (Params, error) {
|
|||||||
params.AddNonZero("max_connections", config.MaxConnections)
|
params.AddNonZero("max_connections", config.MaxConnections)
|
||||||
err := params.AddInterface("allowed_updates", config.AllowedUpdates)
|
err := params.AddInterface("allowed_updates", config.AllowedUpdates)
|
||||||
params.AddBool("drop_pending_updates", config.DropPendingUpdates)
|
params.AddBool("drop_pending_updates", config.DropPendingUpdates)
|
||||||
|
params.AddNonEmpty("secret_token", config.SecretToken)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
@ -1240,6 +1293,29 @@ func (config InlineConfig) params() (Params, error) {
|
|||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AnswerWebAppQueryConfig is used to set the result of an interaction with a
|
||||||
|
// Web App and send a corresponding message on behalf of the user to the chat
|
||||||
|
// from which the query originated.
|
||||||
|
type AnswerWebAppQueryConfig struct {
|
||||||
|
// WebAppQueryID is the unique identifier for the query to be answered.
|
||||||
|
WebAppQueryID string `json:"web_app_query_id"`
|
||||||
|
// Result is an InlineQueryResult object describing the message to be sent.
|
||||||
|
Result interface{} `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config AnswerWebAppQueryConfig) method() string {
|
||||||
|
return "answerWebAppQuery"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config AnswerWebAppQueryConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params["web_app_query_id"] = config.WebAppQueryID
|
||||||
|
err := params.AddInterface("result", config.Result)
|
||||||
|
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
// CallbackConfig contains information on making a CallbackQuery response.
|
// CallbackConfig contains information on making a CallbackQuery response.
|
||||||
type CallbackConfig struct {
|
type CallbackConfig struct {
|
||||||
CallbackQueryID string `json:"callback_query_id"`
|
CallbackQueryID string `json:"callback_query_id"`
|
||||||
@ -1324,8 +1400,9 @@ type KickChatMemberConfig = BanChatMemberConfig
|
|||||||
// RestrictChatMemberConfig contains fields to restrict members of chat
|
// RestrictChatMemberConfig contains fields to restrict members of chat
|
||||||
type RestrictChatMemberConfig struct {
|
type RestrictChatMemberConfig struct {
|
||||||
ChatMemberConfig
|
ChatMemberConfig
|
||||||
UntilDate int64
|
UntilDate int64
|
||||||
Permissions *ChatPermissions
|
UseIndependentChatPermissions bool
|
||||||
|
Permissions *ChatPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config RestrictChatMemberConfig) method() string {
|
func (config RestrictChatMemberConfig) method() string {
|
||||||
@ -1337,6 +1414,7 @@ func (config RestrictChatMemberConfig) params() (Params, error) {
|
|||||||
|
|
||||||
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
|
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
|
||||||
params.AddNonZero64("user_id", config.UserID)
|
params.AddNonZero64("user_id", config.UserID)
|
||||||
|
params.AddBool("use_independent_chat_permissions", config.UseIndependentChatPermissions)
|
||||||
|
|
||||||
err := params.AddInterface("permissions", config.Permissions)
|
err := params.AddInterface("permissions", config.Permissions)
|
||||||
params.AddNonZero64("until_date", config.UntilDate)
|
params.AddNonZero64("until_date", config.UntilDate)
|
||||||
@ -1353,11 +1431,12 @@ type PromoteChatMemberConfig struct {
|
|||||||
CanPostMessages bool
|
CanPostMessages bool
|
||||||
CanEditMessages bool
|
CanEditMessages bool
|
||||||
CanDeleteMessages bool
|
CanDeleteMessages bool
|
||||||
CanManageVoiceChats bool
|
CanManageVideoChats bool
|
||||||
CanInviteUsers bool
|
CanInviteUsers bool
|
||||||
CanRestrictMembers bool
|
CanRestrictMembers bool
|
||||||
CanPinMessages bool
|
CanPinMessages bool
|
||||||
CanPromoteMembers bool
|
CanPromoteMembers bool
|
||||||
|
CanManageTopics bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config PromoteChatMemberConfig) method() string {
|
func (config PromoteChatMemberConfig) method() string {
|
||||||
@ -1376,11 +1455,12 @@ func (config PromoteChatMemberConfig) params() (Params, error) {
|
|||||||
params.AddBool("can_post_messages", config.CanPostMessages)
|
params.AddBool("can_post_messages", config.CanPostMessages)
|
||||||
params.AddBool("can_edit_messages", config.CanEditMessages)
|
params.AddBool("can_edit_messages", config.CanEditMessages)
|
||||||
params.AddBool("can_delete_messages", config.CanDeleteMessages)
|
params.AddBool("can_delete_messages", config.CanDeleteMessages)
|
||||||
params.AddBool("can_manage_voice_chats", config.CanManageVoiceChats)
|
params.AddBool("can_manage_video_chats", config.CanManageVideoChats)
|
||||||
params.AddBool("can_invite_users", config.CanInviteUsers)
|
params.AddBool("can_invite_users", config.CanInviteUsers)
|
||||||
params.AddBool("can_restrict_members", config.CanRestrictMembers)
|
params.AddBool("can_restrict_members", config.CanRestrictMembers)
|
||||||
params.AddBool("can_pin_messages", config.CanPinMessages)
|
params.AddBool("can_pin_messages", config.CanPinMessages)
|
||||||
params.AddBool("can_promote_members", config.CanPromoteMembers)
|
params.AddBool("can_promote_members", config.CanPromoteMembers)
|
||||||
|
params.AddBool("can_manage_topics", config.CanManageTopics)
|
||||||
|
|
||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
@ -1500,7 +1580,8 @@ func (ChatAdministratorsConfig) method() string {
|
|||||||
// restrict members.
|
// restrict members.
|
||||||
type SetChatPermissionsConfig struct {
|
type SetChatPermissionsConfig struct {
|
||||||
ChatConfig
|
ChatConfig
|
||||||
Permissions *ChatPermissions
|
UseIndependentChatPermissions bool
|
||||||
|
Permissions *ChatPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (SetChatPermissionsConfig) method() string {
|
func (SetChatPermissionsConfig) method() string {
|
||||||
@ -1511,6 +1592,7 @@ func (config SetChatPermissionsConfig) params() (Params, error) {
|
|||||||
params := make(Params)
|
params := make(Params)
|
||||||
|
|
||||||
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
|
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
|
||||||
|
params.AddBool("use_independent_chat_permissions", config.UseIndependentChatPermissions)
|
||||||
err := params.AddInterface("permissions", config.Permissions)
|
err := params.AddInterface("permissions", config.Permissions)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
@ -1759,6 +1841,64 @@ func (config InvoiceConfig) method() string {
|
|||||||
return "sendInvoice"
|
return "sendInvoice"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InvoiceLinkConfig contains information for createInvoiceLink method
|
||||||
|
type InvoiceLinkConfig struct {
|
||||||
|
Title string //Required
|
||||||
|
Description string //Required
|
||||||
|
Payload string //Required
|
||||||
|
ProviderToken string //Required
|
||||||
|
Currency string //Required
|
||||||
|
Prices []LabeledPrice //Required
|
||||||
|
MaxTipAmount int
|
||||||
|
SuggestedTipAmounts []int
|
||||||
|
ProviderData string
|
||||||
|
PhotoURL string
|
||||||
|
PhotoSize int
|
||||||
|
PhotoWidth int
|
||||||
|
PhotoHeight int
|
||||||
|
NeedName bool
|
||||||
|
NeedPhoneNumber bool
|
||||||
|
NeedEmail bool
|
||||||
|
NeedShippingAddress bool
|
||||||
|
SendPhoneNumberToProvider bool
|
||||||
|
SendEmailToProvider bool
|
||||||
|
IsFlexible bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config InvoiceLinkConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params["title"] = config.Title
|
||||||
|
params["description"] = config.Description
|
||||||
|
params["payload"] = config.Payload
|
||||||
|
params["provider_token"] = config.ProviderToken
|
||||||
|
params["currency"] = config.Currency
|
||||||
|
if err := params.AddInterface("prices", config.Prices); err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
params.AddNonZero("max_tip_amount", config.MaxTipAmount)
|
||||||
|
err := params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts)
|
||||||
|
params.AddNonEmpty("provider_data", config.ProviderData)
|
||||||
|
params.AddNonEmpty("photo_url", config.PhotoURL)
|
||||||
|
params.AddNonZero("photo_size", config.PhotoSize)
|
||||||
|
params.AddNonZero("photo_width", config.PhotoWidth)
|
||||||
|
params.AddNonZero("photo_height", config.PhotoHeight)
|
||||||
|
params.AddBool("need_name", config.NeedName)
|
||||||
|
params.AddBool("need_phone_number", config.NeedPhoneNumber)
|
||||||
|
params.AddBool("need_email", config.NeedEmail)
|
||||||
|
params.AddBool("need_shipping_address", config.NeedShippingAddress)
|
||||||
|
params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
|
||||||
|
params.AddBool("send_email_to_provider", config.SendEmailToProvider)
|
||||||
|
params.AddBool("is_flexible", config.IsFlexible)
|
||||||
|
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config InvoiceLinkConfig) method() string {
|
||||||
|
return "createInvoiceLink"
|
||||||
|
}
|
||||||
|
|
||||||
// ShippingConfig contains information for answerShippingQuery request.
|
// ShippingConfig contains information for answerShippingQuery request.
|
||||||
type ShippingConfig struct {
|
type ShippingConfig struct {
|
||||||
ShippingQueryID string // required
|
ShippingQueryID string // required
|
||||||
@ -1782,7 +1922,7 @@ func (config ShippingConfig) params() (Params, error) {
|
|||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
|
// PreCheckoutConfig contains information for answerPreCheckoutQuery request.
|
||||||
type PreCheckoutConfig struct {
|
type PreCheckoutConfig struct {
|
||||||
PreCheckoutQueryID string // required
|
PreCheckoutQueryID string // required
|
||||||
OK bool // required
|
OK bool // required
|
||||||
@ -1979,6 +2119,24 @@ func (config GetStickerSetConfig) params() (Params, error) {
|
|||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCustomEmojiStickersConfig get information about
|
||||||
|
// custom emoji stickers by their identifiers.
|
||||||
|
type GetCustomEmojiStickersConfig struct {
|
||||||
|
CustomEmojiIDs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config GetCustomEmojiStickersConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddInterface("custom_emoji_ids", config.CustomEmojiIDs)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config GetCustomEmojiStickersConfig) method() string {
|
||||||
|
return "getCustomEmojiStickers"
|
||||||
|
}
|
||||||
|
|
||||||
// UploadStickerConfig allows you to upload a sticker for use in a set later.
|
// UploadStickerConfig allows you to upload a sticker for use in a set later.
|
||||||
type UploadStickerConfig struct {
|
type UploadStickerConfig struct {
|
||||||
UserID int64
|
UserID int64
|
||||||
@ -2013,8 +2171,9 @@ type NewStickerSetConfig struct {
|
|||||||
Title string
|
Title string
|
||||||
PNGSticker RequestFileData
|
PNGSticker RequestFileData
|
||||||
TGSSticker RequestFileData
|
TGSSticker RequestFileData
|
||||||
|
StickerType string
|
||||||
Emojis string
|
Emojis string
|
||||||
ContainsMasks bool
|
ContainsMasks bool // deprecated
|
||||||
MaskPosition *MaskPosition
|
MaskPosition *MaskPosition
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2028,11 +2187,10 @@ func (config NewStickerSetConfig) params() (Params, error) {
|
|||||||
params.AddNonZero64("user_id", config.UserID)
|
params.AddNonZero64("user_id", config.UserID)
|
||||||
params["name"] = config.Name
|
params["name"] = config.Name
|
||||||
params["title"] = config.Title
|
params["title"] = config.Title
|
||||||
|
|
||||||
params["emojis"] = config.Emojis
|
params["emojis"] = config.Emojis
|
||||||
|
|
||||||
params.AddBool("contains_masks", config.ContainsMasks)
|
params.AddBool("contains_masks", config.ContainsMasks)
|
||||||
|
params.AddNonEmpty("sticker_type", string(config.StickerType))
|
||||||
err := params.AddInterface("mask_position", config.MaskPosition)
|
err := params.AddInterface("mask_position", config.MaskPosition)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
@ -2195,16 +2353,246 @@ func (config DeleteChatStickerSetConfig) params() (Params, error) {
|
|||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetForumTopicIconStickersConfig allows you to get custom emoji stickers,
|
||||||
|
// which can be used as a forum topic icon by any user.
|
||||||
|
type GetForumTopicIconStickersConfig struct{}
|
||||||
|
|
||||||
|
func (config GetForumTopicIconStickersConfig) method() string {
|
||||||
|
return "getForumTopicIconStickers"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config GetForumTopicIconStickersConfig) params() (Params, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseForum is a base type for all forum config types.
|
||||||
|
type BaseForum struct {
|
||||||
|
ChatID int64
|
||||||
|
SuperGroupUsername string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config BaseForum) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateForumTopicConfig allows you to create a topic
|
||||||
|
// in a forum supergroup chat.
|
||||||
|
type CreateForumTopicConfig struct {
|
||||||
|
BaseForum
|
||||||
|
Name string
|
||||||
|
IconColor int
|
||||||
|
IconCustomEmojiID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config CreateForumTopicConfig) method() string {
|
||||||
|
return "createForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config CreateForumTopicConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddNonEmpty("name", config.Name)
|
||||||
|
params.AddNonZero("icon_color", config.IconColor)
|
||||||
|
params.AddNonEmpty("icon_custom_emoji_id", config.IconCustomEmojiID)
|
||||||
|
|
||||||
|
p1, _ := config.BaseForum.params()
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditForumTopicConfig allows you to edit
|
||||||
|
// name and icon of a topic in a forum supergroup chat.
|
||||||
|
type EditForumTopicConfig struct {
|
||||||
|
BaseForum
|
||||||
|
MessageThreadID int
|
||||||
|
Name string
|
||||||
|
IconCustomEmojiID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config EditForumTopicConfig) method() string {
|
||||||
|
return "editForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config EditForumTopicConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddNonZero("message_thread_id", config.MessageThreadID)
|
||||||
|
params.AddNonEmpty("name", config.Name)
|
||||||
|
params.AddNonEmpty("icon_custom_emoji_id", config.IconCustomEmojiID)
|
||||||
|
|
||||||
|
p1, _ := config.BaseForum.params()
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseForumTopicConfig allows you to close
|
||||||
|
// an open topic in a forum supergroup chat.
|
||||||
|
type CloseForumTopicConfig struct {
|
||||||
|
BaseForum
|
||||||
|
MessageThreadID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config CloseForumTopicConfig) method() string {
|
||||||
|
return "closeForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config CloseForumTopicConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddNonZero("message_thread_id", config.MessageThreadID)
|
||||||
|
|
||||||
|
p1, _ := config.BaseForum.params()
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReopenForumTopicConfig allows you to reopen
|
||||||
|
// an closed topic in a forum supergroup chat.
|
||||||
|
type ReopenForumTopicConfig struct {
|
||||||
|
BaseForum
|
||||||
|
MessageThreadID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config ReopenForumTopicConfig) method() string {
|
||||||
|
return "reopenForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config ReopenForumTopicConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
|
||||||
|
params.AddNonZero("message_thread_id", config.MessageThreadID)
|
||||||
|
|
||||||
|
p1, _ := config.BaseForum.params()
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteForumTopicConfig allows you to delete a forum topic
|
||||||
|
// along with all its messages in a forum supergroup chat.
|
||||||
|
type DeleteForumTopicConfig struct {
|
||||||
|
BaseForum
|
||||||
|
MessageThreadID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config DeleteForumTopicConfig) method() string {
|
||||||
|
return "deleteForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config DeleteForumTopicConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddNonZero("message_thread_id", config.MessageThreadID)
|
||||||
|
|
||||||
|
p1, _ := config.BaseForum.params()
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpinAllForumTopicMessagesConfig allows you to clear the list
|
||||||
|
// of pinned messages in a forum topic.
|
||||||
|
type UnpinAllForumTopicMessagesConfig struct {
|
||||||
|
BaseForum
|
||||||
|
MessageThreadID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config UnpinAllForumTopicMessagesConfig) method() string {
|
||||||
|
return "unpinAllForumTopicMessages"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config UnpinAllForumTopicMessagesConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
|
||||||
|
params.AddNonZero("message_thread_id", config.MessageThreadID)
|
||||||
|
|
||||||
|
p1, _ := config.BaseForum.params()
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnpinAllForumTopicMessagesConfig allows you to edit the name of
|
||||||
|
// the 'General' topic in a forum supergroup chat.
|
||||||
|
// The bot must be an administrator in the chat for this to work
|
||||||
|
// and must have can_manage_topics administrator rights. Returns True on success.
|
||||||
|
type EditGeneralForumTopicConfig struct {
|
||||||
|
BaseForum
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config EditGeneralForumTopicConfig) method() string {
|
||||||
|
return "editGeneralForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config EditGeneralForumTopicConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddNonEmpty("name", config.Name)
|
||||||
|
|
||||||
|
p1, _ := config.BaseForum.params()
|
||||||
|
params.Merge(p1)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseGeneralForumTopicConfig allows you to to close an open 'General' topic
|
||||||
|
// in a forum supergroup chat. The bot must be an administrator in the chat
|
||||||
|
// for this to work and must have the can_manage_topics administrator rights.
|
||||||
|
// Returns True on success.
|
||||||
|
type CloseGeneralForumTopicConfig struct{ BaseForum }
|
||||||
|
|
||||||
|
func (config CloseGeneralForumTopicConfig) method() string {
|
||||||
|
return "closeGeneralForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseGeneralForumTopicConfig allows you to reopen a closed 'General' topic
|
||||||
|
// in a forum supergroup chat. The bot must be an administrator in the chat
|
||||||
|
// for this to work and must have the can_manage_topics administrator rights.
|
||||||
|
// The topic will be automatically unhidden if it was hidden.
|
||||||
|
// Returns True on success.
|
||||||
|
type ReopenGeneralForumTopicConfig struct{ BaseForum }
|
||||||
|
|
||||||
|
func (config ReopenGeneralForumTopicConfig) method() string {
|
||||||
|
return "reopenGeneralForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
// HideGeneralForumTopicConfig allows you to hide the 'General' topic
|
||||||
|
// in a forum supergroup chat. The bot must be an administrator in the chat
|
||||||
|
// for this to work and must have the can_manage_topics administrator rights.
|
||||||
|
// The topic will be automatically closed if it was open.
|
||||||
|
// Returns True on success.
|
||||||
|
type HideGeneralForumTopicConfig struct{ BaseForum }
|
||||||
|
|
||||||
|
func (config HideGeneralForumTopicConfig) method() string {
|
||||||
|
return "hideGeneralForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnhideGeneralForumTopicConfig allows you to unhide the 'General' topic
|
||||||
|
// in a forum supergroup chat. The bot must be an administrator in the chat
|
||||||
|
// for this to work and must have the can_manage_topics administrator rights.
|
||||||
|
// Returns True on success.
|
||||||
|
type UnhideGeneralForumTopicConfig struct{ BaseForum }
|
||||||
|
|
||||||
|
func (config UnhideGeneralForumTopicConfig) method() string {
|
||||||
|
return "unhideGeneralForumTopic"
|
||||||
|
}
|
||||||
|
|
||||||
// MediaGroupConfig allows you to send a group of media.
|
// MediaGroupConfig allows you to send a group of media.
|
||||||
//
|
//
|
||||||
// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
|
// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
|
||||||
type MediaGroupConfig struct {
|
type MediaGroupConfig struct {
|
||||||
ChatID int64
|
BaseChat
|
||||||
ChannelUsername string
|
Media []interface{}
|
||||||
|
|
||||||
Media []interface{}
|
|
||||||
DisableNotification bool
|
|
||||||
ReplyToMessageID int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config MediaGroupConfig) method() string {
|
func (config MediaGroupConfig) method() string {
|
||||||
@ -2212,13 +2600,16 @@ func (config MediaGroupConfig) method() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (config MediaGroupConfig) params() (Params, error) {
|
func (config MediaGroupConfig) params() (Params, error) {
|
||||||
params := make(Params)
|
params, err := config.BaseChat.params()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
|
params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
|
||||||
params.AddBool("disable_notification", config.DisableNotification)
|
params.AddBool("disable_notification", config.DisableNotification)
|
||||||
params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
|
params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
|
||||||
|
|
||||||
err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
|
err = params.AddInterface("media", prepareInputMediaForParams(config.Media))
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
@ -2313,6 +2704,81 @@ func (config DeleteMyCommandsConfig) params() (Params, error) {
|
|||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetChatMenuButtonConfig changes the bot's menu button in a private chat,
|
||||||
|
// or the default menu button.
|
||||||
|
type SetChatMenuButtonConfig struct {
|
||||||
|
ChatID int64
|
||||||
|
ChannelUsername string
|
||||||
|
|
||||||
|
MenuButton *MenuButton
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config SetChatMenuButtonConfig) method() string {
|
||||||
|
return "setChatMenuButton"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config SetChatMenuButtonConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
if err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername); err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
err := params.AddInterface("menu_button", config.MenuButton)
|
||||||
|
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetChatMenuButtonConfig struct {
|
||||||
|
ChatID int64
|
||||||
|
ChannelUsername string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config GetChatMenuButtonConfig) method() string {
|
||||||
|
return "getChatMenuButton"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config GetChatMenuButtonConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
|
||||||
|
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetMyDefaultAdministratorRightsConfig struct {
|
||||||
|
Rights ChatAdministratorRights
|
||||||
|
ForChannels bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config SetMyDefaultAdministratorRightsConfig) method() string {
|
||||||
|
return "setMyDefaultAdministratorRights"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config SetMyDefaultAdministratorRightsConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
err := params.AddInterface("rights", config.Rights)
|
||||||
|
params.AddBool("for_channels", config.ForChannels)
|
||||||
|
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetMyDefaultAdministratorRightsConfig struct {
|
||||||
|
ForChannels bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config GetMyDefaultAdministratorRightsConfig) method() string {
|
||||||
|
return "getMyDefaultAdministratorRights"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config GetMyDefaultAdministratorRightsConfig) params() (Params, error) {
|
||||||
|
params := make(Params)
|
||||||
|
|
||||||
|
params.AddBool("for_channels", config.ForChannels)
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
// prepareInputMediaParam evaluates a single InputMedia and determines if it
|
// prepareInputMediaParam evaluates a single InputMedia and determines if it
|
||||||
// needs to be modified for a successful upload. If it returns nil, then the
|
// needs to be modified for a successful upload. If it returns nil, then the
|
||||||
// value does not need to be included in the params. Otherwise, it will return
|
// value does not need to be included in the params. Otherwise, it will return
|
@ -1,7 +1,14 @@
|
|||||||
package tgbotapi
|
package tgbotapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewMessage creates a new Message.
|
// NewMessage creates a new Message.
|
||||||
@ -171,7 +178,9 @@ func NewVoice(chatID int64, file RequestFileData) 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{
|
||||||
ChatID: chatID,
|
BaseChat: BaseChat{
|
||||||
|
ChatID: chatID,
|
||||||
|
},
|
||||||
Media: files,
|
Media: files,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,7 +576,7 @@ func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEditMessageTextAndMarkup allows you to edit the text and replymarkup of a message.
|
// NewEditMessageTextAndMarkup allows you to edit the text and reply markup of a message.
|
||||||
func NewEditMessageTextAndMarkup(chatID int64, messageID int, text string, replyMarkup InlineKeyboardMarkup) EditMessageTextConfig {
|
func NewEditMessageTextAndMarkup(chatID int64, messageID int, text string, replyMarkup InlineKeyboardMarkup) EditMessageTextConfig {
|
||||||
return EditMessageTextConfig{
|
return EditMessageTextConfig{
|
||||||
BaseEdit: BaseEdit{
|
BaseEdit: BaseEdit{
|
||||||
@ -618,6 +627,15 @@ func NewKeyboardButton(text string) KeyboardButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewKeyboardButtonWebApp creates a keyboard button with text
|
||||||
|
// which goes to a WebApp.
|
||||||
|
func NewKeyboardButtonWebApp(text string, webapp WebAppInfo) KeyboardButton {
|
||||||
|
return KeyboardButton{
|
||||||
|
Text: text,
|
||||||
|
WebApp: &webapp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewKeyboardButtonContact creates a keyboard button that requests
|
// NewKeyboardButtonContact creates a keyboard button that requests
|
||||||
// user contact information upon click.
|
// user contact information upon click.
|
||||||
func NewKeyboardButtonContact(text string) KeyboardButton {
|
func NewKeyboardButtonContact(text string) KeyboardButton {
|
||||||
@ -673,6 +691,15 @@ func NewInlineKeyboardButtonData(text, data string) InlineKeyboardButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewInlineKeyboardButtonWebApp creates an inline keyboard button with text
|
||||||
|
// which goes to a WebApp.
|
||||||
|
func NewInlineKeyboardButtonWebApp(text string, webapp WebAppInfo) InlineKeyboardButton {
|
||||||
|
return InlineKeyboardButton{
|
||||||
|
Text: text,
|
||||||
|
WebApp: &webapp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewInlineKeyboardButtonLoginURL creates an inline keyboard button with text
|
// NewInlineKeyboardButtonLoginURL creates an inline keyboard button with text
|
||||||
// which goes to a LoginURL.
|
// which goes to a LoginURL.
|
||||||
func NewInlineKeyboardButtonLoginURL(text string, loginURL LoginURL) InlineKeyboardButton {
|
func NewInlineKeyboardButtonLoginURL(text string, loginURL LoginURL) InlineKeyboardButton {
|
||||||
@ -925,3 +952,38 @@ func NewDeleteMyCommandsWithScope(scope BotCommandScope) DeleteMyCommandsConfig
|
|||||||
func NewDeleteMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string) DeleteMyCommandsConfig {
|
func NewDeleteMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string) DeleteMyCommandsConfig {
|
||||||
return DeleteMyCommandsConfig{Scope: &scope, LanguageCode: languageCode}
|
return DeleteMyCommandsConfig{Scope: &scope, LanguageCode: languageCode}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateWebAppData validate data received via the Web App
|
||||||
|
// https://core.telegram.org/bots/webapps#validating-data-received-via-the-web-app
|
||||||
|
func ValidateWebAppData(token, telegramInitData string) (bool, error) {
|
||||||
|
initData, err := url.ParseQuery(telegramInitData)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error parsing data %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dataCheckString := make([]string, 0, len(initData))
|
||||||
|
for k, v := range initData {
|
||||||
|
if k == "hash" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(v) > 0 {
|
||||||
|
dataCheckString = append(dataCheckString, fmt.Sprintf("%s=%s", k, v[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(dataCheckString)
|
||||||
|
|
||||||
|
secret := hmac.New(sha256.New, []byte("WebAppData"))
|
||||||
|
secret.Write([]byte(token))
|
||||||
|
|
||||||
|
hHash := hmac.New(sha256.New, secret.Sum(nil))
|
||||||
|
hHash.Write([]byte(strings.Join(dataCheckString, "\n")))
|
||||||
|
|
||||||
|
hash := hex.EncodeToString(hHash.Sum(nil))
|
||||||
|
|
||||||
|
if initData.Get("hash") != hash {
|
||||||
|
return false, errors.New("hash not equal")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
@ -95,3 +95,10 @@ func (p Params) AddFirstValid(key string, args ...interface{}) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge merges two sets of parameters. Overwrites old fields if present
|
||||||
|
func (p *Params) Merge(p1 Params) {
|
||||||
|
for k, v := range p1 {
|
||||||
|
(*p)[k] = v
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
@ -83,9 +83,6 @@ github.com/fsnotify/fsnotify
|
|||||||
# github.com/go-asn1-ber/asn1-ber v1.5.3
|
# github.com/go-asn1-ber/asn1-ber v1.5.3
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/go-asn1-ber/asn1-ber
|
github.com/go-asn1-ber/asn1-ber
|
||||||
# github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1
|
|
||||||
## explicit; go 1.16
|
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api/v5
|
|
||||||
# github.com/golang-jwt/jwt v3.2.2+incompatible
|
# github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||||
## explicit
|
## explicit
|
||||||
github.com/golang-jwt/jwt
|
github.com/golang-jwt/jwt
|
||||||
@ -234,6 +231,9 @@ github.com/matterbridge/logrus-prefixed-formatter
|
|||||||
# github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d
|
# github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
github.com/matterbridge/matterclient
|
github.com/matterbridge/matterclient
|
||||||
|
# github.com/matterbridge/telegram-bot-api/v6 v6.5.0
|
||||||
|
## explicit; go 1.16
|
||||||
|
github.com/matterbridge/telegram-bot-api/v6
|
||||||
# github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404
|
# github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404
|
||||||
## explicit
|
## explicit
|
||||||
github.com/mattermost/go-i18n/i18n
|
github.com/mattermost/go-i18n/i18n
|
||||||
|
Loading…
Reference in New Issue
Block a user