All Projects → oklahomer → Go Sarah

oklahomer / Go Sarah

Licence: mit
Simple yet customizable bot framework written in Go.

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to Go Sarah

Slack Machine
A sexy, simple, yet powerful and extendable Slack bot
Stars: ✭ 91 (-51.6%)
Mutual labels:  bot, bot-framework, slack-bot, slackbot, slack
Slacker
Slack Bot Framework
Stars: ✭ 495 (+163.3%)
Mutual labels:  bot, bot-framework, slack-bot, slackbot, slack
Jbot
Make Slack and Facebook Bots in Java.
Stars: ✭ 1,148 (+510.64%)
Mutual labels:  bot, bot-framework, slack-bot, slackbot, slack
Awesome Bots
The most awesome list about bots ⭐️🤖
Stars: ✭ 2,864 (+1423.4%)
Mutual labels:  bot-framework, slack-bot, slackbot, slack
Obed Bot
🍴 Obed Slack Bot, na požiadanie kontroluje aktuálnu ponuku denného menu reštaurácii. [only for slovak|czech users]
Stars: ✭ 32 (-82.98%)
Mutual labels:  bot, slack-bot, slackbot, slack
Slick
Slick, a Slack bot in Go
Stars: ✭ 150 (-20.21%)
Mutual labels:  bot, bot-framework, slack-bot, slack
Botonomous
A PHP Framework For Creating Autonomous Slack Bots
Stars: ✭ 109 (-42.02%)
Mutual labels:  bot, slack-bot, slackbot, slack
Slack Block Builder
Lightweight, no-dependency JavaScript library for creating Slack Block Kit UIs, with a builder syntax, inspired by SwiftUI.
Stars: ✭ 129 (-31.38%)
Mutual labels:  bot-framework, slack-bot, slackbot, slack
Sactive Bot
😈 An extensible chat bot framework. sactive-bot is an evolution of the open source hubot project. - https://www.shipengqi.top/sactive-bot .
Stars: ✭ 212 (+12.77%)
Mutual labels:  bot, slack-bot, slackbot, slack
Intelligo
🤖 Chatbot Framework for Node.js.
Stars: ✭ 347 (+84.57%)
Mutual labels:  bot, bot-framework, slack-bot, slack
Slack Poster
Simple gem to post messages on Slack using web hooks.
Stars: ✭ 49 (-73.94%)
Mutual labels:  bot, slackbot, slack
Marvin
The paranoid bot (framework)
Stars: ✭ 51 (-72.87%)
Mutual labels:  bot, slack-bot, slack
Hubcommander
A Slack bot for GitHub organization management -- and other things too
Stars: ✭ 1,149 (+511.17%)
Mutual labels:  bot, slack-bot, slack
Slack Ruby Client
A Ruby and command-line client for the Slack Web, Real Time Messaging and Event APIs.
Stars: ✭ 957 (+409.04%)
Mutual labels:  slack-bot, slackbot, slack
Wc2018 Slack Bot
World Cup 2018 Slack Bot
Stars: ✭ 11 (-94.15%)
Mutual labels:  slack-bot, slackbot, slack
Integrations
Connect your App to Multiple Messaging Channels with the W3C Open standard.
Stars: ✭ 721 (+283.51%)
Mutual labels:  bot, gitter, slack
Ex mustang
✨ A simple, clueless bot
Stars: ✭ 67 (-64.36%)
Mutual labels:  bot, slack-bot, slack
Php Slack Bot
Slack bot user written in PHP
Stars: ✭ 161 (-14.36%)
Mutual labels:  bot, slack-bot, slack
Office Simulator
Miss the office life? You won't any more with this wonderful office slack simulator.
Stars: ✭ 152 (-19.15%)
Mutual labels:  bot, slackbot, slack
Chatskills
Run and debug Alexa skills on the command-line. Create bots. Run them in Slack. Run them anywhere!
Stars: ✭ 171 (-9.04%)
Mutual labels:  slack-bot, slackbot, slack

GoDoc Go Report Card Build Status Coverage Status Maintainability Join the chat at https://gitter.im/go-sarah-dev/community

Introduction

Sarah is a general-purpose bot framework named after the author's firstborn daughter.

This comes with a unique feature called "stateful command" as well as some basic features such as command and scheduled task. In addition to those fundamental features, this project provides rich life cycle management including live configuration update, customizable alerting mechanism, automated command/task (re-)building, and panic-proofed concurrent command/task execution.

Such features are achieved with a composition of fine-grained components. Each component has its own interface and a default implementation, so developers are free to customize their bot experience by replacing the default implementation for a particular component with their own implementation. Thanks to such segmentalized lifecycle management architecture, the adapter component to interact with each chat service has fewer responsibilities comparing to other bot frameworks; An adapter developer may focus on implementing the protocol to interacting with the corresponding chat service. To take a look at those components and their relations, see Components.

IMPORTANT NOTICE

v4 Release

This is the fourth major version of go-sarah, which involves some architectural changes:

  • sarah.NewBot now returns a single value: sarah.Bot
  • Utility packages including logger, retry, and worker are now hosted at github.com/oklahomer/go-kasumi

v3 Release

This is the third major version of go-sarah, which introduces the Slack adapter's improvement to support both RTM and Events API. Breaking interface change for Slack adapter was inevitable and that is the sole reason for this major version up. Other than that, this does not include any breaking change. See Migrating from v2.x to v3.x for details.

v2 Release

The second major version introduced some breaking changes to go-sarah. This version still supports and maintains all functionalities, better interfaces for easier integration are added. See Migrating from v1.x to v2.x to migrate from the older version.

Supported Chat Services/Protocols

Although a developer may implement sarah.Adapter to integrate with the desired chat service, some adapters are provided as reference implementations:

At a Glance

General Command Execution

hello world

Above is a general use of go-sarah. Registered commands are checked against user input and matching one is executed; when a user inputs ".hello," hello command is executed and a message "Hello, 世界" is returned.

Stateful Command Execution

The below image depicts how a command with a user's conversational context works. The idea and implementation of "user's conversational context" is go-sarah's signature feature that makes bot command "state-aware."

The above example is a good way to let a user input a series of arguments in a conversational manner. Below is another example that uses a stateful command to entertain the user.

Example Code

Following is the minimal code that implements such general command and stateful command introduced above. In this example, two ways to implement sarah.Command are shown. One simply implements sarah.Command interface; while another uses sarah.CommandPropsBuilder for lazy construction. Detailed benefits of using sarah.CommandPropsBuilder and sarah.CommandProps are described at its wiki page, CommandPropsBuilder.

For more practical examples, see ./examples.

package main

import (
	"context"
	"fmt"
	"github.com/oklahomer/go-sarah/v4"
	"github.com/oklahomer/go-sarah/v4/slack"
	
	"os"
	"os/signal"
	"syscall"
	
	// Below packages register commands in their init().
	// Importing with blank identifier will do the magic.
	_ "guess"
	_ "hello"
)

func main() {
	// Setup Slack adapter
	setupSlack()
	
	// Prepare go-sarah's core context.
	ctx, cancel := context.WithCancel(context.Background())

	// Run
	config := sarah.NewConfig()
	err := sarah.Run(ctx, config)
	if err != nil {
		panic(fmt.Errorf("failed to run: %s", err.Error()))
	}
	
	// Stop when signal is sent.
	c := make(chan os.Signal, 1)
   	signal.Notify(c, syscall.SIGTERM)
   	select {
   	case <-c:
   		cancel()
   
   	}
}

func setupSlack() {
	// Setup slack adapter.
	slackConfig := slack.NewConfig()
	slackConfig.Token = "REPLACE THIS"
	adapter, err := slack.NewAdapter(slackConfig, slack.WithRTMPayloadHandler(slack.DefaultRTMPayloadHandler))
	if err != nil {
		panic(fmt.Errorf("faileld to setup Slack Adapter: %s", err.Error()))
	}

	// Setup optional storage so conversational context can be stored.
	cacheConfig := sarah.NewCacheConfig()
	storage := sarah.NewUserContextStorage(cacheConfig)

	// Setup Bot with slack adapter and default storage.
	bot := sarah.NewBot(adapter, sarah.BotWithStorage(storage))
	
	sarah.RegisterBot(bot)
}

package guess

import (
	"context"
	"github.com/oklahomer/go-sarah/v4"
	"github.com/oklahomer/go-sarah/v4/slack"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

func init() {
	sarah.RegisterCommandProps(props)
}

var props = sarah.NewCommandPropsBuilder().
	BotType(slack.SLACK).
	Identifier("guess").
	Instruction("Input .guess to start a game.").
	MatchFunc(func(input sarah.Input) bool {
		return strings.HasPrefix(strings.TrimSpace(input.Message()), ".guess")
	}).
	Func(func(ctx context.Context, input sarah.Input) (*sarah.CommandResponse, error) {
		// Generate answer value at the very beginning.
		rand.Seed(time.Now().UnixNano())
		answer := rand.Intn(10)

		// Let user guess the right answer.
		return slack.NewResponse(input, "Input number.", slack.RespWithNext(func(c context.Context, i sarah.Input) (*sarah.CommandResponse, error){
			return guessFunc(c, i, answer)
		}))
	}).
	MustBuild()

func guessFunc(_ context.Context, input sarah.Input, answer int) (*sarah.CommandResponse, error) {
	// For handiness, create a function that recursively calls guessFunc until user input right answer.
	retry := func(c context.Context, i sarah.Input) (*sarah.CommandResponse, error) {
		return guessFunc(c, i, answer)
	}

	// See if user inputs valid number.
	guess, err := strconv.Atoi(strings.TrimSpace(input.Message()))
	if err != nil {
		return slack.NewResponse(input, "Invalid input format.", slack.RespWithNext(retry))
	}

	// If guess is right, tell user and finish current user context.
	// Otherwise let user input next guess with bit of a hint.
	if guess == answer {
		return slack.NewResponse(input, "Correct!")
	} else if guess > answer {
		return slack.NewResponse(input, "Smaller!", slack.RespWithNext(retry))
	} else {
		return slack.NewResponse(input, "Bigger!", slack.RespWithNext(retry))
	}
}

package hello

import (
	"context"
	"github.com/oklahomer/go-sarah/v4"
	"github.com/oklahomer/go-sarah/v4/slack"
	"strings"
)

func init() {
    sarah.RegisterCommand(slack.SLACK, &command{})	
}

type command struct {
}

var _ sarah.Command = (*command)(nil)

func (hello *command) Identifier() string {
	return "hello"
}

func (hello *command) Execute(_ context.Context, i sarah.Input) (*sarah.CommandResponse, error) {
	return slack.NewResponse(i, "Hello!")
}

func (hello *command) Instruction(input *sarah.HelpInput) string {
	if 12 < input.SentAt().Hour() {
		// This command is only active in the morning.
		// Do not show instruction in the afternoon.
		return ""
	}
	return "Input .hello to greet"
}

func (hello *command) Match(input sarah.Input) bool {
	return strings.TrimSpace(input.Message()) == ".hello"
}

Supported Golang Versions

Official Release Policy says "each major Go release is supported until there are two newer major releases." Following this policy would help this project enjoy the improvements introduced in the later versions. However, not all projects can immediately switch to a newer environment. Migration could especially be difficult when this project cuts off the older version's support right after a new major Go release.

As a transition period, this project includes support for one older version than Go project does. Such a version is guaranteed to be listed in .travis.ci. In other words, new features/interfaces introduced in 1.10 can be used in this project only after 1.12 is out.

Further Readings

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].