criuscommander

package module
v2.5.0 Latest Latest
Warning

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

Go to latest
Published: Nov 24, 2021 License: BSD-3-Clause Imports: 15 Imported by: 0

README

Crius Commander v2

Usage

  1. Install with go get gitlab.com/crius-bots/criuscommander/v2
  2. Make a map[criuscommander.PlatformType]string to hold your access tokens
    • This should look like below
      tokens := map[criuscommander.PlatformType]string{
       criuscommander.PlatformDiscord: os.Getenv("discord_token")
      }
      
  3. Init the bot with criuscommander.NewCommander, passing in a *criuscommander.CCConfig
    • Unless you're using a custom loader (see loaders), pass criuscommander.DefaultLoaderChain (or nothing at all if you're not using the loader system)
    • Pass any platforms you want to use into Platforms, i.e. Platforms: []criuscommander.Platform{discord.New()}
    • If you have plugins you want to load automatically (recommended) then set AutoloadPlugins to true
      • note that this will not do anything unless you pass loaders in as above.
    • Optionally pass a context as the second parameter. This is useful if you have a struct you want to share like a database or permissions checking functions
  4. Call .Open() when you're ready to connect
    • note that Open does not block.
  5. Call .Close() when you're finished.

Writing Plugins

First, make a folder for your plugin, in there, create a file called plugin.json.

If your editor supports it, I would recommend setting the file's JSON schema to this repo's schema.json

Fill the data in for the plugin. You may have to provide a plugin type, which Commander uses to pick which loader to use.[^1] Refer to the documentation for the loader for this value. You will also have to supply the supported platforms. If you are only supporting one platform, just use its number. If you are supporting many, add all the numbers up and Commander will make sure only the correct platforms call your plugin functions.

The values for each platform are provided below and in platforms.go

You will also have to make an entry in plugin.json for every command.

  • Name and Help are self-explanatory
  • Supported_platforms is the same as above. Useful if you have one command in a plugin that only supports one of the plugin's platforms
  • Activator is what users will use after the prefix to call your command. i.e. Help's activator is "help"
  • handler_name is used to map commands in this file to compiled functions.

Once you've written your plugin, put both the code for the loader and the plugin.json in a folder called plugins/[pluginname].

The code that you provide will depend on the loader (and even if you're using one or not). If you are using a loader, refer to its documentation for what to ship.

If you're manually loading plugins (see below), use a function which takes a context.Context and returns a map[string]criuscommander.CommandHandler and an error (unless you're doing something spectacular you can hardcode this to nil). This map should have the handler_name as the key and then the function you wish to call as the value.

[^1]: You don't have to fill this field if you're loading plugins through SetupPluginFromConfig, which is the recommended way of doing so currently.

Using Plugins

If you're using a loader, all you have to do is pass it into Loaders in config and set AutoloadPlugins to true.

If you're manually loading, call (*Commander).SetupPluginFromConfig, passing in a function (see Writing Plugins) and a config

The Native Loader

Note that the native loader uses Go plugins which do not support Windows yet
I would strongly advise against using this, as Go is incredibly picky about plugins and versioning, plugin authors are advised to just publish their source and consumers are advised to import

To compile your plugin for the native loader, first ensure the package at the top of every file for the plugin is main. This is a restriction of Go's Plugin code.

You will need a Setup function which takes a context.Context and returns a map[string]criuscommander.CommandHandler and an error (unless you're doing something spectacular you can hardcode this to nil). This map should have the handler_name as the key and then the function you wish to call as the value.

The functions you make should have the signature FunctionName (*criuscommander.MessageContext, []string) error where the second parameter is the args, split per utils.ArgsSplitter

When you've written your functions, you need to build as a go plugin, which can be done by using go build -buildmode=plugin.

Context

The context you pass into NewCommander is augmented with every loaded platform's client (by their Platform.ToString()) (this means that you can get direct access to DiscordGo to do reactions, for example.), a reference to the event bus (see below), and the OtherConfig map you passed into (under name config)

Events

This is useful if you need to subscribe to a certain library's events, i.e. DiscordGo's OnReactionAdd.

You can do this by getting bus from context and casting it to EventBus.BusSubscriber and then calling .Subscribe() with a string (which will be provided by the platform), and a function

Platform Support

  • [1] Discord
  • [2] Glimesh
  • [4] Twitch

Other platforms will come in the future (including Guilded as soon as their bot API launches.)

Youtube will not be supported until they add an actually usable chat API (ie. websockets, because I'm not polling.)

Loaders

Loaders are a way of implementing different ways of setting up a plugin, or to even embed a scripting language for use in commands.
Included is a deprecated loader that uses Go's Plugin system.

Due to restrictions with Go's plugin system, Windows is not supported when using the native loader.

To implement your own loader, see loader.go which contains the interface.

Documentation

Index

Constants

View Source
const (
	EventCommanderClose = "commander:close"
	MaxDepth            = 8
)

Variables

View Source
var DefaultLoaderChain = []LoaderFactory{}

Functions

func ArgsSplitter

func ArgsSplitter(in string) []string

Types

type CCConfig

type CCConfig struct {
	Platforms       []Platform
	Prefix          string
	AutoloadPlugins bool
	PluginLoaders   []LoaderFactory
	Tokens          map[PlatformType]string
	OtherConfig     map[string]interface{}

	// Where supported, join these channels when commander starts
	AutoJoinChannels map[PlatformType][]interface{}
}

type Command

type Command struct {
	Handler     CommandHandler
	Info        *PJCommand
	Subcommands map[string]*Command
}

type CommandGroupContainer

type CommandGroupContainer struct {
	Commands map[string]*Command
	Info     *PluginJSON
}

type CommandHandler

type CommandHandler func(*MessageContext, []string) error

type Commander

type Commander struct {
	OnError func(error)

	// returning false *will stop execution*
	GuardBeforeCommandCheck func(*MessageContext, string, []string) bool
	// returning false *will stop execution*
	GuardBeforeCommandExec func(*MessageContext, string, []string) bool
	GuardPostCommandCheck  func(*MessageContext, string, []string)
	// contains filtered or unexported fields
}

func NewCommander

func NewCommander(config *CCConfig, ctx context.Context) (*Commander, error)

Make a new instance of a commander.

func (*Commander) Close

func (c *Commander) Close()

Stop the commander & discord

func (*Commander) GetCommandGroups

func (c *Commander) GetCommandGroups() map[string]*CommandGroupContainer

func (*Commander) GetCommands

func (c *Commander) GetCommands() map[string]*Command

func (*Commander) HandleError

func (c *Commander) HandleError(f func(error))

func (*Commander) Help

func (c *Commander) Help(m *MessageContext, args []string) error

func (*Commander) JoinChannel

func (c *Commander) JoinChannel(platform PlatformType, channel interface{}) error

func (*Commander) LeaveChannel

func (c *Commander) LeaveChannel(platform PlatformType, channel interface{}) error

func (*Commander) Open

func (c *Commander) Open() error

func (*Commander) RegisterCommand deprecated

func (c *Commander) RegisterCommand(groupName string) func(info *PJCommand, handler CommandHandler) error

Deprecated: RegisterCommand does not support subcommands. Do not use it directly.

func (*Commander) SendMessage

func (c *Commander) SendMessage(platform PlatformType, channelID interface{}, message interface{}) (interface{}, error)

func (*Commander) SetupPlugin deprecated

func (c *Commander) SetupPlugin(setup func(RegisterCommand, context.Context), info *PluginJSON)

Deprecated: With the move to loaders, this no longer works properly and you may have to faff for it to work. Use the new loader system. Register the plugin into the list of 'groups' (read: plugins)

func (*Commander) SetupPluginFromConfig

func (c *Commander) SetupPluginFromConfig(setup func(ctx context.Context) (map[string]CommandHandler, error), info *PluginJSON) error

type GetCommandHandler

type GetCommandHandler func(string) (CommandHandler, error)

type GetPlugin

type GetPlugin func(string) (interface{}, error)

type Loader

type Loader interface {
	LoadPlugin(string) error
	GetCommandHandler(string) (CommandHandler, error)
}

type LoaderFactory

type LoaderFactory interface {
	GetTypeName() PluginType

	// We pass context in here just in case you need to build some stuff up (the native loader does)
	New(context.Context) Loader
}

type Message

type Message struct {
	RealmID string
	Author  MessageUser
}

type MessageContext

type MessageContext struct {
	PlatformData interface{}
	Context      context.Context
	Message
}

func (*MessageContext) Send

func (m *MessageContext) Send(message interface{}) (interface{}, error)

func (*MessageContext) SendTo

func (m *MessageContext) SendTo(channelID interface{}, message interface{}) (interface{}, error)

type MessageUser

type MessageUser struct {
	ID       string
	Username string

	IsMod      func() bool
	IsStreamer func() bool
}

type NativeLoader

type NativeLoader struct {
	Context context.Context
	// contains filtered or unexported fields
}

func (*NativeLoader) GetCommandHandler

func (n *NativeLoader) GetCommandHandler(name string) (CommandHandler, error)

func (*NativeLoader) LoadPlugin

func (n *NativeLoader) LoadPlugin(name string) error

type NewNativeLoader

type NewNativeLoader struct{}

func (*NewNativeLoader) GetTypeName

func (n *NewNativeLoader) GetTypeName() PluginType

func (*NewNativeLoader) New

func (n *NewNativeLoader) New(ctx context.Context) Loader

type PJCommand

type PJCommand struct {
	Name               string
	Activator          string
	Help               string
	HandlerName        string       `json:"handler_name"`
	SupportedPlatforms PlatformType `json:"supported_platforms"`
	Subcommands        []*PJCommand
}

type Platform

type Platform interface {
	// The string here will be a token (since that's what most platforms use)
	Setup(string) error

	GetPlatformType() PlatformType

	// sometimes we have a need to access the underlying funcs for a platform (i.e. DiscordGo's Session.State)
	GetClient() interface{}

	// Register events with your library like OnServerJoin or OnMemberJoin or the like.
	// The events from your library should be passed through EventBus using BusPublisher.Publish
	RegisterEvents(EventBus.BusPublisher) error
	RegisterMessageHandler(func(string, *MessageContext)) error

	// Begin the connection.
	// Context is passed so that you can store it and pass it down to events
	Open(context.Context) error

	// Close the connection.
	// Fire off *your* close event, but not a EventCommanderClose.
	Close() error

	// Allow each platform to generate its own help messages (i.e. discord can use embeds, twitch can send a link &c.)
	// The interface will be a map[string]*Command or a map[string]*CommandGroupContainer depending on the passed param
	GenHelp(interface{}, *MessageContext) error

	// Join another channel by the given name/id/whatever.
	JoinChannel(interface{}) error

	// Leave a channel with given name/id
	LeaveChannel(interface{}) error
}

type PlatformType

type PlatformType uint
const (
	PlatformDiscord PlatformType = 1 << iota
	PlatformGlimesh
	PlatformTwitch
)

func (PlatformType) ToString

func (pt PlatformType) ToString() string

type PluginJSON

type PluginJSON struct {
	Name               string
	Creator            string
	License            string
	URL                string `json:"url"`
	Description        string
	PluginType         PluginType   `json:"plugin_type"`
	SupportedPlatforms PlatformType `json:"supported_platforms"`
	Commands           []*PJCommand
	HideInHelp         bool `json:"hide_in_help"`
}

type PluginType

type PluginType string
const NativePluginLoader PluginType = "uk.co.rpgpn.crius.commander.loader:native"

type RegisterCommand

type RegisterCommand func(*PJCommand, CommandHandler) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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