From 82902e9dc3ad67c49e4f9381b83d38a659efa083 Mon Sep 17 00:00:00 2001 From: bt Date: Sat, 16 May 2026 19:15:21 +0200 Subject: Add history reading --- client/client.go | 12 ++++++++++++ cmd/client/main.go | 9 +++++++++ core/data.go | 3 +++ core/payload.go | 41 +++++++++++++++++++++++++++++++++++++++++ docs/rfc.md | 3 ++- server/user.go | 23 +++++++++++++++++++++++ 6 files changed, 90 insertions(+), 1 deletion(-) diff --git a/client/client.go b/client/client.go index 775fbb6..b07bc27 100644 --- a/client/client.go +++ b/client/client.go @@ -4,6 +4,7 @@ import ( "errors" "io" "net" + "time" "go.rctt.net/solec/core" ) @@ -83,6 +84,17 @@ func (c *Client) Leave(channel string) error { return core.Send(c.conn, umod) } +func (c *Client) GetHistory(channel string, since time.Time, count, offset int) error { + hist := core.History{ + Channel: channel, + Since: since, + Count: int64(count), + Offset: int64(offset), + } + + return core.Send(c.conn, hist) +} + func (c *Client) read() { for { payload, err := core.Read(c.conn) diff --git a/cmd/client/main.go b/cmd/client/main.go index b107d93..bc9f4ff 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -5,6 +5,7 @@ import ( "log" "net" "strings" + "time" "go.rctt.net/solec/client" "go.rctt.net/solec/core" @@ -32,6 +33,7 @@ func main() { prompt.Commands["send"] = sendMessage prompt.Commands["join"] = join prompt.Commands["leave"] = leave + prompt.Commands["history"] = history flag.StringVar(&serverAddr, "a", "localhost:9999", "Server address:port") flag.StringVar(&user, "u", "user", "username") @@ -68,3 +70,10 @@ func leave(args []string) { log.Println("cannot leave channel:", err) } } + +func history(args []string) { + err := c.GetHistory(args[0], time.Time{}, 99999999, 0) + if err != nil { + log.Println("cannot read channel history:", err) + } +} diff --git a/core/data.go b/core/data.go index 2a98347..4d18604 100644 --- a/core/data.go +++ b/core/data.go @@ -24,6 +24,7 @@ const ( PayloadMessage = 0x05 PayloadServerAuth = 0x06 PayloadUsermode = 0x07 + PayloadHistory = 0x08 PayloadTest = 0xFF ) @@ -143,6 +144,8 @@ func Decode(buf io.Reader) (any, error) { return DecodeMessage(buf) case PayloadUsermode: return DecodeUsermode(buf) + case PayloadHistory: + return DecodeHistory(buf) case PayloadTest: return DecodeTest(buf) default: diff --git a/core/payload.go b/core/payload.go index 3c3afa1..b54a8cd 100644 --- a/core/payload.go +++ b/core/payload.go @@ -185,6 +185,47 @@ func DecodeUsermode(buf io.Reader) (Usermode, error) { return u, nil } +type History struct { + Channel string + Since time.Time + Count int64 + Offset int64 +} + +func (h History) Wrap() (PayloadType, []any) { + return PayloadHistory, []any{ + h.Channel, + h.Since, + h.Count, + h.Offset, + } +} + +func DecodeHistory(buf io.Reader) (History, error) { + var h History + err := decodeString(buf, &h.Channel) + if err != nil { + return h, err + } + + err = decodeTime(buf, &h.Since) + if err != nil { + return h, err + } + + err = decodeNumeric(buf, &h.Count) + if err != nil { + return h, err + } + + err = decodeNumeric(buf, &h.Offset) + if err != nil { + return h, err + } + + return h, nil +} + type Test struct { Num1 uint8 Time1 time.Time diff --git a/docs/rfc.md b/docs/rfc.md index b5fa585..e60527f 100644 --- a/docs/rfc.md +++ b/docs/rfc.md @@ -163,6 +163,7 @@ Payload type attributes describes following characteristics: | 0x05 | Message | SC | | 0x06 | ServerAuth | S | | 0x07 | UserMode | C | +| 0x08 | History. | C | | 0xFF | Test | R | ### Success @@ -243,7 +244,7 @@ example: joining, leaving or setting privilages. | 0x00 | none | | 0x01 | in_channel | -### GetHistory +### History Read messages previously send to a specific channel. User has to member of the channel to perform this action. *since* field specifies start of time range for which history should be retrieved. *count* specifes how many messages should be returned in a single response. *GetHistory* is a locking sequence and it cannot be cancelled while in progress so *count* should be set relatively low. To get more messages use multiple requests with incremented *offset*. diff --git a/server/user.go b/server/user.go index 002ed89..6b0e946 100644 --- a/server/user.go +++ b/server/user.go @@ -118,6 +118,8 @@ func (s *Server) handleUserPayload(user *User, sender net.Conn, payload any) err return s.handleMessage(sender, core.ConnTypeUser, v) case core.Usermode: return s.handleUsermode(user, sender, v) + case core.History: + return s.handleHistory(user, sender, v) default: return core.ErrUnexpectedPayloadType } @@ -151,3 +153,24 @@ func (s *Server) handleUsermode(user *User, conn net.Conn, mode core.Usermode) e return nil } + +func (s *Server) handleHistory(user *User, conn net.Conn, hist core.History) error { + // TODO: Add permissions check + + messages, err := s.Storage.Read(hist.Channel, hist.Since, int(hist.Count), int(hist.Offset)) + if err != nil { + return err + } + + for _, m := range messages { + data, err := core.Encode(m) + if err != nil { + return err + } + if _, err := conn.Write(data); err != nil { + return err + } + } + + return nil +} -- cgit v1.2.3