go-telegram-bot-api / telegram-bot-api Goto Github PK
View Code? Open in Web Editor NEWGolang bindings for the Telegram Bot API
Home Page: https://go-telegram-bot-api.dev
License: MIT License
Golang bindings for the Telegram Bot API
Home Page: https://go-telegram-bot-api.dev
License: MIT License
From Telegram Bot Api oficial page:
Recent changes
August 29, 2015
Added support for self-signed certificates: upload your certificate using the certificate parameter in the setWebhook method.
From telegram bot api official page:
Recent changes
August 29, 2015
You can now make new requests when responding to webhook updates.
Would be cool to have a helper method to ease this task.
I think that we need an example of answering inline-query, I'm having a little problem making one myself, so hopefully the following code will demonstrate a question/example to be used in README.md
package main
import (
"log"
"gopkg.in/telegram-bot-api.v1"
)
func main() {
bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken")
if err != nil {
log.Panic(err)
}
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := bot.GetUpdatesChan(u)
for update := range updates {
if update.InlineQuery.Query == "" {
continue
}
answer := tgbotapi.InlineQueryResultArticle{
InlineQueryResult: tgbotapi.InlineQueryResult{ // ??
Type: "article",
ID: update.InlineQuery.ID,
},
Title: "Echo",
MessageText: update.InlineQuery.Query,
}
inlineConf := tgbotapi.InlineConfig{
InlineQueryID: update.InlineQuery.Query,
Results: []tgbotapi.InlineQueryResult{answer.InlineQueryResult}, // ??
}
if _, err := bot.AnswerInlineQuery(inlineConf); err != nil {
log.Println(err)
}
}
}
I'm not sure how to deal with InlineQueryResult
, this example will hit this error: [Error]: Bad request: Can't find field "message_text"
I'm failing to send a document or a video which is considered not too small, something like ~60Mb, with the debug set to true, the following lines will be shown:
<html>
<head><title>413 Request Entity Too Large</title></head>
<body bgcolor="white">
<center><h1>413 Request Entity Too Large</h1></center>
<hr><center>nginx/1.9.1</center>
</body>
</html>
the code
package main
import (
"log"
"github.com/Syfaro/telegram-bot-api"
)
func main() {
bot, err := tgbotapi.NewBotAPI("DatToken")
if err != nil {
log.Panic(err)
}
bot.Debug = true
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := bot.GetUpdatesChan(u)
for update := range updates {
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
msg := tgbotapi.NewDocumentUpload(update.Message.Chat.ID, "NotTooSmallOfaFile")
bot.Send(msg)
}
}
Please show example with NewInlineKeyboardMarkup with callbacks for processing . I dont understand how i should procces the event when user click inline button.
package main
import (
"log"
"gopkg.in/telegram-bot-api.v4"
)
func main() {
bot, err := tgbotapi.NewBotAPI("XXXX")
if err != nil {
log.Panic(err)
}
bot.Debug = true
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := bot.GetUpdatesChan(u)
for update := range updates {
if update.InlineQuery.Query != "" { // this will cause a panic, it didn't in v2
log.Printf("This was an inline query update\n")
}
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
msg.ReplyToMessageID = update.Message.MessageID
bot.Send(msg)
}
}
Create an internal HTTP server to get webhooks (only started when needed), and provide updates with the Updates
chan.
Trying to send a Photo by URL results in nil pointer dereference
This is the panic:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x476208]
goroutine 52 [running]:
panic(0x6224a0, 0xc42000c0d0)
/usr/lib/go/src/runtime/panic.go:500 +0x1a1
io.(*multiReader).Read(0xc42023c1a0, 0xc4204572e7, 0x44, 0xd19, 0x1cc, 0x0, 0x0)
/usr/lib/go/src/io/multi.go:20 +0x98
io/ioutil.(*nopCloser).Read(0xc42022a270, 0xc4204572e7, 0x44, 0xd19, 0x1cc, 0x0, 0x0)
<autogenerated>:4 +0x6b
io.(*LimitedReader).Read(0xc420376640, 0xc4204572e7, 0xd19, 0xd19, 0x1cc, 0x0, 0x0)
/usr/lib/go/src/io/io.go:436 +0x6c
bufio.(*Writer).ReadFrom(0xc420322f80, 0x75f9e0, 0xc420376640, 0xc4200fcbb8, 0x1, 0x18)
/usr/lib/go/src/bufio/bufio.go:693 +0xcc
io.copyBuffer(0x75f660, 0xc420322f80, 0x75f9e0, 0xc420376640, 0x0, 0x0, 0x0, 0x631bc0, 0x1, 0xc420376640)
/usr/lib/go/src/io/io.go:384 +0x323
io.Copy(0x75f660, 0xc420322f80, 0x75f9e0, 0xc420376640, 0xf, 0xc420379100, 0x581d02)
/usr/lib/go/src/io/io.go:360 +0x68
net/http.(*transferWriter).WriteBody(0xc4202fa7e0, 0x75f660, 0xc420322f80, 0x2, 0x2)
/usr/lib/go/src/net/http/transfer.go:227 +0x677
net/http.(*Request).write(0xc4200c01e0, 0x75f660, 0xc420322f80, 0x0, 0xc420365890, 0x0, 0x0, 0x0)
/usr/lib/go/src/net/http/request.go:565 +0x778
net/http.(*persistConn).writeLoop(0xc420474300)
/usr/lib/go/src/net/http/transport.go:1649 +0x1ac
created by net/http.(*Transport).dialConn
/usr/lib/go/src/net/http/transport.go:1063 +0x50e
exit status 2
This is my code:
package main
import (
"log"
"github.com/go-telegram-bot-api/telegram-bot-api"
"net/url"
)
func main() {
bot, err := tgbotapi.NewBotAPI("pls enter some token here")
if err != nil {
log.Panic(err)
}
bot.Debug = true
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := bot.GetUpdatesChan(u)
url_ptr, _ := url.Parse("https://assets-cdn.github.com/images/modules/site/home-ill-platform.png")
url := *url_ptr
for update := range updates {
if update.Message == nil {
continue
}
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
msg := tgbotapi.NewPhotoUpload(update.Message.Chat.ID, url)
bot.Send(msg);
}
}
The panic is caused by this line:
Line 171 in 99170e2
The panic only happens when sending a Photo via URL, if NewPhotoUpload is called with file path, no panic happens and the Photo is sent correctly.
thumb_url
it became a required parameter, in consequence of InlineQueryResultPhoto function gives an is guaranteed error.
This is a proposal for a feature which will allow a user to stop the update loop (the goroutine) that is created on a call to GetUpdatesChan
.
The rationale behind this request is to allow safe cleaning of a bot listener created with the polling method, without killing the whole program.
An example for such a need would be in an application which starts multiple listeners for different bots, and from time to time needs to stop some of them, and listen to new ones, according to a configuration.
What would happen currently is there is currently no way to stop a bot update loop - a user can use goroutines, and exit them according to some signal in his application, but the update loop will still run internally, and if in the future the user will try to create a listener to the same bot, he will get conflicts on calls to the Telegram API.
I've written code that allows to do that, and will submit a PR, hope it'll get accepted as I think this is a useful feature, anyways, if it's not implemented good enough we can discuss how it should be implemented here :)
our project is github.com/pyed/example
contains one package telegram
that uses telegram-bot-api
and a main.go
$GOPATH/src/github.com/pyed/example
├── main.go
└── telegram
└── telegram.go
telegram/telegram.go
package telegram
import (
"log"
"github.com/Syfaro/telegram-bot-api"
)
var Bot *tgbotapi.BotAPI
func init() {
Bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken")
if err != nil {
log.Panic(err)
}
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
err = Bot.UpdatesChan(u)
if err != nil {
log.Panic(err)
}
log.Printf("Authorized on account %s", Bot.Self.UserName)
}
example/main.go
package main
import (
"log"
"github.com/pyed/example/telegram"
)
func main() {
for update := range telegram.Bot.Updates {
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
}
}
trying to go run main.go
will produce the following
2015/08/07 07:41:47 Authorized on account myawesomebot
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x50 pc=0x2038]
goroutine 1 [running]:
main.main()
$GOPATH/src/github.com/pyed/example/main.go:10 +0x38
goroutine 1 [select]:
net/http.(*persistConn).roundTrip(0xc20806e000, 0xc208267640, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/transport.go:1082 +0x7ad
net/http.(*Transport).RoundTrip(0xc208064000, 0xc208033930, 0xc20826b6e0, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/transport.go:235 +0x558
net/http.send(0xc208033930, 0x611cd8, 0xc208064000, 0x54, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/client.go:219 +0x4fc
net/http.(*Client).send(0xc20803a9f0, 0xc208033930, 0x54, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/client.go:142 +0x15b
net/http.(*Client).doFollowingRedirects(0xc20803a9f0, 0xc208033930, 0x367330, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/client.go:367 +0xb25
net/http.(*Client).Post(0xc20803a9f0, 0xc20826b680, 0x54, 0x327210, 0x21, 0x611d28, 0xc20825f9a0, 0x54, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/client.go:441 +0x10d
net/http.(*Client).PostForm(0xc20803a9f0, 0xc20826b680, 0x54, 0xc2081eefc0, 0x2, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/client.go:461 +0x11c
github.com/Syfaro/telegram-bot-api.(*BotAPI).MakeRequest(0xc208058060, 0x2f33b0, 0xa, 0xc2081eefc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
$GOPATH/src/github.com/Syfaro/telegram-bot-api/methods.go:150 +0x1ee
github.com/Syfaro/telegram-bot-api.(*BotAPI).GetUpdates(0xc208058060, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0)
$GOPATH/src/github.com/Syfaro/telegram-bot-api/methods.go:771 +0x671
github.com/Syfaro/telegram-bot-api.func·001()
$GOPATH/src/github.com/Syfaro/telegram-bot-api/updates.go:14 +0x58
created by github.com/Syfaro/telegram-bot-api.(*BotAPI).UpdatesChan
$GOPATH/src/github.com/Syfaro/telegram-bot-api/updates.go:34 +0x12e
goroutine 9 [IO wait]:
net.(*pollDesc).Wait(0xc2080101b0, 0x72, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/fd_poll_runtime.go:84 +0x47
net.(*pollDesc).WaitRead(0xc2080101b0, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/fd_poll_runtime.go:89 +0x43
net.(*netFD).Read(0xc208010150, 0xc208030800, 0x400, 0x400, 0x0, 0x611ae0, 0xc2082674e8)
/usr/local/Cellar/go/1.4.2/libexec/src/net/fd_unix.go:242 +0x40f
net.(*conn).Read(0xc208036048, 0xc208030800, 0x400, 0x400, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/net.go:121 +0xdc
crypto/tls.(*block).readFromUntil(0xc20803ac90, 0x612ec0, 0xc208036048, 0x5, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/crypto/tls/conn.go:454 +0xe6
crypto/tls.(*Conn).readRecord(0xc208072000, 0x17, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/crypto/tls/conn.go:539 +0x2da
crypto/tls.(*Conn).Read(0xc208072000, 0xc20809c000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/crypto/tls/conn.go:904 +0x166
net/http.noteEOFReader.Read(0x6179d8, 0xc208072000, 0xc20806e058, 0xc20809c000, 0x1000, 0x1000, 0x257600, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/transport.go:1270 +0x6e
net/http.(*noteEOFReader).Read(0xc20825f6a0, 0xc20809c000, 0x1000, 0x1000, 0xc208012000, 0x0, 0x0)
<autogenerated>:125 +0xd4
bufio.(*Reader).fill(0xc20826b4a0)
/usr/local/Cellar/go/1.4.2/libexec/src/bufio/bufio.go:97 +0x1ce
bufio.(*Reader).Peek(0xc20826b4a0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.4.2/libexec/src/bufio/bufio.go:132 +0xf0
net/http.(*persistConn).readLoop(0xc20806e000)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/transport.go:842 +0xa4
created by net/http.(*Transport).dialConn
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/transport.go:660 +0xc9f
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/Cellar/go/1.4.2/libexec/src/runtime/asm_amd64.s:2232 +0x1
goroutine 10 [select]:
net/http.(*persistConn).writeLoop(0xc20806e000)
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/transport.go:945 +0x41d
created by net/http.(*Transport).dialConn
/usr/local/Cellar/go/1.4.2/libexec/src/net/http/transport.go:661 +0xcbc
exit status 2
How to send two keyboards (inline and normal) by one function Send()
?
The Telegram API allows to specify a negative offset ("The negative offset can be specified to retrieve updates starting from -offset update from the end of the updates queue."), but (bot *BotAPI) GetUpdates
accepts only a positive offset:
if config.Offset > 0 {
v.Add("offset", strconv.Itoa(config.Offset))
}
Some of us (like me) have their bots in GAE (Google App Engine) since the sendPicture method only takes a file path it can't be used in GAE because the system is readonly so would be cool to add a param or override those methods that send files picture, audio, document, etc to have to posiblity to send a ReaderCloser (like response.Body) or a []bytes that can be parsed inside them.
This is an example on how I achieved this with the same library you're using:
ms.WriteReader(paramType, "card." + extension, contentLength, resp.Body)
req, _ := http.NewRequest("POST", BASE_URL + methodName, nil)
ms.SetupRequest(req)
Since the telegram group is not working I ask it here.
We have updates that we receive and chattables that we send and messages which are the result of sending chattables. But chattables are private interfaces which made me suspect if they have also private state.
Can we serialize Update, Message and Chattables to/from JSON safely?
itemsSel := [][]string{}
itemsSel = append(itemsSel, []string{item1.Caption, item2.Caption, item3.Caption})
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "Select item")
msg.ReplyMarkup = &tgbotapi.ReplyKeyboardMarkup{
Keyboard: itemsSel,
ResizeKeyboard: true,
OneTimeKeyboard: false,
Selective: false,
}
log.Println(msg.ReplyMarkup)
msg.ReplyToMessageID = update.Message.MessageID
_, err = bot.Send(msg)
But the keyboard is no longer displayed in the chat.
Logs:
2015/11/25 14:43:37 &{[[Hot set Samurai set Sunrise set]] true false false}
2015/11/25 14:43:37 SendMessage {"ok":true,"result":{"message_id":238,"from":{"id":xxx,"first_name":"xxx","username":"xxx"},"chat":{"id":xxx,"first_name":"xxx","last_name":"xxx","username":"xxx","type":"private"},"date":1448444617,"reply_to_message":{"message_id":234,"from":{"id":xxx,"first_name":"xxx","last_name":"xxx","username":"xxx"},"chat":{"id":xxx,"first_name":"xxx","last_name":"xxx","username":"xxx","type":"private"},"date":1448444615,"text":"new"},"text":"xxx"}}
2015/11/25 14:43:37 SendMessage req : map[chat_id:[xxx] reply_to_message_id:[234] text:[Select item] disable_web_page_preview:[false]]
Before commit #29 it worked. Or I'm doing something wrong?
When we set InlineMessageId in BaseEdit struct of EditMessageTextConfig , values of ChatID and MessageID not omitted and sets to 0. This gives Chat not found error. We need test InlineMessageId existence in BaseEdit.values func and Add either inline_message_id or chat_id and message_id
This is probably unrelated to tgbotapi
but I'm not sure what's causing this issue, could be telegram's markdown parser ?
while running the following:
package main
import (
"fmt"
"log"
"gopkg.in/telegram-bot-api.v4"
)
func main() {
bot, err := tgbotapi.NewBotAPI("ThatAwesomeToken")
if err != nil {
log.Panic(err)
}
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := bot.GetUpdatesChan(u)
for update := range updates {
if update.Message == nil {
continue
}
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
var text string
for i := 1; i < 35; i++ {
text += fmt.Sprintf("*%d*- *%s*, `%s`\n", i, "Hello", "World!")
}
fmt.Println(len(text))
msg := tgbotapi.NewMessage(update.Message.Chat.ID, text)
msg.ParseMode = "markdown"
bot.Send(msg)
}
}
it'll just respond with 34 <n> Hello, World!
with some markdown. notice that all of them will be correctly formatted until the 34th, after the 34th the markdown will vanish!
I've been having an issue with a Telegram Bot silently failing to send messages intermittently. The SendPhoto function is returning error == nil in such cases indicating no failure occurred but the message has not delivered.
While looking into what could cause a nil error while still having an error I noticed that the APIResponce returned by MakeRequest is not checked at all, more specifically the Ok and ErrorCode fields.
While I haven't monkeypatched anything in yet to see if the server is rejecting my sent messages gracefully, it seems like this library should be checking the values or at least making the APIResponse accessible to the user user code if required.
If I use
file := "http://...../img.jpg"
msg := tgbotapi.NewPhotoUpload(update.Message.Chat.ID, file)
bot.Send(msg)
I got "Bad Request: there is no photo in the request"
If I use
file := "http://...../img.jpg"
msg := tgbotapi.NewPhotoUpload(update.Message.Chat.ID, nil)
msg.FileID = file
bot.Send(msg)
I got "open ...: no such file or directory"
but if I use
file := "http://...../img.jpg"
msg := tgbotapi.NewPhotoUpload(update.Message.Chat.ID, nil)
msg.FileID = file
msg.UseExisting = true
bot.Send(msg)
all works
It may be possible to make to support this method in NewPhotoUpload if last argument is url?
What else can be tested?
I'm having a bytes.Buffer
with a photo in it, trying to send &bytes.Buffer
will hit bad file type
, I'm not sure what to use to get a FileBytes
or FileReader
, google did not help :-/
switch f := file.(type) {
case string:
fileHandle, err := os.Open(f)
if err != nil {
return APIResponse{}, err
}
defer fileHandle.Close()
fi, err := os.Stat(f)
if err != nil {
return APIResponse{}, err
}
ms.WriteReader(fieldname, fileHandle.Name(), fi.Size(), fileHandle)
case FileBytes:
buf := bytes.NewBuffer(f.Bytes)
ms.WriteReader(fieldname, f.Name, int64(len(f.Bytes)), buf)
case FileReader:
if f.Size != -1 {
ms.WriteReader(fieldname, f.Name, f.Size, f.Reader)
break
}
data, err := ioutil.ReadAll(f.Reader)
if err != nil {
return APIResponse{}, err
}
buf := bytes.NewBuffer(data)
ms.WriteReader(fieldname, f.Name, int64(len(data)), buf)
default:
return APIResponse{}, errors.New("bad file type")
}
As I see, all the result recieved from telegram server are getting unmarshal, it's an unneeded thing,
Users can do'it their self or you could put an option that if they want it to unmarshal the result...
It would save a lot of time for server as we know Json (Un)Marshaling is a little slow in Golang...
Thanks in advance @Syfaro
For consistency its good to have the response feedback from this API method, I could even submit a PR doing this, it will be trivial, anyway I like how you have done this API client, its awesome, thanks.
Getting this error on appengine
bad runtime process port ['']
2017/01/08 13:54:31 Post https://api.telegram.org/bot$TOKEN/getMe: http.DefaultTransport and http.DefaultClient are not available in App Engine. See https://cloud.google.com/appengine/docs/go/urlfetch/
Hello, I'm tried use the telegram-bot-api
but without success.
My code is the same example of README.
Steps to reproduce the error:
Go: 1.7.3
go run main.go
Log:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x49eff6]
goroutine 37 [running]:
panic(0x6213c0, 0xc42000c130)
/home/fguedes/go/go/src/runtime/panic.go:500 +0x1a1
net/http.(*Client).deadline(0x0, 0xc42002c020, 0x8900000000000000, 0x8)
/home/fguedes/go/go/src/net/http/client.go:193 +0x26
net/http.(*Client).doFollowingRedirects(0x0, 0xc4203723c0, 0x683bb0, 0x66bf9d, 0x21, 0xc4203f4200)
/home/fguedes/go/go/src/net/http/client.go:446 +0x8b
net/http.(*Client).Post(0x0, 0xc42039c270, 0x27, 0x66bf9d, 0x21, 0x75e220, 0xc4203f4200, 0x40, 0xc42039c270, 0x27)
/home/fguedes/go/go/src/net/http/client.go:579 +0xe2
net/http.(*Client).PostForm(0x0, 0xc42039c270, 0x27, 0xc42039c240, 0x2, 0xc42039c270, 0x27)
/home/fguedes/go/go/src/net/http/client.go:605 +0xdd
gopkg.in/telegram-bot-api%2ev4.(*BotAPI).MakeRequest(0xc4200e2060, 0x665077, 0xa, 0xc42039c240, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/home/fguedes/go/gandalf/src/gopkg.in/telegram-bot-api.v4/bot.go:60 +0x1b8
gopkg.in/telegram-bot-api%2ev4.(*BotAPI).GetUpdates(0xc4200e2060, 0x0, 0x0, 0x3c, 0x0, 0x0, 0x0, 0x0, 0x0)
/home/fguedes/go/gandalf/src/gopkg.in/telegram-bot-api.v4/bot.go:386 +0xc8
gopkg.in/telegram-bot-api%2ev4.(*BotAPI).GetUpdatesChan.func1(0xc4200e2060, 0xc4203f41a0, 0xc4200e2180)
/home/fguedes/go/gandalf/src/gopkg.in/telegram-bot-api.v4/bot.go:456 +0x72
created by gopkg.in/telegram-bot-api%2ev4.(*BotAPI).GetUpdatesChan
/home/fguedes/go/gandalf/src/gopkg.in/telegram-bot-api.v4/bot.go:472 +0xa9
Anyone can help me?
Bad Request: BUTTON_TYPE_INVALID
if I try remove InlineKeyboard in message by this code:
edit := tgbotapi.NewEditMessageReplyMarkup(
callback.Message.Chat.ID,
callback.Message.MessageID,
tgbotapi.InlineKeyboardMarkup{},
)
bot.Send(edit)
P.S.: Also, as and with this variant:
var markup tgbotapi.InlineKeyboardMarkup
edit := tgbotapi.NewEditMessageText(
callback.Message.Chat.ID,
callback.Message.MessageID,
"sample text",
)
edit.ReplyMarkup = &markup
bot.Send(edit)
I want to use logrus, or my logger. Can you implement setLogger
?
Is there any way to send GIFs via this package right now? I tried using tgbotapi.NewPhotoUpload but this is just sending a normal image.
I could implement it myself and send a PR if you want
Hello, there! Just wanted to inquirer is there any reason type updatesChannel
is private?
As far as I can see it has single public method Clear()
which is not used anywhere in the library which in my eyes creates a contradiction where type has public method but no consumer can use it due to type being private.
The issue came up when I switched to webHook from polling. I would love to add switch from polling to webHook with single boolean parameter and use code similar to this
var updates tgbotapi.updatesChannel
if isWebHook{
//listen for updates
} else {
//get updates channel
}
for update := range updates{
// deal with update
}
but since updatesChannel
is private I cannot do this as updates would be uninitialised.
On new message keyboard show, on inline not.
package main
import (
"log"
"strconv"
"github.com/go-telegram-bot-api/telegram-bot-api"
)
func main() {
bot, err := tgbotapi.NewBotAPI("")
if err != nil {
log.Panic(err)
}
bot.Debug = true
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := bot.GetUpdatesChan(u)
lastid := 0
for update := range updates {
if lastid != 0 && update.CallbackQuery != nil {
msg := tgbotapi.NewEditMessageText(update.CallbackQuery.Message.Chat.ID, lastid, "li:"+strconv.Itoa(lastid))
butt := tgbotapi.NewInlineKeyboardRow(tgbotapi.NewInlineKeyboardButtonData("Next 2", "next"))
keyb := tgbotapi.NewInlineKeyboardMarkup(butt)
msg.ReplyMarkup = &keyb
sm, _ := bot.Send(msg)
lastid = sm.MessageID
} else if update.Message != nil {
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
butt := tgbotapi.NewInlineKeyboardRow(tgbotapi.NewInlineKeyboardButtonData("Next 1", "next"))
keyb := tgbotapi.NewInlineKeyboardMarkup(butt)
msg.ReplyMarkup = &keyb
sm, _ := bot.Send(msg)
lastid = sm.MessageID
}
}
}
I made for myself corrections, but not sure that they are correct:
diff --git a/configs.go b/configs.go
index 64a88e4..85310bf 100644
--- a/configs.go
+++ b/configs.go
@@ -560,7 +560,6 @@ type EditMessageTextConfig struct {
Text string
ParseMode string
DisableWebPagePreview bool
- ReplyMarkup *InlineKeyboardMarkup
}
func (config EditMessageTextConfig) values() (url.Values, error) {
@@ -580,8 +579,7 @@ func (config EditMessageTextConfig) method() string {
// EditMessageCaptionConfig allows you to modify the caption of a message.
type EditMessageCaptionConfig struct {
BaseEdit
- Caption string
- ReplyMarkup *InlineKeyboardMarkup
+ Caption string
}
func (config EditMessageCaptionConfig) values() (url.Values, error) {
@@ -600,7 +598,6 @@ func (config EditMessageCaptionConfig) method() string {
// of a message.
type EditMessageReplyMarkupConfig struct {
BaseEdit
- ReplyMarkup *InlineKeyboardMarkup
}
func (config EditMessageReplyMarkupConfig) values() (url.Values, error) {
diff --git a/helpers.go b/helpers.go
index 6af3e65..d6e6a38 100644
--- a/helpers.go
+++ b/helpers.go
@@ -421,10 +421,10 @@ func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMess
func NewEditMessageReplyMarkup(chatID int64, messageID int, replyMarkup InlineKeyboardMarkup) EditMessageReplyMarkupConfig {
return EditMessageReplyMarkupConfig{
BaseEdit: BaseEdit{
- ChatID: chatID,
- MessageID: messageID,
+ ChatID: chatID,
+ MessageID: messageID,
+ ReplyMarkup: &replyMarkup,
},
- ReplyMarkup: &replyMarkup,
}
}
Is there a way to get user's @ with go?
I'm getting lot of troubles with this.
2015/08/09 09:10:50 getUpdates: []
2015/08/09 09:11:10 getUpdates {"ok":true,"result":[]}
2015/08/09 09:11:10 getUpdates: []
2015/08/09 09:11:30 getUpdates {"ok":true,"result":[]}
2015/08/09 09:11:30 getUpdates: []
2015/08/09 09:11:38 getUpdates <html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.6.2</center>
</body>
</html>
panic:
goroutine 11 [running]:
github.com/Syfaro/telegram-bot-api.func·001()
/root/go/src/github.com/Syfaro/telegram-bot-api/updates.go:17 +0xd5
created by github.com/Syfaro/telegram-bot-api.(*BotAPI).UpdatesChan
/root/go/src/github.com/Syfaro/telegram-bot-api/updates.go:34 +0x12e
goroutine 1 [chan receive, 607 minutes]:
main.main()
/usr/local/src/freeswitch_golang_scripts/telegram.go:26 +0x3e4
goroutine 17 [syscall, 628 minutes, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1
goroutine 101 [runnable]:
net/http.(*persistConn).readLoop(0xc208076bb0)
/usr/local/go/src/net/http/transport.go:928 +0x9ce
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:660 +0xc9f
goroutine 102 [select]:
net/http.(*persistConn).writeLoop(0xc208076bb0)
/usr/local/go/src/net/http/transport.go:945 +0x41d
created by net/http.(*Transport).dialConn
/usr/local/go/src/net/http/transport.go:661 +0xcbc
When a request fails, the Telegram API responds with some useful information in error_code, description, and parameters as per https://core.telegram.org/bots/api#making-requests
Unfortunately, this line of code prevents reading anything from the returned api response other than the description as passed through the error:
Line 84 in c034de5
The most obvious fix would be to change the returned empty struct APIResponse{} to the retrieved apiResp on that line.
This will this flow on to other functions such as AnswerInlineQuery, AnswerCallbackQuery, etc that simply return bot.MakeRequest() directly.
data3
Any help or tips would be great for me. thanks.
the testing has been done with the following code.
package main
import (
"log"
"github.com/Syfaro/telegram-bot-api"
)
func main() {
bot, err := tgbotapi.NewBotAPI("YourAwesomeAPIToken")
if err != nil {
log.Panic(err)
}
bot.Debug = true
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
err = bot.UpdatesChan(u)
if err != nil {
log.Panic(err)
}
videofile := "1.mp4"
for update := range bot.Updates {
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "video on the way")
msg.ReplyToMessageID = update.Message.MessageID
bot.SendMessage(msg)
newVid := tgbotapi.NewVideoUpload(update.Message.Chat.ID, videofile)
if _, err := bot.SendVideo(newVid); err != nil {
log.Panic(err)
}
}
}
I tested sending videos with multiple mp4
files and they all show the same behavior, when the bot sends them they will have no thumbnail, and the time of the video will be 00:00
, also I should mention that on the iPhone Telegram app they can not be played!, it will just show a black background, on the OS X client it will work, but as I said, no thumbnail and no time.
I don't think that this is an API issue, because the OS X client handles them perfectly, using the drop-in feature it will ask you to send them with compression or "in a quick way", if you choose without compression I believe it will send them as a document, with the compression they'll be okay.
for testing you could download this http://i.imgur.com/CGaKrhh.gifv
Twas using this in production, couldnt figure out why the weekly autobuild was failing till I looked at the logs....
I dont think anyone really cares if the method is called UpdatesChan as opposed to GetUpdatesChan, or Send vs SendMessage, but I can say that if every time I git pull things break because someone likes one naming scheme better I would be looking for a different library.
^ Strikethrough cuz rude. What I mean to say is this: when you release a project that ends up being used heavilly in many other projects, you need to have some stability
Some ideas going forward:
That would be very interesting. There are various cases, like if you message a bot in a group and send him "/command@bot".
I have a bot manager, that creates some bot instances in goroutings. And it must have a posibility to stop them. but i don't see how to stop bot.GetUpdates() here?
func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) (<-chan Update, error) {
updatesChan := make(chan Update, 100)
go func() {
for {
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
updatesChan <- update
}
}
}
}()
return updatesChan, nil
}
It continues to get Updates until the whole programm is closed. Is it posible to create method for stopping bot?
Sending large files with SendDocument
or SendVideo
will result in high memory usage, and after the file done sending, this memory won't get freed
consider the following code
package main
import (
"log"
"github.com/Syfaro/telegram-bot-api"
)
func main() {
bot, err := tgbotapi.NewBotAPI("MyAwesomeToken")
if err != nil {
log.Panic(err)
}
// bot.Debug = true
log.Printf("Authorized on account %s", bot.Self.UserName)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
err = bot.UpdatesChan(u)
if err != nil {
log.Panic(err)
}
filename := "file.dat" // ~33Mb, should be fairly a big file to notice
for update := range bot.Updates {
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "the file on its way")
msg.ReplyToMessageID = update.Message.MessageID
bot.SendMessage(msg)
newDoc := tgbotapi.NewDocumentUpload(update.Message.Chat.ID, filename)
if _, err := bot.SendDocument(newDoc); err != nil {
log.Panic(err)
}
}
}
Now running this bot on OS X will start with 8.2 MB
of Real Mem
"according to Activity Monitor
"
after sending the first message, the bot will start sending file.dat
, Real Mem
will jump to 107.6 MB
it will finish sending but it will not free the memory, requesting the file again will rise Real Mem
again to 180 MB
... etc
I took a look at the code and I figured it has to be in the UploadFile
method, and I found that a usage to os.Open()
bond to a variable called f
hasn't get closed, I tried closing it, but it did not solve the problem.
NewMessage
accepts chatID
only in int64
format while the API method sendMessage
supports Integer
or String
.
Is there a workaround for this? Looks like only UploadFile
supports map format....
At the moment this library does not allow a developer to replace the golang default log package to capture logs to redirect to say syslog as is common with services.
This is mainly apparent in the UpdatesChan goroutine when an error occurs during the poll.
Where to pass an array of arrays for custom keyboard for bot? Please, help!
The development group doesn't work.
tag v4.1.0
$ go test -v
bot/src/gopkg.in/telegram-bot-api.v4
# gopkg.in/telegram-bot-api.v4_test
./helpers_test.go:60: undefined: tgbotapi.NewInlineQueryResultAudio
./helpers_test.go:71: undefined: tgbotapi.NewInlineQueryResultVoice
./helpers_test.go:82: undefined: tgbotapi.NewInlineQueryResultDocument
./helpers_test.go:94: undefined: tgbotapi.NewInlineQueryResultLocation
FAIL gopkg.in/telegram-bot-api.v4 [build failed]
This is strange, but the sent callback through pressing the keyboard button from the inline search result does not return the body of the parent. Only identifiers, data and date.
there's no 'caption' in documentConfig even if it's supported: https://core.telegram.org/bots/api#senddocument
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.