bot

package module
v0.5.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2020 License: MIT Imports: 17 Imported by: 1

README

bot

Is a mini framework that alow you to create a plugin that works with multiple platform

Feature

  • Work with Slack and Telegram
  • Plugin as middleware. Multiple plugin can be combined together
  • Upload file (☑︎Slack, 🗹Telegram)

Example

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/yulrizka/bot"
)

// marcoPolo is an example plugin that will reply text marco with polo
type marcoPolo struct {
	cl  bot.Client
	out chan bot.Message
}

func (*marcoPolo) Name() string {
	return "MarcoPolo"
}

// Init should store the out channel to send message and do initialization
func (m *marcoPolo) Init(out chan bot.Message, cl bot.Client) error {
	m.out = out
	m.cl = cl
	return nil
}

// Handle incoming message that could be in any type (*bot.Message, *bot.JoinMessage, etc).
// return handled false will pass modifiedMsg to other plugins down the chain
func (m *marcoPolo) Handle(rawMsg interface{}) (handled bool, modifiedMsg interface{}) {
	if inMessage, ok := rawMsg.(*bot.Message); ok {
		if strings.TrimSpace(strings.ToLower(inMessage.Text)) == "marco" {
			text := fmt.Sprintf("POLO! -> %s (<@%s>)\n", inMessage.From.FullName(), inMessage.From.Username)
			// send message
			msg := bot.Message{
				Chat: inMessage.Chat,
				Text: text,
			}
			m.out <- msg
		}
	}

	// handled true will stop exit the middleware chain. Handle method of the next plugin will not be called
	// modifiedMsg give plugin a chance to modify the message for the next plugin
	handled, modifiedMsg = false, rawMsg
	return
}

func init() {
	// Log message is callback method that gives you chance to handle the log using your preferred library
	bot.Log = func(record bot.LogRecord) {
		log.Print(record)
	}
}

func main() {
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)

	key := os.Getenv("SLACK_KEY")
	if key == "" {
		panic("SLACK_KEY can not be empty")
	}
	var client bot.Client
	var err error

	client, err = bot.NewSlack(context.Background(), key)
	if err != nil {
		log.Fatal(err)
	}
	plugin := new(marcoPolo)
	if err := client.AddPlugins(plugin); err != nil {
		panic(err)
	}

	client.Start()
}

Project using this library

  • fam100 a game of family feud

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// OutboxBufferSize is the size of the outbox channel
	OutboxBufferSize = 100
	// OutboxWorker is the number of worker that sends message to telegram api
	OutboxWorker = 5

	// VERSION compile time info
	VERSION = ""
)

Options

View Source
var (
	StatsMsgPerUpdateCount   = metrics.NewRegisteredCounter("telegram.messagePerUpdate", metrics.DefaultRegistry)
	StatsUpdateCount         = metrics.NewRegisteredCounter("telegram.updates.count", metrics.DefaultRegistry)
	StatsUpdateDuration      = metrics.NewRegisteredTimer("telegram.updates.duration", metrics.DefaultRegistry)
	StatsSendMessageDuration = metrics.NewRegisteredTimer("telegram.sendMessage.duration", metrics.DefaultRegistry)
	StatsMsgTimeoutCount     = metrics.NewRegisteredCounter("telegram.sendMessage.timeout", metrics.DefaultRegistry)
	StatsMsgFailedCount      = metrics.NewRegisteredCounter("telegram.sendMessage.failed", metrics.DefaultRegistry)
	StatsMsgDiscardedCount   = metrics.NewRegisteredCounter("telegram.sendMessage.discarded", metrics.DefaultRegistry)
	StatsMsgDroppedCount     = metrics.NewRegisteredCounter("telegram.sendMessage.dropped", metrics.DefaultRegistry)
)

Metrics for telegram

View Source
var Log = func(record LogRecord) {}

Log function that will be called for logging. By default it's null logger, client can override this to implement their logging of their choice

View Source
var TChatTypeMap = map[string]ChatType{
	"private":    Private,
	"group":      Group,
	"supergroup": SuperGroup,
	"channel":    Channel,
}

TChatTypeMap maps betwwen string to bot.ChatType

Functions

func TelegramEscape added in v0.2.0

func TelegramEscape(s string) string

TelegramEscape escapes html that is acceptable by telegram noinspection GoUnusedExportedFunction

Types

type Attachment added in v0.2.0

type Attachment struct {
	Fallback string `json:"fallback"`
	Text     string `json:"text"`
	Pretext  string `json:"pretext"`
	Title    string `json:"title"`
	ID       int64  `json:"id"`
}

type ChannelMigratedMessage

type ChannelMigratedMessage struct {
	FromID     string
	ToID       string
	ReceivedAt time.Time
	Raw        json.RawMessage `json:"-"`
}

ChannelMigratedMessage represents that a chat type has been upgraded. Currently works on telegram

type Chat

type Chat struct {
	ID       string
	Type     ChatType
	Title    string
	Username string
}

Chat represents a chat session

func (Chat) Name added in v0.2.0

func (t Chat) Name() string

Name returns the title of the bot

type ChatInfo added in v0.2.0

type ChatInfo struct {
	ID          string
	Type        ChatType
	Title       string
	Topic       string
	Description string
}

type ChatType

type ChatType string

ChatType is type of the message

const (
	Channel    ChatType = "channel"
	Group      ChatType = "group"
	Private    ChatType = "private"
	SuperGroup ChatType = "supergroup"
	Thread     ChatType = "thread"
)

Available ChatType

type Client added in v0.2.0

type Client interface {
	// AddPlugins will add each plugin as middleware, each message will flow to the Handle for each plugin unless
	// previous plugin return handled equals true
	AddPlugins(...Plugin) error
	// Start listening for new messages and block
	Start(context.Context) error
	// UserName of the bot
	UserName() string
	//Mentioned will return true filed is a mention to a user
	Mentioned(field string) bool
	// Mention a user
	Mention(user User) string
	// UserByName find user by username
	UserByName(username string) (User, bool)
	// Get chat information such as topic etc
	ChatInfo(ctx context.Context, chatID string) (ChatInfo, error)
	// SetTopic for a channel
	SetTopic(ctx context.Context, chatID, topic string) error
	// UploadFile to a channel
	UploadFile(ctx context.Context, chatID string, filename string, r io.Reader) error
	// Get all replies to a threaded message
	ThreadReplies(ctx context.Context, chat Chat, threadID string) ([]*Message, error)
	// Get Permanent link of a message
	MessagePermalink(ctx context.Context, msg *Message) (string, error)
	// Fetch Private Image that needs authentication
	FetchImage(ctx context.Context, fileURL string) (io.ReadCloser, error)
	// SendMessage
	SendMessage(ctx context.Context, msg Message)
}

Client represent a chat client. Currently supports telegram

type ErrorLevel added in v0.2.1

type ErrorLevel int
const (
	Error ErrorLevel = iota
	Info
	Warn
	Debug
)

Error level in order of value Error < Info < Warn < Debug

type File added in v0.3.0

type File struct {
	Id        string
	Name      string
	Mimetype  string
	Filetype  string
	Url       string
	UrlPublic string
	To        []FileAddress
	From      []FileAddress
	PlainText string `json:"plain_text"`
}

type FileAddress added in v0.3.0

type FileAddress struct {
	Address  string `json:"address"`
	Name     string `json:"name"`
	Original string `json:"original"`
}

type JoinMessage added in v0.2.0

type JoinMessage struct {
	*Message
}

JoinMessage represents information that a user join a chat

type LeftMessage added in v0.2.0

type LeftMessage struct {
	*Message
}

LeftMessage represents information that a user left a chat

type LogRecord added in v0.2.1

type LogRecord struct {
	Message string
	Level   ErrorLevel
}

func (LogRecord) String added in v0.2.1

func (l LogRecord) String() string

type Message

type Message struct {
	ID              string
	From            User
	Date            time.Time
	Chat            Chat
	Text            string
	Format          MessageFormat
	ReplyTo         *Message
	ReplyToID       string
	ReceivedAt      time.Time
	Attachments     []Attachment
	Files           []File
	PreviousMessage *Message        // if message was edited, this is original message
	Raw             json.RawMessage `json:"-"`
	Retry           int             `json:"-"`
	DiscardAfter    time.Time       `json:"-"`
	// contains filtered or unexported fields
}

Message represents chat message

func (*Message) Context added in v0.2.0

func (m *Message) Context() context.Context

func (*Message) WithContext added in v0.2.0

func (m *Message) WithContext(ctx context.Context) *Message

type MessageFormat

type MessageFormat string

MessageFormat represents formatting of the message

const (
	Text     MessageFormat = ""
	Markdown MessageFormat = "markdown"
	HTML     MessageFormat = "html"
)

Available MessageFormat

type Plugin

type Plugin interface {
	Name() string
	Init(ctx context.Context, out chan Message, cl Client) error
	Handle(ctx context.Context, in interface{}) (handled bool, msg interface{})
}

Plugin is pluggable module to process messages

type Slack added in v0.2.0

type Slack struct {
	// contains filtered or unexported fields
}

func NewSlack added in v0.2.0

func NewSlack(token string) (*Slack, error)

func (*Slack) AddPlugins added in v0.2.0

func (s *Slack) AddPlugins(plugins ...Plugin) error

func (*Slack) ChatInfo added in v0.2.0

func (s *Slack) ChatInfo(ctx context.Context, chatID string) (ChatInfo, error)

func (*Slack) EmulateReceiveMessage added in v0.2.0

func (s *Slack) EmulateReceiveMessage(raw []byte) error

func (*Slack) FetchImage added in v0.4.0

func (s *Slack) FetchImage(_ context.Context, fileURL string) (io.ReadCloser, error)

func (*Slack) Mention added in v0.2.0

func (s *Slack) Mention(u User) string

func (*Slack) Mentioned added in v0.2.0

func (s *Slack) Mentioned(field string) bool
func (s *Slack) MessagePermalink(ctx context.Context, msg *Message) (string, error)

func (*Slack) ParseRawMessage added in v0.3.0

func (s *Slack) ParseRawMessage(rawMsg []byte) (*Message, error)

func (*Slack) SendMessage added in v0.5.4

func (s *Slack) SendMessage(ctx context.Context, msg Message)

func (*Slack) SetTopic added in v0.2.0

func (s *Slack) SetTopic(ctx context.Context, chatID string, topic string) error

func (*Slack) Start added in v0.2.0

func (s *Slack) Start(ctx context.Context) error

func (*Slack) ThreadReplies added in v0.4.0

func (s *Slack) ThreadReplies(ctx context.Context, chat Chat, threadID string) ([]*Message, error)

func (*Slack) UploadFile added in v0.2.0

func (s *Slack) UploadFile(ctx context.Context, chatID string, filename string, r io.Reader) error

func (*Slack) UserByName added in v0.2.1

func (s *Slack) UserByName(username string) (User, bool)

func (*Slack) UserName added in v0.2.0

func (s *Slack) UserName() string

type TChat

type TChat struct {
	Type  string `json:"type"`
	Title string `json:"title"`
	TUser
}

TChat represents Telegram chat session

type TChatMember added in v0.2.0

type TChatMember struct {
	User   TUser `json:"user"`
	Status string
}

TChatMember represent user membership of a group

type TError added in v0.2.0

type TError struct {
	ErrorCode   int64  `json:"error_code,omitempty"`
	Description string `json:"description"`
}

TError error response structure

func (TError) Error added in v0.2.0

func (t TError) Error() string

type TMessage

type TMessage struct {
	MessageID       int64           `json:"message_id"`
	From            TUser           `json:"from"`
	Date            int64           `json:"date"`
	Chat            TChat           `json:"chat"`
	Text            string          `json:"text"`
	ParseMode       string          `json:"parse_mode,omitempty"`
	MigrateToChatID *int64          `json:"migrate_to_chat_id,omitempty"`
	ReplyTo         *TMessage       `json:"reply_to_message,omitempty"`
	NewChatMember   *TUser          `json:"new_chat_member,omitempty"`
	LeftChatMember  *TUser          `json:"left_chat_member,omitempty"`
	ReceivedAt      time.Time       `json:"-"`
	Raw             json.RawMessage `json:"-"`
}

TMessage is Telegram incomming message

func (*TMessage) ToMessage added in v0.2.0

func (m *TMessage) ToMessage() *Message

ToMessage converts TMessage to *bot.Message

func (*TMessage) ToMigratedMessage added in v0.2.0

func (m *TMessage) ToMigratedMessage() ChannelMigratedMessage

ToMigratedMessage converts Telegram Message to bot.ChannelMigratedMessage

type TOutMessage

type TOutMessage struct {
	ChatID           string `json:"chat_id"`
	Text             string `json:"text"`
	ParseMode        string `json:"parse_mode,omitempty"`
	ReplyToMessageID *int64 `json:"reply_to_message_id,omitempty"`
}

TOutMessage is Telegram outgoing message

type TResponse

type TResponse struct {
	Ok     bool            `json:"ok"`
	Result json.RawMessage `json:"result,omitempty"`
	TError
}

TResponse represents response from telegram

type TUpdate

type TUpdate struct {
	UpdateID int64           `json:"update_id"`
	Message  json.RawMessage `json:"message"`
}

TUpdate represents an update event from telegram

type TUser

type TUser struct {
	ID        int64  `json:"id"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Username  string `json:"username"`
}

TUser is Telegram User

func (TUser) ToUser added in v0.2.0

func (u TUser) ToUser() User

ToUser converts to bot.User

type Telegram

type Telegram struct {
	// contains filtered or unexported fields
}

Telegram API

func NewTelegram

func NewTelegram(ctx context.Context, key string) (*Telegram, error)

NewTelegram creates telegram API Client noinspection GoUnusedExportedFunction

func (*Telegram) AddPlugins added in v0.2.0

func (t *Telegram) AddPlugins(plugins ...Plugin) error

AddPlugin add processing module to telegram

func (*Telegram) Chat added in v0.2.0

func (t *Telegram) Chat(ctx context.Context, id string) (*TChat, error)

Chat gets chat information based on chatID

func (*Telegram) ChatInfo added in v0.2.0

func (t *Telegram) ChatInfo(ctx context.Context, chatID string) (ChatInfo, error)

func (*Telegram) FetchImage added in v0.4.0

func (t *Telegram) FetchImage(ctx context.Context, fileURL string) (io.ReadCloser, error)

func (*Telegram) Kick added in v0.2.0

func (t *Telegram) Kick(ctx context.Context, chatID, userID string) error

Kick userID from chatID

func (*Telegram) Leave

func (t *Telegram) Leave(ctx context.Context, chatID string) error

Leave a chat

func (*Telegram) Member added in v0.2.0

func (t *Telegram) Member(ctx context.Context, chatID, userID string) (*TChatMember, error)

Member check if userID is member of chatID

func (*Telegram) MembersCount added in v0.2.0

func (t *Telegram) MembersCount(ctx context.Context, chatID string) (int, error)

MembersCount gets the counts of member for a chat id

func (*Telegram) Mention added in v0.2.0

func (t *Telegram) Mention(u User) string

func (*Telegram) Mentioned added in v0.2.0

func (t *Telegram) Mentioned(field string) bool
func (t *Telegram) MessagePermalink(ctx context.Context, msg *Message) (string, error)

func (*Telegram) SendMessage added in v0.5.4

func (t *Telegram) SendMessage(ctx context.Context, msg Message)

func (*Telegram) SetTopic added in v0.2.0

func (t *Telegram) SetTopic(ctx context.Context, chatID string, topic string) error

func (*Telegram) Start

func (t *Telegram) Start(ctx context.Context) error

Start consuming from telegram

func (*Telegram) Stop added in v0.2.0

func (t *Telegram) Stop()

func (*Telegram) ThreadReplies added in v0.4.0

func (t *Telegram) ThreadReplies(ctx context.Context, chat Chat, threadID string) ([]*Message, error)

func (*Telegram) Unban added in v0.2.0

func (t *Telegram) Unban(ctx context.Context, chatID, userID string) error

Unban userID from chatID

func (*Telegram) UploadFile added in v0.2.0

func (t *Telegram) UploadFile(ctx context.Context, chatID string, filename string, r io.Reader) error

func (*Telegram) UserByName added in v0.2.1

func (t *Telegram) UserByName(username string) (User, bool)

func (*Telegram) UserName added in v0.2.0

func (t *Telegram) UserName() string

Username returns bot's username

type User

type User struct {
	ID        string
	FirstName string
	LastName  string
	Username  string
}

User represents user information

func (User) FullName

func (u User) FullName() string

FullName returns first name + last name

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL