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

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package main
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/irccloud/go-ircevent"
  6. "github.com/spf13/viper"
  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 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. cmd := exec.Command(viper.GetString("commands.handler"))
  32. cmd.Env = append(os.Environ(), fmt.Sprintf("IRCCAT_NICK=%s", event.Nick),
  33. fmt.Sprintf("IRCCAT_USER=%s", event.User),
  34. fmt.Sprintf("IRCCAT_HOST=%s", event.Host),
  35. fmt.Sprintf("IRCCAT_CHANNEL=%s", channel),
  36. fmt.Sprintf("IRCCAT_RESPOND_TO=%s", respond_to),
  37. fmt.Sprintf("IRCCAT_COMMAND=%s", parts[0][1:]),
  38. fmt.Sprintf("IRCCAT_ARGS=%s", args),
  39. fmt.Sprintf("IRCCAT_RAW=%s", event.Raw))
  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. }