Commit Diff


commit - 8b8eab1e23b712caf0560716ad255220160d2bf1
commit + 4ef66cd9dfe84823e5777b2c8d68680ea78d5298
blob - 06b86c200ca5387446c79fd8b54565b212507f7d
blob + b2026fa867121a4422b1862579a262a2f52d58be
--- client/client.go
+++ client/client.go
@@ -1,4 +1,4 @@
-// NNTP Client library.
+// Package nntpclient provides an NNTP Client.
 package nntpclient
 
 import (
@@ -11,13 +11,13 @@ import (
 	"github.com/dustin/go-nntp"
 )
 
-// The client
+// Client is an NNTP client.
 type Client struct {
 	conn   *textproto.Conn
 	Banner string
 }
 
-// Connect a client to an NNTP server.
+// New connects a client to an NNTP server.
 func New(net, addr string) (*Client, error) {
 	conn, err := textproto.Dial(net, addr)
 	if err != nil {
@@ -92,7 +92,7 @@ func (c *Client) List(sub string) (rv []nntp.Group, er
 	return
 }
 
-// Select a group.
+// Group selects a group.
 func (c *Client) Group(name string) (rv nntp.Group, err error) {
 	var msg string
 	_, msg, err = c.Command("GROUP "+name, 211)
@@ -121,7 +121,7 @@ func (c *Client) Group(name string) (rv nntp.Group, er
 	return
 }
 
-// Grab an article
+// Article grabs an article
 func (c *Client) Article(specifier string) (int64, string, io.Reader, error) {
 	err := c.conn.PrintfLine("ARTICLE %s", specifier)
 	if err != nil {
@@ -130,7 +130,7 @@ func (c *Client) Article(specifier string) (int64, str
 	return c.articleish(220)
 }
 
-// Get the headers for an article
+// Head gets the headers for an article
 func (c *Client) Head(specifier string) (int64, string, io.Reader, error) {
 	err := c.conn.PrintfLine("HEAD %s", specifier)
 	if err != nil {
@@ -139,7 +139,7 @@ func (c *Client) Head(specifier string) (int64, string
 	return c.articleish(221)
 }
 
-// Get the body of an article
+// Body gets the body of an article
 func (c *Client) Body(specifier string) (int64, string, io.Reader, error) {
 	err := c.conn.PrintfLine("BODY %s", specifier)
 	if err != nil {
@@ -185,7 +185,7 @@ func (c *Client) Post(r io.Reader) error {
 	return err
 }
 
-// Send a low-level command and get a response.
+// Command sends a low-level command and get a response.
 //
 // This will return an error if the code doesn't match the expectCode
 // prefix.  For example, if you specify "200", the response code MUST
blob - 29ab008f6a16519bb5f1ff2b5a6a5906bca4533d
blob + 41430094f467ef2062b05ee9d2db69e29fd383fa
--- examples/couchserver/couchserver.go
+++ examples/couchserver/couchserver.go
@@ -153,7 +153,7 @@ func (cb *couchBackend) GetGroup(name string) (*nntp.G
 	}
 	g, exists := cb.groups[name]
 	if !exists {
-		return nil, nntpserver.NoSuchGroup
+		return nil, nntpserver.ErrNoSuchGroup
 	}
 	return g, nil
 }
@@ -179,14 +179,14 @@ func (cb *couchBackend) GetArticle(group *nntp.Group, 
 		}, &results)
 
 		if len(results.Rows) != 1 {
-			return nil, nntpserver.InvalidArticleNumber
+			return nil, nntpserver.ErrInvalidArticleNumber
 		}
 
 		ar = results.Rows[0].Article
 	} else {
 		err := cb.db.Retrieve(cleanupId(id, false), &ar)
 		if err != nil {
-			return nil, nntpserver.InvalidMessageId
+			return nil, nntpserver.ErrInvalidMessageID
 		}
 	}
 
@@ -269,7 +269,7 @@ func (cb *couchBackend) Post(article *nntp.Article) er
 	if len(a.Nums) == 0 {
 		log.Printf("Found no matching groups in %v",
 			article.Header["Newsgroups"])
-		return nntpserver.PostingFailed
+		return nntpserver.ErrPostingFailed
 	}
 
 	if *optimisticPost {
@@ -283,7 +283,7 @@ func (cb *couchBackend) Post(article *nntp.Article) er
 		_, _, err = cb.db.Insert(&a)
 		if err != nil {
 			log.Printf("error posting article: %v", err)
-			return nntpserver.PostingFailed
+			return nntpserver.ErrPostingFailed
 		}
 	}
 
@@ -295,7 +295,7 @@ func (tb *couchBackend) Authorized() bool {
 }
 
 func (tb *couchBackend) Authenticate(user, pass string) (nntpserver.Backend, error) {
-	return nil, nntpserver.AuthRejected
+	return nil, nntpserver.ErrAuthRejected
 }
 
 func maybefatal(err error, f string, a ...interface{}) {
blob - 09734a75b8b7d4188640743b90255e31cd1a1e51
blob + a6aebe3555dc5d6d2e46131770637c8c1ae6e87e
--- examples/server/exampleserver.go
+++ examples/server/exampleserver.go
@@ -85,7 +85,7 @@ func (tb *testBackendType) GetGroup(name string) (*nnt
 	}
 
 	if group == nil {
-		return nil, nntpserver.NoSuchGroup
+		return nil, nntpserver.ErrNoSuchGroup
 	}
 
 	return group, nil
blob - e9d06c94738fa3c3253d28936d68c3cd26cb010c
blob + dedc4e7c011437367d7f7101c057fbdc85bd635e
--- nntp.go
+++ nntp.go
@@ -1,4 +1,4 @@
-// NNTP definitions.
+// Package nntp provides base NNTP definitions.
 package nntp
 
 import (
@@ -7,9 +7,10 @@ import (
 	"net/textproto"
 )
 
-// Posting status type for groups.
+// PostingStatus type for groups.
 type PostingStatus byte
 
+// PostingStatus values.
 const (
 	Unknown             = PostingStatus(0)
 	PostingPermitted    = PostingStatus('y')
@@ -21,7 +22,7 @@ func (ps PostingStatus) String() string {
 	return fmt.Sprintf("%c", ps)
 }
 
-// A usenet newsgroup.
+// Group represents a usenet newsgroup.
 type Group struct {
 	Name        string
 	Description string
@@ -31,7 +32,7 @@ type Group struct {
 	Posting     PostingStatus
 }
 
-// An article that may appear in one or more groups.
+// An Article that may appear in one or more groups.
 type Article struct {
 	// The article's headers
 	Header textproto.MIMEHeader
@@ -43,7 +44,7 @@ type Article struct {
 	Lines int
 }
 
-// Convenient access to the article's Message ID.
-func (a *Article) MessageId() string {
+// MessageID provides convenient access to the article's Message ID.
+func (a *Article) MessageID() string {
 	return a.Header.Get("Message-Id")
 }
blob - 41c71d3705aeb77c4cf1a3ac7022dd6feae17dcc
blob + bde4869b9d4b8f2b1af79ef472d7515a59ec7f3d
--- server/server.go
+++ server/server.go
@@ -1,4 +1,4 @@
-// Everything you need for your own NNTP server.
+// Package nnntpserver provides everything you need for your own NNTP server.
 package nntpserver
 
 import (
@@ -14,42 +14,68 @@ import (
 	"github.com/dustin/go-nntp"
 )
 
-// Coded NNTP error message.
+// An NNTPError is a coded NNTP error message.
 type NNTPError struct {
 	Code int
 	Msg  string
 }
 
-var NoSuchGroup = &NNTPError{411, "No such newsgroup"}
+// ErrNoSuchGroup is returned for a request for a group that can't be found.
+var ErrNoSuchGroup = &NNTPError{411, "No such newsgroup"}
 
-var NoGroupSelected = &NNTPError{412, "No newsgroup selected"}
+// ErrNoSuchGroup is returned for a request that requires a current
+// group when none has been selected.
+var ErrNoGroupSelected = &NNTPError{412, "No newsgroup selected"}
 
-var InvalidMessageId = &NNTPError{430, "No article with that message-id"}
-var InvalidArticleNumber = &NNTPError{423, "No article with that number"}
-var NoCurrentArticle = &NNTPError{420, "Current article number is invalid"}
+// ErrInvalidMessageID is returned when a message is requested that can't be found.
+var ErrInvalidMessageID = &NNTPError{430, "No article with that message-id"}
 
-var UnknownCommand = &NNTPError{500, "Unknown command"}
-var SyntaxError = &NNTPError{501, "not supported, or syntax error"}
+// ErrInvalidArticleNumber is returned when an article is requested that can't be found.
+var ErrInvalidArticleNumber = &NNTPError{423, "No article with that number"}
 
-var PostingNotPermitted = &NNTPError{440, "Posting not permitted"}
-var PostingFailed = &NNTPError{441, "posting failed"}
-var NotWanted = &NNTPError{435, "Article not wanted"}
+// ErrNoCurrentArticle is returned when a command is executed that
+// requires a current article when one has not been selected.
+var ErrNoCurrentArticle = &NNTPError{420, "Current article number is invalid"}
 
-var AuthRequired = &NNTPError{450, "authorization required"}
-var AuthRejected = &NNTPError{452, "authorization rejected"}
-var NotAuthenticated = &NNTPError{480, "authentication required"}
+// ErrUnknownCommand is returned for unknown comands.
+var ErrUnknownCommand = &NNTPError{500, "Unknown command"}
 
-// Low-level protocol handler
+// ErrSyntax is returned when a command can't be parsed.
+var ErrSyntax = &NNTPError{501, "not supported, or syntax error"}
+
+// ErrPostingNotPermitted is returned as the response to an attempt to
+// post an article where posting is not permitted.
+var ErrPostingNotPermitted = &NNTPError{440, "Posting not permitted"}
+
+// ErrPostingFailed is returned when an attempt to post an article fails.
+var ErrPostingFailed = &NNTPError{441, "posting failed"}
+
+// ErrNotWanted is returned when an attempt to post an article is
+// rejected due the server not wanting the article.
+var ErrNotWanted = &NNTPError{435, "Article not wanted"}
+
+// ErrAuthRequired is returned to indicate authentication is required
+// to proceed.
+var ErrAuthRequired = &NNTPError{450, "authorization required"}
+
+// ErrAuthRejected is returned for invalid authentication.
+var ErrAuthRejected = &NNTPError{452, "authorization rejected"}
+
+// ErrNotAuthenticated is returned when a command is issued that requires
+// authentication, but authentication was not provided.
+var ErrNotAuthenticated = &NNTPError{480, "authentication required"}
+
+// Handler is a low-level protocol handler
 type Handler func(args []string, s *session, c *textproto.Conn) error
 
-// When listing articles in a group, this provides local sequence
-// numbers to articles.
+// A NumberedArticle provides local sequence nubers to articles When
+// listing articles in a group.
 type NumberedArticle struct {
 	Num     int64
 	Article *nntp.Article
 }
 
-// The backend that provides the things and does the stuff.
+// The Backend that provides the things and does the stuff.
 type Backend interface {
 	ListGroups(max int) ([]*nntp.Group, error)
 	GetGroup(name string) (*nntp.Group, error)
@@ -69,7 +95,7 @@ type session struct {
 	group   *nntp.Group
 }
 
-// The server handle.
+// The Server handle.
 type Server struct {
 	// Handlers are dispatched by command name.
 	Handlers map[string]Handler
@@ -79,7 +105,7 @@ type Server struct {
 	group *nntp.Group
 }
 
-// Build a new server handle request to a backend.
+// NewServer builds a new server handle request to a backend.
 func NewServer(backend Backend) *Server {
 	rv := Server{
 		Handlers: make(map[string]Handler),
@@ -195,7 +221,7 @@ func parseRange(spec string) (low, high int64) {
 
 func handleOver(args []string, s *session, c *textproto.Conn) error {
 	if s.group == nil {
-		return NoGroupSelected
+		return ErrNoGroupSelected
 	}
 	from, to := parseRange(args[0])
 	articles, err := s.backend.GetArticles(s.group, from, to)
@@ -271,7 +297,7 @@ func handleNewGroups(args []string, s *session, c *tex
 }
 
 func handleDefault(args []string, s *session, c *textproto.Conn) error {
-	return UnknownCommand
+	return ErrUnknownCommand
 }
 
 func handleQuit(args []string, s *session, c *textproto.Conn) error {
@@ -281,7 +307,7 @@ func handleQuit(args []string, s *session, c *textprot
 
 func handleGroup(args []string, s *session, c *textproto.Conn) error {
 	if len(args) < 1 {
-		return NoSuchGroup
+		return ErrNoSuchGroup
 	}
 
 	group, err := s.backend.GetGroup(args[0])
@@ -298,7 +324,7 @@ func handleGroup(args []string, s *session, c *textpro
 
 func (s *session) getArticle(args []string) (*nntp.Article, error) {
 	if s.group == nil {
-		return nil, NoGroupSelected
+		return nil, ErrNoGroupSelected
 	}
 	return s.backend.GetArticle(s.group, args[0])
 }
@@ -330,7 +356,7 @@ func handleHead(args []string, s *session, c *textprot
 	if err != nil {
 		return err
 	}
-	c.PrintfLine("221 1 %s", article.MessageId())
+	c.PrintfLine("221 1 %s", article.MessageID())
 	dw := c.DotWriter()
 	defer dw.Close()
 	for k, v := range article.Header {
@@ -372,7 +398,7 @@ func handleBody(args []string, s *session, c *textprot
 	if err != nil {
 		return err
 	}
-	c.PrintfLine("222 1 %s", article.MessageId())
+	c.PrintfLine("222 1 %s", article.MessageID())
 	dw := c.DotWriter()
 	defer dw.Close()
 	_, err = io.Copy(dw, article.Body)
@@ -412,7 +438,7 @@ func handleArticle(args []string, s *session, c *textp
 	if err != nil {
 		return err
 	}
-	c.PrintfLine("220 1 %s", article.MessageId())
+	c.PrintfLine("220 1 %s", article.MessageID())
 	dw := c.DotWriter()
 	defer dw.Close()
 
@@ -443,7 +469,7 @@ func handleArticle(args []string, s *session, c *textp
 
 func handlePost(args []string, s *session, c *textproto.Conn) error {
 	if !s.backend.AllowPost() {
-		return PostingNotPermitted
+		return ErrPostingNotPermitted
 	}
 
 	c.PrintfLine("340 Go ahead")
@@ -451,7 +477,7 @@ func handlePost(args []string, s *session, c *textprot
 	var article nntp.Article
 	article.Header, err = c.ReadMIMEHeader()
 	if err != nil {
-		return PostingFailed
+		return ErrPostingFailed
 	}
 	article.Body = c.DotReader()
 	err = s.backend.Post(&article)
@@ -464,20 +490,20 @@ func handlePost(args []string, s *session, c *textprot
 
 func handleIHave(args []string, s *session, c *textproto.Conn) error {
 	if !s.backend.AllowPost() {
-		return NotWanted
+		return ErrNotWanted
 	}
 
 	// XXX:  See if we have it.
 	article, err := s.backend.GetArticle(nil, args[0])
 	if article != nil {
-		return NotWanted
+		return ErrNotWanted
 	}
 
 	c.PrintfLine("335 send it")
 	article = &nntp.Article{}
 	article.Header, err = c.ReadMIMEHeader()
 	if err != nil {
-		return PostingFailed
+		return ErrPostingFailed
 	}
 	article.Body = c.DotReader()
 	err = s.backend.Post(article)
@@ -516,10 +542,10 @@ func handleMode(args []string, s *session, c *textprot
 
 func handleAuthInfo(args []string, s *session, c *textproto.Conn) error {
 	if len(args) < 2 {
-		return SyntaxError
+		return ErrSyntax
 	}
 	if strings.ToLower(args[0]) != "user" {
-		return SyntaxError
+		return ErrSyntax
 	}
 
 	if s.backend.Authorized() {
@@ -530,7 +556,7 @@ func handleAuthInfo(args []string, s *session, c *text
 	a, err := c.ReadLine()
 	parts := strings.SplitN(a, " ", 3)
 	if strings.ToLower(parts[0]) != "authinfo" || strings.ToLower(parts[1]) != "pass" {
-		return SyntaxError
+		return ErrSyntax
 	}
 	b, err := s.backend.Authenticate(args[1], parts[2])
 	if err == nil {