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.

roleplay.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package irc
  4. import (
  5. "bytes"
  6. "github.com/oragono/oragono/irc/history"
  7. "github.com/oragono/oragono/irc/modes"
  8. "github.com/oragono/oragono/irc/utils"
  9. )
  10. const (
  11. npcNickMask = "*%s*!%s@npc.fakeuser.invalid"
  12. sceneNickMask = "=Scene=!%s@npc.fakeuser.invalid"
  13. )
  14. func sendRoleplayMessage(server *Server, client *Client, source string, targetString string, isAction bool, messageParts []string, rb *ResponseBuffer) {
  15. config := server.Config()
  16. if !config.Roleplay.enabled {
  17. rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Roleplaying has been disabled by the server administrators"))
  18. return
  19. }
  20. if config.Roleplay.RequireOper && !client.HasRoleCapabs("roleplay") {
  21. rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Insufficient privileges"))
  22. return
  23. }
  24. // block attempts to send CTCP messages to Tor clients
  25. if len(messageParts) > 0 && len(messageParts[0]) > 0 && messageParts[0][0] == '\x01' {
  26. return
  27. }
  28. var buf bytes.Buffer
  29. if isAction {
  30. buf.WriteString("\x01ACTION ")
  31. }
  32. for i, part := range messageParts {
  33. buf.WriteString(part)
  34. if i != len(messageParts)-1 {
  35. buf.WriteByte(' ')
  36. }
  37. }
  38. if config.Roleplay.addSuffix {
  39. buf.WriteString(" (")
  40. buf.WriteString(client.Nick())
  41. buf.WriteString(")")
  42. }
  43. splitMessage := utils.MakeMessage(buf.String())
  44. target, cerr := CasefoldChannel(targetString)
  45. if cerr == nil {
  46. channel := server.channels.Get(target)
  47. if channel == nil {
  48. rb.Add(nil, server.name, ERR_NOSUCHCHANNEL, client.nick, targetString, client.t("No such channel"))
  49. return
  50. }
  51. targetString = channel.Name()
  52. if !channel.CanSpeak(client) {
  53. rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, targetString, client.t("Cannot send to channel"))
  54. return
  55. }
  56. if !channel.flags.HasMode(modes.ChanRoleplaying) {
  57. rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Channel doesn't have roleplaying mode available"))
  58. return
  59. }
  60. if config.Roleplay.RequireChanops && !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
  61. rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, targetString, client.t("Insufficient privileges"))
  62. return
  63. }
  64. for _, member := range channel.Members() {
  65. for _, session := range member.Sessions() {
  66. // see discussion on #865: clients do not understand how to do local echo
  67. // of roleplay commands, so send them a copy whether they have echo-message
  68. // or not
  69. if rb.session == session {
  70. rb.AddSplitMessageFromClient(source, "", nil, "PRIVMSG", targetString, splitMessage)
  71. } else {
  72. session.sendSplitMsgFromClientInternal(false, source, "", nil, "PRIVMSG", targetString, splitMessage)
  73. }
  74. }
  75. }
  76. channel.AddHistoryItem(history.Item{
  77. Type: history.Privmsg,
  78. Message: splitMessage,
  79. Nick: source,
  80. }, client.Account())
  81. } else {
  82. target, err := CasefoldName(targetString)
  83. user := server.clients.Get(target)
  84. if err != nil || user == nil {
  85. rb.Add(nil, server.name, ERR_NOSUCHNICK, client.nick, target, client.t("No such nick"))
  86. return
  87. }
  88. if !user.HasMode(modes.UserRoleplaying) {
  89. rb.Add(nil, client.server.name, ERR_CANNOTSENDRP, user.nick, client.t("User doesn't have roleplaying mode enabled"))
  90. return
  91. }
  92. cnick := client.Nick()
  93. tnick := user.Nick()
  94. for _, session := range user.Sessions() {
  95. session.sendSplitMsgFromClientInternal(false, source, "", nil, "PRIVMSG", tnick, splitMessage)
  96. }
  97. if away, awayMessage := user.Away(); away {
  98. //TODO(dan): possibly implement cooldown of away notifications to users
  99. rb.Add(nil, server.name, RPL_AWAY, cnick, tnick, awayMessage)
  100. }
  101. }
  102. }