mirror of
https://github.com/tucnak/telebot
synced 2024-11-03 09:40:18 +00:00
Protecting callbacks with callback guards.
This commit is contained in:
parent
eae6345b88
commit
6f068bdacb
28
bot.go
28
bot.go
@ -20,10 +20,16 @@ func NewBot(pref Settings) (*Bot, error) {
|
||||
pref.Updates = 100
|
||||
}
|
||||
|
||||
if pref.Guard != nil && pref.Secret == "" {
|
||||
panic("telebot: can't set guard with no secret")
|
||||
}
|
||||
|
||||
bot := &Bot{
|
||||
Token: pref.Token,
|
||||
Updates: make(chan Update, pref.Updates),
|
||||
Secret: pref.Secret,
|
||||
Poller: pref.Poller,
|
||||
Guard: pref.Guard,
|
||||
|
||||
handlers: make(map[string]interface{}),
|
||||
}
|
||||
@ -41,10 +47,12 @@ func NewBot(pref Settings) (*Bot, error) {
|
||||
type Bot struct {
|
||||
Me *User
|
||||
Token string
|
||||
Secret string
|
||||
Updates chan Update
|
||||
Poller Poller
|
||||
Errors chan error
|
||||
Guard Guard
|
||||
|
||||
Errors chan error
|
||||
handlers map[string]interface{}
|
||||
}
|
||||
|
||||
@ -59,6 +67,12 @@ type Settings struct {
|
||||
|
||||
// Poller is the provider of Updates.
|
||||
Poller Poller
|
||||
|
||||
// Callback guard (de-)encrypts callback data.
|
||||
Guard Guard
|
||||
|
||||
// Bot secret will be used when encrypting callback data.
|
||||
Secret string
|
||||
}
|
||||
|
||||
// Update object represents an incoming update.
|
||||
@ -232,6 +246,10 @@ func (b *Bot) Start() {
|
||||
if upd.Callback.Data != "" {
|
||||
data := upd.Callback.Data
|
||||
|
||||
if b.Guard != nil {
|
||||
data = b.Guard.Decrypt(data, b.Secret)
|
||||
}
|
||||
|
||||
if data[0] == '\f' {
|
||||
match := cbackRx.FindAllStringSubmatch(data, -1)
|
||||
|
||||
@ -414,7 +432,7 @@ func (b *Bot) SendAlbum(to Recipient, a Album, options ...interface{}) ([]Messag
|
||||
}
|
||||
|
||||
sendOpts := extractOptions(options)
|
||||
embedSendOptions(params, sendOpts)
|
||||
b.embedSendOptions(params, sendOpts)
|
||||
|
||||
respJSON, err := b.sendFiles("sendMediaGroup", files, params)
|
||||
if err != nil {
|
||||
@ -477,7 +495,7 @@ func (b *Bot) Forward(to Recipient, what *Message, options ...interface{}) (*Mes
|
||||
}
|
||||
|
||||
sendOpts := extractOptions(options)
|
||||
embedSendOptions(params, sendOpts)
|
||||
b.embedSendOptions(params, sendOpts)
|
||||
|
||||
respJSON, err := b.sendCommand("forwardMessage", params)
|
||||
if err != nil {
|
||||
@ -509,7 +527,7 @@ func (b *Bot) Edit(originalMsg Editable, text string, options ...interface{}) (*
|
||||
}
|
||||
|
||||
sendOpts := extractOptions(options)
|
||||
embedSendOptions(params, sendOpts)
|
||||
b.embedSendOptions(params, sendOpts)
|
||||
|
||||
respJSON, err := b.sendCommand("editMessageText", params)
|
||||
if err != nil {
|
||||
@ -714,7 +732,7 @@ func (b *Bot) Pin(message Editable, options ...interface{}) error {
|
||||
}
|
||||
|
||||
sendOpts := extractOptions(options)
|
||||
embedSendOptions(params, sendOpts)
|
||||
b.embedSendOptions(params, sendOpts)
|
||||
|
||||
respJSON, err := b.sendCommand("pinChatMessage", params)
|
||||
if err != nil {
|
||||
|
40
guard.go
Normal file
40
guard.go
Normal file
@ -0,0 +1,40 @@
|
||||
package telebot
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Guard is a callback guard, it performs some sort
|
||||
// of encryption for callbacks and callback data.
|
||||
type Guard interface {
|
||||
Encrypt(text, secret string) string
|
||||
Decrypt(ciphertext, secret string) string
|
||||
}
|
||||
|
||||
// XorGuard implements simple XOR encryption.
|
||||
type XorGuard struct{}
|
||||
|
||||
func sha1str(data string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(data))
|
||||
bs := h.Sum(nil)
|
||||
return fmt.Sprintf("%x", bs)
|
||||
}
|
||||
|
||||
func (x *XorGuard) Encrypt(text, secret string) string {
|
||||
// and hope for the best
|
||||
key := sha1str(secret)
|
||||
|
||||
ctext := make([]byte, len(text))
|
||||
|
||||
for i, _ := range text {
|
||||
ctext[i] = text[i] ^ key[i%len(key)]
|
||||
}
|
||||
|
||||
return string(ctext)
|
||||
}
|
||||
|
||||
func (x *XorGuard) Decrypt(ctext, secret string) string {
|
||||
return x.Encrypt(ctext, secret)
|
||||
}
|
18
sendable.go
18
sendable.go
@ -25,7 +25,7 @@ func (p *Photo) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
|
||||
"caption": p.Caption,
|
||||
}
|
||||
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
msg, err := b.sendObject(&p.File, "photo", params)
|
||||
if err != nil {
|
||||
@ -44,7 +44,7 @@ func (a *Audio) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
|
||||
"chat_id": to.Recipient(),
|
||||
"caption": a.Caption,
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
msg, err := b.sendObject(&a.File, "audio", params)
|
||||
if err != nil {
|
||||
@ -63,7 +63,7 @@ func (d *Document) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error
|
||||
"chat_id": to.Recipient(),
|
||||
"caption": d.Caption,
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
msg, err := b.sendObject(&d.File, "document", params)
|
||||
if err != nil {
|
||||
@ -81,7 +81,7 @@ func (s *Sticker) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error)
|
||||
params := map[string]string{
|
||||
"chat_id": to.Recipient(),
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
msg, err := b.sendObject(&s.File, "sticker", params)
|
||||
if err != nil {
|
||||
@ -100,7 +100,7 @@ func (v *Video) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
|
||||
"chat_id": to.Recipient(),
|
||||
"caption": v.Caption,
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
msg, err := b.sendObject(&v.File, "video", params)
|
||||
if err != nil {
|
||||
@ -118,7 +118,7 @@ func (v *Voice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
|
||||
params := map[string]string{
|
||||
"chat_id": to.Recipient(),
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
msg, err := b.sendObject(&v.File, "voice", params)
|
||||
if err != nil {
|
||||
@ -136,7 +136,7 @@ func (v *VideoNote) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, erro
|
||||
params := map[string]string{
|
||||
"chat_id": to.Recipient(),
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
msg, err := b.sendObject(&v.File, "videoNote", params)
|
||||
if err != nil {
|
||||
@ -156,7 +156,7 @@ func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error
|
||||
"latitude": fmt.Sprintf("%f", x.Lat),
|
||||
"longitude": fmt.Sprintf("%f", x.Lng),
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
respJSON, err := b.sendCommand("sendLocation", params)
|
||||
if err != nil {
|
||||
@ -176,7 +176,7 @@ func (v *Venue) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
|
||||
"address": v.Address,
|
||||
"foursquare_id": v.FoursquareID,
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
respJSON, err := b.sendCommand("sendVenue", params)
|
||||
if err != nil {
|
||||
|
11
util.go
11
util.go
@ -33,7 +33,7 @@ func (b *Bot) sendText(to Recipient, text string, opt *SendOptions) (*Message, e
|
||||
"chat_id": to.Recipient(),
|
||||
"text": text,
|
||||
}
|
||||
embedSendOptions(params, opt)
|
||||
b.embedSendOptions(params, opt)
|
||||
|
||||
respJSON, err := b.sendCommand("sendMessage", params)
|
||||
if err != nil {
|
||||
@ -132,7 +132,7 @@ func extractOptions(how []interface{}) *SendOptions {
|
||||
return opts
|
||||
}
|
||||
|
||||
func embedSendOptions(params map[string]string, opt *SendOptions) {
|
||||
func (b *Bot) embedSendOptions(params map[string]string, opt *SendOptions) {
|
||||
if opt == nil {
|
||||
return
|
||||
}
|
||||
@ -160,7 +160,12 @@ func embedSendOptions(params map[string]string, opt *SendOptions) {
|
||||
for j, _ := range keys[i] {
|
||||
key := &keys[i][j]
|
||||
if key.Unique != "" {
|
||||
key.Data = "\f" + key.Unique + "|" + key.Data
|
||||
data := "\f" + key.Unique + "|" + key.Data
|
||||
if b.Guard != nil {
|
||||
data = b.Guard.Encrypt(data, b.Secret)
|
||||
}
|
||||
|
||||
key.Data = data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user