|
@@ -210,8 +210,6 @@ func (channel *Channel) MarkDirty(dirtyBits uint) {
|
210
|
210
|
// ChannelManager's lock (that way, no one can join and make the channel dirty again
|
211
|
211
|
// between this method exiting and the actual deletion).
|
212
|
212
|
func (channel *Channel) IsClean() bool {
|
213
|
|
- config := channel.server.Config()
|
214
|
|
-
|
215
|
213
|
if !channel.writerSemaphore.TryAcquire() {
|
216
|
214
|
// a database write (which may fail) is in progress, the channel cannot be cleaned up
|
217
|
215
|
return false
|
|
@@ -223,13 +221,8 @@ func (channel *Channel) IsClean() bool {
|
223
|
221
|
if len(channel.members) != 0 {
|
224
|
222
|
return false
|
225
|
223
|
}
|
226
|
|
- if channel.registeredFounder == "" {
|
227
|
|
- return true
|
228
|
|
- }
|
229
|
|
- // a registered channel must be fully written to the DB,
|
230
|
|
- // and not set to ephemeral history (#704)
|
231
|
|
- return channel.dirtyBits == 0 &&
|
232
|
|
- channelHistoryStatus(config, true, channel.settings.History) != HistoryEphemeral
|
|
224
|
+ // see #1507 and #704 among others; registered channels should never be removed
|
|
225
|
+ return channel.registeredFounder == ""
|
233
|
226
|
}
|
234
|
227
|
|
235
|
228
|
func (channel *Channel) wakeWriter() {
|
|
@@ -793,7 +786,7 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
|
793
|
786
|
return joinErr, ""
|
794
|
787
|
}
|
795
|
788
|
|
796
|
|
- client.server.logger.Debug("join", fmt.Sprintf("%s joined channel %s", details.nick, chname))
|
|
789
|
+ client.server.logger.Debug("channels", fmt.Sprintf("%s joined channel %s", details.nick, chname))
|
797
|
790
|
|
798
|
791
|
givenMode := func() (givenMode modes.Mode) {
|
799
|
792
|
channel.joinPartMutex.Lock()
|
|
@@ -1033,7 +1026,7 @@ func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer)
|
1033
|
1026
|
}, details.account)
|
1034
|
1027
|
}
|
1035
|
1028
|
|
1036
|
|
- client.server.logger.Debug("part", fmt.Sprintf("%s left channel %s", details.nick, chname))
|
|
1029
|
+ client.server.logger.Debug("channels", fmt.Sprintf("%s left channel %s", details.nick, chname))
|
1037
|
1030
|
}
|
1038
|
1031
|
|
1039
|
1032
|
// Resume is called after a successful global resume to:
|
|
@@ -1539,6 +1532,32 @@ func (channel *Channel) Kick(client *Client, target *Client, comment string, rb
|
1539
|
1532
|
channel.Quit(target)
|
1540
|
1533
|
}
|
1541
|
1534
|
|
|
1535
|
+// handle a purge: kick everyone off the channel, clean up all the pointers between
|
|
1536
|
+// *Channel and *Client
|
|
1537
|
+func (channel *Channel) Purge(source string) {
|
|
1538
|
+ if source == "" {
|
|
1539
|
+ source = channel.server.name
|
|
1540
|
+ }
|
|
1541
|
+
|
|
1542
|
+ channel.stateMutex.Lock()
|
|
1543
|
+ chname := channel.name
|
|
1544
|
+ members := channel.membersCache
|
|
1545
|
+ channel.membersCache = nil
|
|
1546
|
+ channel.members = make(MemberSet)
|
|
1547
|
+ // TODO try to prevent Purge racing against (pending) Join?
|
|
1548
|
+ channel.stateMutex.Unlock()
|
|
1549
|
+
|
|
1550
|
+ now := time.Now().UTC()
|
|
1551
|
+ for _, member := range members {
|
|
1552
|
+ tnick := member.Nick()
|
|
1553
|
+ msgid := utils.GenerateSecretToken()
|
|
1554
|
+ for _, session := range member.Sessions() {
|
|
1555
|
+ session.sendFromClientInternal(false, now, msgid, source, "*", nil, "KICK", chname, tnick, member.t("This channel has been purged by the server administrators and cannot be used"))
|
|
1556
|
+ }
|
|
1557
|
+ member.removeChannel(channel)
|
|
1558
|
+ }
|
|
1559
|
+}
|
|
1560
|
+
|
1542
|
1561
|
// Invite invites the given client to the channel, if the inviter can do so.
|
1543
|
1562
|
func (channel *Channel) Invite(invitee *Client, inviter *Client, rb *ResponseBuffer) {
|
1544
|
1563
|
channel.stateMutex.RLock()
|