Implement BODY command

This commit is contained in:
ChronosX88 2022-02-05 17:46:25 +03:00
parent ac390d3945
commit 0a92a2cabf
Signed by: ChronosXYZ
GPG Key ID: 085A69A82C8C511A
3 changed files with 73 additions and 2 deletions

View File

@ -26,7 +26,7 @@
- :construction: Article retrieving - :construction: Article retrieving
- :heavy_check_mark: `ARTICLE` - :heavy_check_mark: `ARTICLE`
- :heavy_check_mark: `HEAD` - :heavy_check_mark: `HEAD`
- :x: `BODY` - :heavy_check_mark: `BODY`
- :x: `STAT` - :x: `STAT`
- :x: Articles overview - :x: Articles overview
- :x: `OVER` - :x: `OVER`

View File

@ -58,6 +58,7 @@ const (
CommandListGroup = "LISTGROUP" CommandListGroup = "LISTGROUP"
CommandArticle = "ARTICLE" CommandArticle = "ARTICLE"
CommandHead = "HEAD" CommandHead = "HEAD"
CommandBody = "BODY"
) )
const ( const (

View File

@ -1,6 +1,7 @@
package server package server
import ( import (
"bufio"
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -37,6 +38,7 @@ func NewHandler(b backend.StorageBackend, serverDomain string) *Handler {
protocol.CommandListGroup: h.handleListgroup, protocol.CommandListGroup: h.handleListgroup,
protocol.CommandArticle: h.handleArticle, protocol.CommandArticle: h.handleArticle,
protocol.CommandHead: h.handleHead, protocol.CommandHead: h.handleHead,
protocol.CommandBody: h.handleBody,
} }
h.serverDomain = serverDomain h.serverDomain = serverDomain
return h return h
@ -386,7 +388,6 @@ func (h *Handler) handleListgroup(s *Session, arguments []string, id uint) error
return dw.Close() return dw.Close()
} }
// TODO refactor this, because it's mostly duplicate of ARTICLE handler function
func (h *Handler) handleArticle(s *Session, arguments []string, id uint) error { func (h *Handler) handleArticle(s *Session, arguments []string, id uint) error {
s.tconn.StartResponse(id) s.tconn.StartResponse(id)
defer s.tconn.EndResponse(id) defer s.tconn.EndResponse(id)
@ -457,6 +458,7 @@ func (h *Handler) handleArticle(s *Session, arguments []string, id uint) error {
return dw.Close() return dw.Close()
} }
// FIXME refactor this, because it's mostly duplicate of ARTICLE handler function
func (h *Handler) handleHead(s *Session, arguments []string, id uint) error { func (h *Handler) handleHead(s *Session, arguments []string, id uint) error {
s.tconn.StartResponse(id) s.tconn.StartResponse(id)
defer s.tconn.EndResponse(id) defer s.tconn.EndResponse(id)
@ -521,6 +523,74 @@ func (h *Handler) handleHead(s *Session, arguments []string, id uint) error {
return dw.Close() return dw.Close()
} }
// FIXME refactor this, because it's mostly duplicate of ARTICLE handler function
func (h *Handler) handleBody(s *Session, arguments []string, id uint) error {
s.tconn.StartResponse(id)
defer s.tconn.EndResponse(id)
if len(arguments) == 0 && s.currentArticle == nil {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 420, Message: "No current article selected"}.String())
}
if len(arguments) > 1 {
return s.tconn.PrintfLine(protocol.ErrSyntaxError.String())
}
getByArticleNum := true
num, err := strconv.Atoi(arguments[0])
if err != nil {
getByArticleNum = false
}
if getByArticleNum && s.currentGroup == nil {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 412, Message: "No newsgroup selected"}.String())
}
var a models.Article
if getByArticleNum {
a, err = h.backend.GetArticleByNumber(s.currentGroup, num)
if err != nil {
if err == sql.ErrNoRows {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 423, Message: "No article with that number"}.String())
} else {
return err
}
}
} else {
a, err = h.backend.GetArticle(arguments[0])
if err != nil {
if err == sql.ErrNoRows {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 430, Message: "No Such Article Found"}.String())
} else {
return err
}
}
}
s.currentArticle = &a
dw := s.tconn.DotWriter()
_, err = dw.Write([]byte(protocol.NNTPResponse{Code: 222, Message: fmt.Sprintf("%d %s", num, a.Header.Get("Message-ID"))}.String() + protocol.CRLF))
if err != nil {
return err
}
w := bufio.NewWriter(dw)
_, err = w.Write([]byte(a.Body))
if err != nil {
return err
}
err = w.Flush()
if err != nil {
return err
}
return dw.Close()
}
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 {