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.

channel.go 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2014-2015 Edmund Huber
  3. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  4. // released under the MIT license
  5. package irc
  6. import (
  7. "bytes"
  8. "fmt"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "sync"
  13. "github.com/oragono/oragono/irc/caps"
  14. "github.com/oragono/oragono/irc/history"
  15. "github.com/oragono/oragono/irc/modes"
  16. "github.com/oragono/oragono/irc/utils"
  17. )
  18. // Channel represents a channel that clients can join.
  19. type Channel struct {
  20. flags *modes.ModeSet
  21. lists map[modes.Mode]*UserMaskSet
  22. key string
  23. members MemberSet
  24. membersCache []*Client // allow iteration over channel members without holding the lock
  25. name string
  26. nameCasefolded string
  27. server *Server
  28. createdTime time.Time
  29. registeredFounder string
  30. registeredTime time.Time
  31. stateMutex sync.RWMutex // tier 1
  32. joinPartMutex sync.Mutex // tier 3
  33. topic string
  34. topicSetBy string
  35. topicSetTime time.Time
  36. userLimit int
  37. accountToUMode map[string]modes.Mode
  38. history history.Buffer
  39. }
  40. // NewChannel creates a new channel from a `Server` and a `name`
  41. // string, which must be unique on the server.
  42. func NewChannel(s *Server, name string, regInfo *RegisteredChannel) *Channel {
  43. casefoldedName, err := CasefoldChannel(name)
  44. if err != nil {
  45. s.logger.Error("internal", "Bad channel name", name, err.Error())
  46. return nil
  47. }
  48. channel := &Channel{
  49. createdTime: time.Now(), // may be overwritten by applyRegInfo
  50. flags: modes.NewModeSet(),
  51. lists: map[modes.Mode]*UserMaskSet{
  52. modes.BanMask: NewUserMaskSet(),
  53. modes.ExceptMask: NewUserMaskSet(),
  54. modes.InviteMask: NewUserMaskSet(),
  55. },
  56. members: make(MemberSet),
  57. name: name,
  58. nameCasefolded: casefoldedName,
  59. server: s,
  60. accountToUMode: make(map[string]modes.Mode),
  61. }
  62. config := s.Config()
  63. if regInfo != nil {
  64. channel.applyRegInfo(regInfo)
  65. } else {
  66. for _, mode := range config.Channels.defaultModes {
  67. channel.flags.SetMode(mode, true)
  68. }
  69. }
  70. channel.history.Initialize(config.History.ChannelLength)
  71. return channel
  72. }
  73. // read in channel state that was persisted in the DB
  74. func (channel *Channel) applyRegInfo(chanReg *RegisteredChannel) {
  75. channel.registeredFounder = chanReg.Founder
  76. channel.registeredTime = chanReg.RegisteredAt
  77. channel.topic = chanReg.Topic
  78. channel.topicSetBy = chanReg.TopicSetBy
  79. channel.topicSetTime = chanReg.TopicSetTime
  80. channel.name = chanReg.Name
  81. channel.createdTime = chanReg.RegisteredAt
  82. channel.key = chanReg.Key
  83. for _, mode := range chanReg.Modes {
  84. channel.flags.SetMode(mode, true)
  85. }
  86. for _, mask := range chanReg.Banlist {
  87. channel.lists[modes.BanMask].Add(mask)
  88. }
  89. for _, mask := range chanReg.Exceptlist {
  90. channel.lists[modes.ExceptMask].Add(mask)
  91. }
  92. for _, mask := range chanReg.Invitelist {
  93. channel.lists[modes.InviteMask].Add(mask)
  94. }
  95. for account, mode := range chanReg.AccountToUMode {
  96. channel.accountToUMode[account] = mode
  97. }
  98. }
  99. // obtain a consistent snapshot of the channel state that can be persisted to the DB
  100. func (channel *Channel) ExportRegistration(includeFlags uint) (info RegisteredChannel) {
  101. channel.stateMutex.RLock()
  102. defer channel.stateMutex.RUnlock()
  103. info.Name = channel.name
  104. info.Founder = channel.registeredFounder
  105. info.RegisteredAt = channel.registeredTime
  106. if includeFlags&IncludeTopic != 0 {
  107. info.Topic = channel.topic
  108. info.TopicSetBy = channel.topicSetBy
  109. info.TopicSetTime = channel.topicSetTime
  110. }
  111. if includeFlags&IncludeModes != 0 {
  112. info.Key = channel.key
  113. info.Modes = channel.flags.AllModes()
  114. }
  115. if includeFlags&IncludeLists != 0 {
  116. for mask := range channel.lists[modes.BanMask].masks {
  117. info.Banlist = append(info.Banlist, mask)
  118. }
  119. for mask := range channel.lists[modes.ExceptMask].masks {
  120. info.Exceptlist = append(info.Exceptlist, mask)
  121. }
  122. for mask := range channel.lists[modes.InviteMask].masks {
  123. info.Invitelist = append(info.Invitelist, mask)
  124. }
  125. info.AccountToUMode = make(map[string]modes.Mode)
  126. for account, mode := range channel.accountToUMode {
  127. info.AccountToUMode[account] = mode
  128. }
  129. }
  130. return
  131. }
  132. // SetRegistered registers the channel, returning an error if it was already registered.
  133. func (channel *Channel) SetRegistered(founder string) error {
  134. channel.stateMutex.Lock()
  135. defer channel.stateMutex.Unlock()
  136. if channel.registeredFounder != "" {
  137. return errChannelAlreadyRegistered
  138. }
  139. channel.registeredFounder = founder
  140. channel.registeredTime = time.Now()
  141. channel.accountToUMode[founder] = modes.ChannelFounder
  142. return nil
  143. }
  144. // SetUnregistered deletes the channel's registration information.
  145. func (channel *Channel) SetUnregistered(expectedFounder string) {
  146. channel.stateMutex.Lock()
  147. defer channel.stateMutex.Unlock()
  148. if channel.registeredFounder != expectedFounder {
  149. return
  150. }
  151. channel.registeredFounder = ""
  152. var zeroTime time.Time
  153. channel.registeredTime = zeroTime
  154. channel.accountToUMode = make(map[string]modes.Mode)
  155. }
  156. // IsRegistered returns whether the channel is registered.
  157. func (channel *Channel) IsRegistered() bool {
  158. channel.stateMutex.RLock()
  159. defer channel.stateMutex.RUnlock()
  160. return channel.registeredFounder != ""
  161. }
  162. func (channel *Channel) regenerateMembersCache() {
  163. channel.stateMutex.RLock()
  164. result := make([]*Client, len(channel.members))
  165. i := 0
  166. for client := range channel.members {
  167. result[i] = client
  168. i++
  169. }
  170. channel.stateMutex.RUnlock()
  171. channel.stateMutex.Lock()
  172. channel.membersCache = result
  173. channel.stateMutex.Unlock()
  174. }
  175. // Names sends the list of users joined to the channel to the given client.
  176. func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
  177. isMultiPrefix := client.capabilities.Has(caps.MultiPrefix)
  178. isUserhostInNames := client.capabilities.Has(caps.UserhostInNames)
  179. maxNamLen := 480 - len(client.server.name) - len(client.Nick())
  180. var namesLines []string
  181. var buffer bytes.Buffer
  182. for _, target := range channel.Members() {
  183. var nick string
  184. if isUserhostInNames {
  185. nick = target.NickMaskString()
  186. } else {
  187. nick = target.Nick()
  188. }
  189. channel.stateMutex.RLock()
  190. modes := channel.members[target]
  191. channel.stateMutex.RUnlock()
  192. if modes == nil {
  193. continue
  194. }
  195. prefix := modes.Prefixes(isMultiPrefix)
  196. if buffer.Len()+len(nick)+len(prefix)+1 > maxNamLen {
  197. namesLines = append(namesLines, buffer.String())
  198. buffer.Reset()
  199. }
  200. if buffer.Len() > 0 {
  201. buffer.WriteString(" ")
  202. }
  203. buffer.WriteString(prefix)
  204. buffer.WriteString(nick)
  205. }
  206. if buffer.Len() > 0 {
  207. namesLines = append(namesLines, buffer.String())
  208. }
  209. for _, line := range namesLines {
  210. if buffer.Len() > 0 {
  211. rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, line)
  212. }
  213. }
  214. rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
  215. }
  216. func channelUserModeIsAtLeast(clientModes *modes.ModeSet, permission modes.Mode) bool {
  217. if clientModes == nil {
  218. return false
  219. }
  220. for _, mode := range modes.ChannelUserModes {
  221. if clientModes.HasMode(mode) {
  222. return true
  223. }
  224. if mode == permission {
  225. break
  226. }
  227. }
  228. return false
  229. }
  230. // ClientIsAtLeast returns whether the client has at least the given channel privilege.
  231. func (channel *Channel) ClientIsAtLeast(client *Client, permission modes.Mode) bool {
  232. channel.stateMutex.RLock()
  233. clientModes := channel.members[client]
  234. channel.stateMutex.RUnlock()
  235. return channelUserModeIsAtLeast(clientModes, permission)
  236. }
  237. func (channel *Channel) ClientPrefixes(client *Client, isMultiPrefix bool) string {
  238. channel.stateMutex.RLock()
  239. defer channel.stateMutex.RUnlock()
  240. modes, present := channel.members[client]
  241. if !present {
  242. return ""
  243. } else {
  244. return modes.Prefixes(isMultiPrefix)
  245. }
  246. }
  247. func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool {
  248. channel.stateMutex.RLock()
  249. clientModes := channel.members[client]
  250. targetModes := channel.members[target]
  251. channel.stateMutex.RUnlock()
  252. if clientModes.HasMode(modes.ChannelFounder) {
  253. // founder can kick anyone
  254. return true
  255. } else if clientModes.HasMode(modes.ChannelAdmin) {
  256. // admins cannot kick other admins
  257. return !channelUserModeIsAtLeast(targetModes, modes.ChannelAdmin)
  258. } else if clientModes.HasMode(modes.ChannelOperator) {
  259. // operators *can* kick other operators
  260. return !channelUserModeIsAtLeast(targetModes, modes.ChannelAdmin)
  261. } else if clientModes.HasMode(modes.Halfop) {
  262. // halfops cannot kick other halfops
  263. return !channelUserModeIsAtLeast(targetModes, modes.Halfop)
  264. } else {
  265. // voice and unprivileged cannot kick anyone
  266. return false
  267. }
  268. }
  269. func (channel *Channel) hasClient(client *Client) bool {
  270. channel.stateMutex.RLock()
  271. defer channel.stateMutex.RUnlock()
  272. _, present := channel.members[client]
  273. return present
  274. }
  275. // <mode> <mode params>
  276. func (channel *Channel) modeStrings(client *Client) (result []string) {
  277. isMember := client.HasMode(modes.Operator) || channel.hasClient(client)
  278. showKey := isMember && (channel.key != "")
  279. showUserLimit := channel.userLimit > 0
  280. mods := "+"
  281. // flags with args
  282. if showKey {
  283. mods += modes.Key.String()
  284. }
  285. if showUserLimit {
  286. mods += modes.UserLimit.String()
  287. }
  288. mods += channel.flags.String()
  289. channel.stateMutex.RLock()
  290. defer channel.stateMutex.RUnlock()
  291. result = []string{mods}
  292. // args for flags with args: The order must match above to keep
  293. // positional arguments in place.
  294. if showKey {
  295. result = append(result, channel.key)
  296. }
  297. if showUserLimit {
  298. result = append(result, strconv.Itoa(channel.userLimit))
  299. }
  300. return
  301. }
  302. func (channel *Channel) IsEmpty() bool {
  303. channel.stateMutex.RLock()
  304. defer channel.stateMutex.RUnlock()
  305. return len(channel.members) == 0
  306. }
  307. // Join joins the given client to this channel (if they can be joined).
  308. func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *ResponseBuffer) {
  309. details := client.Details()
  310. channel.stateMutex.RLock()
  311. chname := channel.name
  312. chcfname := channel.nameCasefolded
  313. founder := channel.registeredFounder
  314. chkey := channel.key
  315. limit := channel.userLimit
  316. chcount := len(channel.members)
  317. _, alreadyJoined := channel.members[client]
  318. persistentMode := channel.accountToUMode[details.account]
  319. channel.stateMutex.RUnlock()
  320. if alreadyJoined {
  321. // no message needs to be sent
  322. return
  323. }
  324. // the founder can always join (even if they disabled auto +q on join);
  325. // anyone who automatically receives halfop or higher can always join
  326. hasPrivs := isSajoin || (founder != "" && founder == details.account) || (persistentMode != 0 && persistentMode != modes.Voice)
  327. if !hasPrivs && limit != 0 && chcount >= limit {
  328. rb.Add(nil, client.server.name, ERR_CHANNELISFULL, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "l"))
  329. return
  330. }
  331. if !hasPrivs && chkey != "" && !utils.SecretTokensMatch(chkey, key) {
  332. rb.Add(nil, client.server.name, ERR_BADCHANNELKEY, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "k"))
  333. return
  334. }
  335. isInvited := client.CheckInvited(chcfname) || channel.lists[modes.InviteMask].Match(details.nickMaskCasefolded)
  336. if !hasPrivs && channel.flags.HasMode(modes.InviteOnly) && !isInvited {
  337. rb.Add(nil, client.server.name, ERR_INVITEONLYCHAN, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "i"))
  338. return
  339. }
  340. if !hasPrivs && channel.lists[modes.BanMask].Match(details.nickMaskCasefolded) &&
  341. !isInvited &&
  342. !channel.lists[modes.ExceptMask].Match(details.nickMaskCasefolded) {
  343. rb.Add(nil, client.server.name, ERR_BANNEDFROMCHAN, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "b"))
  344. return
  345. }
  346. client.server.logger.Debug("join", fmt.Sprintf("%s joined channel %s", details.nick, chname))
  347. givenMode := func() (givenMode modes.Mode) {
  348. channel.joinPartMutex.Lock()
  349. defer channel.joinPartMutex.Unlock()
  350. func() {
  351. channel.stateMutex.Lock()
  352. defer channel.stateMutex.Unlock()
  353. channel.members.Add(client)
  354. firstJoin := len(channel.members) == 1
  355. newChannel := firstJoin && channel.registeredFounder == ""
  356. if newChannel {
  357. givenMode = modes.ChannelOperator
  358. } else {
  359. givenMode = persistentMode
  360. }
  361. if givenMode != 0 {
  362. channel.members[client].SetMode(givenMode, true)
  363. }
  364. }()
  365. channel.regenerateMembersCache()
  366. message := utils.SplitMessage{}
  367. message.Msgid = details.realname
  368. channel.history.Add(history.Item{
  369. Type: history.Join,
  370. Nick: details.nickMask,
  371. AccountName: details.accountName,
  372. Message: message,
  373. })
  374. return
  375. }()
  376. client.addChannel(channel)
  377. var modestr string
  378. if givenMode != 0 {
  379. modestr = fmt.Sprintf("+%v", givenMode)
  380. }
  381. for _, member := range channel.Members() {
  382. if member == client {
  383. continue
  384. }
  385. if member.capabilities.Has(caps.ExtendedJoin) {
  386. member.Send(nil, details.nickMask, "JOIN", chname, details.accountName, details.realname)
  387. } else {
  388. member.Send(nil, details.nickMask, "JOIN", chname)
  389. }
  390. if givenMode != 0 {
  391. member.Send(nil, client.server.name, "MODE", chname, modestr, details.nick)
  392. }
  393. }
  394. if client.capabilities.Has(caps.ExtendedJoin) {
  395. rb.Add(nil, details.nickMask, "JOIN", chname, details.accountName, details.realname)
  396. } else {
  397. rb.Add(nil, details.nickMask, "JOIN", chname)
  398. }
  399. channel.SendTopic(client, rb, false)
  400. channel.Names(client, rb)
  401. // TODO #259 can be implemented as Flush(false) (i.e., nonblocking) while holding joinPartMutex
  402. rb.Flush(true)
  403. replayLimit := channel.server.Config().History.AutoreplayOnJoin
  404. if replayLimit > 0 {
  405. items := channel.history.Latest(replayLimit)
  406. channel.replayHistoryItems(rb, items)
  407. rb.Flush(true)
  408. }
  409. }
  410. // Part parts the given client from this channel, with the given message.
  411. func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer) {
  412. chname := channel.Name()
  413. if !channel.hasClient(client) {
  414. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, chname, client.t("You're not on that channel"))
  415. return
  416. }
  417. channel.Quit(client)
  418. details := client.Details()
  419. for _, member := range channel.Members() {
  420. member.Send(nil, details.nickMask, "PART", chname, message)
  421. }
  422. rb.Add(nil, details.nickMask, "PART", chname, message)
  423. channel.history.Add(history.Item{
  424. Type: history.Part,
  425. Nick: details.nickMask,
  426. AccountName: details.accountName,
  427. Message: utils.MakeSplitMessage(message, true),
  428. })
  429. client.server.logger.Debug("part", fmt.Sprintf("%s left channel %s", details.nick, chname))
  430. }
  431. // Resume is called after a successful global resume to:
  432. // 1. Replace the old client with the new in the channel's data structures
  433. // 2. Send JOIN and MODE lines to channel participants (including the new client)
  434. // 3. Replay missed message history to the client
  435. func (channel *Channel) Resume(newClient, oldClient *Client, timestamp time.Time) {
  436. now := time.Now()
  437. channel.resumeAndAnnounce(newClient, oldClient)
  438. if !timestamp.IsZero() {
  439. channel.replayHistoryForResume(newClient, timestamp, now)
  440. }
  441. }
  442. func (channel *Channel) resumeAndAnnounce(newClient, oldClient *Client) {
  443. var oldModeSet *modes.ModeSet
  444. func() {
  445. channel.joinPartMutex.Lock()
  446. defer channel.joinPartMutex.Unlock()
  447. defer channel.regenerateMembersCache()
  448. channel.stateMutex.Lock()
  449. defer channel.stateMutex.Unlock()
  450. newClient.channels[channel] = true
  451. oldModeSet = channel.members[oldClient]
  452. if oldModeSet == nil {
  453. oldModeSet = modes.NewModeSet()
  454. }
  455. channel.members.Remove(oldClient)
  456. channel.members[newClient] = oldModeSet
  457. }()
  458. // construct fake modestring if necessary
  459. oldModes := oldModeSet.String()
  460. if 0 < len(oldModes) {
  461. oldModes = "+" + oldModes
  462. }
  463. // send join for old clients
  464. nick := newClient.Nick()
  465. nickMask := newClient.NickMaskString()
  466. accountName := newClient.AccountName()
  467. realName := newClient.Realname()
  468. for _, member := range channel.Members() {
  469. if member.capabilities.Has(caps.Resume) {
  470. continue
  471. }
  472. if member.capabilities.Has(caps.ExtendedJoin) {
  473. member.Send(nil, nickMask, "JOIN", channel.name, accountName, realName)
  474. } else {
  475. member.Send(nil, nickMask, "JOIN", channel.name)
  476. }
  477. if 0 < len(oldModes) {
  478. member.Send(nil, channel.server.name, "MODE", channel.name, oldModes, nick)
  479. }
  480. }
  481. rb := NewResponseBuffer(newClient)
  482. // use blocking i/o to synchronize with the later history replay
  483. if newClient.capabilities.Has(caps.ExtendedJoin) {
  484. rb.Add(nil, nickMask, "JOIN", channel.name, accountName, realName)
  485. } else {
  486. rb.Add(nil, nickMask, "JOIN", channel.name)
  487. }
  488. channel.SendTopic(newClient, rb, false)
  489. channel.Names(newClient, rb)
  490. if 0 < len(oldModes) {
  491. rb.Add(nil, newClient.server.name, "MODE", channel.name, oldModes, nick)
  492. }
  493. rb.Send(true)
  494. }
  495. func (channel *Channel) replayHistoryForResume(newClient *Client, after time.Time, before time.Time) {
  496. items, complete := channel.history.Between(after, before, false, 0)
  497. rb := NewResponseBuffer(newClient)
  498. channel.replayHistoryItems(rb, items)
  499. if !complete && !newClient.resumeDetails.HistoryIncomplete {
  500. // warn here if we didn't warn already
  501. rb.Add(nil, "HistServ", "NOTICE", channel.Name(), newClient.t("Some additional message history may have been lost"))
  502. }
  503. rb.Send(true)
  504. }
  505. func stripMaskFromNick(nickMask string) (nick string) {
  506. index := strings.Index(nickMask, "!")
  507. if index == -1 {
  508. return
  509. }
  510. return nickMask[0:index]
  511. }
  512. func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.Item) {
  513. chname := channel.Name()
  514. client := rb.target
  515. serverTime := client.capabilities.Has(caps.ServerTime)
  516. for _, item := range items {
  517. var tags map[string]string
  518. if serverTime {
  519. tags = map[string]string{"time": item.Time.Format(IRCv3TimestampFormat)}
  520. }
  521. // TODO(#437) support history.Tagmsg
  522. switch item.Type {
  523. case history.Privmsg:
  524. rb.AddSplitMessageFromClient(item.Nick, item.AccountName, tags, "PRIVMSG", chname, item.Message)
  525. case history.Notice:
  526. rb.AddSplitMessageFromClient(item.Nick, item.AccountName, tags, "NOTICE", chname, item.Message)
  527. case history.Join:
  528. nick := stripMaskFromNick(item.Nick)
  529. var message string
  530. if item.AccountName == "*" {
  531. message = fmt.Sprintf(client.t("%s joined the channel"), nick)
  532. } else {
  533. message = fmt.Sprintf(client.t("%[1]s [account: %[2]s] joined the channel"), nick, item.AccountName)
  534. }
  535. rb.Add(tags, "HistServ", "PRIVMSG", chname, message)
  536. case history.Part:
  537. nick := stripMaskFromNick(item.Nick)
  538. message := fmt.Sprintf(client.t("%[1]s left the channel (%[2]s)"), nick, item.Message.Message)
  539. rb.Add(tags, "HistServ", "PRIVMSG", chname, message)
  540. case history.Quit:
  541. nick := stripMaskFromNick(item.Nick)
  542. message := fmt.Sprintf(client.t("%[1]s quit (%[2]s)"), nick, item.Message.Message)
  543. rb.Add(tags, "HistServ", "PRIVMSG", chname, message)
  544. case history.Kick:
  545. nick := stripMaskFromNick(item.Nick)
  546. // XXX Msgid is the kick target
  547. message := fmt.Sprintf(client.t("%[1]s kicked %[2]s (%[3]s)"), nick, item.Message.Msgid, item.Message.Message)
  548. rb.Add(tags, "HistServ", "PRIVMSG", chname, message)
  549. }
  550. }
  551. }
  552. // SendTopic sends the channel topic to the given client.
  553. // `sendNoTopic` controls whether RPL_NOTOPIC is sent when the topic is unset
  554. func (channel *Channel) SendTopic(client *Client, rb *ResponseBuffer, sendNoTopic bool) {
  555. if !channel.hasClient(client) {
  556. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.nick, channel.name, client.t("You're not on that channel"))
  557. return
  558. }
  559. channel.stateMutex.RLock()
  560. name := channel.name
  561. topic := channel.topic
  562. topicSetBy := channel.topicSetBy
  563. topicSetTime := channel.topicSetTime
  564. channel.stateMutex.RUnlock()
  565. if topic == "" {
  566. if sendNoTopic {
  567. rb.Add(nil, client.server.name, RPL_NOTOPIC, client.nick, name, client.t("No topic is set"))
  568. }
  569. return
  570. }
  571. rb.Add(nil, client.server.name, RPL_TOPIC, client.nick, name, topic)
  572. rb.Add(nil, client.server.name, RPL_TOPICTIME, client.nick, name, topicSetBy, strconv.FormatInt(topicSetTime.Unix(), 10))
  573. }
  574. // SetTopic sets the topic of this channel, if the client is allowed to do so.
  575. func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffer) {
  576. if !(client.HasMode(modes.Operator) || channel.hasClient(client)) {
  577. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
  578. return
  579. }
  580. if channel.flags.HasMode(modes.OpOnlyTopic) && !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
  581. rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
  582. return
  583. }
  584. topicLimit := client.server.Limits().TopicLen
  585. if len(topic) > topicLimit {
  586. topic = topic[:topicLimit]
  587. }
  588. channel.stateMutex.Lock()
  589. channel.topic = topic
  590. channel.topicSetBy = client.nickMaskString
  591. channel.topicSetTime = time.Now()
  592. channel.stateMutex.Unlock()
  593. for _, member := range channel.Members() {
  594. if member == client {
  595. rb.Add(nil, client.nickMaskString, "TOPIC", channel.name, topic)
  596. } else {
  597. member.Send(nil, client.nickMaskString, "TOPIC", channel.name, topic)
  598. }
  599. }
  600. go channel.server.channelRegistry.StoreChannel(channel, IncludeTopic)
  601. }
  602. // CanSpeak returns true if the client can speak on this channel.
  603. func (channel *Channel) CanSpeak(client *Client) bool {
  604. channel.stateMutex.RLock()
  605. defer channel.stateMutex.RUnlock()
  606. _, hasClient := channel.members[client]
  607. if channel.flags.HasMode(modes.NoOutside) && !hasClient {
  608. return false
  609. }
  610. if channel.flags.HasMode(modes.Moderated) && !channel.ClientIsAtLeast(client, modes.Voice) {
  611. return false
  612. }
  613. if channel.flags.HasMode(modes.RegisteredOnly) && client.Account() == "" {
  614. return false
  615. }
  616. return true
  617. }
  618. func (channel *Channel) SendSplitMessage(command string, minPrefix *modes.Mode, clientOnlyTags map[string]string, client *Client, message utils.SplitMessage, rb *ResponseBuffer) {
  619. var histType history.ItemType
  620. switch command {
  621. case "PRIVMSG":
  622. histType = history.Privmsg
  623. case "NOTICE":
  624. histType = history.Notice
  625. case "TAGMSG":
  626. histType = history.Tagmsg
  627. default:
  628. channel.server.logger.Error("internal", "unrecognized Channel.SendSplitMessage command", command)
  629. return
  630. }
  631. if !channel.CanSpeak(client) {
  632. rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
  633. return
  634. }
  635. // for STATUSMSG
  636. var minPrefixMode modes.Mode
  637. if minPrefix != nil {
  638. minPrefixMode = *minPrefix
  639. }
  640. // send echo-message
  641. if client.capabilities.Has(caps.EchoMessage) {
  642. var tagsToUse map[string]string
  643. if client.capabilities.Has(caps.MessageTags) {
  644. tagsToUse = clientOnlyTags
  645. }
  646. nickMaskString := client.NickMaskString()
  647. accountName := client.AccountName()
  648. if command == "TAGMSG" && client.capabilities.Has(caps.MessageTags) {
  649. rb.AddFromClient(message.Msgid, nickMaskString, accountName, tagsToUse, command, channel.name)
  650. } else {
  651. rb.AddSplitMessageFromClient(nickMaskString, accountName, tagsToUse, command, channel.name, message)
  652. }
  653. }
  654. nickmask := client.NickMaskString()
  655. account := client.AccountName()
  656. now := time.Now().UTC()
  657. for _, member := range channel.Members() {
  658. if minPrefix != nil && !channel.ClientIsAtLeast(member, minPrefixMode) {
  659. // STATUSMSG
  660. continue
  661. }
  662. // echo-message is handled above, so skip sending the msg to the user themselves as well
  663. if member == client {
  664. continue
  665. }
  666. var tagsToUse map[string]string
  667. if member.capabilities.Has(caps.MessageTags) {
  668. tagsToUse = clientOnlyTags
  669. } else if command == "TAGMSG" {
  670. continue
  671. }
  672. if command == "TAGMSG" {
  673. member.sendFromClientInternal(false, now, message.Msgid, nickmask, account, tagsToUse, command, channel.name)
  674. } else {
  675. member.sendSplitMsgFromClientInternal(false, now, nickmask, account, tagsToUse, command, channel.name, message)
  676. }
  677. }
  678. channel.history.Add(history.Item{
  679. Type: histType,
  680. Message: message,
  681. Nick: nickmask,
  682. AccountName: account,
  683. Time: now,
  684. })
  685. }
  686. func (channel *Channel) applyModeToMember(client *Client, mode modes.Mode, op modes.ModeOp, nick string, rb *ResponseBuffer) (result *modes.ModeChange) {
  687. casefoldedName, err := CasefoldName(nick)
  688. target := channel.server.clients.Get(casefoldedName)
  689. if err != nil || target == nil {
  690. rb.Add(nil, client.server.name, ERR_NOSUCHNICK, client.Nick(), nick, client.t("No such nick"))
  691. return nil
  692. }
  693. channel.stateMutex.Lock()
  694. modeset, exists := channel.members[target]
  695. if exists {
  696. if modeset.SetMode(mode, op == modes.Add) {
  697. result = &modes.ModeChange{
  698. Op: op,
  699. Mode: mode,
  700. Arg: nick,
  701. }
  702. }
  703. }
  704. channel.stateMutex.Unlock()
  705. if !exists {
  706. rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.Nick(), channel.Name(), client.t("They aren't on that channel"))
  707. }
  708. return
  709. }
  710. // ShowMaskList shows the given list to the client.
  711. func (channel *Channel) ShowMaskList(client *Client, mode modes.Mode, rb *ResponseBuffer) {
  712. // choose appropriate modes
  713. var rpllist, rplendoflist string
  714. if mode == modes.BanMask {
  715. rpllist = RPL_BANLIST
  716. rplendoflist = RPL_ENDOFBANLIST
  717. } else if mode == modes.ExceptMask {
  718. rpllist = RPL_EXCEPTLIST
  719. rplendoflist = RPL_ENDOFEXCEPTLIST
  720. } else if mode == modes.InviteMask {
  721. rpllist = RPL_INVITELIST
  722. rplendoflist = RPL_ENDOFINVITELIST
  723. }
  724. nick := client.Nick()
  725. channel.stateMutex.RLock()
  726. // XXX don't acquire any new locks in this section, besides Socket.Write
  727. for mask := range channel.lists[mode].masks {
  728. rb.Add(nil, client.server.name, rpllist, nick, channel.name, mask)
  729. }
  730. channel.stateMutex.RUnlock()
  731. rb.Add(nil, client.server.name, rplendoflist, nick, channel.name, client.t("End of list"))
  732. }
  733. func (channel *Channel) applyModeMask(client *Client, mode modes.Mode, op modes.ModeOp, mask string, rb *ResponseBuffer) bool {
  734. list := channel.lists[mode]
  735. if list == nil {
  736. // This should never happen, but better safe than panicky.
  737. return false
  738. }
  739. if (op == modes.List) || (mask == "") {
  740. channel.ShowMaskList(client, mode, rb)
  741. return false
  742. }
  743. if !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
  744. rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You're not a channel operator"))
  745. return false
  746. }
  747. if op == modes.Add {
  748. return list.Add(mask)
  749. }
  750. if op == modes.Remove {
  751. return list.Remove(mask)
  752. }
  753. return false
  754. }
  755. // Quit removes the given client from the channel
  756. func (channel *Channel) Quit(client *Client) {
  757. channelEmpty := func() bool {
  758. channel.joinPartMutex.Lock()
  759. defer channel.joinPartMutex.Unlock()
  760. channel.stateMutex.Lock()
  761. channel.members.Remove(client)
  762. channelEmpty := len(channel.members) == 0
  763. channel.stateMutex.Unlock()
  764. channel.regenerateMembersCache()
  765. return channelEmpty
  766. }()
  767. if channelEmpty {
  768. client.server.channels.Cleanup(channel)
  769. }
  770. client.removeChannel(channel)
  771. }
  772. func (channel *Channel) Kick(client *Client, target *Client, comment string, rb *ResponseBuffer) {
  773. if !(client.HasMode(modes.Operator) || channel.hasClient(client)) {
  774. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
  775. return
  776. }
  777. if !channel.hasClient(target) {
  778. rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.nick, channel.name, client.t("They aren't on that channel"))
  779. return
  780. }
  781. if !channel.ClientHasPrivsOver(client, target) {
  782. rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, client.t("You don't have enough channel privileges"))
  783. return
  784. }
  785. kicklimit := client.server.Limits().KickLen
  786. if len(comment) > kicklimit {
  787. comment = comment[:kicklimit]
  788. }
  789. clientMask := client.NickMaskString()
  790. targetNick := target.Nick()
  791. for _, member := range channel.Members() {
  792. member.Send(nil, clientMask, "KICK", channel.name, targetNick, comment)
  793. }
  794. message := utils.SplitMessage{}
  795. message.Message = comment
  796. message.Msgid = targetNick // XXX abuse this field
  797. channel.history.Add(history.Item{
  798. Type: history.Kick,
  799. Nick: clientMask,
  800. AccountName: target.AccountName(),
  801. Message: message,
  802. })
  803. channel.Quit(target)
  804. }
  805. // Invite invites the given client to the channel, if the inviter can do so.
  806. func (channel *Channel) Invite(invitee *Client, inviter *Client, rb *ResponseBuffer) {
  807. chname := channel.Name()
  808. if channel.flags.HasMode(modes.InviteOnly) && !channel.ClientIsAtLeast(inviter, modes.ChannelOperator) {
  809. rb.Add(nil, inviter.server.name, ERR_CHANOPRIVSNEEDED, chname, inviter.t("You're not a channel operator"))
  810. return
  811. }
  812. if !channel.hasClient(inviter) {
  813. rb.Add(nil, inviter.server.name, ERR_NOTONCHANNEL, chname, inviter.t("You're not on that channel"))
  814. return
  815. }
  816. if channel.flags.HasMode(modes.InviteOnly) {
  817. invitee.Invite(channel.NameCasefolded())
  818. }
  819. for _, member := range channel.Members() {
  820. if member.capabilities.Has(caps.InviteNotify) && member != inviter && member != invitee && channel.ClientIsAtLeast(member, modes.Halfop) {
  821. member.Send(nil, inviter.NickMaskString(), "INVITE", invitee.Nick(), chname)
  822. }
  823. }
  824. cnick := inviter.Nick()
  825. tnick := invitee.Nick()
  826. rb.Add(nil, inviter.server.name, RPL_INVITING, cnick, tnick, chname)
  827. invitee.Send(nil, inviter.NickMaskString(), "INVITE", tnick, chname)
  828. if invitee.HasMode(modes.Away) {
  829. rb.Add(nil, inviter.server.name, RPL_AWAY, cnick, tnick, invitee.AwayMessage())
  830. }
  831. }