grug

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2021 License: MIT Imports: 14 Imported by: 0

README

grug

Grug is a customizable Discord bot with composable and pluggable commands that are loaded as configurations at runtime.

Grug commands

Grug commands consist of 4 parts:

  • A name - A descriptive name of the command
  • A description - A description of the command and how to use it
  • Activators - A list of ways to invoke the command
  • A command plan - A list of actions or conditionals

When a command is invoked using one of its activators, Grug executes the command plan sequentially.

Templating

Grug features simple templating to access stored values and user arguments. All templated values start with ! followed by either a name (for stored values) or a number (for user arguments).

Example template User args Store Output
Your first arg was !1 hello world Your first arg was hello
Your first arg was !1 "hello world" Your first arg was hello world
!food is !2 foo good food: "cake" cake is good
Actions

Actions are the base unit of Grug. They are (preferrably simple) tasks that may or may not take arguments, and may or may not produce output. Action output may be stored in named fields, and a failure plan may be specified as a plan to be executed when the action fails.

Actions are implemented in code as reusable components for composing commands.

action: Plus # Action for adding the two arguments together
args:
  - "!1" # Use the first user supplied argument as an action argument for Plus
  - "!2" # Use the second user supplied argument as an action argument for Plus
store: plus_result # Store the result of the Plus action in the field "plus_result"
Conditionals

Conditionals are fancy wrappers for an action execution where the result determines which plan should be executed.

For a list of available conditionals see conditional_actions.go

if:
  condition: int> # int> is just a normal action that returns a bool
  args:
    - !1
    - 2
  true: # The plan to execute if user arg #1 > 2
    ...
  false: # The plan to execute if user arg #1 <= 2
    ...
Failure handling

If a plan fails to execute normally, indicated by the action returning an error from its Exec implementation, and a failure plan is configured, the failure plan is executed in its entirety before the next action in the plan is executed.

The haltOnFailure option may also be set to true to abort command execution if the action fails. If a failure plan is specified, it will be executed before the command halts.

- action: GetCommandMessageID
  store: msgID
- action: GetLastMediaMessageIDAroundID
  args:
    - "!msgID"
  store: mediaMsgID
  haltOnFailure: true # Halt command execution if this action fails
  failurePlan: # The plan to execute if this action fails
    - action: Reply
      args:
        - "Couldn't find any messages with media :/"
...
Example

For more examples, see example/commands.

name: "Calculator" # Command name
desc: "Perform some simple calculation" # Command description
activators: # List of ways to invoke the command
  - "calc"
plan: # Actions are executed sequentially according to the plan
  - action: Plus # Add arg 1 and arg 2 together
    args:
      - "!1" # Use the first user supplied argument as an action argument for Plus
      - "!2" # Use the second user supplied argument as an action argument for Plus
    store: plus_result # Store the result of the Plus action
  - action: Reply # Reply in the same channel that the message was sent from
    args:
      - "!1 + !2 = !plus_result"
  - if: # Conditionally perform one of two action sequences
      condition: int> # The name of the conditional action to use for evaluating the condition
      args: # Operands/arguments to the conditional action
        - "!plus_result"
        - 100
      true: # Action sequence to perform if the condition was true
        - action: Reply
          args:
            - "wow that number was really big"
      false: # Action sequence to perform if the condition was false
        - action: Reply
          args:
            - "that number was kinda small"

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AllActions []Action

AllActions holds all actions that can be used by Grug

Functions

func ParseArgs

func ParseArgs(cfgArgs []interface{}, usrArgs []string) ([]interface{}, error)

ParseArgs parses templated values and inserts their respective actual values

func PurgeArgStore

func PurgeArgStore()

PurgeArgStore clears the arg store by recreating it

func StoreArg

func StoreArg(name string, val interface{}) error

StoreArg stores the given value in the given field in an arg store

Types

type Action

type Action struct {
	Name string                                                  // Name of the action
	Exec func(*GrugSession, ...interface{}) (interface{}, error) // Function that executes the action
}

Action is any named task

type ActionActivator

type ActionActivator struct {
	ActionName  string             `yaml:"action"`        // Name of the action to execute
	Arguments   []interface{}      `yaml:"args"`          // Arguments taken by the action and their type
	Store       string             `yaml:"store"`         // If set, the result of the action is stored in a field with this name
	FailurePlan *ActionSequence    `yaml:"failurePlan"`   // An action sequence to perform if this step fails during execution
	HaltOnFail  bool               `yaml:"haltOnFailure"` // Whether or not to halt command execution on failure of this step
	Conditional *ConditionalAction `yaml:"if"`            // If set, this activator is considered an conditional and will instead alter flow of the sequence
}

ActionActivator is a YAML-(un)marshallable struct for storing the name of and arguments for an action

type ActionSequence

type ActionSequence []ActionActivator

ActionSequence is a list of action activations to be performed in sequential order

type Command

type Command struct {
	Name        string         `yaml:"name"`       // Descriptive name of the command
	Description string         `yaml:"desc"`       // Description of the command
	Activators  []string       `yaml:"activators"` // A list of ways to invoke the command
	Plan        ActionSequence `yaml:"plan"`       // The action sequence to perform when the command is invoked
}

Command represents an invokable Grug command and holds its activators and execution plan

type ConditionalAction

type ConditionalAction struct {
	ActionName    string         `yaml:"condition"` // Name of the action performing the conditional
	Arguments     []interface{}  `yaml:"args"`      // Arguments taken by the conditional action
	TrueSequence  ActionSequence `yaml:"true"`      // The action sequence to perform when the condition evaluates to true
	FalseSequence ActionSequence `yaml:"false"`     // The action sequence to perform when the condition evaluates to false
}

ConditionalAction represents a conditional part of an action sequence. Performs no action, but determines which action sequence is taken after evaluation

type GrugConfig

type GrugConfig struct {
	Name     string   `yaml:"name"`     // Name of the bot
	Token    string   `yaml:"token"`    // Discord Bot Token to use
	Invoker  string   `yaml:"invoker"`  // The command prefix that invokes grug
	Commands []string `yaml:"commands"` // A list of paths to command config files
	Verbose  bool     `yaml:"verbose"`  // Whether or not to use verbose logging
}

GrugConfig holds the master configuration values for a Grug session

type GrugSession

type GrugSession struct {
	Config         *GrugConfig              // The Grug master config
	Commands       []Command                // All loaded commands
	Actions        []Action                 // All actions used by Grug
	ActivatorMap   map[string]Command       // Uniquely maps command name to Command struct
	ActionMap      map[string]Action        // Uniquely maps action name to Action struct
	DiscordSession *discordgo.Session       // The underlying Discord session
	CurrentCommand *discordgo.MessageCreate // The message command that is currently being executed
}

GrugSession holds all information relevant to the operation of Grug

func (*GrugSession) Close

func (g *GrugSession) Close()

Close closes the Discord session associated with the Grug session

func (*GrugSession) ConstructActionMap

func (g *GrugSession) ConstructActionMap()

ConstructActionMap takes a list of actions and constructs a map from each action's name to their respective action struct

func (*GrugSession) ConstructActivatorMap

func (g *GrugSession) ConstructActivatorMap() error

ConstructActivatorMap takes a list of commands and constructs a map from each command's activators to their respective command Returns an error if two commands have conflicting activators

func (*GrugSession) LoadCommands

func (g *GrugSession) LoadCommands() error

LoadCommands loads the commands specified by the master config

func (*GrugSession) LoadMasterConfig

func (g *GrugSession) LoadMasterConfig(cfgPath string) error

LoadMasterConfig loads the master grug config into the grug session

func (*GrugSession) Log

func (g *GrugSession) Log(level int, logMsg ...interface{})

Log prints a log message tagged with "GRUG" and the log level

func (*GrugSession) New

func (g *GrugSession) New(cfgPath string)

New sets up a Grug session by parsing its master config, loading commands and establishing a Discord session

func (*GrugSession) PerformAction

func (g *GrugSession) PerformAction(activator ActionActivator, userArgs []string) error

PerformAction performs an action given an activator for the function and any user supplied arguments

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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