1
0
Fork 0
mirror of https://github.com/diamondburned/cchat-mock.git synced 2024-11-14 09:52:45 +00:00
cchat-mock/channel.go

147 lines
3.2 KiB
Go
Raw Normal View History

2020-05-20 07:13:12 +00:00
package mock
import (
"errors"
"math/rand"
2020-05-20 21:23:44 +00:00
"strconv"
2020-05-22 20:57:35 +00:00
"strings"
2020-05-20 07:13:12 +00:00
"sync/atomic"
"time"
"github.com/Pallinder/go-randomdata"
"github.com/diamondburned/cchat"
)
type Channel struct {
2020-05-23 02:44:50 +00:00
session *Session
2020-05-20 21:23:44 +00:00
id uint32
2020-05-20 07:13:12 +00:00
name string
done chan struct{}
2020-06-03 23:13:06 +00:00
send chan cchat.SendableMessage // ideally this should be another type
2020-05-20 07:13:12 +00:00
lastID uint32
}
var (
2020-05-22 20:57:35 +00:00
_ cchat.Server = (*Channel)(nil)
_ cchat.ServerMessage = (*Channel)(nil)
_ cchat.ServerMessageSender = (*Channel)(nil)
_ cchat.ServerMessageSendCompleter = (*Channel)(nil)
2020-05-20 07:13:12 +00:00
)
2020-05-20 21:23:44 +00:00
func (ch *Channel) ID() string {
return strconv.Itoa(int(ch.id))
}
2020-05-20 07:13:12 +00:00
func (ch *Channel) Name() (string, error) {
return ch.name, nil
}
func (ch *Channel) JoinServer(container cchat.MessagesContainer) error {
2020-06-03 23:13:06 +00:00
var lastAuthor string
var nextID = func() uint32 {
id := ch.lastID
ch.lastID++
return id
}
var readID = func() uint32 {
return atomic.LoadUint32(&ch.lastID)
}
var randomMsg = func() Message {
msg := randomMessage(nextID())
lastAuthor = msg.author
return msg
2020-05-20 07:13:12 +00:00
}
// Write the backlog.
for i := 0; i < 30; i++ {
2020-06-03 23:13:06 +00:00
container.CreateMessage(randomMsg())
2020-05-20 07:13:12 +00:00
}
ch.done = make(chan struct{})
2020-06-03 23:13:06 +00:00
ch.send = make(chan cchat.SendableMessage)
2020-05-20 07:13:12 +00:00
go func() {
2020-06-03 23:13:06 +00:00
ticker := time.NewTicker(4 * time.Second)
defer ticker.Stop()
editTick := time.NewTicker(10 * time.Second)
defer editTick.Stop()
deleteTick := time.NewTicker(15 * time.Second)
defer deleteTick.Stop()
2020-05-20 07:13:12 +00:00
for {
select {
case msg := <-ch.send:
2020-06-03 23:13:06 +00:00
container.CreateMessage(echoMessage(msg, nextID(), ch.session.username))
case <-ticker.C:
container.CreateMessage(randomMsg())
case <-editTick.C:
container.UpdateMessage(newRandomMessage(readID(), lastAuthor))
case <-deleteTick.C:
container.DeleteMessage(newEmptyMessage(readID(), lastAuthor))
2020-05-20 07:13:12 +00:00
case <-ch.done:
return
}
}
}()
return nil
}
func (ch *Channel) LeaveServer() error {
ch.done <- struct{}{}
2020-06-03 23:13:06 +00:00
ch.send = nil
2020-05-20 07:13:12 +00:00
return nil
}
func (ch *Channel) SendMessage(msg cchat.SendableMessage) error {
if emulateAustralianInternet() {
return errors.New("Failed to send message: Australian Internet unsupported.")
}
2020-06-03 23:13:06 +00:00
go func() {
// Make no guarantee that a message may arrive immediately when the
// function exits.
<-time.After(time.Second)
ch.send <- msg
}()
2020-05-20 07:13:12 +00:00
return nil
}
2020-05-22 20:57:35 +00:00
func (ch *Channel) CompleteMessage(words []string, i int) []string {
switch {
case strings.HasPrefix("complete", words[i]):
words[i] = "complete"
case strings.HasPrefix("me", words[i]) && i > 0 && words[i-1] == "complete":
words[i] = "me"
default:
return nil
}
return words
}
2020-05-23 02:44:50 +00:00
func generateChannels(s *Session, amount int) []cchat.Server {
2020-05-20 07:13:12 +00:00
var channels = make([]cchat.Server, amount)
for i := range channels {
2020-05-20 21:23:44 +00:00
channels[i] = &Channel{
session: s,
id: atomic.AddUint32(&s.lastid, 1),
name: "#" + randomdata.Noun(),
}
2020-05-20 07:13:12 +00:00
}
return channels
}
// emulate network latency
func emulateAustralianInternet() (lost bool) {
var ms = rand.Intn(internetMaxLatency-internetMinLatency) + internetMinLatency
2020-05-20 07:13:12 +00:00
<-time.After(time.Duration(ms) * time.Millisecond)
// because australia, drop packet 20% of the time if internetCanFail is
// true.
return internetCanFail && rand.Intn(100) < 20
}