drc

package module
v0.0.0-...-b1846a3 Latest Latest
Warning

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

Go to latest
Published: Mar 27, 2022 License: MIT Imports: 17 Imported by: 7

README

DRCgo

An early alpha Command handler for discord go

Documentation

Overview

Package drc is an early alpha command router and middleware for discordgo its primary function is handling certain tasks like permissions checks, argument parsing, and finding and executing command functions

Index

Constants

View Source
const (
	ErrorUnknown d2ErrTypes = iota
	ErrorDenied
	ErrorFailure
	ErrorParsing
)

Const values / enum containing internal error types

View Source
const Library = "drc.go"

Library is the name of the library

View Source
const Version = "v0.5.4 alpha"

Version is the version of the library

Variables

This section is empty.

Functions

func BitwiseDescriptionGen

func BitwiseDescriptionGen(n map[int64]string, b int64) []string

BitwiseDescriptionGen takes a map containing the names to go with each bitwise permission, and an int containing a set of bits, and it outputs a string array containing each entry of n that is located in b (using a bitwise AND comparison)

func DisableSubcommands

func DisableSubcommands(s ...string) map[string]trit.Trit

DisableSubcommands takes a list of any amount of subcommands and generates a map of trits containing them To be used as an alterative to using map[string]trit.Trit{"command1": 1, "command2": 1} in Command.SubcommandToggle

func FindFlag

func FindFlag(args []string, name string) (pos int, addition string)

FindFlag finds if the flag signaled by name is located in args using a syntax where a flag is prefixed with either - or -- if it comes across an entry in args that is solely "--" it will halt returning -2, if the flag contains : or = it will return an additional argument containing the contents after that

func GetErrorType

func GetErrorType(err error) (bool, string)

GetErrorType returns whether or not the error is a d2cmd error, as well as its d2cmd type

func IsDenied

func IsDenied(err error) bool

IsDenied tells you if an error is a permission denied type

func IsFailure

func IsFailure(err error) bool

IsFailure tells you if an error is a Failure type

func IsParsingError

func IsParsingError(err error) bool

IsParsingError tells you if an error is a parsing error type

func NewDenied

func NewDenied(payload error, message string, details ...interface{}) error

NewDenied returns a new error with a 'permission denied' designation

func NewFailure

func NewFailure(payload error, message string, details ...interface{}) error

NewFailure returns a new error with a 'failure' designation

func NewParseError

func NewParseError(payload error, message string, details ...interface{}) error

NewParseError returns a new error with a 'parsing error' designation

func ParseArgflags

func ParseArgflags(args []string, flags map[string]string) (remainder []string, out map[string]Argument, err error)

ParseArgflags works similarly to ParseBoolflags except instead of booleans it returns a map of arguments (strings with the parsing methods from parse)

func ParseBoolflags

func ParseBoolflags(args []string, flags map[string]bool) (remainder []string, out map[string]bool, err error)

ParseBoolflags takes a list of arguments, and a list of flags with a default state and searches through the args to find all flags which are specified it returns a remainder that no longer contains those flags, and a map containing all the flag states

func ParseChannel

func ParseChannel(s *discordgo.Session, channel, guild string) (*discordgo.Channel, error)

ParseChannel takes a string and attempts to find a channel that matches that string

func ParseMember

func ParseMember(s *discordgo.Session, member, guild string) (*discordgo.Member, error)

ParseMember takes a string and attempts to find a member that matches that string

func ParseRole

func ParseRole(s *discordgo.Session, role, guild string) (*discordgo.Role, error)

ParseRole takes a string and attempts to find a role that matches that string

func PermissionCheck

func PermissionCheck(perms, required int64) int64

PermissionCheck determines if a user has the specified permissions if all required permissions are present it will return 0, else it will return the bits of the missing permissions

func PermissionCheckChannel

func PermissionCheckChannel(s *discordgo.Session, userID, channelID string, permissions int64) (bool, int64, error)

PermissionCheckChannel checks to make sure a user has the required permissions to do an action in a specific channel

func PermissionCheckGuild

func PermissionCheckGuild(s *discordgo.Session, userID, guildID string, permissions int64) (bool, int64, error)

PermissionCheckGuild is used for checking a user has required guild level permissions

func PermissionsGetGuild

func PermissionsGetGuild(s *discordgo.Session, guildID, userID string) (perms int64, err error)

PermissionsGetGuild grabs the permission bits from all of a users roles

func RemDash

func RemDash(args []string) []string

RemDash searches and removes the first instance of `--` NOTE: this is only public for testing and may be removed in the future

Types

type ActOn

type ActOn struct {
	Error   trit.Trit // Act if a command or the handler runs into an error
	Denied  trit.Trit // Act if a user is lacking permissions to run a command, or a command returns a permission denied error
	Failure trit.Trit // Act if a command returns an error type stating that the command failed for some reason
	Success trit.Trit // Act if a command succeeds

	// SendRawErrorContent Is ignored for ReactOn
	// This determines if it should send the raw error data
	SendRawErrorContent trit.Trit
}

ActOn is a type containing some configuration for whether it should act or react on a certain event

type ActionReactions

type ActionReactions struct {
	Error   string
	Parser  string
	Denied  string
	Failure string
	Success string
}

ActionReactions is a type containing the emotes to use for the ReactOn cases Must be set with a discord API ready emote string

type Argument

type Argument struct {
	Raw string

	// currently only used for flags, determines if a flag is set or not
	IsSet bool
}

Argument specified a type used for command arguments containing a raw string and some various parsing methods

func (Argument) Bool

func (a Argument) Bool() (bool, error)

Bool parses the argument into int64 form, returns an error if an error occours

func (Argument) Channel

func (a Argument) Channel(ctx *Context) (*discordgo.Channel, bool, error)

Channel attempts to locate a channel using the data specified in the argument the boolean argument specifies if its marked as set for flags, this can be ignored for arguments but is important for flags as defaults may not be able to be relied on for dynamic data

func (Argument) Duration

func (a Argument) Duration() (time.Duration, error)

Duration parses the argument into int64 form, returns an error if an error occours

func (Argument) Float64

func (a Argument) Float64() (float64, error)

Float64 parses the argument into int64 form, returns an error if an error occours

func (Argument) Int

func (a Argument) Int() (int, error)

Int parses the argument into int form, returns an error if an error occours

func (Argument) Int64

func (a Argument) Int64() (int64, error)

Int64 parses the argument into int64 form, returns an error if an error occours

func (Argument) Member

func (a Argument) Member(ctx *Context) (*discordgo.Member, bool, error)

Member attempts to locate a member using the data specified in the argument the boolean argument specifies if its marked as set for flags, this can be ignored for arguments but is important for flags as defaults may not be able to be relied on for dynamic data

func (Argument) Role

func (a Argument) Role(ctx *Context) (*discordgo.Role, bool, error)

Role attempts to locate a role using the data specified in the argument the boolean argument specifies if its marked as set for flags, this can be ignored for arguments but is important for flags as defaults may not be able to be relied on for dynamic data

func (Argument) String

func (a Argument) String() (string, error)

func (Argument) Uint

func (a Argument) Uint() (uint, error)

Uint parses the argument into uint form, returns an error if an error occours

func (Argument) Uint64

func (a Argument) Uint64() (uint64, error)

Uint64 parses the argument into uint64 form, returns an error if an error occours

type BotAllowState

type BotAllowState uint8

BotAllowState is a setting type for noting whether or not bots should be able to run commands

const (
	BotAllowNone BotAllowState = iota
	// BotAllowLetList // TODO
	BotAllowAllExceptWebhooks
	BotAllowAll
	BotAllowOnlyExceptWebhooks
	BotAllowOnly
)

The various states of whether or not

type CfgCommand

type CfgCommand struct {
	// Whether or not the command should be listed in the command list
	Listable bool
	// Whether or not bots can run this command
	AllowBots BotAllowState
	// Whether or not the command should be DMs or Guild Only
	DMSettings CommandDMConfig

	// Whether or not to React on or Reply on certain events such as errors
	ReactOn ActOn
	ReplyOn ActOn

	// whether or not to enable the definable automatically added subcommands
	SubcommandToggle map[string]trit.Trit

	// boolean flags are used for toggles are parsed in advance and they only take up the flag itself
	// bool flags are configured with a default state, if used in a command it will be the inverse of the default
	// however you may also specify the value when calling them via doing -b=true or -bol:true (anything after = or : must be valid to be parsed by strconv.ParseBool() )
	BoolFlags map[string]bool

	// Data flags function more like arguments, they are read and removed from the arguments on parsetime and can be found in context.Flags
	// however they are not typed and must be parsed in command time similar to arguments, like with boolflags you can give it a default to use if it is not added into a command
	DataFlags map[string]string

	// The minimum number of arguments that must be passed in order for the command to be executed
	MinimumArgs int
}

CfgCommand is a type containing the various command specific settings

type CfgHandler

type CfgHandler struct {
	Prefixes []string
	Manual   []string
	Admins   []string
	Name     string

	// disable the ability to use an @mention as a command prefix for the bot
	DisableMentionAsPrefix bool

	// Whether or not to React on or Reply on certain events such as errors
	// These can be overrided on a per command level
	ReactOn ActOn
	ReplyOn ActOn

	// The Emotes to use for ReactOn Events
	ReactionEmotes ActionReactions

	// Default permissions to apply to *all* commands
	DefaultPermissions Permissions

	// PanicLog as an optional addition for logging panics (it will always log to stderr regardless)
	PanicLogger PanicLog

	// Logger is used for setting the interface which to log internal events to
	Logger Logging
	// LogDebug is whether or not to also log debug and trace stuff
	LogDebug bool

	// Add subcommands which will by default be added to all commands by default
	// Which then can be disabled on a command by command bases via Command.SubcommandToggle
	DefaultSubcommands []Command

	// The templates to send error messages with per the specifications of the stdlib text/template package.
	// {{.Error}} for the embeded payload error if applicable or the raw error if not applicable,
	// {{.RawError}} for the Raw error message,
	// {{.Details}} for extra details (such as the exact permissions missing in a permission error),
	// {{.Description}} for the embedded error message if applicable or the same as error if not applicable,
	// {{.HasExtras}} contains whether or not it has the extras from a d2cmd error,
	// {{.Msg}} is a substruct containing the full message create event,
	// {{.Msg.Author.String}} for a representation of the users username,
	// {{if .Cfg.SendRawErrorContent.Bool}} can be used to add an if to include the full raw error content
	ErrorTemplates struct {
		ParserError string
		Denied      string
		Failure     string
		Error       string
	}

	// The names the permission name generator will use for each permission, the key is the bitwise bit of the permission, see discordgo docs for the list of all permission bits
	PermissionNames map[int64]string

	// Use custom implementations of the built in ctx.Reply methods
	GenericReply func(session *discordgo.Session, targetChannel string, message string) (*discordgo.Message, error)
}

CfgHandler is a type containing some configuration and settings for the handler

type Command

type Command struct {
	Name        string   // Command name
	Manual      []string // Command Help / documentation
	Description string   // (**DEPRECATED** use page 0 of Manual instead) A small description of a commands purpose

	Config CfgCommand // Config Settings

	Permissions Permissions // Permission Settings for what settings it will expect users to have

	CommandPerms int64 // The perms the bot requires itself to have in order to execute

	AliasPointer *Command // Pointer based alias
	AliasText    []string // Text based alias, can add arguments via this method

	Subcommands CommandMap // The list of subcommands

	Exec func(*Context) error // The function to be executed

	Parent *Command // The parent command if this is a subcommand (note that this primarily exists for the "help" commands and should not be relied on otherwise)
	// contains filtered or unexported fields
}

Command is a struct containing all the various thingies for commands

func (Command) Perms

func (c Command) Perms() Permissions

Perms returns the modified state of the permissions after initialisation

func (Command) Settings

func (c Command) Settings() CfgCommand

Settings Returns the Modified state of the config after initialisation

type CommandDMConfig

type CommandDMConfig uint8

CommandDMConfig is a setting type for if commands should be able to be used in DMs

const (
	// CommandDMsAndGuild : Allow in both DMs and guilds, Default
	CommandDMsAndGuild CommandDMConfig = iota
	// CommandDMsBlock : Only allow in guilds, disabled in DMs
	CommandDMsBlock
	// CommandDMsOnly : Only allow in DMs, disabled in guilds
	CommandDMsOnly
)

type CommandListStructure

type CommandListStructure struct {
	Name        string
	Description string
	Permissions Permissions
	SubLists    []CommandListStructure
}

CommandListStructure describes a type that contains a name, some extra properties and a list of subentries, used by CommandMap.ListRecursiveStructured()

type CommandMap

type CommandMap struct {
	Map map[string]*Command
}

CommandMap is the central type used for storing commands

func (*CommandMap) Add

func (cm *CommandMap) Add(cmd *Command) *Command

Add adds a command to the map

func (*CommandMap) AddAliasPointer

func (cm *CommandMap) AddAliasPointer(name string, to *Command) *Command

AddAliasPointer adds an alias command which aliases to a pointer

func (*CommandMap) AddAliasString

func (cm *CommandMap) AddAliasString(name string, to ...string) *Command

AddAliasString adds an alias command which aliases to a string

func (*CommandMap) AddBulk

func (cm *CommandMap) AddBulk(cmds []*Command)

AddBulk adds an array of commands onto the current command

func (*CommandMap) List

func (cm *CommandMap) List(listAll bool) []string

List lists all commands on this commandmap, 1st argument defines whether or not it should ignore commands not set to be listable

func (*CommandMap) ListRecursive

func (cm *CommandMap) ListRecursive(listAll bool, maxDepth int, prefix bool) []string

ListRecursive lists all commands and subcommands on this commandmap 1st argument defines whether or not it should ignore commands not set to be listable, 2nd argument specifies the max layers of depth (if set below 1 it'll go forever until an int overflow eventually brings it to 0) 3rd argument tells it what to prefix with, false will have it prefixed with a variable amount of "- "s, true will have it prefixed by the command names

func (*CommandMap) ListRecursiveStructured

func (cm *CommandMap) ListRecursiveStructured(listAll bool, maxDepth int) []ListStructure

ListRecursiveStructured is like ListStructured but without any of the extra details, note that this may not stick around in later releases, and just exists as a lazy way to fetch a command list to throw into a formatter function

func (*CommandMap) ListStructured

func (cm *CommandMap) ListStructured(listAll bool, maxDepth int) []CommandListStructure

ListStructured lists all commands and subcommands on this commandmap returning the data in a structured fromat 1st argument defines whether or not it should ignore commands not set to be listable, 2nd argument specifies the max layers of depth (if set below 1 it'll go forever until an int overflow eventually brings it to 0)

type Context

type Context struct {
	Args    []Argument // Args contains the arguments passed after the command
	RawArgs []string   // Args contains all arguments passed after the command but in raw string form
	AllArgs []string   // RawArgs contains all arguments, including the commands that would be stripped away in Context.Args

	BoolFlags map[string]bool     // Boolean toggle flags
	Flags     map[string]Argument // Data flags that function similarly to arguments

	CommandPath []string // The path to the command which was just executed

	Ses *discordgo.Session
	Mes *discordgo.MessageCreate
	Han *Handler
	Com *Command
}

Context is a struct that contains many helper functions and data for use in commands

func (Context) DumpReply

func (c Context) DumpReply(title string, text ...interface{}) (err error)

DumpReply is used for dumping a large amount of text, usually for debug purposes, it encases the content in a discord code block and if its length is greater than 2000 it splits it into multiple messages at linebreaks, NOTE that if a single line is greater than 2000 characters it will still error from being too long

func (Context) DumpReplyf

func (c Context) DumpReplyf(title, layout string, text ...interface{}) error

DumpReplyf is like DumpReply except it uses fmt.Sprintf logic instead of fmt.Sprint logic

func (Context) Print

func (c Context) Print(txt ...interface{}) error

Print creates a simple reply in the channel which spawned this context

func (Context) Reply

func (c Context) Reply(txt ...interface{}) error

Reply creates a reply in the channel which spawned this context

func (Context) ReplyEmbed

func (c Context) ReplyEmbed(embed *discordgo.MessageEmbed) error

ReplyEmbed creates an embed reply in the channel which spawned this context

func (Context) Replyf

func (c Context) Replyf(layout string, txt ...interface{}) error

Replyf creates a reply in the channel which spawned this context using the same logic as fmt.Sprintf for formatting

func (Context) XPrint

func (c Context) XPrint(txt ...interface{}) (*discordgo.Message, error)

XPrint creates a simple reply in the channel which spawned this context and returns the message object of the sent message

func (Context) XReply

func (c Context) XReply(txt ...interface{}) (*discordgo.Message, error)

XReply creates a reply in the channel which spawned this context and returns the message object of the sent message

func (Context) XReplyEmbed

func (c Context) XReplyEmbed(embed *discordgo.MessageEmbed) (*discordgo.Message, error)

XReplyEmbed creates an embed reply in the channel which spawned this context and returns the message object of the sent message

func (Context) XReplyf

func (c Context) XReplyf(layout string, txt ...interface{}) (*discordgo.Message, error)

XReplyf creates a reply in the channel which spawned this context and returns the message object of the sent message using the same logic as fmt.Sprintf for formatting

type DefaultLogger

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

DefaultLogger is a default implementation for the logger To be rewritten with a better logger in the future

func NewDefaultLogger

func NewDefaultLogger(timeformat string) *DefaultLogger

NewDefaultLogger returns an instance of the default logger

func (DefaultLogger) Error

func (l DefaultLogger) Error(in ...interface{})

Error logs info of type error to stderr

func (DefaultLogger) Info

func (l DefaultLogger) Info(in ...interface{})

Info logs info of type info to stdout

type FetcherData

type FetcherData struct {
	Args   []string // Normal command arguments
	PreArg []string // Arguments that come before a command in cases like ( !command argument subcommand )
	Path   []string // The full path to a command
	// contains filtered or unexported fields
}

FetcherData contains the various argument types to be returned by the fetcher

type Handler

type Handler struct {
	Config CfgHandler

	ServerPrefixes map[string]*[]string

	Commands CommandMap
	// contains filtered or unexported fields
}

Handler is the central type that encompasses everything

func NewHandler

func NewHandler(config CfgHandler, s *discordgo.Session) *Handler

NewHandler returns a new handler for you to use

func (*Handler) BotPermissionCheck

func (h *Handler) BotPermissionCheck(s *discordgo.Session, channelID string, permissions int64) (bool, int64, error)

BotPermissionCheck checks if the bot has the required permissions in a certain channel

func (*Handler) CheckAlias

func (h *Handler) CheckAlias(cmd *Command) (*Command, FetcherData)

CheckAlias checks if a command is an alias to another command, returning the command object if so, returning nil if not

func (*Handler) CheckPrefix

func (h *Handler) CheckPrefix(content, guild string) (length int)

CheckPrefix checks whether or not a string of text contains any of the known/set prefixes on a specified guild, returning the length of the prefix if so, and returning -1 if it does not contain any prefix

func (*Handler) CommandPermissionCheck

func (h *Handler) CommandPermissionCheck(s *discordgo.Session, m *discordgo.MessageCreate, p Permissions) (bool, int64, error)

CommandPermissionCheck checks if a user in a message create event has the required permissions to run a command

func (*Handler) FetchCommand

func (h *Handler) FetchCommand(List CommandMap, data FetcherData) (*Command, FetcherData)

FetchCommand recursively checks down the list of arguments to figure out which command is referenced in the chain of arguments It returns the furthest down valid command in the chain, and the remainder arguments, doupper if set to true will make it case sentitive (by default it ToLowers the key when it checks it) this is used internally in the alias handler so that commands defined with uppercase symbols are only accessable via aliases

func (*Handler) IsReady

func (h *Handler) IsReady() bool

IsReady Returns whether or not Handler.Ready has been called

func (*Handler) IsUserBotAdmin

func (h *Handler) IsUserBotAdmin(userID string) bool

IsUserBotAdmin Determines if a user is in the bots whitelisted list of 'bot admins'

func (*Handler) OnMessage

func (h *Handler) OnMessage(s *discordgo.Session, m *discordgo.MessageCreate) (err error)

OnMessage is the primary entry point function for the message and command routing functionality This should be placed somewhere in the MessageCreate handler for discordgo

func (*Handler) OnMessageWithCheck

func (h *Handler) OnMessageWithCheck(s *discordgo.Session, m *discordgo.MessageCreate) (ok bool, err error)

OnMessageWithCheck is the same as OnMessage, except it also returns if a command has been ran

func (*Handler) PermissionDescriptionGen

func (h *Handler) PermissionDescriptionGen(p int64) []string

PermissionDescriptionGen generates a string array containing all the permissions given in p using the names in handler.Config.PermissionNames

func (*Handler) Ready

func (h *Handler) Ready() (err error)

Ready finalises the settings for operation. This method must be called after everything is added but before the connection to discord

func (*Handler) ServerPrefixesAdd

func (h *Handler) ServerPrefixesAdd(server, prefix string)

ServerPrefixesAdd appends a new server prefix

func (*Handler) ServerPrefixesExists

func (h *Handler) ServerPrefixesExists(server string) bool

ServerPrefixesExists checks if a custom prefixes list has been initialised for a server

func (*Handler) ServerPrefixesGet

func (h *Handler) ServerPrefixesGet(server string) []string

ServerPrefixesGet returns the list of prefixes on a specified server

func (*Handler) ServerPrefixesGetAll

func (h *Handler) ServerPrefixesGetAll(server string) (prefixes map[string][]string)

ServerPrefixesGetAll returns all set server prefixes

func (*Handler) ServerPrefixesInit

func (h *Handler) ServerPrefixesInit(server string)

ServerPrefixesInit initialises custom prefixes on a server, making it use a copy of the defaults instead of the defaults

func (*Handler) ServerPrefixesRemove

func (h *Handler) ServerPrefixesRemove(server, prefix string)

ServerPrefixesRemove removes a prefix from a server prefixes list

func (*Handler) ServerPrefixesSet

func (h *Handler) ServerPrefixesSet(server string, prefixes []string)

ServerPrefixesSet sets the server prefixes to a custom list of prefixes Note that you will need to implement a method of storing and loading custom prefixes yourself

func (*Handler) ServerPrefixesSetBulk

func (h *Handler) ServerPrefixesSetBulk(list map[string][]string)

ServerPrefixesSetBulk allows you to set server prefixes in bulk

type ListStructure

type ListStructure struct {
	Name     string
	SubLists []ListStructure
}

ListStructure is like CommandListStructure but without any of the extra details, note that this may not stick around in later releases

type Logging

type Logging interface {
	Info(...interface{})
	Error(...interface{})
}

Logging is the interface used for the handler logging

type PanicLog

type PanicLog interface {
	Print(stack string, msg interface{})
}

PanicLog as an optional addition for logging panics (it will always log to stderr regardless)

type Permissions

type Permissions struct {
	BotAdmin       trit.Trit // Whether or not to require a user being in the configured admin letlist
	Discord        int64     // Discord permissions to require the user to *globally* have (channel overrides excluded)
	DiscordChannel int64     // Discord permissions to require the user have within the channel that command was run in
}

Permissions is a type defining some various permission requirements

Notes

Bugs

  • custom server prefixes are currently untested TODO? Replace custom prefix system with an interface as to allow the bot to handle managing them instead of having an internal list that has to be saved and loaded in bulk

Directories

Path Synopsis
Package subpresets contains some presets and premade 'default' subcommands for DRC 0.X These can be added to the handler.Config.DefaultSubcommands array where they'll be automatically added to all commands at init time They can also be excluded from being added from certain commands via Command.SubcommandToggle Note these commands are designed to be used as subcommands, see the other presets package for root level commands
Package subpresets contains some presets and premade 'default' subcommands for DRC 0.X These can be added to the handler.Config.DefaultSubcommands array where they'll be automatically added to all commands at init time They can also be excluded from being added from certain commands via Command.SubcommandToggle Note these commands are designed to be used as subcommands, see the other presets package for root level commands

Jump to

Keyboard shortcuts

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