3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-12-22 18:52:41 +01:00

Merge pull request #546 from slingamn/issue536.3

fix #536
This commit is contained in:
Daniel Oaks 2019-06-10 01:13:02 +10:00 committed by GitHub
commit dc322f8fd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 5 deletions

View File

@ -624,12 +624,16 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
// TODO #259 can be implemented as Flush(false) (i.e., nonblocking) while holding joinPartMutex // TODO #259 can be implemented as Flush(false) (i.e., nonblocking) while holding joinPartMutex
rb.Flush(true) rb.Flush(true)
channel.autoReplayHistory(client, rb, message.Msgid)
}
func (channel *Channel) autoReplayHistory(client *Client, rb *ResponseBuffer, skipMsgid string) {
// autoreplay any messages as necessary // autoreplay any messages as necessary
config := channel.server.Config() config := channel.server.Config()
var items []history.Item var items []history.Item
if rb.session.zncPlaybackTimes != nil && (rb.session.zncPlaybackTimes.targets == nil || rb.session.zncPlaybackTimes.targets[chcfname]) { if rb.session.zncPlaybackTimes != nil && (rb.session.zncPlaybackTimes.targets == nil || rb.session.zncPlaybackTimes.targets[channel.NameCasefolded()]) {
items, _ = channel.history.Between(rb.session.zncPlaybackTimes.after, rb.session.zncPlaybackTimes.before, false, config.History.ChathistoryMax) items, _ = channel.history.Between(rb.session.zncPlaybackTimes.after, rb.session.zncPlaybackTimes.before, false, config.History.ChathistoryMax)
} else { } else if !rb.session.HasHistoryCaps() {
var replayLimit int var replayLimit int
customReplayLimit := client.AccountSettings().AutoreplayLines customReplayLimit := client.AccountSettings().AutoreplayLines
if customReplayLimit != nil { if customReplayLimit != nil {
@ -648,7 +652,7 @@ func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *Resp
// remove the client's own JOIN line from the replay // remove the client's own JOIN line from the replay
numItems := len(items) numItems := len(items)
for i := len(items) - 1; 0 <= i; i-- { for i := len(items) - 1; 0 <= i; i-- {
if items[i].Message.Msgid == message.Msgid { if items[i].Message.Msgid == skipMsgid {
// zero'ed items will not be replayed because their `Type` field is not recognized // zero'ed items will not be replayed because their `Type` field is not recognized
items[i] = history.Item{} items[i] = history.Item{}
numItems-- numItems--

View File

@ -162,6 +162,13 @@ func (session *Session) SetDestroyed() {
atomic.StoreUint32(&session.destroyed, 1) atomic.StoreUint32(&session.destroyed, 1)
} }
// returns whether the client supports a smart history replay cap,
// and therefore autoreplay-on-join and similar should be suppressed
func (session *Session) HasHistoryCaps() bool {
// TODO the chathistory cap will go here as well
return session.capabilities.Has(caps.ZNCPlayback)
}
// WhoWas is the subset of client details needed to answer a WHOWAS query // WhoWas is the subset of client details needed to answer a WHOWAS query
type WhoWas struct { type WhoWas struct {
nick string nick string
@ -473,6 +480,13 @@ func (client *Client) playReattachMessages(session *Session) {
client.server.playRegistrationBurst(session) client.server.playRegistrationBurst(session)
for _, channel := range session.client.Channels() { for _, channel := range session.client.Channels() {
channel.playJoinForSession(session) channel.playJoinForSession(session)
// clients should receive autoreplay-on-join lines, if applicable;
// if they negotiated znc.in/playback or chathistory, they will receive nothing,
// because those caps disable autoreplay-on-join and they haven't sent the relevant
// *playback PRIVMSG or CHATHISTORY command yet
rb := NewResponseBuffer(session)
channel.autoReplayHistory(client, rb, "")
rb.Send(true)
} }
} }

View File

@ -73,8 +73,21 @@ func zncPlaybackHandler(client *Client, command string, params []string, rb *Res
var targets map[string]bool var targets map[string]bool
// OK: the user's PMs get played back immediately on receiving this, // three cases:
// then we save the timestamps in the session to handle replay on future channel joins // 1. the user's PMs get played back immediately upon receiving this
// 2. if this is a new connection (from the server's POV), save the information
// and use it to process subsequent joins
// 3. if this is a reattach (from the server's POV), immediately play back
// history for channels that the client is already joined to. In this scenario,
// there are three total attempts to play the history:
// 3.1. During the initial reattach (no-op because the *playback privmsg
// hasn't been received yet, but they negotiated the znc.in/playback
// cap so we know we're going to receive it later)
// 3.2 Upon receiving the *playback privmsg, i.e., now: we should play
// the relevant history lines
// 3.3 When the client sends a subsequent redundant JOIN line for those
// channels; redundant JOIN is a complete no-op so we won't replay twice
config := client.server.Config() config := client.server.Config()
if params[1] == "*" { if params[1] == "*" {
items, _ := client.history.Between(after, before, false, config.History.ChathistoryMax) items, _ := client.history.Between(after, before, false, config.History.ChathistoryMax)
@ -95,4 +108,9 @@ func zncPlaybackHandler(client *Client, command string, params []string, rb *Res
before: before, before: before,
targets: targets, targets: targets,
} }
for _, channel := range client.Channels() {
channel.autoReplayHistory(client, rb, "")
rb.Flush(true)
}
} }