aboutsummaryrefslogtreecommitdiff
path: root/internal/chat/chan.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--internal/chat/chan.go69
1 files changed, 69 insertions, 0 deletions
diff --git a/internal/chat/chan.go b/internal/chat/chan.go
new file mode 100644
index 0000000..ae78bb6
--- /dev/null
+++ b/internal/chat/chan.go
@@ -0,0 +1,69 @@
+package chat
+
+import (
+ "context"
+ "log/slog"
+ "sync"
+ "time"
+)
+
+type Channel struct {
+ Name string
+ Users map[*User]struct{}
+ Events chan any
+ mu sync.RWMutex
+}
+
+func (c *Channel) Listen(ctx context.Context) {
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case ev := <-c.Events:
+ c.processEvent(ev)
+ }
+ }
+}
+
+func (c *Channel) processEvent(ev any) {
+ slog.Info("channel event", slog.String("channel", c.Name), slog.Any("event", ev))
+
+ for u := range c.Users {
+ select {
+ case u.Events <- ev:
+ default:
+ }
+ }
+}
+
+func (c *Channel) Join(u *User) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if _, ok := c.Users[u]; ok {
+ return
+ }
+ c.Events <- UserJoined{
+ User: u,
+ Time: time.Now(),
+ Chan: c,
+ }
+
+ c.Users[u] = struct{}{}
+}
+
+func (c *Channel) Leave(u *User) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if _, ok := c.Users[u]; !ok {
+ return
+ }
+ c.Events <- UserLeft{
+ User: u,
+ Time: time.Now(),
+ Chan: c,
+ }
+
+ delete(c.Users, u)
+}