You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

command.go 2.0KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "strings"
  8. "time"
  9. "github.com/spf13/viper"
  10. "github.com/thoj/go-ircevent"
  11. )
  12. func (i *IRCCat) handleCommand(event *irc.Event) {
  13. msg := event.Message()
  14. channel := ""
  15. respond_to := event.Arguments[0]
  16. if i.inChannel(respond_to) {
  17. channel = respond_to
  18. } else {
  19. respond_to = event.Nick
  20. if !i.authorisedUser(event.Nick) {
  21. log.Infof("Unauthorised command: %s (%s) %s", event.Nick, respond_to, msg)
  22. return
  23. }
  24. }
  25. log.Infof("Authorised command: %s (%s) %s", event.Nick, respond_to, msg)
  26. parts := strings.SplitN(msg, " ", 2)
  27. args := ""
  28. if len(parts) > 1 {
  29. args = parts[1]
  30. }
  31. handler := viper.GetString("commands.handler")
  32. if handler != "" {
  33. cmd := exec.Command(handler)
  34. cmd.Env = append(os.Environ(), fmt.Sprintf("IRCCAT_NICK=%s", event.Nick),
  35. fmt.Sprintf("IRCCAT_USER=%s", event.User),
  36. fmt.Sprintf("IRCCAT_HOST=%s", event.Host),
  37. fmt.Sprintf("IRCCAT_CHANNEL=%s", channel),
  38. fmt.Sprintf("IRCCAT_RESPOND_TO=%s", respond_to),
  39. fmt.Sprintf("IRCCAT_COMMAND=%s", parts[0][1:]),
  40. fmt.Sprintf("IRCCAT_ARGS=%s", args),
  41. fmt.Sprintf("IRCCAT_RAW=%s", event.Raw))
  42. i.runCommand(cmd, respond_to)
  43. }
  44. }
  45. // Run a command with the output going to the nick/channel identified by respond_to
  46. func (i *IRCCat) runCommand(cmd *exec.Cmd, respond_to string) {
  47. var out bytes.Buffer
  48. cmd.Stdout = &out
  49. cmd.Stderr = &out
  50. err := cmd.Run()
  51. if err != nil {
  52. log.Errorf("Running command %s failed: %s", cmd.Args, err)
  53. i.irc.Privmsgf(respond_to, "Command failed: %s", err)
  54. }
  55. lines := strings.Split(out.String(), "\n")
  56. line_count := len(lines)
  57. if line_count > viper.GetInt("commands.max_response_lines") {
  58. line_count = viper.GetInt("commands.max_response_lines")
  59. }
  60. for _, line := range lines[0:line_count] {
  61. if line != "" {
  62. // 360 bytes is the worst-case maximum size for PRIVMSG lines. Truncate the lines at that length.
  63. if len(line) > 360 {
  64. line = line[:360]
  65. }
  66. i.irc.Privmsg(respond_to, line)
  67. }
  68. // Pause between lines to avoid being flooded out
  69. time.Sleep(250)
  70. }
  71. }