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

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