Skip to content

Commit 5be2526

Browse files
committed
Initial work on improving docs.
1 parent 2f7211a commit 5be2526

12 files changed

+674
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.idea/
22
coverage.out
33
tmp/
4+
book/

book.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[book]
2+
authors = ["Syfaro"]
3+
language = "en"
4+
multilingual = false
5+
src = "docs"
6+
title = "Go Telegram Bot API"
7+
8+
[output.html]
9+
git-repository-url = "https://github.com/go-telegram-bot-api/telegram-bot-api"

docs/SUMMARY.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Summary
2+
3+
- [Getting Started](./getting-started/README.md)
4+
* [Library Structure](./getting-started/library-structure.md)
5+
* [Files](./getting-started/files.md)
6+
- [Examples](./examples/README.md)
7+
* [Command Handling](./examples/command-handling.md)
8+
* [Keyboard](./examples/keyboard.md)
9+
- [Change Log]()
10+
11+
# Contributing
12+
13+
- [Internals](./internals/README.md)
14+
* [Adding Endpoints](./internals/adding-endpoints.md)
15+
* [Uploading Files](./internals/uploading-files.md)

docs/examples/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Examples
2+
3+
With a better understanding of how the library works, let's look at some more
4+
examples showing off some of Telegram's features.

docs/examples/command-handling.md

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Command Handling
2+
3+
This is a simple example of changing behavior based on a provided command.
4+
5+
```go
6+
package main
7+
8+
import (
9+
"log"
10+
"os"
11+
12+
"github.com/go-telegram-bot-api/telegram-bot-api"
13+
)
14+
15+
func main() {
16+
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
17+
if err != nil {
18+
log.Panic(err)
19+
}
20+
21+
bot.Debug = true
22+
23+
log.Printf("Authorized on account %s", bot.Self.UserName)
24+
25+
u := tgbotapi.NewUpdate(0)
26+
u.Timeout = 60
27+
28+
updates := bot.GetUpdatesChan(u)
29+
30+
for update := range updates {
31+
if update.Message == nil { // ignore any non-Message updates
32+
continue
33+
}
34+
35+
if !update.Message.IsCommand() { // ignore any non-command Messages
36+
continue
37+
}
38+
39+
// Create a new MessageConfig. We don't have text yet,
40+
// so we leave it empty.
41+
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "")
42+
43+
// Extract the command from the Message.
44+
switch update.Message.Command() {
45+
case "help":
46+
msg.Text = "I understand /sayhi and /status."
47+
case "sayhi":
48+
msg.Text = "Hi :)"
49+
case "status":
50+
msg.Text = "I'm ok."
51+
default:
52+
msg.Text = "I don't know that command"
53+
}
54+
55+
if _, err := bot.Send(msg); err != nil {
56+
log.Panic(err)
57+
}
58+
}
59+
}
60+
```

docs/examples/keyboard.md

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Keyboard
2+
3+
This bot shows a numeric keyboard when you send a "open" message and hides it
4+
when you send "close" message.
5+
6+
```go
7+
package main
8+
9+
import (
10+
"log"
11+
"os"
12+
13+
"github.com/go-telegram-bot-api/telegram-bot-api"
14+
)
15+
16+
var numericKeyboard = tgbotapi.NewReplyKeyboard(
17+
tgbotapi.NewKeyboardButtonRow(
18+
tgbotapi.NewKeyboardButton("1"),
19+
tgbotapi.NewKeyboardButton("2"),
20+
tgbotapi.NewKeyboardButton("3"),
21+
),
22+
tgbotapi.NewKeyboardButtonRow(
23+
tgbotapi.NewKeyboardButton("4"),
24+
tgbotapi.NewKeyboardButton("5"),
25+
tgbotapi.NewKeyboardButton("6"),
26+
),
27+
)
28+
29+
func main() {
30+
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
31+
if err != nil {
32+
log.Panic(err)
33+
}
34+
35+
bot.Debug = true
36+
37+
log.Printf("Authorized on account %s", bot.Self.UserName)
38+
39+
u := tgbotapi.NewUpdate(0)
40+
u.Timeout = 60
41+
42+
updates := bot.GetUpdatesChan(u)
43+
44+
for update := range updates {
45+
if update.Message == nil { // ignore non-Message updates
46+
continue
47+
}
48+
49+
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
50+
51+
switch update.Message.Text {
52+
case "open":
53+
msg.ReplyMarkup = numericKeyboard
54+
case "close":
55+
msg.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true)
56+
}
57+
58+
if _, err := bot.Send(msg); err != nil {
59+
log.Panic(err)
60+
}
61+
}
62+
}
63+
```

docs/getting-started/README.md

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Getting Started
2+
3+
This library is designed as a simple wrapper around the Telegram Bot API.
4+
It's encouraged to read [Telegram's docs][telegram-docs] first to get an
5+
understanding of what Bots are capable of doing. They also provide some good
6+
approaches to solve common problems.
7+
8+
[telegram-docs]: https://core.telegram.org/bots
9+
10+
## Installing
11+
12+
```bash
13+
go get -u github.com/go-telegram-bot-api/telegram-bot-api@develop
14+
```
15+
16+
It's currently suggested to use the develop branch. While there may be breaking
17+
changes, it has a number of features not yet available on master.
18+
19+
## A Simple Bot
20+
21+
To walk through the basics, let's create a simple echo bot that replies to your
22+
messages repeating what you said. Make sure you get an API token from
23+
[@Botfather][botfather] before continuing.
24+
25+
Let's start by constructing a new [BotAPI][bot-api-docs].
26+
27+
[botfather]: https://t.me/Botfather
28+
[bot-api-docs]: https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5?tab=doc#BotAPI
29+
30+
```go
31+
package main
32+
33+
import (
34+
"os"
35+
36+
"github.com/go-telegram-bot-api/telegram-bot-api/v5"
37+
)
38+
39+
func main() {
40+
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
41+
if err != nil {
42+
panic(err)
43+
}
44+
45+
bot.Debug = true
46+
}
47+
```
48+
49+
Instead of typing the API token directly into the file, we're using
50+
environment variables. This makes it easy to configure our Bot to use the right
51+
account and prevents us from leaking our real token into the world. Anyone with
52+
your token can send and receive messages from your Bot!
53+
54+
We've also set `bot.Debug = true` in order to get more information about the
55+
requests being sent to Telegram. If you run the example above, you'll see
56+
information about a request to the [`getMe`][get-me] endpoint. The library
57+
automatically calls this to ensure your token is working as expected. It also
58+
fills in the `Self` field in your `BotAPI` struct with information about the
59+
Bot.
60+
61+
Now that we've connected to Telegram, let's start getting updates and doing
62+
things. We can add this code in right after the line enabling debug mode.
63+
64+
[get-me]: https://core.telegram.org/bots/api#getme
65+
66+
```go
67+
// Create a new UpdateConfig struct with an offset of 0. Offsets are used
68+
// to make sure Telegram knows we've handled previous values and we don't
69+
// need them repeated.
70+
updateConfig := tgbotapi.NewUpdate(0)
71+
72+
// Tell Telegram we should wait up to 30 seconds on each request for an
73+
// update. This way we can get information just as quickly as making many
74+
// frequent requests without having to send nearly as many.
75+
updateConfig.Timeout = 30
76+
77+
// Start polling Telegram for updates.
78+
updates := bot.GetUpdatesChan(updateConfig)
79+
80+
// Let's go through each update that we're getting from Telegram.
81+
for update := range updates {
82+
// Telegram can send many types of updates depending on what your Bot
83+
// is up to. We only want to look at messages for now, so we can
84+
// discard any other updates.
85+
if update.Message == nil {
86+
continue
87+
}
88+
89+
// Now that we know we've gotten a new message, we can construct a
90+
// reply! We'll take the Chat ID and Text from the incoming message
91+
// and use it to create a new message.
92+
msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
93+
// We'll also say that this message is a reply to the previous message.
94+
// For any other specifications than Chat ID or Text, you'll need to
95+
// set fields on the `MessageConfig`.
96+
msg.ReplyToMessageID = update.Message.MessageID
97+
98+
// Okay, we're sending our message off! We don't care about the message
99+
// we just sent, so we'll discard it.
100+
if _, err := bot.Send(msg); err != nil {
101+
// Note that panics are a bad way to handle errors. Telegram can
102+
// have service outages or network errors, you should retry sending
103+
// messages or more gracefully handle failures.
104+
panic(err)
105+
}
106+
}
107+
```
108+
109+
Congradulations! You've made your very own bot!
110+
111+
Now that you've got some of the basics down, we can start talking about how the
112+
library is structured and more advanced features.

docs/getting-started/files.md

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Files
2+
3+
Telegram supports specifying files in many different formats. In order to
4+
accommodate them all, there are multiple structs and type aliases required.
5+
6+
| Type | Description |
7+
| ---- | ----------- |
8+
| `string` | Used as a local path to a file |
9+
| `FileID` | Existing file ID on Telegram's servers |
10+
| `FileURL` | URL to file, must be served with expected MIME type |
11+
| `FileReader` | Use an `io.Reader` to provide a file. Lazily read to save memory. |
12+
| `FileBytes` | `[]byte` containing file data. Prefer to use `FileReader` to save memory. |
13+
14+
## `string`
15+
16+
A path to a local file.
17+
18+
```go
19+
file := "tests/image.jpg"
20+
```
21+
22+
## `FileID`
23+
24+
An ID previously uploaded to Telegram. IDs may only be reused by the same bot
25+
that received them. Additionally, thumbnail IDs cannot be reused.
26+
27+
```go
28+
file := tgbotapi.FileID("AgACAgIAAxkDAALesF8dCjAAAa_…")
29+
```
30+
31+
## `FileURL`
32+
33+
A URL to an existing resource. It must be served with a correct MIME type to
34+
work as expected.
35+
36+
```go
37+
file := tgbotapi.FileURL("https://i.imgur.com/unQLJIb.jpg")
38+
```
39+
40+
## `FileReader`
41+
42+
Use an `io.Reader` to provide file contents as needed. Requires a filename for
43+
the virtual file.
44+
45+
```go
46+
var reader io.Reader
47+
48+
file := tgbotapi.FileReader{
49+
Name: "image.jpg",
50+
Reader: reader,
51+
}
52+
```
53+
54+
## `FileBytes`
55+
56+
Use a `[]byte` to provide file contents. Generally try to avoid this as it
57+
results in high memory usage. Also requires a filename for the virtual file.
58+
59+
```go
60+
var data []byte
61+
62+
file := tgbotapi.FileBytes{
63+
Name: "image.jpg",
64+
Bytes: data,
65+
}
66+
```
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Library Structure
2+
3+
This library is generally broken into three components you need to understand.
4+
5+
## Configs
6+
7+
Configs are collections of fields related to a single request. For example, if
8+
one wanted to use the `sendMessage` endpoint, you could use the `MessageConfig`
9+
struct to configure the request. There is a one-to-one relationship between
10+
Telegram endpoints and configs. They generally have the naming pattern of
11+
removing the `send` prefix and they all end with the `Config` suffix. They
12+
generally implement the `Chattable` interface. If they can send files, they
13+
implement the `Fileable` interface.
14+
15+
## Helpers
16+
17+
Helpers are easier ways of constructing common Configs. Instead of having to
18+
create a `MessageConfig` struct and remember to set the `ChatID` and `Text`,
19+
you can use the `NewMessage` helper method. It takes the two required parameters
20+
for the request to succeed. You can then set fields on the resulting
21+
`MessageConfig` after it's creation. They are generally named the same as
22+
method names except with `send` replaced with `New`.
23+
24+
## Methods
25+
26+
Methods are used to send Configs after they are constructed. Generally,
27+
`Request` is the lowest level method you'll have to call. It accepts a
28+
`Chattable` parameter and knows how to upload files if needed. It returns an
29+
`APIResponse`, the most general return type from the Bot API. This method is
30+
called for any endpoint that doesn't have a more specific return type. For
31+
example, `setWebhook` only returns `true` or an error. Other methods may have
32+
more specific return types. The `getFile` endpoint returns a `File`. Almost
33+
every other method returns a `Message`, which you can use `Send` to obtain.
34+
35+
There's lower level methods such as `MakeRequest` which require an endpoint and
36+
parameters instead of accepting configs. These are primarily used internally.
37+
If you find yourself having to use them, please open an issue.

docs/internals/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Internals
2+
3+
If you want to contribute to the project, here's some more information about
4+
the internal structure of the library.

0 commit comments

Comments
 (0)