How to make a WhatsApp Bot in Go [Part 1 of N]

WhatsApp Logo

Such a long time since I’ve published my last post, I’m back with a simple and small post: How to make a simple Whatsapp Bot in Go.


Note about this post and its examples

The most important thing is to take into account that WhatsApp does not provide a public API that you can use to create a Bot, or any kind of program that interacts with it. Every open source (and free) solution found on the Internet relies on some sort of scrapping or reverse engineering. So the solution presented in this post may not be stable (or need an update) by the time you read this post.


Requirements

  • Go (Golang) version 1.11 or newer (Go modules are used)
  • An active WhatsApp account logged in a phone

Dependencies

Getting Started

From a terminal in your favourite OS (one of the beautiful things of a Multiplatform language as Golang) create a module as follow:

$ mkdir whatsapp-bot-test
$ cd whatsapp-bot-test
$ go mod init github.com/eaceto/whatsapp-bot-test
go: creating new go.mod: module github.com/eaceto/whatsapp-bot

In order to import Lucas Engelke’s go-whatsapp run the following command inside your project directory

$ go get github.com/Rhymen/go-whatsapp

Now the content of go.mod will look like this

module github.com/eaceto/whatsapp-bot
go 1.13
require github.com/Rhymen/go-whatsapp v0.1.0 // indirect

Connecting to WhatsApp requires establishing a connection and authenticating using a QRCode that is scanned with your (already authenticated) phone. This session can be started in your Go app by running

waconn, err := whatsapp.NewConn(10 * time.Second) //10secs of timeout
if err != nil {
    panic(err)
}

I have written a small function that given a connection handles the login process if there is no stored session, or if the stored one cannot be retrieved.

func login(waconn *whatsapp.Conn) error {
	var sessionError error = fmt.Errorf("no session")
	//try to find a session stored in the file system
	session, sessionError := readSessionFromFileSystem()
	if sessionError == nil {
		//try to restore saved session
		session, sessionError = waconn.RestoreWithSession(session)
		if sessionError != nil {
			log.Printf("error restoring session from file system: %v\n", sessionError)
		}
	} else {
		log.Printf("no session found on session from file system: %v\n", sessionError)
	}
	if sessionError != nil {
		//perform a regular login
		session, sessionError = loginImpl(waconn)
		if sessionError != nil {
			return fmt.Errorf("error during login: %v\n", sessionError)
		}
	}
	//save session
	sessionError = writeSessionToFileSystem(session)
	if sessionError != nil {
		return fmt.Errorf("error saving session: %v\n", sessionError)
	}
	return nil
}

The function loginImpl gets the QRCode from the API and renders it on the terminal. At this point, if you are writing a Web Application or Service, you can transmit the QRCode as an image, or if it is a bot, just render it on the terminal using qrcode-termina-go.

func loginImpl(waconn *whatsapp.Conn) (whatsapp.Session, error) {
	qr := make(chan string)
	go func() {
		terminal := qrcodeTerminal.New()
		terminal.Get(<-qr).Print()
	}()
	return waconn.Login(qr)
}

Where readSessionFromFileSystem and writeSessiontoFileSystem are declared as follows

func readSessionFromFileSystem() (whatsapp.Session, error) {
	session := whatsapp.Session{}
	file, err := os.Open(os.TempDir() + "waSession.gob")
	if err != nil {
		return session, err
	}
	defer file.Close()
	decoder := gob.NewDecoder(file)
	err = decoder.Decode(&session)
	if err != nil {
		return session, err
	}
	return session, nil
}
func writeSessionToFileSystem(session whatsapp.Session) error {
	file, err := os.Create(os.TempDir() + "waSession.gob")
	if err != nil {
		return err
	}
	defer file.Close()
	encoder := gob.NewEncoder(file)
	err = encoder.Encode(session)
	if err != nil {
		return err
	}
	return nil
}

Using the login function is as simple as calling like this

//login or restore your WhatsApp connection
if err := login(waconn); err != nil {
    log.Fatalf("error logging in: %v\n", err)
}

The QRCode will be printed in the console, and go-whatsapp is smart enough and saves the session so it is possible to restore it without authenticating again.

WhatsApp login QR Code

Sé el primero en comentar

Dejar una contestacion