Krishnanand
Posted on May 8, 2020
The adoption of chat-bots are at a peak now. Since facebook opened up its developer platform and opened the world of possibilities for chat-bots many platforms supported bots. Telegram is one of the leading platforms with bot functionality.
There is almost a bot for everything on telegram. For memes, searching movies, downloading youtube videos, dating and many more. Businesses engage with users through these bots. Crypto companies do airdrops, giveaways using these bots. Bots are literally everywhere.
Today we are going to checkout how to build a telegram bot using Golang. So if you don't know Go this article is not for you.
We are not using any telegram bot api wrapper libraries .We are using only the net/http
package to have a better understanding how things work under the hood. Let's dive right in.
Getting started
First thing you have to do is to get a bot token after creating a bot using botfather bot on telegram and declare a constant.
const botToken = "BOT_TOKEN"
Let's start by creating a main.go file.
The first thing we need is the net/http
package we also require the log
package for logging the errors so import them and code the main function which looks like this.
func main() {
err := http.ListenAndServe(":8080", http.HandlerFunc(webHookHandler))
if err != nil {
log.Fatal(err)
return
}
}
Yep that's it . That' how much it takes to make a simple http server in go.It listens at the port 8080 and invokes the function webHookHandler
on recieving a http Request the next line is just how we handle errors in go.
Now that we have setup a server we want to create the webHookHandler
function. You may think why the name webHookhandler
its because we are using the webHooks. You can find more details here on Telegram bot docs.
Now lets take a look at the webHookHandler
function.
The bot we are going to built reply's with a random joke when the user sends the command "/joke". For this we use a free API http://api.icndb.com/jokes/random.
Our WebHookHandler Function looks like this
func webHookHandler(rw http.ResponseWriter, req *http.Request) {
// Create our web hook request body type instance
body := &webHookReqBody{}
// Decodes the incoming request into our cutom webhookreqbody type
if err := json.NewDecoder(req.Body).Decode(body); err != nil {
log.Printf("An error occured (webHookHandler)")
log.Panic(err)
return
}
// If the command /joke is recieved call the sendReply function
if strings.ToLower(body.Message.Text) == "/joke" {
err := sendReply(body.Message.Chat.ID)
if err != nil {
log.Panic(err)
return
}
}
}
Whenever a message is received by the bot our http Server gets a request and we handle the request using this function.
You can see a webHookReqBody type which is a struct to which we decode the data received via http Request.
The webHookReqBody struct declaration :
We need to import the encoding/json package for this
type webHookReqBody struct {
Message struct {
Text string `json:"text"`
Chat struct {
ID int64 `json:"id"`
} `json:"chat"`
} `json:"message"`
}
Now whenever our bot recieves a message an http request is recieved by our server and that http request body is decoded into the webHookHandler struct. Then we check if the message is "/joke" if it is then we call the sendReply
Function :
func sendReply(chatID int64) error {
fmt.Println("sendReply called")
// calls the joke fetcher fucntion and gets a random joke from the API
text, err := jokeFetcher()
if err != nil {
return err
}
//Creates an instance of our custom sendMessageReqBody Type
reqBody := &sendMessageReqBody{
ChatID: chatID,
Text: text,
}
// Convert our custom type into json format
reqBytes, err := json.Marshal(reqBody)
if err != nil {
return err
}
// Make a request to send our message using the POST method to the telegram bot API
resp, err := http.Post(
"https://api.telegram.org/bot"+botToken+"/"+"sendMessage",
"application/json",
bytes.NewBuffer(reqBytes),
)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return errors.New("unexpected status" + resp.Status)
}
return err
}
sendReply
takes an argument the CHATID which is used to identify the telegram user inside the sendReply we first generate the text to be sent using the jokFetcher function which calls our API and gets a random joke for us.
func jokeFetcher() (string, error) {
resp, err := http.Get("http://api.icndb.com/jokes/random")
c := &joke{}
if err != nil {
return "", err
}
err = json.NewDecoder(resp.Body).Decode(c)
return c.Value.Joke, err
}
We have joke struct into which the joke gets decoded into
type joke struct {
Value struct {
Joke string `json:"joke"`
} `json:"value"`
}
In the senReply Function we have sendMessageReqBody struct whose declaration is as follows :
type sendMessageReqBody struct {
ChatID int64 `json:"chat_id"`
Text string `json:"text"`
}
Check out the full code here main.go
Now in order to test our bot you should first install ngrok on your system
then run
ngrok http 8080
Now you will get a screen containing an https url copy that url and run the command
curl -F "url=YOUR_NGROK_URL_HERE" https://api.telegram.org/botYOUR_BOT_TOKEN_HERE/setWebhook
Now run your main.go file then send your bot a message "/joke". Enjoy .!!!
Posted on May 8, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.