Mirror of github.com/gissleh/irc
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.

121 lines
3.6 KiB

  1. package handlers
  2. import (
  3. "strings"
  4. "github.com/gissleh/irc"
  5. "github.com/gissleh/irc/ircutil"
  6. )
  7. // MRoleplay is a handler that adds commands for cutting NPC commands, as well as cleaning up
  8. // the input from the server. It's named after Charybdis IRCd's m_roleplay module.
  9. func MRoleplay(event *irc.Event, client *irc.Client) {
  10. switch event.Name() {
  11. case "input.enablerp", "input.disablerp":
  12. {
  13. sign := "+"
  14. if event.Verb() == "disablerp" {
  15. sign = "-"
  16. }
  17. // If the target is a channel, use RPCHAN or, if not stated, N.
  18. chanMode, chanModeOk := client.ISupport().Get("RPCHAN")
  19. channel := event.ChannelTarget()
  20. if channel != nil {
  21. if chanModeOk {
  22. client.SendQueuedf("MODE %s %s%s", channel.Name(), sign, chanMode)
  23. } else {
  24. client.SendQueuedf("MODE %s %sN", channel.Name(), sign)
  25. }
  26. }
  27. // Otherwise enable it on yourself, but only if RPUSER is set as that is not supported.
  28. // by servers without this ISupport tag.
  29. userMode, userModeOk := client.ISupport().Get("RPUSER")
  30. query := event.QueryTarget()
  31. status := event.StatusTarget()
  32. if (query != nil || status != nil) && userModeOk {
  33. client.SendQueuedf("MODE %s%s", sign, userMode)
  34. }
  35. }
  36. // Parse roleplaying messages, and replace underscored-nick with a render tag.
  37. case "packet.privmsg", "ctcp.action":
  38. {
  39. // Detect m_roleplay
  40. if strings.HasPrefix(event.Nick, "\x1F") {
  41. event.Nick = event.Nick[1 : len(event.Nick)-2]
  42. if event.Verb() == "PRIVMSG" {
  43. event.RenderTags["mRoleplay"] = "npc"
  44. } else {
  45. event.RenderTags["mRoleplay"] = "npca"
  46. }
  47. } else if strings.HasPrefix(event.Nick, "=") {
  48. event.RenderTags["mRoleplay"] = "scene"
  49. } else {
  50. break
  51. }
  52. // Some servers use this.
  53. lastSpace := strings.LastIndex(event.Text, " ")
  54. lastParentheses := strings.LastIndex(event.Text, "(")
  55. if lastParentheses != -1 && lastSpace != -1 && lastParentheses == lastSpace+1 {
  56. event.Text = event.Text[:lastSpace]
  57. }
  58. }
  59. // NPC commands
  60. case "input.npcc", "input.npcac":
  61. {
  62. isAction := event.Verb() == "npcac"
  63. nick, text := ircutil.ParseArgAndText(event.Text)
  64. if nick == "" || text == "" {
  65. client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /"+event.Verb()+" <nick> <text...>", "usage_"+event.Verb(), nil))
  66. break
  67. }
  68. channel := event.ChannelTarget()
  69. if channel == nil {
  70. client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Target is not a channel", "target_not_channel", nil))
  71. break
  72. }
  73. overhead := ircutil.MessageOverhead("\x1f"+nick+"\x1f", client.Nick(), "npc.fakeuser.invalid", channel.Name(), isAction)
  74. cuts := ircutil.CutMessage(text, overhead)
  75. for _, cut := range cuts {
  76. npcCommand := "NPC"
  77. if isAction {
  78. npcCommand = "NPCA"
  79. }
  80. client.SendQueuedf("%s %s %s :%s", npcCommand, channel.Name(), nick, cut)
  81. }
  82. event.PreventDefault()
  83. }
  84. // Scene/narrator command
  85. case "input.scenec", "input.narratorc":
  86. {
  87. if event.Text == "" {
  88. client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Usage: /"+event.Verb()+" <text...>", "usage_"+event.Verb(), nil))
  89. break
  90. }
  91. channel := event.ChannelTarget()
  92. if channel == nil {
  93. client.EmitNonBlocking(irc.NewErrorEventTarget(event.Target(), "input", "Target is not a channel", "target_not_channel", nil))
  94. break
  95. }
  96. overhead := ircutil.MessageOverhead("=Scene=", client.Nick(), "npc.fakeuser.invalid", channel.Name(), false)
  97. cuts := ircutil.CutMessage(event.Text, overhead)
  98. for _, cut := range cuts {
  99. client.SendQueuedf("SCENE %s :%s", channel.Name(), cut)
  100. }
  101. event.PreventDefault()
  102. }
  103. }
  104. }