package ircmw import ( "context" "strings" "time" "tuxpa.in/a/irc/pkg/ircv3" ) type Capabilities struct { pending int } var capabilitiesKey struct{} func AddPending(ctx context.Context, i int) { val, ok := ctx.Value(capabilitiesKey).(*Capabilities) if !ok { return } val.pending += i } func (c *Capabilities) Middleware(next ircv3.Handler) ircv3.Handler { return ircv3.HandlerFunc(func(ctx context.Context, w ircv3.MessageWriter, m *ircv3.Message) { ctx = context.WithValue(ctx, capabilitiesKey, c) if m.Command == "" { c.pending++ w.WriteMessage(ircv3.NewMessage("CAP", "LS", "302")) } next.Handle(ctx, w, m) if m.Command == "CAP" && m.Param(0) == "*" && m.Param(1) == "LS" { c.pending-- } if c.pending == 0 { c.pending = -1 w.WriteMessage(ircv3.NewMessage("CAP", "END")) } }) } func CapabilityExchange(next ircv3.Handler) ircv3.Handler { return ircv3.HandlerFunc(func(ctx context.Context, w ircv3.MessageWriter, m *ircv3.Message) { next.Handle(ctx, w, m) }) } var keyServerTime struct{} func ServerTime(ctx context.Context) time.Time { val, ok := ctx.Value(keyServerTime).(time.Time) if !ok { return time.Time{} } return val } func CapabilityServerTime(next ircv3.Handler) ircv3.Handler { enabled := false return ircv3.HandlerFunc(func(ctx context.Context, w ircv3.MessageWriter, m *ircv3.Message) { if m.Command == "CAP" && m.Param(0) == "*" && m.Param(1) == "LS" { if strings.Contains(m.Param(2), "server-time") { AddPending(ctx, 1) w.WriteMessage(ircv3.NewMessage("CAP", "REQ", "server-time")) } } if m.Command == "CAP" && m.Param(1) == "ACK" && m.Param(2) == "server-time" { AddPending(ctx, -1) enabled = true } if enabled { tString := m.Tags.Get("time") if tString != "" { parsedTime, err := time.Parse("2006-01-02T15:04:05.000Z", tString) if err == nil { ctx = context.WithValue(ctx, keyServerTime, parsedTime) } } } next.Handle(ctx, w, m) }) }