router.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package mux
  2. import (
  3. "errors"
  4. "strings"
  5. "github.com/sirupsen/logrus"
  6. "git.mgmcomp.net/thisnthat/discordgo"
  7. )
  8. // RouteOptions holds information about a specific message route handler
  9. type RouteOptions struct {
  10. Name string // match name that should trigger this route handler
  11. Description string // short description of this route
  12. Usage string // How to use the route
  13. Category string // The category to put the route under
  14. Type RouteType // The type of route this is
  15. Callback Handler // route handler function to call
  16. }
  17. type route struct {
  18. Name string
  19. Description string
  20. Usage string
  21. CategoryID int
  22. Type RouteType
  23. Run Handler
  24. }
  25. type category struct {
  26. Name string
  27. Description string
  28. ID int
  29. }
  30. // RouteType is the type of route being created
  31. type RouteType int
  32. const (
  33. // MessageRoute is a route for handling OnMessageCreate events
  34. MessageRoute RouteType = 1001
  35. )
  36. // Handler is the function signature required for a message route handler.
  37. type Handler func(*discordgo.Session, *discordgo.Message, *Context)
  38. // Context holds a bit of extra data we pass along to route handlers
  39. // This way processing some of this only needs to happen once.
  40. type Context struct {
  41. Fields []string
  42. Content string
  43. isDirectMessage bool // Indicates the message was sent via direct message
  44. Method Method
  45. }
  46. // Method is the method a command was received
  47. type Method int
  48. const (
  49. // DirectMethod Discord DM to the bot
  50. DirectMethod Method = 1001
  51. // MentionMethod is a message started with a @mention to the bot
  52. MentionMethod Method = 1002
  53. // PrefixMethod is a message started with a command prefix
  54. PrefixMethod Method = 1003
  55. )
  56. // Router is the main struct for all mux methods.
  57. type Router struct {
  58. routes []*route
  59. helpRoute *route
  60. prefix string
  61. categories []*category
  62. }
  63. // New returns a new Discord message route mux
  64. func New() *Router {
  65. r := &Router{}
  66. helpRoute := &route{}
  67. helpRoute.Name = "help"
  68. helpRoute.Usage = "help"
  69. helpRoute.Description = "Get Help"
  70. helpRoute.Run = r.helpCommandHandler
  71. r.helpRoute = helpRoute
  72. return r
  73. }
  74. // SetCommandPrefix will set the prefix used for message commands
  75. func (r *Router) SetCommandPrefix(cmdPrefix string) {
  76. r.prefix = cmdPrefix + " "
  77. }
  78. // ErrRegisterRouteNameRequired is returned when registering a new route without a name
  79. var ErrRegisterRouteNameRequired = errors.New("All routes must have a name")
  80. // ErrRegisterInvalidRouteType is returned when registering a new route with an invalid type
  81. var ErrRegisterInvalidRouteType = errors.New("Invalid route type")
  82. // ErrRegisterCallbackRequired is returned when registering a new route without a callback
  83. var ErrRegisterCallbackRequired = errors.New("A valid callback must be provided")
  84. // Register allows you to register a route
  85. //func (r *Router) Register(routeType RouteType, name, desc string, callback Handler) (*Route, error) {
  86. func (r *Router) Register(name string, options RouteOptions) error {
  87. if name == "" {
  88. return ErrRegisterRouteNameRequired
  89. }
  90. if !isValidRouteType(options.Type) {
  91. return ErrRegisterInvalidRouteType
  92. }
  93. if options.Callback == nil {
  94. return ErrRegisterCallbackRequired
  95. }
  96. route := route{}
  97. route.Type = options.Type
  98. route.Name = name
  99. route.Description = options.Description
  100. route.Usage = options.Usage
  101. route.Run = options.Callback
  102. if options.Category != "" {
  103. for _, category := range r.categories {
  104. if category.Name == options.Category {
  105. route.CategoryID = category.ID
  106. break
  107. }
  108. }
  109. }
  110. r.routes = append(r.routes, &route)
  111. return nil
  112. }
  113. // ErrAddCategoryNameRequired is returned when registering a new route without a name
  114. var ErrAddCategoryNameRequired = errors.New("All categories must have a name")
  115. // AddCategory allows you to a a router category
  116. func (r *Router) AddCategory(name, description string) error {
  117. if name == "" {
  118. return ErrAddCategoryNameRequired
  119. }
  120. category := category{}
  121. category.Name = name
  122. category.Description = description
  123. category.ID = len(r.categories) + 1
  124. r.categories = append(r.categories, &category)
  125. return nil
  126. }
  127. func isValidRouteType(routeType RouteType) bool {
  128. switch routeType {
  129. case MessageRoute:
  130. return true
  131. }
  132. return false
  133. }
  134. func (r *Router) findRoute(searchString string, routeType RouteType) (*route, []string) {
  135. logrus.Printf("Find Route: %s", searchString)
  136. fields := strings.Fields(searchString)
  137. if len(fields) == 0 {
  138. logrus.Printf("No route Found")
  139. return nil, nil
  140. }
  141. commandKey := fields[0]
  142. for _, route := range r.routes {
  143. if route.Type != routeType {
  144. continue
  145. }
  146. if strings.ToLower(commandKey) == strings.ToLower(route.Name) {
  147. logrus.Printf("Route Found: %s", route.Name)
  148. return route, fields[0:]
  149. }
  150. }
  151. return nil, nil
  152. }