nntpclient

package module
v0.0.0-...-42215a0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2023 License: BlueOak-1.0.0 Imports: 14 Imported by: 0

README

nntpclient

This package provides a simple NNTP client that conforms to RFC 3977. It also supports the following extensions:

TODO

  • handle response codes that result in the server hanging-up
  • support pooling (maybe)
  • COMPRESS (maybe)
  • RFC 3977 section 6.3 (article posting)
  • RFC 3977 section 8 (e.g. OVER)

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrCurrentArticleNumInvalid = fmt.Errorf("current article number is invalid: %w", NntpError)
View Source
var ErrNoArticleWithId = fmt.Errorf("no article with that message-id: %w", NntpError)
View Source
var ErrNoArticleWithNum = fmt.Errorf("no article with that number: %w", NntpError)
View Source
var ErrNoGroupSelected = fmt.Errorf("no newsgroup selected: %w", NntpError)
View Source
var ErrNoNextArticle = fmt.Errorf("no next article in this group: %w", NntpError)
View Source
var ErrNoPrevArticle = fmt.Errorf("no previous article in this group: %w", NntpError)
View Source
var ErrNoSuchGroup = fmt.Errorf("no such newsgroup found: %w", NntpError)
View Source
var ErrReadingUnavailable = fmt.Errorf("reading service permanently unavailable: %w", NntpError)
View Source
var ErrUnexpectedEOF = fmt.Errorf("unexpected end of response: %w", NntpError)
View Source
var NntpError = errors.New("nntp error")

NntpError is the base error for all errors that derive from issuing commands to the server. Any such errors can be checked with errors.Is.

Functions

func AuthError

func AuthError(code int, message string) error

func ReadBody

func ReadBody(reader MultibyteReader, writer io.Writer) error

ReadBody is used to read a body, or body-like, block of bytes provided by the passed in reader. The body is not processed in any way, but is instead written to the supplied writer. This allows for processing of bodies according to their content by a client. Reading stops when the termination line (`.\r\n`) is encountered.

If an end of file is encountered before the termination line, the io.EOF error will be returned. In this case, it is not advisable to trust the bytes written to the writer.

func ReadHeaders

func ReadHeaders(reader MultibyteReader) (textproto.MIMEHeader, int, error)

ReadHeaders parses a set of bytes with the expectation that they start with what look like header lines terminated by either an empty line, in the case of a header block at the top of an article, or the message termination line (`.\r\n`) as when reading a `HEAD` command response.

The result of this method, in the success case, is a map of headers and an integer representing the offset of the last read byte, e.g. the start of the body in an article. Otherwise, and error is returned and the other values may be incomplete or incorrect.

If an end of file is reached before a header block termination line then the io.EOF error will be returned along with the last read offset.

func UnexpectedError

func UnexpectedError(code int, message string) error

Types

type Capabilities

type Capabilities map[string][]string

Capabilities is a map of all capability labels to the label's possible arguments. For example, the `COMPRESS` label may have a list of possible arguments that looks like `[DEFLATE]`.

type Client

type Client struct {

	// CanPost indicates if the server will allow the client to post articles.
	// Useful in the future when posting is supported by the client.
	CanPost bool
	// contains filtered or unexported fields
}

Client is a simple [NNTP](https://datatracker.ietf.org/doc/html/rfc3977) client. Client instances should be created with New, NewTls, or NewWithPort (this one being the most flexible).

func New

func New(host string, opts ...Option) (*Client, error)

New creates a new Client instance that connects to the given `host` according to the given options. Instances created with this method will _always_ try to connect on port 119. Thus, it is not compatible with the WithTlsConfig options.

func NewTls

func NewTls(host string, opts ...Option) (*Client, error)

NewTls creates a new Client instance that connects to the given `host` on port 563 utilizing a basic TLS configuration that sets the `ServerName` option to `host`. This should be good enough for most standard NNTP servers that support TLS on the standard port.

func NewWithPort

func NewWithPort(host string, port int, opts ...Option) (*Client, error)

NewWithPort is the most generic method for creating a new Client instance. It supports all options and allows flexibility in defining the destination port. If no TLS configuration is provided, via WithTlsConfig, then the connection will be in plain text.

func (*Client) Article

func (c *Client) Article(id string, writer io.Writer) (textproto.MIMEHeader, error)

Article gets an article from the server. The id parameter may be any of:

1. empty string (`""`) -- retrieve the "next" or "last" selected article 2. group article id -- the internal group article id, e.g. `1` 3. global id -- the global id for an article with brackets, e.g. `<foo.bar>`

Note, when using the global id it is not necessary to select a group first. But when using an internal group id, or the empty string, a group must be selected prior to invoking this function.

After reading the body of the article into the given writer, the headers will be returned if an error did not occur. If an error does occur, whatever part of the article body was read, if any, will have been written to the writer, nil will be returned for the headers, and the error will be returned.

func (*Client) ArticleAsBytes

func (c *Client) ArticleAsBytes(id string) (textproto.MIMEHeader, []byte, error)

ArticleAsBytes is a wrapper for [Article] that reads the whole article into a buffer before returning the headers and the body of the article as a slice of bytes.

func (*Client) Authenticate

func (c *Client) Authenticate(user string, pass string) error

Authenticate provides simple username and password authentication through the AUTHINFO extension (RFC 4643). The absence of an error indicates successful authentication.

func (*Client) Body

func (c *Client) Body(id string, writer io.Writer) error

Body is used to retrieve only the body of an article. As the article is read from the connection it is written to writer. The id parameter is handled in the same way as it is by [Article].

func (*Client) BodyAsBytes

func (c *Client) BodyAsBytes(id string) ([]byte, error)

BodyAsBytes is used to retrieve only the body of an article as a slice of bytes. The full body is read into the slice before it is returned. The id parameter is handled in the same way as it is by [Article].

func (*Client) Capabilities

func (c *Client) Capabilities() (*Capabilities, error)

Capabilities gets a mapping of all supported labels to their possible arguments.

func (*Client) Close

func (c *Client) Close() error

Close is an alias for the Quit method.

func (*Client) Connect

func (c *Client) Connect() error

Connect establishes a connection to the server. This method must be invoked once prior to any command methods.

func (*Client) Date

func (c *Client) Date() (time.Time, error)

Date retrieves the current date and time as it is known by the remote server.

func (*Client) Group

func (c *Client) Group(name string) (*GroupSummary, error)

Group selects a group and returns the summary for that group.

func (*Client) Head

func (c *Client) Head(id string) (textproto.MIMEHeader, error)

Head retrieves only the headers for an article. The id parameter is handled in the same way as it is in [Article].

func (*Client) Help

func (c *Client) Help() (string, error)

Help retrieves the server help page for the support capabilities.

func (*Client) Last

func (c *Client) Last() error

Last sets the selected article to the most recent article in the selected group.

func (*Client) ListActive

func (c *Client) ListActive(wildmat string) (map[string]ListGroup, error)

ListActive retrieves a list of active groups. The wildmat parameter can be the empty string to indicate "all groups."

func (*Client) ListActiveTimes

func (c *Client) ListActiveTimes(wildmat string) (map[string]ListGroupTimes, error)

ListActiveTimes retrieves a list of groups, when they were created, and by whom. The wildmat parameter can be the empty string to indicate "all groups."

func (*Client) ListDistribPats

func (c *Client) ListDistribPats() ([]ListDistribPattern, error)

ListDistribPats retrieves a list of distribution header patterns supported by the server.

func (*Client) ListGroup

func (c *Client) ListGroup(name string) (*GroupList, error)

ListGroup selects a group and returns a summary for the group along with a list of the group local article identifiers.

func (*Client) ListNewsgroups

func (c *Client) ListNewsgroups(wildmat string) (map[string]ListNewsgroup, error)

ListNewsgroups retrieves a list of newsgroups known by the server. The wildmat parameter can be the empty string to indicate "all groups". The result is a map of group names to group names and group descriptions.

func (*Client) ModeReader

func (c *Client) ModeReader() error

ModeReader toggles the connection mode to "reader".

func (*Client) NewGroups

func (c *Client) NewGroups(since time.Time) (map[string]ListGroup, error)

NewGroups queries the server for the list of groups that have been added since a given time. If the location of that time is _not_ UTC, then only the date and time fields will be sent, leaving the interpretation of that time up to the server. If the location is set to UTC, then the GMT parameter is included in the query to the server.

func (*Client) NewNews

func (c *Client) NewNews(wildmat string, since time.Time) ([]string, error)

NewNews queries the server for a list of new articles in groups matching the given wildmat since the given time. As with [NewGroups], the GMT parameter is dependent upon the since time being set to UTC.

func (*Client) Next

func (c *Client) Next() error

Next selects the next article in the selected group.

func (*Client) Quit

func (c *Client) Quit() error

Quit sends a standard `QUIT` to the remote server and terminates the connection.

func (*Client) StartTLS

func (c *Client) StartTLS(config *tls.Config) error

StartTLS upgrades the current connection to a TLS protected one. See RFC 4642.

Note: if a config is not provided, one with the `ServerName` set to the host will be used.

func (*Client) Stat

func (c *Client) Stat(id string) (int, string, error)

Stat is used to determine if an article exists. It works like [Article] in that the id may be the empty string, an internal group id, or a global message id.

If the article exists, its internal group id and global message id is returned. Otherwise, an error is returned along with `-1` and an empty string.

type GroupList

type GroupList struct {
	GroupSummary
	ArticleNumbers []int
}

GroupList represents the details about a group along with the group local id numbers for the articles in the group.

type GroupSummary

type GroupSummary struct {
	Name   string
	Number int
	Low    int
	High   int
}

GroupSummary represents the details about a group.

type ListDistribPattern

type ListDistribPattern struct {
	Weight  int
	Wildmat string
	Value   string
}

ListDistribPattern represents distribution header values supported by the server. See RFC 3977 §7.6.5.

type ListGroup

type ListGroup struct {
	Name   string
	Low    int
	High   int
	Status string
}

ListGroup represents a group information line from a list directive. See RFC 3977 §7.6.3.

type ListGroupTimes

type ListGroupTimes struct {
	Name    string
	Created time.Time
	Creator string
}

ListGroupTimes represents a group information line from a `active.times` command. See RFC 3977 §7.6.4.

type ListNewsgroup

type ListNewsgroup struct {
	Name        string
	Description string
}

ListNewsgroup represents a newsgroup information line from a `list newsgroups` directive. See RFC 3977 §7.6.6.

type MultibyteReader

type MultibyteReader interface {
	ReadBytes(delim byte) ([]byte, error)
}

MultibyteReader is an interface for readers that support reading multiple bytes up to a delimiter in one read. See bufio.Reader.

type Option

type Option func(client *Client)

func WithDialer

func WithDialer(dialer *net.Dialer) Option

WithDialer allows defining the dialer that will be used to establish the connection with the remote server.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger allows defining the logger instance that will be used when logging messages. The default logger logs at the "info" level to the stdout stream.

func WithTlsConfig

func WithTlsConfig(config *tls.Config) Option

WithTlsConfig allows defining the TLS configuration to be used when establishing a connection to a TLS enabled port.

type Response

type Response struct {
	// contains filtered or unexported fields
}

func NewResponse

func NewResponse(conn io.ReadWriteCloser) *Response

func (*Response) ReadBytes

func (r *Response) ReadBytes(delim byte) ([]byte, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL