From ee63c0a9efdeb2c0c6dedd5cf55e3f020a96ef99 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Tue, 25 Jan 2022 19:27:58 +0300 Subject: [PATCH] Implement GROUP command --- README.md | 2 +- internal/backend/sqlite/sqlite.go | 5 +++++ internal/backend/storage_backend.go | 1 + internal/protocol/constants.go | 2 ++ internal/server/handler.go | 35 +++++++++++++++++++++++++++++ internal/server/session.go | 3 +++ 6 files changed, 47 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c96181f..0567513 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ - :heavy_check_mark: `QUIT` - :x: `ARTICLE` - :x: `BODY` -- :x: `GROUP` +- :heavy_check_mark: `GROUP` - :x: `HDR` - :x: `HEAD` - :x: `HELP` diff --git a/internal/backend/sqlite/sqlite.go b/internal/backend/sqlite/sqlite.go index e4eb9c0..cdfb3e5 100644 --- a/internal/backend/sqlite/sqlite.go +++ b/internal/backend/sqlite/sqlite.go @@ -83,3 +83,8 @@ func (sb *SQLiteBackend) GetGroupLowWaterMark(g models.Group) (int, error) { var waterMark int return waterMark, sb.db.Get(&waterMark, "SELECT article_id FROM articles_to_groups WHERE group_id = ? ORDER BY article_id LIMIT 1", g.ID) } + +func (sb *SQLiteBackend) GetGroup(groupName string) (models.Group, error) { + var group models.Group + return group, sb.db.Get(&group, "SELECT * FROM groups WHERE group_name = ?", groupName) +} diff --git a/internal/backend/storage_backend.go b/internal/backend/storage_backend.go index 6fe0a4a..3a01bac 100644 --- a/internal/backend/storage_backend.go +++ b/internal/backend/storage_backend.go @@ -9,6 +9,7 @@ const ( type StorageBackend interface { ListGroups() ([]models.Group, error) ListGroupsByPattern(pattern string) ([]models.Group, error) + GetGroup(groupName string) (models.Group, error) GetArticlesCount(g models.Group) (int, error) GetGroupLowWaterMark(g models.Group) (int, error) GetGroupHighWaterMark(g models.Group) (int, error) diff --git a/internal/protocol/constants.go b/internal/protocol/constants.go index d5b4414..49a7f52 100644 --- a/internal/protocol/constants.go +++ b/internal/protocol/constants.go @@ -11,6 +11,7 @@ const ( CommandDate = "DATE" CommandMode = "MODE" CommandList = "LIST" + CommandGroup = "GROUP" ) const ( @@ -34,4 +35,5 @@ const ( MessageErrorHappened = "403 Failed to process command:" MessageListOfNewsgroupsFollows = "215 list of newsgroups follows" MessageSyntaxError = "501 Syntax Error" + MessageNoSuchGroup = "411 No such newsgroup" ) diff --git a/internal/server/handler.go b/internal/server/handler.go index 30c340f..7fb3260 100644 --- a/internal/server/handler.go +++ b/internal/server/handler.go @@ -1,6 +1,7 @@ package server import ( + "database/sql" "fmt" "github.com/ChronosX88/yans/internal/backend" "github.com/ChronosX88/yans/internal/models" @@ -23,6 +24,7 @@ func NewHandler(b backend.StorageBackend) *Handler { protocol.CommandQuit: h.handleQuit, protocol.CommandList: h.handleList, protocol.CommandMode: h.handleModeReader, + protocol.CommandGroup: h.handleGroup, } return h } @@ -143,6 +145,39 @@ func (h *Handler) handleModeReader(s *Session, arguments []string, id uint) erro return s.tconn.PrintfLine(protocol.MessageReaderModePostingProhibited) // TODO vary on auth status } +func (h *Handler) handleGroup(s *Session, arguments []string, id uint) error { + s.tconn.StartResponse(id) + defer s.tconn.EndResponse(id) + + if len(arguments) == 0 || len(arguments) > 1 { + return s.tconn.PrintfLine(protocol.MessageSyntaxError) + } + + g, err := h.backend.GetGroup(arguments[0]) + if err != nil { + if err == sql.ErrNoRows { + return s.tconn.PrintfLine(protocol.MessageNoSuchGroup) + } + return err + } + highWaterMark, err := h.backend.GetGroupHighWaterMark(g) + if err != nil { + return err + } + lowWaterMark, err := h.backend.GetGroupLowWaterMark(g) + if err != nil { + return err + } + articlesCount, err := h.backend.GetArticlesCount(g) + if err != nil { + return err + } + + s.currentGroup = &g + + return s.tconn.PrintfLine("211 %d %d %d %s", articlesCount, lowWaterMark, highWaterMark, g.GroupName) +} + func (h *Handler) Handle(s *Session, message string, id uint) error { splittedMessage := strings.Split(message, " ") for i, v := range splittedMessage { diff --git a/internal/server/session.go b/internal/server/session.go index 533609e..8a2dcb5 100644 --- a/internal/server/session.go +++ b/internal/server/session.go @@ -2,6 +2,7 @@ package server import ( "context" + "github.com/ChronosX88/yans/internal/models" "github.com/ChronosX88/yans/internal/protocol" "io" "log" @@ -24,6 +25,8 @@ type Session struct { id string closed chan<- bool h *Handler + + currentGroup *models.Group mode SessionMode }