Browse Source

Added the ability to group routes into categories

Mathew Medoff 4 years ago
parent
commit
99171377ed
2 changed files with 142 additions and 5 deletions
  1. 98 2
      bot/event/mux/help.go
  2. 44 3
      bot/event/mux/router.go

+ 98 - 2
bot/event/mux/help.go

@@ -20,6 +20,102 @@ func (r *Router) helpCommandHandler(s *discordgo.Session, m *discordgo.Message,
 		displayPrefix = fmt.Sprintf("@%s ", s.State.User.Username)
 	}
 
+	maxDisplayLen := 0
+	cmdmap := make(map[string]*route)
+	catMap := make(map[string][]string)
+	var cats []string
+
+	for _, v := range r.categories {
+		keys := make([]string, 0, len(r.routes))
+		for _, route := range r.routes {
+			if route.CategoryID == v.ID {
+				l := len(route.Usage) // TODO: Add the +args part :)
+				if l > maxDisplayLen {
+					maxDisplayLen = l
+				}
+				cmdmap[route.Name] = route
+				keys = append(keys, route.Name)
+			}
+		}
+
+		if len(keys) > 0 {
+			sort.Strings(keys)
+			catMap[v.Description] = keys
+			cats = append(cats, v.Description)
+		}
+	}
+
+	keys := make([]string, 0, len(r.routes))
+	for _, route := range r.routes {
+		if route.CategoryID == 0 {
+			l := len(route.Usage) // TODO: Add the +args part :)
+			if l > maxDisplayLen {
+				maxDisplayLen = l
+			}
+			cmdmap[route.Name] = route
+
+			if route.Name == "help" || route.Name == "about" {
+				continue
+			}
+
+			keys = append(keys, route.Name)
+		}
+	}
+
+	v, ok := cmdmap["help"]
+	if ok {
+		keys = append([]string{v.Name}, keys...)
+	}
+
+	v, ok = cmdmap["about"]
+	if ok {
+		keys = append([]string{v.Name}, keys...)
+	}
+
+	if len(keys) > 0 {
+		sort.Strings(keys)
+		catMap[""] = keys
+		cats = append(cats, "")
+	}
+
+	maxDisplayLen = maxDisplayLen + 3
+
+	// TODO: Learn more link needs to be configurable
+	resp := "```autoit\n"
+
+	// Add sorted result to help msg
+	for _, catKey := range cats {
+		if catKey != "" {
+			resp += fmt.Sprintf("\n%s\n", catKey)
+		} else {
+			resp += fmt.Sprint("\n\n")
+		}
+
+		routes := catMap[catKey]
+		for _, routeKey := range routes {
+			route := cmdmap[routeKey]
+			resp += fmt.Sprintf("%s%-"+strconv.Itoa(maxDisplayLen)+"s # %s\n", displayPrefix, route.Usage, route.Description)
+		}
+	}
+
+	resp += "```\n"
+	s.ChannelMessageSend(m.ChannelID, resp)
+
+	return
+}
+
+func (r *Router) helpCommandHandlerOld(s *discordgo.Session, m *discordgo.Message, ctx *Context) {
+	displayPrefix := ""
+
+	switch ctx.Method {
+	case DirectMethod:
+		displayPrefix = ""
+	case PrefixMethod:
+		displayPrefix = r.prefix
+	case MentionMethod:
+		displayPrefix = fmt.Sprintf("@%s ", s.State.User.Username)
+	}
+
 	// Sort commands
 	maxDisplayLen := 0
 	keys := make([]string, 0, len(r.routes))
@@ -32,7 +128,7 @@ func (r *Router) helpCommandHandler(s *discordgo.Session, m *discordgo.Message,
 		}
 
 		// Calculate the max length of command+args string
-		l := len(v.Name) // TODO: Add the +args part :)
+		l := len(v.Usage) // TODO: Add the +args part :)
 		if l > maxDisplayLen {
 			maxDisplayLen = l
 		}
@@ -65,7 +161,7 @@ func (r *Router) helpCommandHandler(s *discordgo.Session, m *discordgo.Message,
 	// Add sorted result to help msg
 	for _, k := range keys {
 		v := cmdmap[k]
-		resp += fmt.Sprintf("%s%-"+strconv.Itoa(maxDisplayLen)+"s # %s\n", displayPrefix, v.Name, v.Description)
+		resp += fmt.Sprintf("%s%-"+strconv.Itoa(maxDisplayLen)+"s # %s\n", displayPrefix, v.Usage, v.Description)
 	}
 
 	resp += "```\n"

+ 44 - 3
bot/event/mux/router.go

@@ -13,6 +13,8 @@ import (
 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
 }
@@ -20,10 +22,18 @@ type RouteOptions struct {
 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
 
@@ -58,9 +68,10 @@ const (
 
 // Router is the main struct for all mux methods.
 type Router struct {
-	routes    []*route
-	helpRoute *route
-	prefix    string
+	routes     []*route
+	helpRoute  *route
+	prefix     string
+	categories []*category
 }
 
 // New returns a new Discord message route mux
@@ -69,6 +80,7 @@ func New() *Router {
 
 	helpRoute := &route{}
 	helpRoute.Name = "help"
+	helpRoute.Usage = "help"
 	helpRoute.Description = "Get Help"
 	helpRoute.Run = r.helpCommandHandler
 
@@ -110,12 +122,41 @@ func (r *Router) Register(name string, options RouteOptions) error {
 	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: