A general-purpose bot library inspired by Hubot but written in Go. :robot:

Joe Bot 🤖

A general-purpose bot library inspired by Hubot but written in Go.


Joe is a library used to write chat bots in the Go programming language. It is very much inspired by the awesome Hubot framework developed by the folks at Github and brings its power to people who want to implement chat bots using Go.

Getting Started

Joe is a software library that is packaged as Go module. You can get it via:

go get github.com/go-joe/joe

Example usage

You can find all code examples, more explanation and complete recipes at https://joe-bot.net

Each bot consists of a chat Adapter (e.g. to integrate with Slack), a Memory implementation to remember key-value data (e.g. using Redis) and a Brain which routes new messages or custom events (e.g. receiving an HTTP call) to the corresponding registered handler functions.

By default joe.New(…) uses the CLI adapter which makes the bot read messages from stdin and respond on stdout. Additionally the bot will store key value data in-memory which means it will forget anything you told it when it is restarted. This default setup is useful for local development without any dependencies but you will quickly want to add other Modules to extend the bots capabilities.

The following example connects the Bot with a Slack workspace and stores key-value data in Redis. To allow the message handlers to access the memory we define them as functions on a custom ExampleBottype which embeds the joe.Bot.

package main

import (
	"fmt"

	"github.com/go-joe/joe"
	"github.com/go-joe/redis-memory"
	"github.com/go-joe/slack-adapter/v2"
)

type ExampleBot struct {
	*joe.Bot
}

func main() {
	b := &ExampleBot{
		Bot: joe.New("example",
			redis.Memory("localhost:6379"),
			slack.Adapter("xoxb-1452345…"),
		),
	}

	b.Respond("remember (.+) is (.+)", b.Remember)
	b.Respond("what is (.+)", b.WhatIs)

	err := b.Run()
	if err != nil {
		b.Logger.Fatal(err.Error())
	}
}

func (b *ExampleBot) Remember(msg joe.Message) error {
	key, value := msg.Matches[0], msg.Matches[1]
	msg.Respond("OK, I'll remember %s is %s", key, value)
	return b.Store.Set(key, value)
}

func (b *ExampleBot) WhatIs(msg joe.Message) error {
	key := msg.Matches[0]
	var value string
	ok, err := b.Store.Get(key, &value)
	if err != nil {
		return fmt.Errorf("failed to retrieve key %q from brain: %w", key, err)
	}

	if ok {
		msg.Respond("%s is %s", key, value)
	} else {
		msg.Respond("I do not remember %q", key)
	}

	return nil
}

Available modules

Joe ships with no third-party modules such as Redis integration to avoid pulling in more dependencies than you actually require. There are however already some modules that you can use directly to extend the functionality of your bot without writing too much code yourself.

If you have written a module and want to share it, please add it to this list and open a pull request.

Chat Adapters

Memory Modules

Other Modules

Built With

  • zap - Blazing fast, structured, leveled logging in Go
  • multierr - Package multierr allows combining one or more errors together
  • testify - A simple unit test library

Contributing

Please read CONTRIBUTING.md for details on our code of conduct and on the process for submitting pull requests to this repository.

Versioning

THIS SOFTWARE IS STILL IN ALPHA AND THERE ARE NO GUARANTEES REGARDING API STABILITY YET.

All significant (e.g. breaking) changes are documented in the CHANGELOG.md.

After the v1.0 release we plan to use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

  • Friedrich Große - Initial work - fgrosse

See also the list of contributors who participated in this project.

License

This project is licensed under the BSD-3-Clause License - see the LICENSE file for details.

Acknowledgments

  • Hubot and its great community for the inspiration
  • embedmd for a cool tool to embed source code in markdown files
Comments
  • Add Reactions to Messages

    Add Reactions to Messages

    Summary

    Many chat services (e.g. Slack, Rocket.Chat, Mattermost, etc.) offer the ability to "react" to messages with emoji. It would be nice to be able to make use of that capability.

    Basic example

    func DoWork(msg joe.Message) error {
      msg.React(":+1:")
      time.Sleep(1 * time.Second)
      msg.Respond("Job is done")
    }
    

    Motivation

    Using reactions is an easy way to acknowledge that a command has been received without cluttering up the chat with intermediate results. Simple commands could even skip output entirely and just use reactions.

    Potential Issues

    Not all Adapters will be able to support reactions (e.g. CLI Adapter). A decision would be necessary for how to handle reactions in this case. My thought would be to fail silently (optionally with a logger warning) and to document that reactions are optional for adapters. An alternative would be to error if not available and to offer a capability to test if reactions are available ReactionsEnabled or perhaps msg.ReactIfEnabled.

    Edit 1

    Perhaps a pragmatic way to handle the absence of reactions would be a ReactOrRespond function that would add a reaction if able, respond if not.

    func DoWork(msg joe.Message) error {
      msg.ReactOrRespond(":+1:", "Job started")
      time.Sleep(1 * time.Second)
      msg.Respond("Job is done")
    }
    
  • Implement an API to allow chat adapters to implement emoji reactions

    Implement an API to allow chat adapters to implement emoji reactions

    Fixes #21

    The slack implementation is pretty much done but not yet really tested. Reviews and feedback welcome, otherwise I will probably merge this mid or end of next week :)

  • Registering a default response when no match

    Registering a default response when no match

    Fixes #25

    • improve documentation about how multiple matching event handlers are executed
    • add a way for handlers to prevent execution of later event handlers
    • use this in Bot.Respond(…) so only the first matching handler is executed
    • unit test it all
  • Add link to Telegram adapter

    Add link to Telegram adapter

    I wrote an adapter for Telegram over the weekend...

    I also have a memory implementation using bolt

    Both still need a README with some documentation but I wanted to open these anyway in case anybody else is interested in this...

  • Auth continued

    Auth continued

    • Make Auth.Grant(…) idempotent and do not unnecessarily add smaller scopes
    • Support extending permissions via Auth.Grant(…)
    • Add boolean return value to Auth.Grant(…) to indicate if a new permission was granted
    • Add Auth.Revoke(…) to remove permissions
    • Fix flaky unit test TestBrain_Memory
    • Fix flaky TestCLIAdapter_Register test
  • Correct which adapters support reactions

    Correct which adapters support reactions

    Currently, the Rocket.Chat adapter does not have a released version with Reactions support. I have some initial code on my master branch, but there are some bugs yet to be resolved.

    On the other hand, the Mattermost adapter does support Reactions (at least adding them to messages, still working on the event support).

  • Registering a default response when no match

    Registering a default response when no match

    I've been trying to figure out how I can make my bot respond with a helpful message when no message is matched.

    Naively I've tried the following approach which results in both handlers to be executed

    b.Respond("foo", b.FooHandler)
    b.Respond(".*", b.HelpHandler)
    

    Unless I'm missing something, there does not seem to be a way to register a default handler that would only be executed if no other handler matches the message.

    There also does not appear to be a way to stop processing handlers after the FooHandler is executed.

  • Add link to Rocket.Chat Adapter

    Add link to Rocket.Chat Adapter

    I've written an adapter for use with Rocket.Chat based off of the Slack adapter.

    I'd be happy to make changes if there are any issues you would like corrected.

  • List support in Memory

    List support in Memory

    I'd really like to have support for lists in Memory implementations, without having to build it up from KV considering that some of the Memory implementations have first class support (Redis). Would you want to add this concept to joe?

    I'd also like to have Sets since my ultimate goal is actually a list of unique objects, and if we have List, and Set I can compose them into UniqList anyway.

  • Allow for specifying whether message is DM in `ReceiveMessageEvent`

    Allow for specifying whether message is DM in `ReceiveMessageEvent`

    Currently, the standard joe.ReceiveMessageEvent sent by all documented adapters does not specify whether the message is "private" (a one-on-one chat in Slack, a /msg in IRC, etc).

    This can be useful in having handlers process commands differently (e.g. allow admin-level commands in direct chats) depending on the communication mode, without having to either parse the Channel or Data fields (which assumes the handler knows which adapter is being used) or having to use custom events, which assume adapter support.

  • Possible to send a message without having Message struct?

    Possible to send a message without having Message struct?

    Thanks for putting together this library, I'm just starting to explore it. I was wondering if there is a recommended method to send an arbitrary message to a channel without needing to "Respond" to a message that has come in.

    My [first] use case is that I want to send a message to a channel after receiving a webhook via the http-server.

    I suppose one way that I might be able to achieve this is to have the webhook handler publish a joe.ReceiveMessageEvent event with the desired channel that I want to send a message to, then listen for this 'silent' event emitted and respond to it. This will likely work, but it seems like quite a workaround to achieve my goal.

    Any insight you can provide would be appreciated.

    Thanks

  • Prefix Scans for Storage Keys

    Prefix Scans for Storage Keys

    Summary

    Since many uses of the Storage interface may have hierarchical keys, e.g. the permissions, it would be beneficial to have a way to iterate over keys matching a given prefix.

    Basic example

    for _, key := range a.store.KeysWithPrefix("joe.permissions.mymodule.") {
      ...
    }
    

    Motivation

    From #28

    Since we are iterating over all keys the bot knows we should expect that also non-permission keys are among them.

    I suggest you update your unit test to check this is also handled correctly.

    Rather than push this onto any developer who needs to interact with the permissions, we could require the Storage interface to support prefix scans. Some storage engines may have a higher performance way of doing prefix scans and we could take advantage of that. If the storage engine does not offer it, the bot could handle the naive looping over keys itself. This removes the burden from developers to implement/test this independently.

    Potential Issues

    • If the prefix scan isn't optional for the Storage interface, a new release would break any third party implementations. As described above, this would not be an issue.
DingTalk (dingding) is the go implementation of the DingTalk robot. DingTalk(dingding) 是钉钉机器人的 go 实现
DingTalk (dingding) is the go implementation of the DingTalk robot. DingTalk(dingding) 是钉钉机器人的 go 实现

DingTalk (dingding) is the go implementation of the DingTalk robot. Support Docker, Jenkinsfile, command line mode, module mode, signature security settings, chain syntax to create messages, support text, link, markdown,ActionCard,FeedCard message types.

Jan 3, 2023
A trading robot, that can submit basic orders in an automated fashion.
A trading robot, that can submit basic orders in an automated fashion.

Source: https://github.com/harunnryd/btrade Issues: https://github.com/harunnryd/btrade/issues Twitter: @harunnryd LinkedIn: @harunnryd btrade is a ro

Jan 26, 2022
Bot-template - A simple bot template for creating a bot which includes a config, postgresql database

bot-template This is a simple bot template for creating a bot which includes a c

Sep 9, 2022
A bot based on Telegram Bot API written in Golang allows users to download public Instagram photos, videos, and albums without receiving the user's credentials.

InstagramRobot InstagramRobot is a bot based on Telegram Bot API written in Golang that allows users to download public Instagram photos, videos, and

Dec 16, 2021
its the same idea as bruh-bot, but with golang, and add more bots
its the same idea as bruh-bot, but with golang, and add more bots

bruh-bot but more powerful! requirements python go you can used on mac and linux the idea its really simple, can make a lot of bots with the same task

Jul 7, 2021
Dlercloud-telegram-bot - A Telegram bot for managing your Dler Cloud account

Dler Cloud Telegram Bot A Telegram bot for managing your Dler Cloud account. Usa

Dec 30, 2021
Quote-bot - Un bot utilisant l'API Twitter pour tweeter une citation par jour sur la programmation et les mathématiques.

Description Ceci est un simple bot programmé en Golang qui tweet une citation sur la programmation tout les jours. Ce bot est host sur le compte Twitt

Jan 1, 2022
Discord-bot - A Discord bot with golang

JS discord bots Install Clone repo git clone https://github.com/fu-js/discord-bo

Aug 2, 2022
Bot - Telegram Music Bot in Go

Telegram Music Bot in Go An example bot using gotgcalls. Setup Install the serve

Jun 28, 2022
Pro-bot - A telegram bot to play around with the community telegram channels

pro-bot ?? Pro Bot A Telegram Bot to Play Around With The Community Telegram Cha

Jan 24, 2022
Slack-emoji-bot - This Slack bot will post the newly created custom Slack emojis to the channel of your choice

Slack Emoji Bot This Slack bot will post the newly created custom Slack emojis t

Oct 21, 2022
Sex-bot - The sex bot and its uncreative responses
Sex-bot - The sex bot and its uncreative responses

Sex Bot The sex bot, made with golang! The sex bot can't hear the word "sexo" he

Nov 11, 2022
Feline-bot - Feline Bot for Discord using Golang

Feline Bot for Discord Development This bot is implemented using Golang. Feature

Feb 10, 2022
Account Generator Bot, written in GoLang via gotgbot library.

Account Generator Bot Account Generator Bot, written in GoLang via gotgbot library. Variables Env Vars - BOT_TOKEN - Get it from @BotFather CHANNEL_ID

Jul 7, 2022
Telegram bot written in Golang using gotgbot library

go_tgbot Telegram bot written in Golang using gotgbot library. How to run go get -u github.com/itsLuuke/go_tgbot rename sample.env to .env and fill in

Nov 4, 2022
Library for working with golang telegram client + bot based on tdlib. This library was taken from the user Arman92 and changed for the current version of tdlib.

go-tdlib Golang Telegram TdLib JSON bindings Install To install, you need to run inside a docker container (it is given below) go get -u github.com/ka

Dec 2, 2022
IRC, Slack, Telegram and RocketChat bot written in go
IRC, Slack, Telegram and RocketChat bot written in go

go-bot IRC, Slack & Telegram bot written in Go using go-ircevent for IRC connectivity, nlopes/slack for Slack and Syfaro/telegram-bot-api for Telegram

Dec 20, 2022
Simple yet customizable bot framework written in Go.
Simple yet customizable bot framework written in Go.

Introduction Sarah is a general-purpose bot framework named after the author's firstborn daughter. This comes with a unique feature called "stateful c

Dec 12, 2022
Slack bot core/framework written in Go with support for reactions to message updates/deletes
Slack bot core/framework written in Go with support for reactions to message updates/deletes

Overview Requirements Features Demo The Name Concepts Create Your Own Slackscot Assembling the Parts and Bringing Your slackscot to Life Configuration

Oct 28, 2022