Implement NEWGROUPS command

This commit is contained in:
ChronosX88 2022-01-26 00:29:30 +03:00
parent ee63c0a9ef
commit e8aa350c53
Signed by: ChronosXYZ
GPG Key ID: 085A69A82C8C511A
5 changed files with 79 additions and 5 deletions

View File

@ -28,7 +28,7 @@
- :x: `IHAVE` - :x: `IHAVE`
- :x: `LAST` - :x: `LAST`
- :x: `LISTGROUP` - :x: `LISTGROUP`
- :x: `NEWGROUPS` - :heavy_check_mark: `NEWGROUPS`
- :x: `NEWNEWS` - :x: `NEWNEWS`
- :x: `NEXT` - :x: `NEXT`
- :x: `OVER` - :x: `OVER`

View File

@ -88,3 +88,8 @@ func (sb *SQLiteBackend) GetGroup(groupName string) (models.Group, error) {
var group models.Group var group models.Group
return group, sb.db.Get(&group, "SELECT * FROM groups WHERE group_name = ?", groupName) return group, sb.db.Get(&group, "SELECT * FROM groups WHERE group_name = ?", groupName)
} }
func (sb *SQLiteBackend) GetNewGroupsSince(timestamp int64) ([]models.Group, error) {
var groups []models.Group
return groups, sb.db.Select(&groups, "SELECT * FROM groups WHERE created_at > ?", timestamp)
}

View File

@ -10,6 +10,7 @@ type StorageBackend interface {
ListGroups() ([]models.Group, error) ListGroups() ([]models.Group, error)
ListGroupsByPattern(pattern string) ([]models.Group, error) ListGroupsByPattern(pattern string) ([]models.Group, error)
GetGroup(groupName string) (models.Group, error) GetGroup(groupName string) (models.Group, error)
GetNewGroupsSince(timestamp int64) ([]models.Group, error)
GetArticlesCount(g models.Group) (int, error) GetArticlesCount(g models.Group) (int, error)
GetGroupLowWaterMark(g models.Group) (int, error) GetGroupLowWaterMark(g models.Group) (int, error)
GetGroupHighWaterMark(g models.Group) (int, error) GetGroupHighWaterMark(g models.Group) (int, error)

View File

@ -12,6 +12,7 @@ const (
CommandMode = "MODE" CommandMode = "MODE"
CommandList = "LIST" CommandList = "LIST"
CommandGroup = "GROUP" CommandGroup = "GROUP"
CommandNewGroups = "NEWGROUPS"
) )
const ( const (
@ -34,6 +35,7 @@ const (
MessageUnknownCommand = "500 Unknown command" MessageUnknownCommand = "500 Unknown command"
MessageErrorHappened = "403 Failed to process command:" MessageErrorHappened = "403 Failed to process command:"
MessageListOfNewsgroupsFollows = "215 list of newsgroups follows" MessageListOfNewsgroupsFollows = "215 list of newsgroups follows"
MessageNewGroupsListOfNewsgroupsFollows = "231 list of new newsgroups follows"
MessageSyntaxError = "501 Syntax Error" MessageSyntaxError = "501 Syntax Error"
MessageNoSuchGroup = "411 No such newsgroup" MessageNoSuchGroup = "411 No such newsgroup"
) )

View File

@ -25,6 +25,7 @@ func NewHandler(b backend.StorageBackend) *Handler {
protocol.CommandList: h.handleList, protocol.CommandList: h.handleList,
protocol.CommandMode: h.handleModeReader, protocol.CommandMode: h.handleModeReader,
protocol.CommandGroup: h.handleGroup, protocol.CommandGroup: h.handleGroup,
protocol.CommandNewGroups: h.handleNewGroups,
} }
return h return h
} }
@ -157,19 +158,20 @@ func (h *Handler) handleGroup(s *Session, arguments []string, id uint) error {
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return s.tconn.PrintfLine(protocol.MessageNoSuchGroup) return s.tconn.PrintfLine(protocol.MessageNoSuchGroup)
} } else {
return err return err
} }
}
highWaterMark, err := h.backend.GetGroupHighWaterMark(g) highWaterMark, err := h.backend.GetGroupHighWaterMark(g)
if err != nil { if err != nil && err != sql.ErrNoRows {
return err return err
} }
lowWaterMark, err := h.backend.GetGroupLowWaterMark(g) lowWaterMark, err := h.backend.GetGroupLowWaterMark(g)
if err != nil { if err != nil && err != sql.ErrNoRows {
return err return err
} }
articlesCount, err := h.backend.GetArticlesCount(g) articlesCount, err := h.backend.GetArticlesCount(g)
if err != nil { if err != nil && err != sql.ErrNoRows {
return err return err
} }
@ -178,6 +180,70 @@ func (h *Handler) handleGroup(s *Session, arguments []string, id uint) error {
return s.tconn.PrintfLine("211 %d %d %d %s", articlesCount, lowWaterMark, highWaterMark, g.GroupName) return s.tconn.PrintfLine("211 %d %d %d %s", articlesCount, lowWaterMark, highWaterMark, g.GroupName)
} }
func (h *Handler) handleNewGroups(s *Session, arguments []string, id uint) error {
s.tconn.StartResponse(id)
defer s.tconn.EndResponse(id)
if len(arguments) < 2 || len(arguments) > 3 {
return s.tconn.PrintfLine(protocol.MessageSyntaxError)
}
dateString := arguments[0] + " " + arguments[1]
//isGMT := false
//if len(arguments) == 3 {
// isGMT = true
//}
var date time.Time
var err error
if len(dateString) == 15 {
date, err = time.Parse("20060102 150405", dateString)
if err != nil {
return err
}
} else if len(dateString) == 13 {
date, err = time.Parse("060102 150405", dateString)
if err != nil {
return err
}
} else {
return s.tconn.PrintfLine(protocol.MessageSyntaxError)
}
g, err := h.backend.GetNewGroupsSince(date.Unix())
if err != nil {
return err
}
var sb strings.Builder
sb.Write([]byte(protocol.MessageListOfNewsgroupsFollows + protocol.CRLF))
for _, v := range g {
// TODO set actual post permission status
c, err := h.backend.GetArticlesCount(v)
if err != nil {
return err
}
if c > 0 {
highWaterMark, err := h.backend.GetGroupHighWaterMark(v)
if err != nil {
return err
}
lowWaterMark, err := h.backend.GetGroupLowWaterMark(v)
if err != nil {
return err
}
sb.Write([]byte(fmt.Sprintf("%s %d %d n"+protocol.CRLF, v.GroupName, highWaterMark, lowWaterMark)))
} else {
sb.Write([]byte(fmt.Sprintf("%s 0 1 n"+protocol.CRLF, v.GroupName)))
}
}
sb.Write([]byte(protocol.MultilineEnding))
return s.tconn.PrintfLine(sb.String())
}
func (h *Handler) Handle(s *Session, message string, id uint) error { func (h *Handler) Handle(s *Session, message string, id uint) error {
splittedMessage := strings.Split(message, " ") splittedMessage := strings.Split(message, " ")
for i, v := range splittedMessage { for i, v := range splittedMessage {