Skip to content

message_thread_id to send a message to specific thread in supergroups #783

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 3 additions & 117 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,121 +1,7 @@
# Golang bindings for the Telegram Bot API

[![Go Reference](https://pkg.go.dev/badge/github.com/go-telegram-bot-api/telegram-bot-api/v5.svg)](https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5)
[![Test](https://github.com/go-telegram-bot-api/telegram-bot-api/actions/workflows/test.yml/badge.svg)](https://github.com/go-telegram-bot-api/telegram-bot-api/actions/workflows/test.yml)
### I just added `message_thread_id` to send a message to specific thread in supergroups

All methods are fairly self-explanatory, and reading the [godoc](https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5) page should
explain everything. If something isn't clear, open an issue or submit
a pull request.
changed to golang 1.24.4

There are more tutorials and high-level information on the website, [go-telegram-bot-api.dev](https://go-telegram-bot-api.dev).

The scope of this project is just to provide a wrapper around the API
without any additional features. There are other projects for creating
something with plugins and command handlers without having to design
all that yourself.

Join [the development group](https://telegram.me/go_telegram_bot_api) if
you want to ask questions or discuss development.

## Example

First, ensure the library is installed and up to date by running
`go get -u github.com/go-telegram-bot-api/telegram-bot-api/v5`.

This is a very simple bot that just displays any gotten updates,
then replies it to that chat.

```go
package main

import (
"log"

tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)

func main() {
bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken")
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 := bot.GetUpdatesChan(u)

for update := range updates {
if update.Message != nil { // If we got a message
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)
}
}
}
```

If you need to use webhooks (if you wish to run on Google App Engine),
you may use a slightly different method.

```go
package main

import (
"log"
"net/http"

"github.com/go-telegram-bot-api/telegram-bot-api/v5"
)

func main() {
bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken")
if err != nil {
log.Fatal(err)
}

bot.Debug = true

log.Printf("Authorized on account %s", bot.Self.UserName)

wh, _ := tgbotapi.NewWebhookWithCert("https://www.example.com:8443/"+bot.Token, "cert.pem")

_, err = bot.Request(wh)
if err != nil {
log.Fatal(err)
}

info, err := bot.GetWebhookInfo()
if err != nil {
log.Fatal(err)
}

if info.LastErrorDate != 0 {
log.Printf("Telegram callback failed: %s", info.LastErrorMessage)
}

updates := bot.ListenForWebhook("/" + bot.Token)
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)

for update := range updates {
log.Printf("%+v\n", update)
}
}
```

If you need, you may generate a self-signed certificate, as this requires
HTTPS / TLS. The above example tells Telegram that this is your
certificate and that it should be trusted, even though it is not
properly signed.

openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 3560 -subj "//O=Org\CN=Test" -nodes

Now that [Let's Encrypt](https://letsencrypt.org) is available,
you may wish to generate your free TLS certificate there.
compatible with `golangci-lint`
27 changes: 18 additions & 9 deletions bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, er
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)

var apiResp APIResponse
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
Expand Down Expand Up @@ -171,12 +173,16 @@ func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFi
// This code modified from the very helpful @HirbodBehnam
// https://github.com/go-telegram-bot-api/telegram-bot-api/issues/354#issuecomment-663856473
go func() {
defer w.Close()
defer m.Close()
defer func(w *io.PipeWriter) {
_ = w.Close()
}(w)
defer func(m *multipart.Writer) {
_ = m.Close()
}(m)

for field, value := range params {
if err := m.WriteField(field, value); err != nil {
w.CloseWithError(err)
_ = w.CloseWithError(err)
return
}
}
Expand Down Expand Up @@ -234,7 +240,9 @@ func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFi
if err != nil {
return nil, err
}
defer resp.Body.Close()
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(resp.Body)

var apiResp APIResponse
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
Expand Down Expand Up @@ -729,18 +737,19 @@ func (bot *BotAPI) GetMyDefaultAdministratorRights(config GetMyDefaultAdministra
func EscapeText(parseMode string, text string) string {
var replacer *strings.Replacer

if parseMode == ModeHTML {
switch parseMode {
case ModeHTML:
replacer = strings.NewReplacer("<", "&lt;", ">", "&gt;", "&", "&amp;")
} else if parseMode == ModeMarkdown {
case ModeMarkdown:
replacer = strings.NewReplacer("_", "\\_", "*", "\\*", "`", "\\`", "[", "\\[")
} else if parseMode == ModeMarkdownV2 {
case ModeMarkdownV2:
replacer = strings.NewReplacer(
"_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(",
"\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>",
"#", "\\#", "+", "\\+", "-", "\\-", "=", "\\=", "|",
"\\|", "{", "\\{", "}", "\\}", ".", "\\.", "!", "\\!",
)
} else {
default:
return ""
}

Expand Down
28 changes: 19 additions & 9 deletions bot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func getBot(t *testing.T) (*BotAPI, error) {
bot.Debug = true

logger := testLogger{t}
SetLogger(logger)
_ = SetLogger(logger)

if err != nil {
t.Error(err)
Expand Down Expand Up @@ -548,7 +548,7 @@ func TestSetWebhookWithCert(t *testing.T) {

time.Sleep(time.Second * 2)

bot.Request(DeleteWebhookConfig{})
_, _ = bot.Request(DeleteWebhookConfig{})

wh, err := NewWebhookWithCert("https://example.com/tgbotapi-test/"+bot.Token, FilePath("tests/cert.pem"))

Expand All @@ -567,15 +567,15 @@ func TestSetWebhookWithCert(t *testing.T) {
t.Error(err)
}

bot.Request(DeleteWebhookConfig{})
_, _ = bot.Request(DeleteWebhookConfig{})
}

func TestSetWebhookWithoutCert(t *testing.T) {
bot, _ := getBot(t)

time.Sleep(time.Second * 2)

bot.Request(DeleteWebhookConfig{})
_, _ = bot.Request(DeleteWebhookConfig{})

wh, err := NewWebhook("https://example.com/tgbotapi-test/" + bot.Token)

Expand All @@ -601,7 +601,7 @@ func TestSetWebhookWithoutCert(t *testing.T) {
t.Errorf("failed to set webhook: %s", info.LastErrorMessage)
}

bot.Request(DeleteWebhookConfig{})
_, _ = bot.Request(DeleteWebhookConfig{})
}

func TestSendWithMediaGroupPhotoVideo(t *testing.T) {
Expand Down Expand Up @@ -701,7 +701,7 @@ func ExampleNewBotAPI() {
msg := NewMessage(update.Message.Chat.ID, update.Message.Text)
msg.ReplyToMessageID = update.Message.MessageID

bot.Send(msg)
_, _ = bot.Send(msg)
}
}

Expand Down Expand Up @@ -738,14 +738,19 @@ func ExampleNewWebhook() {
}

updates := bot.ListenForWebhook("/" + bot.Token)
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
go func() {
err = http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
if err != nil {
log.Println(err)
}
}()

for update := range updates {
log.Printf("%+v\n", update)
}
}

func ExampleWebhookHandler() {
func Handler() {
bot, err := NewBotAPI("MyAwesomeBotToken")
if err != nil {
panic(err)
Expand Down Expand Up @@ -782,7 +787,12 @@ func ExampleWebhookHandler() {
}
})

go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
go func() {
err = http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
if err != nil {
log.Println(err)
}
}()
}

func ExampleInlineConfig() {
Expand Down
Loading