package mux import ( "errors" "strings" "github.com/sirupsen/logrus" "git.mgmcomp.net/thisnthat/discordgo" ) // RouteOptions holds information about a specific message route handler type RouteOptions struct { Name string // match name that should trigger this route handler Description string // short description of this route Usage string // How to use the route Category string // The category to put the route under Type RouteType // The type of route this is Callback Handler // route handler function to call } type route struct { Name string Description string Usage string CategoryID int Type RouteType Run Handler } type category struct { Name string Description string ID int } // RouteType is the type of route being created type RouteType int const ( // MessageRoute is a route for handling OnMessageCreate events MessageRoute RouteType = 1001 ) // Handler is the function signature required for a message route handler. type Handler func(*discordgo.Session, *discordgo.Message, *Context) // Context holds a bit of extra data we pass along to route handlers // This way processing some of this only needs to happen once. type Context struct { Fields []string Args []string Content string isDirectMessage bool // Indicates the message was sent via direct message Method Method } // Method is the method a command was received type Method int const ( // DirectMethod Discord DM to the bot DirectMethod Method = 1001 // MentionMethod is a message started with a @mention to the bot MentionMethod Method = 1002 // PrefixMethod is a message started with a command prefix PrefixMethod Method = 1003 ) // Router is the main struct for all mux methods. type Router struct { routes []*route helpRoute *route prefix string categories []*category } // New returns a new Discord message route mux func New() *Router { r := &Router{} helpRoute := &route{} helpRoute.Name = "help" helpRoute.Usage = "help" helpRoute.Description = "Get Help" helpRoute.Run = r.helpCommandHandler r.helpRoute = helpRoute return r } // SetCommandPrefix will set the prefix used for message commands func (r *Router) SetCommandPrefix(cmdPrefix string) { r.prefix = cmdPrefix + " " } // ErrRegisterRouteNameRequired is returned when registering a new route without a name var ErrRegisterRouteNameRequired = errors.New("All routes must have a name") // ErrRegisterInvalidRouteType is returned when registering a new route with an invalid type var ErrRegisterInvalidRouteType = errors.New("Invalid route type") // ErrRegisterCallbackRequired is returned when registering a new route without a callback var ErrRegisterCallbackRequired = errors.New("A valid callback must be provided") // Register allows you to register a route //func (r *Router) Register(routeType RouteType, name, desc string, callback Handler) (*Route, error) { func (r *Router) Register(name string, options RouteOptions) error { if name == "" { return ErrRegisterRouteNameRequired } if !isValidRouteType(options.Type) { return ErrRegisterInvalidRouteType } if options.Callback == nil { return ErrRegisterCallbackRequired } route := route{} route.Type = options.Type route.Name = name route.Description = options.Description route.Usage = options.Usage route.Run = options.Callback if options.Category != "" { for _, category := range r.categories { if category.Name == options.Category { route.CategoryID = category.ID break } } } r.routes = append(r.routes, &route) return nil } // ErrAddCategoryNameRequired is returned when registering a new route without a name var ErrAddCategoryNameRequired = errors.New("All categories must have a name") // AddCategory allows you to a a router category func (r *Router) AddCategory(name, description string) error { if name == "" { return ErrAddCategoryNameRequired } category := category{} category.Name = name category.Description = description category.ID = len(r.categories) + 1 r.categories = append(r.categories, &category) return nil } func isValidRouteType(routeType RouteType) bool { switch routeType { case MessageRoute: return true } return false } func (r *Router) findRoute(searchString string, routeType RouteType) (*route, []string, []string) { logrus.Printf("Find Route: %s", searchString) fields := strings.Fields(searchString) if len(fields) == 0 { logrus.Printf("No route Found") return nil, nil, nil } commandKey := fields[0] for _, route := range r.routes { if route.Type != routeType { continue } if strings.ToLower(commandKey) == strings.ToLower(route.Name) { logrus.Printf("Route Found: %s", route.Name) return route, fields[0:], fields[1:] } } return nil, nil, nil }