GithubHelp home page GithubHelp logo

telebot's Introduction

Telebot

"I never knew creating Telegram bots could be so sexy!"

GoDoc GitHub Actions codecov.io Discuss on Telegram

go get -u gopkg.in/telebot.v3

Overview

Telebot is a bot framework for Telegram Bot API. This package provides the best of its kind API for command routing, inline query requests and keyboards, as well as callbacks. Actually, I went a couple steps further, so instead of making a 1:1 API wrapper I chose to focus on the beauty of API and performance. Some strong sides of Telebot are:

  • Real concise API
  • Command routing
  • Middleware
  • Transparent File API
  • Effortless bot callbacks

All the methods of Telebot API are extremely easy to memorize and get used to. Also, consider Telebot a highload-ready solution. I'll test and benchmark the most popular actions and if necessary, optimize against them without sacrificing API quality.

Getting Started

Let's take a look at the minimal Telebot setup:

package main

import (
	"log"
	"os"
	"time"

	tele "gopkg.in/telebot.v3"
)

func main() {
	pref := tele.Settings{
		Token:  os.Getenv("TOKEN"),
		Poller: &tele.LongPoller{Timeout: 10 * time.Second},
	}

	b, err := tele.NewBot(pref)
	if err != nil {
		log.Fatal(err)
		return
	}

	b.Handle("/hello", func(c tele.Context) error {
		return c.Send("Hello!")
	})

	b.Start()
}

Simple, innit? Telebot's routing system takes care of delivering updates to their endpoints, so in order to get to handle any meaningful event, all you got to do is just plug your function into one of the Telebot-provided endpoints. You can find the full list here.

There are dozens of supported endpoints (see package consts). Let me know if you'd like to see some endpoint or endpoint ideas implemented. This system is completely extensible, so I can introduce them without breaking backwards compatibility.

Context

Context is a special type that wraps a huge update structure and represents the context of the current event. It provides several helpers, which allow getting, for example, the chat that this update had been sent in, no matter what kind of update this is.

b.Handle(tele.OnText, func(c tele.Context) error {
	// All the text messages that weren't
	// captured by existing handlers.

	var (
		user = c.Sender()
		text = c.Text()
	)

	// Use full-fledged bot's functions
	// only if you need a result:
	msg, err := b.Send(user, text)
	if err != nil {
		return err
	}

	// Instead, prefer a context short-hand:
	return c.Send(text)
})

b.Handle(tele.OnChannelPost, func(c tele.Context) error {
	// Channel posts only.
	msg := c.Message()
})

b.Handle(tele.OnPhoto, func(c tele.Context) error {
	// Photos only.
	photo := c.Message().Photo
})

b.Handle(tele.OnQuery, func(c tele.Context) error {
	// Incoming inline queries.
	return c.Answer(...)
})

Middleware

Telebot has a simple and recognizable way to set up middleware — chained functions with access to Context, called before the handler execution.

Import a middleware package to get some basic out-of-box middleware implementations:

import "gopkg.in/telebot.v3/middleware"
// Global-scoped middleware:
b.Use(middleware.Logger())
b.Use(middleware.AutoRespond())

// Group-scoped middleware:
adminOnly := b.Group()
adminOnly.Use(middleware.Whitelist(adminIDs...))
adminOnly.Handle("/ban", onBan)
adminOnly.Handle("/kick", onKick)

// Handler-scoped middleware:
b.Handle(tele.OnText, onText, middleware.IgnoreVia())

Custom middleware example:

// AutoResponder automatically responds to every callback update.
func AutoResponder(next tele.HandlerFunc) tele.HandlerFunc {
	return func(c tele.Context) error {
		if c.Callback() != nil {
			defer c.Respond()
		}
		return next(c) // continue execution chain
	}
}

Poller

Telebot doesn't really care how you provide it with incoming updates, as long as you set it up with a Poller, or call ProcessUpdate for each update:

// Poller is a provider of Updates.
//
// All pollers must implement Poll(), which accepts bot
// pointer and subscription channel and start polling
// synchronously straight away.
type Poller interface {
	// Poll is supposed to take the bot object
	// subscription channel and start polling
	// for Updates immediately.
	//
	// Poller must listen for stop constantly and close
	// it as soon as it's done polling.
	Poll(b *Bot, updates chan Update, stop chan struct{})
}

Commands

When handling commands, Telebot supports both direct (/command) and group-like syntax (/command@botname) and will never deliver messages addressed to some other bot, even if privacy mode is off.

For simplified deep-linking, Telebot also extracts payload:

// Command: /start <PAYLOAD>
b.Handle("/start", func(c tele.Context) error {
	fmt.Println(c.Message().Payload) // <PAYLOAD>
})

For multiple arguments use:

// Command: /tags <tag1> <tag2> <...>
b.Handle("/tags", func(c tele.Context) error {
	tags := c.Args() // list of arguments splitted by a space
	for _, tag := range tags {
		// iterate through passed arguments
	}
})

Files

Telegram allows files up to 50 MB in size.

Telebot allows to both upload (from disk or by URL) and download (from Telegram) files in bot's scope. Also, sending any kind of media with a File created from disk will upload the file to Telegram automatically:

a := &tele.Audio{File: tele.FromDisk("file.ogg")}

fmt.Println(a.OnDisk()) // true
fmt.Println(a.InCloud()) // false

// Will upload the file from disk and send it to the recipient
b.Send(recipient, a)

// Next time you'll be sending this very *Audio, Telebot won't
// re-upload the same file but rather utilize its Telegram FileID
b.Send(otherRecipient, a)

fmt.Println(a.OnDisk()) // true
fmt.Println(a.InCloud()) // true
fmt.Println(a.FileID) // <Telegram file ID>

You might want to save certain Files in order to avoid re-uploading. Feel free to marshal them into whatever format, File only contain public fields, so no data will ever be lost.

Sendable

Send is undoubtedly the most important method in Telebot. Send() accepts a Recipient (could be user, group or a channel) and a Sendable. Other types other than the Telebot-provided media types (Photo, Audio, Video, etc.) are Sendable. If you create composite types of your own, and they satisfy the Sendable interface, Telebot will be able to send them out.

// Sendable is any object that can send itself.
//
// This is pretty cool, since it lets bots implement
// custom Sendables for complex kinds of media or
// chat objects spanning across multiple messages.
type Sendable interface {
	Send(*Bot, Recipient, *SendOptions) (*Message, error)
}

The only type at the time that doesn't fit Send() is Album and there is a reason for that. Albums were added not so long ago, so they are slightly quirky for backwards compatibilities sake. In fact, an Album can be sent, but never received. Instead, Telegram returns a []Message, one for each media object in the album:

p := &tele.Photo{File: tele.FromDisk("chicken.jpg")}
v := &tele.Video{File: tele.FromURL("http://video.mp4")}

msgs, err := b.SendAlbum(user, tele.Album{p, v})

Send options

Send options are objects and flags you can pass to Send(), Edit() and friends as optional arguments (following the recipient and the text/media). The most important one is called SendOptions, it lets you control all the properties of the message supported by Telegram. The only drawback is that it's rather inconvenient to use at times, so Send() supports multiple shorthands:

// regular send options
b.Send(user, "text", &tele.SendOptions{
	// ...
})

// ReplyMarkup is a part of SendOptions,
// but often it's the only option you need
b.Send(user, "text", &tele.ReplyMarkup{
	// ...
})

// flags: no notification && no web link preview
b.Send(user, "text", tele.Silent, tele.NoPreview)

Full list of supported option-flags you can find here.

Editable

If you want to edit some existing message, you don't really need to store the original *Message object. In fact, upon edit, Telegram only requires chat_id and message_id. So you don't really need the Message as a whole. Also, you might want to store references to certain messages in the database, so I thought it made sense for any Go struct to be editable as a Telegram message, to implement Editable:

// Editable is an interface for all objects that
// provide "message signature", a pair of 32-bit
// message ID and 64-bit chat ID, both required
// for edit operations.
//
// Use case: DB model struct for messages to-be
// edited with, say two columns: msg_id,chat_id
// could easily implement MessageSig() making
// instances of stored messages editable.
type Editable interface {
	// MessageSig is a "message signature".
	//
	// For inline messages, return chatID = 0.
	MessageSig() (messageID int, chatID int64)
}

For example, Message type is Editable. Here is the implementation of StoredMessage type, provided by Telebot:

// StoredMessage is an example struct suitable for being
// stored in the database as-is or being embedded into
// a larger struct, which is often the case (you might
// want to store some metadata alongside, or might not.)
type StoredMessage struct {
	MessageID int   `sql:"message_id" json:"message_id"`
	ChatID    int64 `sql:"chat_id" json:"chat_id"`
}

func (x StoredMessage) MessageSig() (int, int64) {
	return x.MessageID, x.ChatID
}

Why bother at all? Well, it allows you to do things like this:

// just two integer columns in the database
var msgs []tele.StoredMessage
db.Find(&msgs) // gorm syntax

for _, msg := range msgs {
	bot.Edit(&msg, "Updated text")
	// or
	bot.Delete(&msg)
}

I find it incredibly neat. Worth noting, at this point of time there exists another method in the Edit family, EditCaption() which is of a pretty rare use, so I didn't bother including it to Edit(), just like I did with SendAlbum() as it would inevitably lead to unnecessary complications.

var m *Message

// change caption of a photo, audio, etc.
bot.EditCaption(m, "new caption")

Keyboards

Telebot supports both kinds of keyboards Telegram provides: reply and inline keyboards. Any button can also act as endpoints for Handle().

var (
	// Universal markup builders.
	menu     = &tele.ReplyMarkup{ResizeKeyboard: true}
	selector = &tele.ReplyMarkup{}

	// Reply buttons.
	btnHelp     = menu.Text("ℹ Help")
	btnSettings = menu.Text("⚙ Settings")

	// Inline buttons.
	//
	// Pressing it will cause the client to
	// send the bot a callback.
	//
	// Make sure Unique stays unique as per button kind
	// since it's required for callback routing to work.
	//
	btnPrev = selector.Data("⬅", "prev", ...)
	btnNext = selector.Data("➡", "next", ...)
)

menu.Reply(
	menu.Row(btnHelp),
	menu.Row(btnSettings),
)
selector.Inline(
	selector.Row(btnPrev, btnNext),
)

b.Handle("/start", func(c tele.Context) error {
	return c.Send("Hello!", menu)
})

// On reply button pressed (message)
b.Handle(&btnHelp, func(c tele.Context) error {
	return c.Edit("Here is some help: ...")
})

// On inline button pressed (callback)
b.Handle(&btnPrev, func(c tele.Context) error {
	return c.Respond()
})

You can use markup constructor for every type of possible button:

r := b.NewMarkup()

// Reply buttons:
r.Text("Hello!")
r.Contact("Send phone number")
r.Location("Send location")
r.Poll(tele.PollQuiz)

// Inline buttons:
r.Data("Show help", "help") // data is optional
r.Data("Delete item", "delete", item.ID)
r.URL("Visit", "https://google.com")
r.Query("Search", query)
r.QueryChat("Share", query)
r.Login("Login", &tele.Login{...})

Inline mode

So if you want to handle incoming inline queries you better plug the tele.OnQuery endpoint and then use the Answer() method to send a list of inline queries back. I think at the time of writing, Telebot supports all of the provided result types (but not the cached ones). This is what it looks like:

b.Handle(tele.OnQuery, func(c tele.Context) error {
	urls := []string{
		"http://photo.jpg",
		"http://photo2.jpg",
	}

	results := make(tele.Results, len(urls)) // []tele.Result
	for i, url := range urls {
		result := &tele.PhotoResult{
			URL:      url,
			ThumbURL: url, // required for photos
		}

		results[i] = result
		// needed to set a unique string ID for each result
		results[i].SetResultID(strconv.Itoa(i))
	}

	return c.Answer(&tele.QueryResponse{
		Results:   results,
		CacheTime: 60, // a minute
	})
})

There's not much to talk about really. It also supports some form of authentication through deep-linking. For that, use fields SwitchPMText and SwitchPMParameter of QueryResponse.

Contributing

  1. Fork it
  2. Clone v3: git clone -b v3 https://github.com/tucnak/telebot
  3. Create your feature branch: git checkout -b v3-feature
  4. Make changes and add them: git add .
  5. Commit: git commit -m "add some feature"
  6. Push: git push origin v3-feature
  7. Pull request

Donate

I do coding for fun, but I also try to search for interesting solutions and optimize them as much as possible. If you feel like it's a good piece of software, I wouldn't mind a tip!

Litecoin: ltc1qskt5ltrtyg7esfjm0ftx6jnacwffhpzpqmerus

Ethereum: 0xB78A2Ac1D83a0aD0b993046F9fDEfC5e619efCAB

License

Telebot is distributed under MIT.

telebot's People

Contributors

0xfedcafe avatar ahmdrz avatar antonibertel avatar aofei avatar demget avatar enrico204 avatar fullpipe avatar googlom avatar idexter avatar irgendwr avatar lcd1232 avatar luoxin avatar nash-well avatar nentenpizza avatar orivej avatar rapour avatar realitycheck avatar riprsa avatar ronmi avatar rostish avatar setval avatar sigurniv avatar stek29 avatar superhacker777 avatar tucnak avatar ulrichschreiner avatar vlad-lukyanov avatar zabawaba99 avatar zoni avatar zry98 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

telebot's Issues

Get rid of redundant IQR*.MarshalJSON methods

There are literally 11 absolutely identical MarshalJSON methods for InlineQueryResult structs. I propose to come up with some backwards compatible refactoring strategy.

I incline to make IQR just a simple interface{} and Marshal corresponding structs in-place.

TypeError

When sending a message, I put in the variable answer in the form of json. Then I'm decoding it and I get the error "<telebot.types.Message instance at 0x29cc0e0> is not JSON serializable". This trouble is in the key of "Entity".

gopkg.in

With the master branch having recently received (potentially?) backwards-incompatible changes, it might be a good idea to adopt a good tagging strategy and link to gopkg.in (like http://gopkg.in/tucnak/telebot.v1) in the README.

I personally use govendor so it doesn't affect me as much, but not everyone does so it may be beneficial, especially to people more new to go.

IGNORE

Sorry, I open an issue in wrong repository :(

Failed to run example: not go 1.3 version

I try to execute example with go1.7 ubuntu 16.04:

`package main

import (
"log"
"os"
"time"

"github.com/tucnak/telebot"

)

func main() {
bot, err := telebot.NewBot(os.Getenv("BOT_TOKEN"))
if err != nil {
log.Fatalln(err)
}

messages := make(chan telebot.Message, 100)
bot.Listen(messages, 1*time.Second)

for message := range messages {
	if message.Text == "/hi" {
		bot.SendMessage(message.Chat,
			"Hello, "+message.Sender.FirstName+"!", nil)
	}
}

}
`

But,when i run i get error:

./mybot.go:8: import /home/user/golang/pkg/linux_amd64/github.com/tucnak/telebot.a: object is [linux amd64 go1.7.4 X:framepointer] expected [linux amd64 go1.3.3 X:precisestack] exit status 2

I use VS Code 1.8.1.

Can you help me?
Thank you!

WebHook support

Is it okay to add support to update message from webhook?
I did some research by adding a new method to type Bot

func (b *Bot) WebHook(url string, subscription chan Message) http.HandlerFunc

and seems working fine.

If you think it's acceptable to add such method, I can send a PR for you. Thanks

handler description & help

I would find it useful if the handlers introduced with #89 had an option to set a description and a category.
This would mean that you could automatically generate a 'help' handler.

The main problem that I see is that adding more arguments to the Handle func would be a breaking change (but on the other hand it's not that bad as the handler was only introduced 5 days ago).

MessageEntity with EntityMention type broken?

Can't receive User info from MessageEntity instance via such code:
for _, v := range message.Entities { if v.Type == telebot.EntityMention || v.Type == telebot.EntityTMention { fmt.Println("[Entity]", v) } }
Possible output:

[Entity] {mention 0 8 {0 }}
[MSG]: From ... in chat #b2: @Riketta
[Entity] {mention 4 8 {0 }}
[MSG]: From ... in chat #b2: qwe @Riketta aasas

Seems like entity.User contains nothing useful. Sorry if I'm doing smth wrong.

AnswerCallbackQuery in URLs

Is any way to use telegram.me/your_bot?start=XXXX with AnswerCallbackQuery ?
Can you show me a sample code ?

getFile support

Bot API allows taking a file from telegram servers using getFile method, see documentation. Would be great if this functionality will be implemented in telebot!

Functionality for `request_location` in `reply_keyboard` markups

The Telegram Bot API guide allows for:

screen shot 2017-10-09 at 11 04 03 pm

But the current API available only allows for buttons to be strings without being able to specify that the button can directly send a location.

@tucnak: can you extend the library to allow for this to happen? Or if you can guide me towards a possible solution, I can create a PR.

V2: Moving towards better API

I set the goal to release v2 by the end of September (see updated 2.0 milestone). As it's going to be a pretty major release, I suggest re-thinking some of the API. Our biggest competitor, telegram-bot-api, 625 stars, is still superior to Telebot in terms of API, so I believe in order to stand out we must provide additional and moreover, sensible value. Telebot has always positioned itself as the framework, while our competitors were and will remain an API wrapper.

Here are some of the issues I'd like to address (in the order of significance).

Memory efficiency

Message is the fattest type in Telebot, taking as much as 1544 bytes on my system (~1.5KB). Mainly because it stores lots of optional fields by-value. This is clearly borderline stupid and uncomfortable (you can't test optionals against nil) and I can't recall why I'd ever thought it was a good idea.

I trivially managed (d8b3194) to reduce memory usage of Message down to 504 bytes (~0.5KB), making a 67.4% decrease in memory usage, which is pretty fucking good, considering Message is the most-used object. No more hassle around optionals also.

Use of reflection for prettier API

We currently use no reflection at all, which is probably a good thing. That said, I think introducing some light weight interface{}-kind of reflection for "optional" parameters may be a good thing.

SendMessage() / Send()

// Definition
func (b *Bot) SendMessage(r Recipient, message string, options ...interface{}) error {}

// Use
b.SendMessage(user, "message") // <-- much better, isn't it?
b.SendMessage(user, "message", &SendOptions{})

In fact, we could go further and generalize it all the way down to Send():

// Definition
func (b *Bot) Send(r Recipient, things ...interface{}) error {}

// Use
b.Send(user, "message")
b.Send(user, "message", &SendOptions{})
b.Send(user, photo)
// Etc..

I wonder whether it'll damage Telebot's performance much, we can't really tell without proper benchmarking. That said, considering there's not much high load in Telegram world, we still must end up the fastest bloke on the block by a huge margin (comparing w/ e.g. Python implementations).

Pros:

  • Much cleaner API and shorter function names
  • We'll finally get rid of huge piles of code duplicates in bot.go

Cons:

  • Potential performance penalties (inferace{} casting)
  • We lose some compile-time safety
  • More documentation to compensate for optional arguments!

Sendable

In fact, we could avoid losing some of the safety and a fair chunk of casting and still introduce a better API by introducing a Sendable interface for all the sendable objects like Photo, Audio, Sticker, etc:

type Sendable interface {
    Send(*Bot) error
}

Each and every corresponding sendable type would implement the necessary actions (which quite differ from type to type). This could also be used as a part of a prettier Send(Recipient, ..interface{}) too.

Message builders

I thought about it for some time now and I believe we could benefit from some sort of builder API for sending messages, like this:

// Use
bot.V()
    .To(recipient)
    .Text("This is a text message")
//  .Photo(&photo) or any other sendable
    .Markdown()
    .Keyboard(keyboard)
    .Error(handlerFunc)
    .Send()

It looks so good!

Other...

I also thought about implementing things like a state machine (telebot users would need to specify a list of states their bot users can be in and also, specify relations between these states) and a global error handler. Unfortunately, I couldn't come up with a reasonable API for "plots" (a state machine) yet though. I usually panic on bot errors and handle them up the stack anyway, so classic if err != nil error handling is rather redundant. I'd love to do things like:

bot.ErrorHandler = func(err error) {
    panic(err)
}

bot.Handle("/start", func(c Context) {
    bot.Send(c.Message.Sender, "Hello") // calls ErrorHandler() -> panic()
})

/cc @zoni @Ronmi @ahmdrz

UPD: I also feel like we are ovelooking inline queries and callbacks from the API design perspective... Bot start/listen/serve is confusing also!

Telegram issued new APIs to download file from server

Do you have any plan about implementing these APIs? I'm willing to help but need your suggestion :)

I read the docs of new APIs, found that new File structure is identical to File struct in telebot. But that structure is only used for download file from server, so I think something like func (b Bot) SaveFile(f File, localFile string) error should be enough. Do you think this implementation is fine?

Get number of seen in channel

Hi everybody
I have a question !!!
How can I get number of seen in channels ?
Does telegram have any way to read number of seen in channels ?
I use github.com/tucnak/telebot for my telegram bot. special tnx 👍

Example Inline Mode is not working

This code raise a panic due to reinitiate var bot:

import (
    "log"
    "time"

    "github.com/tucnak/telebot"
)

var bot *telebot.Bot

func main() {
    bot, err := telebot.NewBot("SECRET TOKEN")
    if err != nil {
        log.Fatalln(err)
    }

    bot.Messages = make(chan telebot.Message, 1000)
    bot.Queries = make(chan telebot.Query, 1000)

    go messages()
    go queries()

    bot.Start(1 * time.Second)
}

func messages() {
    for message := range bot.Messages {
        // ...
    }
}

func queries() {
    for query := range bot.Queries {
        log.Println("--- new query ---")
        log.Println("from:", query.From.Username)
        log.Println("text:", query.Text)

        // Create an article (a link) object to show in our results.
        article := &telebot.InlineQueryResultArticle{
            Title: "Telegram bot framework written in Go",
            URL:   "https://github.com/tucnak/telebot",
            InputMessageContent: &telebot.InputTextMessageContent{
                Text:           "Telebot is a convenient wrapper to Telegram Bots API, written in Golang.",
                DisablePreview: false,
            },
        }

        // Build the list of results. In this instance, just our 1 article from above.
        results := []telebot.InlineQueryResult{article}

        // Build a response object to answer the query.
        response := telebot.QueryResponse{
            Results:    results,
            IsPersonal: true,
        }

        // And finally send the response.
        if err := bot.AnswerInlineQuery(&query, &response); err != nil {
            log.Println("Failed to respond to query:", err)
        }
    }
}

The problem is you're setting a global var on bot which is fine but then in main you're reinitiate this var again

This will raise a panic in your go functions

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x7990b]

goroutine18 [running]:
panic(0x34eec0, 0xc82000a110)
/usr/local/Cellar/go/1.6.2/libexec/src/runtime/panic.go:481 +0x3e6
github.com/tucnak/telebot.(*Bot).SendMessage(0x0, 0x1502168, 0xc82005c7e0, 0xc8203be250, 0xc, 0x0, 0x0, 0x0)
/Users/nick/go/src/github.com/tucnak/telebot/bot.go:103 +0x1bb
main.messages(0xc8201fe0c0)
/Users/nick/go/src/github.com/njuettner/telebot/main.go:34 +0x396
created by main.main
/Users/nick/go/src/github.com/njuettner/telebot/main.go:21 +0x18d
exit status

what you could do is setting an global err or doing this exclusive in your main function
and then remove the colon, like:

bot, err = telebot.NewBot("SECRET TOKEN")

Testing capabilities?

Hey @tucnak, thanks for creating this wonderful tool.

I'm using telebot for a project and I had questions about testing my code. Are there good ways to mock SendMessage and equivalent methods?

How to use inline keyboards ?

Hi everybody,
How can i use inline keyboards with this library ?
Is it enough that i fill InlineKeyboard in ReplyMarkup ?

docs broken after API change

The docs say that to send a message in response to receiving a message, you should write

bot.SendMessage(message.Chat, ...)

but with recent API changes, SendMessage takes a User, not a Chat. At the least, the docs are wrong.

But there seems to be a shortcoming here. The Message type has a Sender field of type User, but the docs say it may be empty for group chats. My bot receives messages from a group. How do I send messages back to the group?

Types.go error possible?

type Video struct {
Audio // File ???

Width  int `json:"width"`
Height int `json:"height"`

.....

Channel messages is empty when there are full messages Telegram queue

Hi Tucnak, I use your example to run my bot. when the traffic is risen up, I occasionally encounter no more messages are processed, even I restart the bot.

messages := make(chan telebot.Message)
    bot.Listen(messages, 1*time.Second)

    for message := range messages {
        if message.Text == "/hi" {
            bot.SendMessage(message.Chat,
                "Hello, "+message.Sender.FirstName+"!", nil)
        }
    }

If I use curl command in terminal curl -X POST [api_url]/getUpdates , then I got 100 messages queuing. Is there any reason why messages channel is not able to pick up these messages.

telebot: Bad request: Field "disable_web_page_preview" must be of type Boolean

Hi,

I tried to implement a simple inline bot, but my generated ArticleResult create an error. This is my code for the ArticleResult an the Result:

result := telebot.ArticleResult{"bla", "blubb", "blablubb", telebot.ModeMarkdown, true, true, "", true, ""}
results := []telebot.Result{result}

if err := bot.Respond(query, results); err != nil {
    fmt.Println("ouch:", err)
}

I get the error:

telebot: Bad request: Field "disable_web_page_preview" must be of type Boolean

I tried a bit in your code and found the fault in the MarshalJSON() method of inline_article.go.
There you create the byte stream for every key value pair with

const tpl = `"%s":"%s",`
b.WriteString(fmt.Sprintf(tpl, key, value))

but that inserts "" around the bools. Telegram don't like that. ;)
I test the method with a hardcoded

if (key == "disable_web_page_preview") {
    b.WriteString(`"disable_web_page_preview":true,`)
} else {
    b.WriteString(fmt.Sprintf(tpl, key, value))
}

and this works! The program now says:

telebot: Bad request: Field "hide_url" must be of type Boolean

I think it would a better idea to add the "" to the strings directly and then only use const tpl = "%s":%s,``.

Does Telebot support Webhooks?

I see,that bot shoud listen telegramm per time,but as i understand it uses cpu (simple while loop).
Does Telebot support Webhooks?

Support for inline-mode

Hi!

First, thanks for this library it really helps me to create a pair of bot telegrams.

Second, are you willing to implement or to accept pull request for support inline-mode? As you should noticed Telegram recently added this interesting feature for bots that I think it will fit into telebot.

does bot.Start work?

The inline example provided does not work although it does not crash. It just is silentt!
Also, I cannot get bot.Start to work, as if it were in an infinite loop

Debugging capabilities

Wouldn't it be nice to have some way of running bots in debug mode with different levels of verbosity?

I want this.

Target go version

Building on go 1.3.3 yields these syntax errors

./bot.go:41: syntax error: unexpected range, expecting {
./bot.go:56: non-declaration statement outside function body
./bot.go:57: syntax error: unexpected }

What is the target go version and could we document it?

More documentation?

Hi.
I see that you're cheating with documentation to silently pass linters.
Please, fix that doc parts.
For example look into that line.

Thanks.

Failed to get updates: Terminated by Long Poll or Webhook

While executing the program, I'm getting
failed to get updates: telebot: Conflict: terminated by other long poll or web hook

The code which I used is same which is being used in the readme document.
Something like as mentioned below:

telebottoken := os.Getenv("TELEBOT_TOKEN")
	bot, err := telebot.NewBot(telebottoken)

	if err != nil {
		fmt.Print(err)
		return
	}

	bot.Messages = make(chan telebot.Message, 100)
	pluginframework.Bot = bot
	go HandleMessages(bot)
	bot.Start(1 * time.Second)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.