From 4aadbbc16c0b485f4f5f2d620d2b17396d46b973 Mon Sep 17 00:00:00 2001 From: "diamondburned (Forefront)" Date: Mon, 8 Jun 2020 20:58:12 -0700 Subject: [PATCH] Bumped to v0.0.22 --- channel.go | 114 ++++++++++++++++++++++++++++++++++------------------- go.mod | 2 +- go.sum | 6 +++ message.go | 8 ++++ server.go | 5 +-- service.go | 26 +++++++----- 6 files changed, 106 insertions(+), 55 deletions(-) diff --git a/channel.go b/channel.go index ac45c26..66fb373 100644 --- a/channel.go +++ b/channel.go @@ -17,6 +17,7 @@ import ( // FetchBacklog is the number of messages to fake-fetch. const FetchBacklog = 35 +const maxBacklog = FetchBacklog * 2 // max number to add to before the next author, with rand.Intn(limit) + incr. const sameAuthorLimit = 12 @@ -30,8 +31,8 @@ type Channel struct { edit chan Message // id messageMutex sync.Mutex - messageIDs map[string]int messages []Message + messageixs map[uint32]int // indices // used for unique ID generation of messages incrID uint32 @@ -39,7 +40,6 @@ type Channel struct { // up to about 12 or so. check sameAuthorLimit. incrAuthor uint8 - // busyWg sync.WaitGroup } @@ -57,24 +57,26 @@ func (ch *Channel) ID() string { return strconv.Itoa(int(ch.id)) } -func (ch *Channel) Name(labeler cchat.LabelContainer) (func(), error) { - labeler.SetLabel(text.Rich{Content: ch.name}) - return func() {}, nil +func (ch *Channel) Name() text.Rich { + return text.Rich{Content: ch.name} } -func (ch *Channel) Nickname(labeler cchat.LabelContainer) (func(), error) { +func (ch *Channel) Nickname(labeler cchat.LabelContainer) error { + // Simulate IO. + simulateAustralianInternet() + labeler.SetLabel(ch.username) - return func() {}, nil + return nil } func (ch *Channel) JoinServer(container cchat.MessagesContainer) (func(), error) { // Is this a fresh channel? If yes, generate messages with some IO latency. - if ch.messageIDs == nil || len(ch.messages) == 0 { - // Emulate IO. - emulateAustralianInternet() + if len(ch.messages) == 0 || ch.messageixs == nil { + // Simulate IO. + simulateAustralianInternet() // Initialize. - ch.messageIDs = map[string]int{} + ch.messageixs = make(map[uint32]int, FetchBacklog) ch.messages = make([]Message, 0, FetchBacklog) // Allocate 2 channels that we won't clean up, because we're lazy. @@ -85,6 +87,11 @@ func (ch *Channel) JoinServer(container cchat.MessagesContainer) (func(), error) for i := 0; i < FetchBacklog; i++ { ch.addMessage(randomMessage(ch.nextID()), container) } + } else { + // Else, flush the old backlog over. + for i := range ch.messages { + container.CreateMessage(ch.messages[i]) + } } // Initialize channels for use. @@ -129,10 +136,15 @@ func (ch *Channel) JoinServer(container cchat.MessagesContainer) (func(), error) } func (ch *Channel) RawMessageContent(id string) (string, error) { + i, err := parseID(id) + if err != nil { + return "", err + } + ch.messageMutex.Lock() defer ch.messageMutex.Unlock() - ix, ok := ch.messageIDs[id] + ix, ok := ch.messageixs[i] if !ok { return "", errors.New("Message not found") } @@ -141,63 +153,81 @@ func (ch *Channel) RawMessageContent(id string) (string, error) { } func (ch *Channel) EditMessage(id, content string) error { - emulateAustralianInternet() + i, err := parseID(id) + if err != nil { + return err + } + + simulateAustralianInternet() ch.messageMutex.Lock() defer ch.messageMutex.Unlock() - ix, ok := ch.messageIDs[id] + ix, ok := ch.messageixs[i] if !ok { - return errors.New("ID not found") + return errors.New("Message not found.") } - msg := ch.messages[ix] - msg.content = content + m := ch.messages[ix] + m.content = content - ch.messages[ix] = msg - ch.edit <- msg + ch.messages[ix] = m + ch.edit <- m return nil } func (ch *Channel) addMessage(msg Message, container cchat.MessagesContainer) { ch.messageMutex.Lock() - defer ch.messageMutex.Unlock() // Clean up the backlog. - if len(ch.messages) > FetchBacklog*2 { + if clean := len(ch.messages) - maxBacklog; clean > 0 { + // Remove them from the map. + for _, m := range ch.messages[:clean] { + delete(ch.messageixs, m.id) + } + // Cut the message IDs away by shifting the slice. + ch.messages = append(ch.messages[:0], ch.messages[clean:]...) } + + ch.messageixs[msg.id] = len(ch.messages) ch.messages = append(ch.messages, msg) + + ch.messageMutex.Unlock() + container.CreateMessage(msg) } func (ch *Channel) updateMessage(msg Message, container cchat.MessagesContainer) { ch.messageMutex.Lock() - defer ch.messageMutex.Unlock() - ix, ok := ch.messageIDs[msg.ID()] - if !ok { - // Unknown message. - return + i, ok := ch.messageixs[msg.id] + if ok { + ch.messages[i] = msg } - ch.messages[ix] = msg - container.UpdateMessage(msg) + ch.messageMutex.Unlock() + + if ok { + container.UpdateMessage(msg) + } } func (ch *Channel) deleteMessage(msg MessageHeader, container cchat.MessagesContainer) { ch.messageMutex.Lock() - defer ch.messageMutex.Unlock() - ix, ok := ch.messageIDs[msg.ID()] - if !ok { - return + i, ok := ch.messageixs[msg.id] + if ok { + ch.messages = append(ch.messages[:i], ch.messages[i+1:]...) + delete(ch.messageixs, msg.id) } - delete(ch.messageIDs, msg.ID()) - ch.messages = append(ch.messages[:ix], ch.messages[ix+1:]...) - container.DeleteMessage(msg) + ch.messageMutex.Unlock() + + if ok { + container.DeleteMessage(msg) + } } // randomMsgID returns a random recent message ID. @@ -228,6 +258,7 @@ func (ch *Channel) randomMsg() (msg Message) { // Should we generate a new author for the new message? if ch.incrAuthor > sameAuthorLimit { msg = randomMessage(ch.nextID()) + ch.incrAuthor = 0 // reset } else { last := ch.messages[len(ch.messages)-1] msg = randomMessageWithAuthor(ch.nextID(), last.author) @@ -241,7 +272,7 @@ func (ch *Channel) nextID() (id uint32) { } func (ch *Channel) SendMessage(msg cchat.SendableMessage) error { - if emulateAustralianInternet() { + if simulateAustralianInternet() { return errors.New("Failed to send message: Australian Internet unsupported.") } @@ -258,7 +289,7 @@ func (ch *Channel) SendMessage(msg cchat.SendableMessage) error { const ( DeleteAction = "Delete" NoopAction = "No-op" - BestTrapAction = "Print best trap" + BestTrapAction = "What's the best trap?" ) func (ch *Channel) MessageActions() []string { @@ -279,8 +310,8 @@ func (ch *Channel) DoMessageAction(c cchat.MessagesContainer, action, messageID return errors.Wrap(err, "Invalid ID") } - // Emulate IO. - emulateAustralianInternet() + // Simulate IO. + simulateAustralianInternet() ch.deleteMessage(MessageHeader{uint32(i), time.Now()}, c) case NoopAction: @@ -321,6 +352,7 @@ func generateChannels(s *Session, amount int) []cchat.Server { }, } } + return channels } @@ -328,8 +360,8 @@ func randClamp(min, max int) int { return rand.Intn(max-min) + min } -// emulate network latency -func emulateAustralianInternet() (lost bool) { +// simulate network latency +func simulateAustralianInternet() (lost bool) { var ms = randClamp(internetMinLatency, internetMaxLatency) <-time.After(time.Duration(ms) * time.Millisecond) diff --git a/go.mod b/go.mod index 9401682..2c1f5a0 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,6 @@ go 1.14 require ( github.com/Pallinder/go-randomdata v1.2.0 - github.com/diamondburned/cchat v0.0.19 + github.com/diamondburned/cchat v0.0.22 github.com/pkg/errors v0.9.1 ) diff --git a/go.sum b/go.sum index 7933d67..f51b5d9 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,12 @@ github.com/diamondburned/cchat v0.0.18 h1:1nTPcYEumpLCangEV/oblNkZrZG9dQ432Ov1qv github.com/diamondburned/cchat v0.0.18/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= github.com/diamondburned/cchat v0.0.19 h1:XPZDqOR8P1tzTWVkYzRb6yZ1H6yU8tSUReGjklIqarw= github.com/diamondburned/cchat v0.0.19/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= +github.com/diamondburned/cchat v0.0.20 h1:jYveuCTscVo1GiixgEpjALBgRtsxv+ITvFm7jjNRh+k= +github.com/diamondburned/cchat v0.0.20/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= +github.com/diamondburned/cchat v0.0.21 h1:2PeC6hC4fFmi3gr2roaF4ojA3PYuZ1Gb5NQUCEiym+M= +github.com/diamondburned/cchat v0.0.21/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= +github.com/diamondburned/cchat v0.0.22 h1:jmt0y3rMlFLbBP15Pb/GeGmeL72nx7vOvZoBA3herFs= +github.com/diamondburned/cchat v0.0.22/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU= github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/message.go b/message.go index 5029b18..46b8bbb 100644 --- a/message.go +++ b/message.go @@ -20,6 +20,14 @@ type MessageHeader struct { var _ cchat.MessageHeader = (*Message)(nil) +func parseID(id string) (uint32, error) { + i, err := strconv.Atoi(id) + if err != nil { + return 0, err + } + return uint32(i), nil +} + func (m MessageHeader) ID() string { return strconv.Itoa(int(m.id)) } diff --git a/server.go b/server.go index fe8304d..7d2bd10 100644 --- a/server.go +++ b/server.go @@ -26,9 +26,8 @@ func (sv *Server) ID() string { return strconv.Itoa(int(sv.id)) } -func (sv *Server) Name(labeler cchat.LabelContainer) (func(), error) { - labeler.SetLabel(text.Rich{Content: sv.name}) - return func() {}, nil +func (sv *Server) Name() text.Rich { + return text.Rich{Content: sv.name} } func (sv *Server) Servers(container cchat.ServersContainer) error { diff --git a/service.go b/service.go index f3d042b..02703d4 100644 --- a/service.go +++ b/service.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "strconv" + "time" "github.com/diamondburned/cchat" "github.com/diamondburned/cchat/services" @@ -26,12 +27,12 @@ var ( _ cchat.SessionRestorer = (*Service)(nil) ) -func (s Service) Name() string { - return "Mock" +func (s Service) Name() text.Rich { + return text.Rich{Content: "Mock"} } func (s Service) RestoreSession(storage map[string]string) (cchat.Session, error) { - if emulateAustralianInternet() { + if simulateAustralianInternet() { return nil, errors.New("Restore failed: server machine broke") } @@ -69,7 +70,7 @@ func (Authenticator) AuthenticateForm() []cchat.AuthenticateEntry { func (Authenticator) Authenticate(form []string) (cchat.Session, error) { // SLOW IO TIME. - if emulateAustralianInternet() { + if simulateAustralianInternet() { return nil, errors.New("Authentication timed out.") } @@ -77,7 +78,7 @@ func (Authenticator) Authenticate(form []string) (cchat.Session, error) { } var ( - // channel.go @ emulateAustralianInternet + // channel.go @ simulateAustralianInternet internetCanFail = true // 500ms ~ 3s internetMinLatency = 500 @@ -139,19 +140,24 @@ func (s *Session) ID() string { return s.username } -func (s *Session) Name(labeler cchat.LabelContainer) (func(), error) { - labeler.SetLabel(text.Rich{Content: s.username}) - return func() {}, nil +func (s *Session) Name() text.Rich { + return text.Rich{Content: s.username} } func (s *Session) Servers(container cchat.ServersContainer) error { + // Simulate slight IO. + <-time.After(time.Second) + container.SetServers(s.servers) return nil } -func (s *Session) Icon(iconer cchat.IconContainer) (func(), error) { +func (s *Session) Icon(iconer cchat.IconContainer) error { + // Simulate IO. + simulateAustralianInternet() + iconer.SetIcon(avatarURL) - return func() {}, nil + return nil } func (s *Session) Save() (map[string]string, error) {