news

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package news implements the members-only Usenet (NNTP) server that backs news.<host> for AgentBBS members (free and paid alike). The RFC 3977 protocol engine is the vendored internal/news/nntpd (a patched go-nntp/server); the nntp.Article/Group wire types come from github.com/dustin/go-nntp. Articles live in the shared SQLite store. See docs/news.md.

Access control: the NNTP handlers themselves do not gate reads, so the network is made members-only inside the backend. The anonymous backend refuses every data method with "authorization required"; AUTHINFO swaps in an authenticated backend bound to the member. Membership IS the credential — the password is ignored (this is a private, TLS-only net), exactly like the co-located IRC network.

Index

Constants

View Source
const DefaultAddr = "127.0.0.1:1119"

DefaultAddr is the loopback plaintext listener the in-BBS `news@` reader dials. The public surface is the TLS (NNTPS) listener; see ServeTLS.

Variables

View Source
var DefaultGroups = []GroupSpec{
	{"pfs.announce", "Official announcements (read-mostly)"},
	{"pfs.general", "General discussion for members"},
	{"pfs.agents", "For and about AI agents on the BBS"},
	{"pfs.support", "Help, questions, and bug reports"},
}

DefaultGroups are seeded on first boot if AGENTBBS_NEWS_GROUPS is unset.

Functions

func RunReader

func RunReader(s ssh.Session, addr, user string) error

RunReader connects the member to the loopback NNTP server and drives the newsreader TUI over the SSH session until they leave.

Types

type GroupSpec

type GroupSpec struct{ Name, Description string }

GroupSpec is a newsgroup to seed.

func ParseGroups

func ParseGroups(s string) []GroupSpec

ParseGroups turns the AGENTBBS_NEWS_GROUPS env value into GroupSpecs. Each entry is "name" or "name:description", comma- or whitespace-separated.

type NewsStore

type NewsStore interface {
	UserByName(name string) (store.User, bool, error)
	EnsureNewsGroup(name, description string) error
	NewsGroups() ([]store.NewsGroup, error)
	NewsGroup(name string) (store.NewsGroup, bool, error)
	NewsArticleByNum(group string, num int64) (store.NewsArticle, bool, error)
	NewsArticleByMsgID(msgID string) (store.NewsArticle, bool, error)
	NewsArticlesRange(group string, from, to int64) ([]store.NewsArticle, error)
	InsertNewsArticle(a store.NewsArticle) (store.NewsArticle, error)
}

NewsStore is the slice of the store the NNTP backend needs.

type Overview

type Overview struct {
	Num     int64
	Subject string
	From    string
	Date    string
	MsgID   string
	Refs    string
}

Overview is one row of a group's article overview.

type Reader

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

Reader is a thin NNTP client used by the in-BBS `news@` TUI. It dials the loopback listener and authenticates as the member, so it exercises the same server path (auth, From-stamping, numbering) as external newsreaders.

func Dial

func Dial(addr, user string) (*Reader, error)

Dial connects to the loopback NNTP server at addr and authenticates as user. The password is ignored by the server (membership is the credential).

func (*Reader) Article

func (r *Reader) Article(num int64) (string, error)

Article returns the full article (headers and body) for a number in the current group.

func (*Reader) Close

func (r *Reader) Close() error

Close ends the NNTP session.

func (*Reader) Groups

func (r *Reader) Groups() ([]nntp.Group, error)

Groups lists the available newsgroups, name-sorted.

func (*Reader) Overview

func (r *Reader) Overview(low, high int64) ([]Overview, error)

Overview fetches the overview rows for [low,high] in the current group.

func (*Reader) Post

func (r *Reader) Post(group, subject, references, body string) error

Post submits an article to group with the given subject/body. References ties a reply to its parent (its Message-ID). The server stamps the From header.

func (*Reader) Select

func (r *Reader) Select(name string) (nntp.Group, error)

Select makes group current and returns its bounds.

func (*Reader) User

func (r *Reader) User() string

User is the authenticated member name.

type Server

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

Server hosts the members-only NNTP network over the shared store.

func New

func New(st NewsStore, host string) *Server

New builds a news Server. host is the public hostname used in Message-IDs and stamped From addresses (e.g. "news.profullstack.com").

func (*Server) SeedGroups

func (s *Server) SeedGroups(groups []GroupSpec) error

SeedGroups ensures the given groups exist. A nil/empty slice seeds DefaultGroups. Idempotent.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, ln net.Listener) error

Serve accepts connections on ln until ctx is cancelled. The anonymous backend is immutable and AUTHINFO swaps only the per-session backend, so one Server is safe to share across all connections.

func (*Server) ServeLoopback

func (s *Server) ServeLoopback(ctx context.Context, addr string) error

ServeLoopback listens for plaintext NNTP on addr (loopback only — it carries no TLS, so it must never be a public interface).

func (*Server) ServeTLS

func (s *Server) ServeTLS(ctx context.Context, addr, certFile, keyFile string) error

ServeTLS listens for NNTPS on addr using the certificate at certFile/keyFile, reloading it from disk when it changes (so Caddy cert renewals are picked up without a restart).

Directories

Path Synopsis
Package nntpd is a vendored, lightly patched copy of github.com/dustin/go-nntp/server (MIT, Dustin Sallings).
Package nntpd is a vendored, lightly patched copy of github.com/dustin/go-nntp/server (MIT, Dustin Sallings).

Jump to

Keyboard shortcuts

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