Refactor all response messages as NNTPResponse type

This commit is contained in:
ChronosX88 2022-02-05 12:54:41 +03:00
parent 5023c13afd
commit 496fbf2a4f
Signed by: ChronosXYZ
GPG Key ID: 085A69A82C8C511A
5 changed files with 13 additions and 90 deletions

6
go.mod
View File

@ -4,13 +4,11 @@ go 1.17
require ( require (
github.com/BurntSushi/toml v1.0.0 github.com/BurntSushi/toml v1.0.0
github.com/dlclark/regexp2 v1.4.0
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/jmoiron/sqlx v1.3.4 github.com/jmoiron/sqlx v1.3.4
github.com/mattn/go-sqlite3 v1.14.10 github.com/mattn/go-sqlite3 v1.14.10
github.com/pressly/goose/v3 v3.5.0 github.com/pressly/goose/v3 v3.5.0
) )
require ( require github.com/pkg/errors v0.9.1 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
)

View File

@ -14,68 +14,3 @@ type Article struct {
Body string `db:"body"` Body string `db:"body"`
Thread sql.NullString `db:"thread"` Thread sql.NullString `db:"thread"`
} }
//func ParseArticle(lines []string) (Article, error) {
// article := Article{}
// headerBlock := true
// for _, v := range lines {
// if v == "" {
// headerBlock = false
// }
//
// if headerBlock {
// kv := strings.Split(v, ":")
// if len(kv) < 2 {
// return Article{}, fmt.Errorf("invalid header format")
// }
//
// kv[0] = strings.TrimSpace(kv[0])
// kv[1] = strings.TrimSpace(kv[1])
//
// if !protocol.IsMessageHeaderAllowed(kv[0]) {
// return Article{}, fmt.Errorf("invalid header element")
// }
// if kv[1] == "" {
// return Article{}, fmt.Errorf("header value should not be empty")
// }
//
// switch kv[0] {
// case "Archive":
// {
// if kv[1] == "yes" {
// article.Archive = true
// } else {
// article.Archive = false
// }
// }
// case "Injection-Date":
// {
// date, err := mail.ParseDate(kv[1])
// if err != nil {
// return Article{}, err
// }
// article.InjectionDate = date
// }
// case "Date":
// {
// date, err := mail.ParseDate(kv[1])
// if err != nil {
// return Article{}, err
// }
// article.Date = date
// }
// case "Expires":
// {
// date, err := mail.ParseDate(kv[1])
// if err != nil {
// return Article{}, err
// }
// article.Expires = date
// }
// }
//
// } else {
// }
// }
// return article, nil
//}

View File

@ -70,14 +70,3 @@ const (
CapabilityNameImplementation = "IMPLEMENTATION" CapabilityNameImplementation = "IMPLEMENTATION"
CapabilityNameModeReader = "MODE-READER" CapabilityNameModeReader = "MODE-READER"
) )
const (
MessageNNTPServiceReadyPostingProhibited = "201 YANS NNTP Service Ready, posting prohibited"
MessageReaderModePostingProhibited = "201 Reader mode, posting prohibited"
MessageNNTPServiceExitsNormally = "205 NNTP Service exits normally, bye!"
MessageErrorHappened = "403 Failed to process command:"
MessageListOfNewsgroupsFollows = "215 list of newsgroups follows"
MessageNoSuchGroup = "411 No such newsgroup"
MessageInputArticle = "340 Input article; end with <CR-LF>.<CR-LF>"
MessageArticleReceived = "240 Article received OK"
)

View File

@ -49,11 +49,11 @@ func (h *Handler) handleCapabilities(s *Session, arguments []string, id uint) er
func (h *Handler) handleDate(s *Session, arguments []string, id uint) error { func (h *Handler) handleDate(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)
return s.tconn.PrintfLine("111 %s", time.Now().UTC().Format("20060102150405")) return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 111, Message: time.Now().UTC().Format("20060102150405")}.String())
} }
func (h *Handler) handleQuit(s *Session, arguments []string, id uint) error { func (h *Handler) handleQuit(s *Session, arguments []string, id uint) error {
s.tconn.PrintfLine(protocol.MessageNNTPServiceExitsNormally) s.tconn.PrintfLine(protocol.NNTPResponse{Code: 205, Message: "NNTP Service exits normally, bye!"}.String())
s.conn.Close() s.conn.Close()
return nil return nil
} }
@ -85,7 +85,7 @@ func (h *Handler) handleList(s *Session, arguments []string, id uint) error {
if err != nil { if err != nil {
return err return err
} }
sb.Write([]byte(protocol.MessageListOfNewsgroupsFollows + protocol.CRLF)) sb.Write([]byte(protocol.NNTPResponse{Code: 215, Message: "list of newsgroups follows"}.String() + protocol.CRLF))
for _, v := range groups { for _, v := range groups {
// TODO set actual post permission status // TODO set actual post permission status
c, err := h.backend.GetArticlesCount(&v) c, err := h.backend.GetArticlesCount(&v)
@ -120,7 +120,7 @@ func (h *Handler) handleList(s *Session, arguments []string, id uint) error {
return err return err
} }
sb.Write([]byte(protocol.MessageListOfNewsgroupsFollows + protocol.CRLF)) sb.Write([]byte(protocol.NNTPResponse{Code: 215, Message: "list of newsgroups follows"}.String() + protocol.CRLF))
for _, v := range groups { for _, v := range groups {
desc := "" desc := ""
if v.Description == nil { if v.Description == nil {
@ -156,7 +156,7 @@ func (h *Handler) handleModeReader(s *Session, arguments []string, id uint) erro
(&s.capabilities).Add(protocol.Capability{Type: protocol.ListCapability, Params: "ACTIVE NEWSGROUPS"}) (&s.capabilities).Add(protocol.Capability{Type: protocol.ListCapability, Params: "ACTIVE NEWSGROUPS"})
s.mode = SessionModeReader s.mode = SessionModeReader
return s.tconn.PrintfLine(protocol.MessageReaderModePostingProhibited) // TODO vary on auth status return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 201, Message: "Reader mode, posting prohibited"}.String()) // TODO vary on auth status
} }
func (h *Handler) handleGroup(s *Session, arguments []string, id uint) error { func (h *Handler) handleGroup(s *Session, arguments []string, id uint) error {
@ -170,7 +170,7 @@ func (h *Handler) handleGroup(s *Session, arguments []string, id uint) error {
g, err := h.backend.GetGroup(arguments[0]) g, err := h.backend.GetGroup(arguments[0])
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.NNTPResponse{Code: 411, Message: "No such newsgroup"}.String())
} else { } else {
return err return err
} }
@ -266,7 +266,7 @@ func (h *Handler) handlePost(s *Session, arguments []string, id uint) error {
return s.tconn.PrintfLine(protocol.ErrSyntaxError.String()) return s.tconn.PrintfLine(protocol.ErrSyntaxError.String())
} }
if err := s.tconn.PrintfLine(protocol.MessageInputArticle); err != nil { if err := s.tconn.PrintfLine(protocol.NNTPResponse{Code: 340, Message: "Input article; end with <CR-LF>.<CR-LF>"}.String()); err != nil {
return err return err
} }
@ -324,7 +324,7 @@ func (h *Handler) handlePost(s *Session, arguments []string, id uint) error {
return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 441, Message: err.Error()}.String()) return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 441, Message: err.Error()}.String())
} }
return s.tconn.PrintfLine(protocol.MessageArticleReceived) return s.tconn.PrintfLine(protocol.NNTPResponse{Code: 240, Message: "Article received OK"}.String())
} }
func (h *Handler) handleListgroup(s *Session, arguments []string, id uint) error { func (h *Handler) handleListgroup(s *Session, arguments []string, id uint) error {

View File

@ -2,6 +2,7 @@ package server
import ( import (
"context" "context"
"fmt"
"github.com/ChronosX88/yans/internal/models" "github.com/ChronosX88/yans/internal/models"
"github.com/ChronosX88/yans/internal/protocol" "github.com/ChronosX88/yans/internal/protocol"
"io" "io"
@ -61,7 +62,7 @@ func (s *Session) loop() {
close(s.closed) close(s.closed)
}() }()
err := s.tconn.PrintfLine(protocol.MessageNNTPServiceReadyPostingProhibited) // by default access mode is read-only err := s.tconn.PrintfLine(protocol.NNTPResponse{Code: 201, Message: "YANS NNTP Service Ready, posting prohibited"}.String()) // by default access mode is read-only
if err != nil { if err != nil {
s.conn.Close() s.conn.Close()
return return
@ -90,7 +91,7 @@ func (s *Session) loop() {
err = s.h.Handle(s, message, id) err = s.h.Handle(s, message, id)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
s.tconn.PrintfLine("%s %s", protocol.MessageErrorHappened, err.Error()) s.tconn.PrintfLine(protocol.NNTPResponse{Code: 403, Message: fmt.Sprintf("Failed to process command: %s", err.Error())}.String())
s.conn.Close() s.conn.Close()
return return
} }