Browse Source

Merge pull request #546 from slingamn/issue536.3

fix #536
tags/v1.1.0-rc1
Daniel Oaks 5 years ago
parent
commit
dc322f8fd4
No account linked to committer's email address
3 changed files with 41 additions and 5 deletions
  1. 7
    3
      irc/channel.go
  2. 14
    0
      irc/client.go
  3. 20
    2
      irc/znc.go

+ 7
- 3
irc/channel.go View File

624
 	// TODO #259 can be implemented as Flush(false) (i.e., nonblocking) while holding joinPartMutex
624
 	// TODO #259 can be implemented as Flush(false) (i.e., nonblocking) while holding joinPartMutex
625
 	rb.Flush(true)
625
 	rb.Flush(true)
626
 
626
 
627
+	channel.autoReplayHistory(client, rb, message.Msgid)
628
+}
629
+
630
+func (channel *Channel) autoReplayHistory(client *Client, rb *ResponseBuffer, skipMsgid string) {
627
 	// autoreplay any messages as necessary
631
 	// autoreplay any messages as necessary
628
 	config := channel.server.Config()
632
 	config := channel.server.Config()
629
 	var items []history.Item
633
 	var items []history.Item
630
-	if rb.session.zncPlaybackTimes != nil && (rb.session.zncPlaybackTimes.targets == nil || rb.session.zncPlaybackTimes.targets[chcfname]) {
634
+	if rb.session.zncPlaybackTimes != nil && (rb.session.zncPlaybackTimes.targets == nil || rb.session.zncPlaybackTimes.targets[channel.NameCasefolded()]) {
631
 		items, _ = channel.history.Between(rb.session.zncPlaybackTimes.after, rb.session.zncPlaybackTimes.before, false, config.History.ChathistoryMax)
635
 		items, _ = channel.history.Between(rb.session.zncPlaybackTimes.after, rb.session.zncPlaybackTimes.before, false, config.History.ChathistoryMax)
632
-	} else {
636
+	} else if !rb.session.HasHistoryCaps() {
633
 		var replayLimit int
637
 		var replayLimit int
634
 		customReplayLimit := client.AccountSettings().AutoreplayLines
638
 		customReplayLimit := client.AccountSettings().AutoreplayLines
635
 		if customReplayLimit != nil {
639
 		if customReplayLimit != nil {
648
 	// remove the client's own JOIN line from the replay
652
 	// remove the client's own JOIN line from the replay
649
 	numItems := len(items)
653
 	numItems := len(items)
650
 	for i := len(items) - 1; 0 <= i; i-- {
654
 	for i := len(items) - 1; 0 <= i; i-- {
651
-		if items[i].Message.Msgid == message.Msgid {
655
+		if items[i].Message.Msgid == skipMsgid {
652
 			// zero'ed items will not be replayed because their `Type` field is not recognized
656
 			// zero'ed items will not be replayed because their `Type` field is not recognized
653
 			items[i] = history.Item{}
657
 			items[i] = history.Item{}
654
 			numItems--
658
 			numItems--

+ 14
- 0
irc/client.go View File

162
 	atomic.StoreUint32(&session.destroyed, 1)
162
 	atomic.StoreUint32(&session.destroyed, 1)
163
 }
163
 }
164
 
164
 
165
+// returns whether the client supports a smart history replay cap,
166
+// and therefore autoreplay-on-join and similar should be suppressed
167
+func (session *Session) HasHistoryCaps() bool {
168
+	// TODO the chathistory cap will go here as well
169
+	return session.capabilities.Has(caps.ZNCPlayback)
170
+}
171
+
165
 // WhoWas is the subset of client details needed to answer a WHOWAS query
172
 // WhoWas is the subset of client details needed to answer a WHOWAS query
166
 type WhoWas struct {
173
 type WhoWas struct {
167
 	nick           string
174
 	nick           string
473
 	client.server.playRegistrationBurst(session)
480
 	client.server.playRegistrationBurst(session)
474
 	for _, channel := range session.client.Channels() {
481
 	for _, channel := range session.client.Channels() {
475
 		channel.playJoinForSession(session)
482
 		channel.playJoinForSession(session)
483
+		// clients should receive autoreplay-on-join lines, if applicable;
484
+		// if they negotiated znc.in/playback or chathistory, they will receive nothing,
485
+		// because those caps disable autoreplay-on-join and they haven't sent the relevant
486
+		// *playback PRIVMSG or CHATHISTORY command yet
487
+		rb := NewResponseBuffer(session)
488
+		channel.autoReplayHistory(client, rb, "")
489
+		rb.Send(true)
476
 	}
490
 	}
477
 }
491
 }
478
 
492
 

+ 20
- 2
irc/znc.go View File

73
 
73
 
74
 	var targets map[string]bool
74
 	var targets map[string]bool
75
 
75
 
76
-	// OK: the user's PMs get played back immediately on receiving this,
77
-	// then we save the timestamps in the session to handle replay on future channel joins
76
+	// three cases:
77
+	// 1. the user's PMs get played back immediately upon receiving this
78
+	// 2. if this is a new connection (from the server's POV), save the information
79
+	// and use it to process subsequent joins
80
+	// 3. if this is a reattach (from the server's POV), immediately play back
81
+	// history for channels that the client is already joined to. In this scenario,
82
+	// there are three total attempts to play the history:
83
+	//     3.1. During the initial reattach (no-op because the *playback privmsg
84
+	//          hasn't been received yet, but they negotiated the znc.in/playback
85
+	//          cap so we know we're going to receive it later)
86
+	//     3.2  Upon receiving the *playback privmsg, i.e., now: we should play
87
+	//          the relevant history lines
88
+	//     3.3  When the client sends a subsequent redundant JOIN line for those
89
+	//          channels; redundant JOIN is a complete no-op so we won't replay twice
90
+
78
 	config := client.server.Config()
91
 	config := client.server.Config()
79
 	if params[1] == "*" {
92
 	if params[1] == "*" {
80
 		items, _ := client.history.Between(after, before, false, config.History.ChathistoryMax)
93
 		items, _ := client.history.Between(after, before, false, config.History.ChathistoryMax)
95
 		before:  before,
108
 		before:  before,
96
 		targets: targets,
109
 		targets: targets,
97
 	}
110
 	}
111
+
112
+	for _, channel := range client.Channels() {
113
+		channel.autoReplayHistory(client, rb, "")
114
+		rb.Flush(true)
115
+	}
98
 }
116
 }

Loading…
Cancel
Save