{"id":13409479,"url":"https://github.com/tucnak/telebot","last_synced_at":"2025-05-11T03:42:50.884Z","repository":{"id":34212009,"uuid":"38069477","full_name":"tucnak/telebot","owner":"tucnak","description":"Telebot is a Telegram bot framework in Go.","archived":false,"fork":false,"pushed_at":"2025-04-22T07:01:32.000Z","size":1055,"stargazers_count":4298,"open_issues_count":46,"forks_count":488,"subscribers_count":58,"default_branch":"v4","last_synced_at":"2025-05-11T03:42:45.010Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tucnak.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-06-25T19:27:50.000Z","updated_at":"2025-05-10T20:03:26.000Z","dependencies_parsed_at":"2023-02-12T01:31:33.886Z","dependency_job_id":"a44d01b9-8ca8-4383-835c-239b28365da9","html_url":"https://github.com/tucnak/telebot","commit_stats":{"total_commits":653,"total_committers":88,"mean_commits":7.420454545454546,"dds":0.664624808575804,"last_synced_commit":"fbd35f210343604adb89e96859a9639d9366e966"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tucnak%2Ftelebot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tucnak%2Ftelebot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tucnak%2Ftelebot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tucnak%2Ftelebot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tucnak","download_url":"https://codeload.github.com/tucnak/telebot/tar.gz/refs/heads/v4","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253514552,"owners_count":21920334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T20:01:01.205Z","updated_at":"2025-05-11T03:42:50.851Z","avatar_url":"https://github.com/tucnak.png","language":"Go","funding_links":[],"categories":["Bot Building","Bot建设","Libraries","Go","Uncategorized","Third-party APIs","机器人相关` 构建和使用机器人的库`","一般机器人（bots）","第三方API","聊天机器人框架","\u003cspan id=\"第三方api-third-party-apis\"\u003e第三方API Third-party APIs\u003c/span\u003e","第三方 APIs","Bots","机器人相关"],"sub_categories":["Telegram","Advanced Console UIs","Contents","HTTP Clients","Go","Free e-books","机器人类库","交流","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","高級控制台界面","Bot Libs","高级控制台界面"],"readme":"# Telebot\n\u003e\"I never knew creating Telegram bots could be so _sexy_!\"\n\n[![GoDoc](https://godoc.org/gopkg.in/telebot.v4?status.svg)](https://godoc.org/gopkg.in/telebot.v4)\n[![GitHub Actions](https://github.com/tucnak/telebot/actions/workflows/go.yml/badge.svg)](https://github.com/tucnak/telebot/actions)\n[![codecov.io](https://codecov.io/gh/tucnak/telebot/coverage.svg?branch=v3)](https://codecov.io/gh/tucnak/telebot)\n[![Discuss on Telegram](https://img.shields.io/badge/telegram-discuss-0088cc.svg)](https://t.me/go_telebot)\n\n```bash\ngo get -u gopkg.in/telebot.v4\n```\n\n* [Overview](#overview)\n* [Getting Started](#getting-started)\n\t- [Context](#context)\n\t- [Middleware](#middleware)\n\t- [Poller](#poller)\n\t- [Commands](#commands)\n\t- [Files](#files)\n\t- [Sendable](#sendable)\n\t- [Editable](#editable)\n\t- [Keyboards](#keyboards)\n\t- [Inline mode](#inline-mode)\n* [Contributing](#contributing)\n* [Donate](#donate)\n* [License](#license)\n\n# Overview\nTelebot is a bot framework for [Telegram Bot API](https://core.telegram.org/bots/api).\nThis package provides the best of its kind API for command routing, inline query requests and keyboards, as well\nas callbacks. Actually, I went a couple steps further, so instead of making a 1:1 API wrapper I chose to focus on\nthe beauty of API and performance. Some strong sides of Telebot are:\n\n* Real concise API\n* Command routing\n* Middleware\n* Transparent File API\n* Effortless bot callbacks\n\nAll the methods of Telebot API are _extremely_ easy to memorize and get used to. Also, consider Telebot a\nhighload-ready solution. I'll test and benchmark the most popular actions and if necessary, optimize\nagainst them without sacrificing API quality.\n\n# Getting Started\nLet's take a look at the minimal Telebot setup:\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"os\"\n\t\"time\"\n\n\ttele \"gopkg.in/telebot.v4\"\n)\n\nfunc main() {\n\tpref := tele.Settings{\n\t\tToken:  os.Getenv(\"TOKEN\"),\n\t\tPoller: \u0026tele.LongPoller{Timeout: 10 * time.Second},\n\t}\n\n\tb, err := tele.NewBot(pref)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t\treturn\n\t}\n\n\tb.Handle(\"/hello\", func(c tele.Context) error {\n\t\treturn c.Send(\"Hello!\")\n\t})\n\n\tb.Start()\n}\n\n```\n\nSimple, innit? Telebot's routing system takes care of delivering updates\nto their endpoints, so in order to get to handle any meaningful event,\nall you got to do is just plug your function into one of the Telebot-provided\nendpoints. You can find the full list\n[here](https://godoc.org/gopkg.in/telebot.v4#pkg-constants).\n\nThere are dozens of supported endpoints (see package consts). Let me know\nif you'd like to see some endpoint or endpoint ideas implemented. This system\nis completely extensible, so I can introduce them without breaking\nbackwards compatibility.\n\n## Context\nContext is a special type that wraps a huge update structure and represents\nthe context of the current event. It provides several helpers, which allow\ngetting, for example, the chat that this update had been sent in, no matter\nwhat kind of update this is.\n\n```go\nb.Handle(tele.OnText, func(c tele.Context) error {\n\t// All the text messages that weren't\n\t// captured by existing handlers.\n\n\tvar (\n\t\tuser = c.Sender()\n\t\ttext = c.Text()\n\t)\n\n\t// Use full-fledged bot's functions\n\t// only if you need a result:\n\tmsg, err := b.Send(user, text)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Instead, prefer a context short-hand:\n\treturn c.Send(text)\n})\n\nb.Handle(tele.OnChannelPost, func(c tele.Context) error {\n\t// Channel posts only.\n\tmsg := c.Message()\n})\n\nb.Handle(tele.OnPhoto, func(c tele.Context) error {\n\t// Photos only.\n\tphoto := c.Message().Photo\n})\n\nb.Handle(tele.OnQuery, func(c tele.Context) error {\n\t// Incoming inline queries.\n\treturn c.Answer(...)\n})\n```\n\n## Middleware\nTelebot has a simple and recognizable way to set up middleware — chained functions with access to `Context`, called before the handler execution.\n\nImport a `middleware` package to get some basic out-of-box middleware\nimplementations:\n```go\nimport \"gopkg.in/telebot.v4/middleware\"\n```\n\n```go\n// Global-scoped middleware:\nb.Use(middleware.Logger())\nb.Use(middleware.AutoRespond())\n\n// Group-scoped middleware:\nadminOnly := b.Group()\nadminOnly.Use(middleware.Whitelist(adminIDs...))\nadminOnly.Handle(\"/ban\", onBan)\nadminOnly.Handle(\"/kick\", onKick)\n\n// Handler-scoped middleware:\nb.Handle(tele.OnText, onText, middleware.IgnoreVia())\n```\n\nCustom middleware example:\n```go\n// AutoResponder automatically responds to every callback update.\nfunc AutoResponder(next tele.HandlerFunc) tele.HandlerFunc {\n\treturn func(c tele.Context) error {\n\t\tif c.Callback() != nil {\n\t\t\tdefer c.Respond()\n\t\t}\n\t\treturn next(c) // continue execution chain\n\t}\n}\n```\n\n## Poller\nTelebot doesn't really care how you provide it with incoming updates, as long\nas you set it up with a Poller, or call ProcessUpdate for each update:\n\n```go\n// Poller is a provider of Updates.\n//\n// All pollers must implement Poll(), which accepts bot\n// pointer and subscription channel and start polling\n// synchronously straight away.\ntype Poller interface {\n\t// Poll is supposed to take the bot object\n\t// subscription channel and start polling\n\t// for Updates immediately.\n\t//\n\t// Poller must listen for stop constantly and close\n\t// it as soon as it's done polling.\n\tPoll(b *Bot, updates chan Update, stop chan struct{})\n}\n```\n\n## Commands\nWhen handling commands, Telebot supports both direct (`/command`) and group-like\nsyntax (`/command@botname`) and will never deliver messages addressed to some\nother bot, even if [privacy mode](https://core.telegram.org/bots#privacy-mode) is off.\n\nFor simplified deep-linking, Telebot also extracts payload:\n```go\n// Command: /start \u003cPAYLOAD\u003e\nb.Handle(\"/start\", func(c tele.Context) error {\n\tfmt.Println(c.Message().Payload) // \u003cPAYLOAD\u003e\n})\n```\n\nFor multiple arguments use:\n```go\n// Command: /tags \u003ctag1\u003e \u003ctag2\u003e \u003c...\u003e\nb.Handle(\"/tags\", func(c tele.Context) error {\n\ttags := c.Args() // list of arguments splitted by a space\n\tfor _, tag := range tags {\n\t\t// iterate through passed arguments\n\t}\n})\n```\n\n## Files\n\u003eTelegram allows files up to 50 MB in size.\n\nTelebot allows to both upload (from disk or by URL) and download (from Telegram)\nfiles in bot's scope. Also, sending any kind of media with a File created\nfrom disk will upload the file to Telegram automatically:\n```go\na := \u0026tele.Audio{File: tele.FromDisk(\"file.ogg\")}\n\nfmt.Println(a.OnDisk()) // true\nfmt.Println(a.InCloud()) // false\n\n// Will upload the file from disk and send it to the recipient\nb.Send(recipient, a)\n\n// Next time you'll be sending this very *Audio, Telebot won't\n// re-upload the same file but rather utilize its Telegram FileID\nb.Send(otherRecipient, a)\n\nfmt.Println(a.OnDisk()) // true\nfmt.Println(a.InCloud()) // true\nfmt.Println(a.FileID) // \u003cTelegram file ID\u003e\n```\n\nYou might want to save certain `File`s in order to avoid re-uploading. Feel free\nto marshal them into whatever format, `File` only contain public fields, so no\ndata will ever be lost.\n\n## Sendable\nSend is undoubtedly the most important method in Telebot. `Send()` accepts a\n`Recipient` (could be user, group or a channel) and a `Sendable`. Other types other than\nthe Telebot-provided media types (`Photo`, `Audio`, `Video`, etc.) are `Sendable`.\nIf you create composite types of your own, and they satisfy the `Sendable` interface,\nTelebot will be able to send them out.\n\n```go\n// Sendable is any object that can send itself.\n//\n// This is pretty cool, since it lets bots implement\n// custom Sendables for complex kinds of media or\n// chat objects spanning across multiple messages.\ntype Sendable interface {\n\tSend(*Bot, Recipient, *SendOptions) (*Message, error)\n}\n```\n\nThe only type at the time that doesn't fit `Send()` is `Album` and there is a reason\nfor that. Albums were added not so long ago, so they are slightly quirky for backwards\ncompatibilities sake. In fact, an `Album` can be sent, but never received. Instead,\nTelegram returns a `[]Message`, one for each media object in the album:\n```go\np := \u0026tele.Photo{File: tele.FromDisk(\"chicken.jpg\")}\nv := \u0026tele.Video{File: tele.FromURL(\"http://video.mp4\")}\n\nmsgs, err := b.SendAlbum(user, tele.Album{p, v})\n```\n\n### Send options\nSend options are objects and flags you can pass to `Send()`, `Edit()` and friends\nas optional arguments (following the recipient and the text/media). The most\nimportant one is called `SendOptions`, it lets you control _all_ the properties of\nthe message supported by Telegram. The only drawback is that it's rather\ninconvenient to use at times, so `Send()` supports multiple shorthands:\n```go\n// regular send options\nb.Send(user, \"text\", \u0026tele.SendOptions{\n\t// ...\n})\n\n// ReplyMarkup is a part of SendOptions,\n// but often it's the only option you need\nb.Send(user, \"text\", \u0026tele.ReplyMarkup{\n\t// ...\n})\n\n// flags: no notification \u0026\u0026 no web link preview\nb.Send(user, \"text\", tele.Silent, tele.NoPreview)\n```\n\nFull list of supported option-flags you can find\n[here](https://pkg.go.dev/gopkg.in/telebot.v4#Option).\n\n## Editable\nIf you want to edit some existing message, you don't really need to store the\noriginal `*Message` object. In fact, upon edit, Telegram only requires `chat_id`\nand `message_id`. So you don't really need the Message as a whole. Also, you\nmight want to store references to certain messages in the database, so I thought\nit made sense for *any* Go struct to be editable as a Telegram message, to implement\n`Editable`:\n```go\n// Editable is an interface for all objects that\n// provide \"message signature\", a pair of 32-bit\n// message ID and 64-bit chat ID, both required\n// for edit operations.\n//\n// Use case: DB model struct for messages to-be\n// edited with, say two columns: msg_id,chat_id\n// could easily implement MessageSig() making\n// instances of stored messages editable.\ntype Editable interface {\n\t// MessageSig is a \"message signature\".\n\t//\n\t// For inline messages, return chatID = 0.\n\tMessageSig() (messageID int, chatID int64)\n}\n```\n\nFor example, `Message` type is Editable. Here is the implementation of `StoredMessage`\ntype, provided by Telebot:\n```go\n// StoredMessage is an example struct suitable for being\n// stored in the database as-is or being embedded into\n// a larger struct, which is often the case (you might\n// want to store some metadata alongside, or might not.)\ntype StoredMessage struct {\n\tMessageID int   `sql:\"message_id\" json:\"message_id\"`\n\tChatID    int64 `sql:\"chat_id\" json:\"chat_id\"`\n}\n\nfunc (x StoredMessage) MessageSig() (int, int64) {\n\treturn x.MessageID, x.ChatID\n}\n```\n\nWhy bother at all? Well, it allows you to do things like this:\n```go\n// just two integer columns in the database\nvar msgs []tele.StoredMessage\ndb.Find(\u0026msgs) // gorm syntax\n\nfor _, msg := range msgs {\n\tbot.Edit(\u0026msg, \"Updated text\")\n\t// or\n\tbot.Delete(\u0026msg)\n}\n```\n\nI find it incredibly neat. Worth noting, at this point of time there exists\nanother method in the Edit family, `EditCaption()` which is of a pretty\nrare use, so I didn't bother including it to `Edit()`, just like I did with\n`SendAlbum()` as it would inevitably lead to unnecessary complications.\n```go\nvar m *Message\n\n// change caption of a photo, audio, etc.\nbot.EditCaption(m, \"new caption\")\n```\n\n## Keyboards\nTelebot supports both kinds of keyboards Telegram provides: reply and inline\nkeyboards. Any button can also act as endpoints for `Handle()`.\n\n```go\nvar (\n\t// Universal markup builders.\n\tmenu     = \u0026tele.ReplyMarkup{ResizeKeyboard: true}\n\tselector = \u0026tele.ReplyMarkup{}\n\n\t// Reply buttons.\n\tbtnHelp     = menu.Text(\"ℹ Help\")\n\tbtnSettings = menu.Text(\"⚙ Settings\")\n\n\t// Inline buttons.\n\t//\n\t// Pressing it will cause the client to\n\t// send the bot a callback.\n\t//\n\t// Make sure Unique stays unique as per button kind\n\t// since it's required for callback routing to work.\n\t//\n\tbtnPrev = selector.Data(\"⬅\", \"prev\", ...)\n\tbtnNext = selector.Data(\"➡\", \"next\", ...)\n)\n\nmenu.Reply(\n\tmenu.Row(btnHelp),\n\tmenu.Row(btnSettings),\n)\nselector.Inline(\n\tselector.Row(btnPrev, btnNext),\n)\n\nb.Handle(\"/start\", func(c tele.Context) error {\n\treturn c.Send(\"Hello!\", menu)\n})\n\n// On reply button pressed (message)\nb.Handle(\u0026btnHelp, func(c tele.Context) error {\n\treturn c.Edit(\"Here is some help: ...\")\n})\n\n// On inline button pressed (callback)\nb.Handle(\u0026btnPrev, func(c tele.Context) error {\n\treturn c.Respond()\n})\n```\n\nYou can use markup constructor for every type of possible button:\n```go\nr := b.NewMarkup()\n\n// Reply buttons:\nr.Text(\"Hello!\")\nr.Contact(\"Send phone number\")\nr.Location(\"Send location\")\nr.Poll(tele.PollQuiz)\n\n// Inline buttons:\nr.Data(\"Show help\", \"help\") // data is optional\nr.Data(\"Delete item\", \"delete\", item.ID)\nr.URL(\"Visit\", \"https://google.com\")\nr.Query(\"Search\", query)\nr.QueryChat(\"Share\", query)\nr.Login(\"Login\", \u0026tele.Login{...})\n```\n\n## Inline mode\nSo if you want to handle incoming inline queries you better plug the `tele.OnQuery`\nendpoint and then use the `Answer()` method to send a list of inline queries\nback. I think at the time of writing, Telebot supports all of the provided result\ntypes (but not the cached ones). This is what it looks like:\n\n```go\nb.Handle(tele.OnQuery, func(c tele.Context) error {\n\turls := []string{\n\t\t\"http://photo.jpg\",\n\t\t\"http://photo2.jpg\",\n\t}\n\n\tresults := make(tele.Results, len(urls)) // []tele.Result\n\tfor i, url := range urls {\n\t\tresult := \u0026tele.PhotoResult{\n\t\t\tURL:      url,\n\t\t\tThumbURL: url, // required for photos\n\t\t}\n\n\t\tresults[i] = result\n\t\t// needed to set a unique string ID for each result\n\t\tresults[i].SetResultID(strconv.Itoa(i))\n\t}\n\n\treturn c.Answer(\u0026tele.QueryResponse{\n\t\tResults:   results,\n\t\tCacheTime: 60, // a minute\n\t})\n})\n```\n\nThere's not much to talk about really. It also supports some form of authentication\nthrough deep-linking. For that, use fields `SwitchPMText` and `SwitchPMParameter`\nof `QueryResponse`.\n\n# Contributing\n\n1. Fork it\n2. Clone v3: `git clone -b v3 https://github.com/tucnak/telebot`\n3. Create your feature branch: `git checkout -b v3-feature`\n4. Make changes and add them: `git add .`\n5. Commit: `git commit -m \"add some feature\"`\n6. Push: `git push origin v3-feature`\n7. Pull request\n\n# Donate\n\nI do coding for fun, but I also try to search for interesting solutions and\noptimize them as much as possible.\nIf you feel like it's a good piece of software, I wouldn't mind a tip!\n\nLitecoin: `ltc1qskt5ltrtyg7esfjm0ftx6jnacwffhpzpqmerus`\n\nEthereum: `0xB78A2Ac1D83a0aD0b993046F9fDEfC5e619efCAB`\n\n# License\n\nTelebot is distributed under MIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftucnak%2Ftelebot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftucnak%2Ftelebot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftucnak%2Ftelebot/lists"}