posts

package
v0.0.0-...-41f0c78 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package posts is everything users do with posts: write, edit, autosave, publish and delete them, comment on them, prompt others to write, export and import a blog, and the API v1 that does the same for scripts.

Index

Constants

View Source
const (
	DefaultCommentMaxLength     = 6_000
	DefaultPostBodyMaxLength    = 20_000
	DefaultPostSubjectMaxLength = 100
	DefaultPromptMaxLength      = 1_400
)

Default text limits, used for every limit the configuration leaves zero; they are also the configuration's defaults.

View Source
const (
	CommentMinLength = 3
	PromptMinLength  = 3
)

Minimum lengths are not tunable.

View Source
const ListMax = 100

ListMax is the most posts one call of List returns.

Variables

View Source
var DefaultTextLimits = TextLimits{
	CommentMaxLength:     DefaultCommentMaxLength,
	PostBodyMaxLength:    DefaultPostBodyMaxLength,
	PostSubjectMaxLength: DefaultPostSubjectMaxLength,
	PromptMaxLength:      DefaultPromptMaxLength,
}

DefaultTextLimits are the limits of a service built without configuration.

Functions

This section is empty.

Types

type Action

type Action string

Action is what the author asked to do when saving.

const (
	ActionSavePost  Action = "save_post"
	ActionMakeDraft Action = "make_draft"
	ActionPublish   Action = "publish"
	ActionDelete    Action = "delete"
	ActionAutosave  Action = "autosave"
)

type CommentInput

type CommentInput struct {
	PostID string
	// ReplyTo is the comment being answered, empty for a top level comment.
	ReplyTo string
	Body    string
}

CommentInput is a comment as its author submitted it.

type EditView

type EditView struct {
	// Post has its author, stats and linked URL loaded.
	Post   *core.Post
	Prompt *postops.PostPrompt
}

EditView is a post as the edit page shows it.

type ListInput

type ListInput struct {
	// UpdatedSince is a Unix time; only posts updated after it are listed.
	UpdatedSince int64
	// Cursor is the Cursor of the previous page.
	Cursor string
	// Limit is the page size, between 1 and ListMax.
	Limit int
}

ListInput selects a page of the actor's posts.

type Listing

type Listing struct {
	Posts  []*core.Post
	Cursor string
}

Listing is a page of posts, newest first. Cursor is empty on the last page.

type Option

type Option func(*Service)

Option changes how New builds the service.

func WithIdentity

func WithIdentity(ident mail.Identity) Option

WithIdentity tells the service the site its mail links point to and the address the mail comes from.

func WithTextLimits

func WithTextLimits(l TextLimits) Option

WithTextLimits sets the text length limits; a zero field keeps its default.

type SaveInput

type SaveInput struct {
	// PostID is the post to change, empty for a new one.
	PostID string
	// PromptID is the prompt a new post answers, if any.
	PromptID   string
	Subject    string
	URL        string
	Body       string
	Visibility core.PostVisibility
	Action     Action
}

SaveInput is a post as the author submitted it.

type Saved

type Saved struct {
	Post    *core.Post
	Created bool
	Deleted bool
}

Saved is what a save left behind. Post is nil after a delete.

type Service

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

func New

func New(store *repo.Store, snd repo.MailQueue, storage server.MediaStorage, opts ...Option) *Service

func (*Service) AddComment

func (s *Service) AddComment(ctx context.Context, actor *core.User, in CommentInput) error

AddComment leaves a comment on a post the actor is connected to, and tells the post's author and everybody else who commented on it.

func (*Service) CanPrompt

func (s *Service) CanPrompt(ctx context.Context, actor *core.User) error

CanPrompt reports whether the actor may send a prompt right now: prompts are rate limited. The error reads as a sentence.

func (*Service) CheckComment

func (s *Service) CheckComment(ctx context.Context, actor *core.User, postID, replyTo string) error

CheckComment reports whether the actor may leave a comment on the post, as a reply to replyTo if it is not empty: ErrNotFound for a post or a comment that is not there, ErrForbidden for a post the actor is not connected to.

func (*Service) CheckEdit

func (s *Service) CheckEdit(ctx context.Context, actor *core.User, post *core.Post) error

CheckEdit reports whether the actor may edit the post: only its author may, as postops.GetPostCapabilities says. Anybody else gets ErrForbidden.

func (*Service) Delete

func (s *Service) Delete(ctx context.Context, actor *core.User, postID string) error

Delete removes the actor's post, draft or published. Somebody else's post is not found.

func (*Service) DeleteDraft

func (s *Service) DeleteDraft(ctx context.Context, actor *core.User, postID string) error

DeleteDraft removes the actor's post if it is still a draft. What the author sees when there is no such draft is the database's own words, as it always was.

func (*Service) DirectConnections

func (s *Service) DirectConnections(ctx context.Context, actor *core.User) ([]*core.User, error)

DirectConnections lists the actor's direct connections, the users they may prompt.

func (*Service) DismissPrompt

func (s *Service) DismissPrompt(ctx context.Context, actor *core.User, promptID string) error

DismissPrompt hides a prompt addressed to the actor. What the actor sees when there is no such prompt is the database's own words, as it always was.

func (*Service) EditComment

func (s *Service) EditComment(ctx context.Context, actor *core.User, commentID, body string) error

EditComment replaces the body of the actor's own comment and tells the post's author and the other participants about it. The actor must still be connected to the post's author. The comment stays as it is, and nobody is told, when the body does not change.

func (*Service) ExportBlog

func (s *Service) ExportBlog(ctx context.Context, actor *core.User) ([]byte, error)

ExportBlog is every post of the actor, with the images they embed, as a zip archive.

func (*Service) ExportPost

func (s *Service) ExportPost(ctx context.Context, authorID, postID string) ([]byte, error)

ExportPost is one post of its author, with the images it embeds, as a zip archive. Whether the viewer may see the post is for the caller to decide.

func (*Service) ForEdit

func (s *Service) ForEdit(ctx context.Context, actor *core.User, postID string) (*EditView, error)

ForEdit loads the actor's post for the edit page: ErrNotFound if there is no such post, ErrForbidden if it is somebody else's.

func (*Service) Import

func (s *Service) Import(ctx context.Context, actor *core.User, archive []byte) (*postops.InjectStats, error)

Import adds the posts and images of an exported archive to the actor's blog. A post that is the actor's own already is updated in place.

func (*Service) InjectPosts

func (s *Service) InjectPosts(ctx context.Context, actor *core.User, posts []*postops.PostWithMeta, images map[string][]byte) (*postops.InjectStats, error)

InjectPosts stores parsed posts and images in the actor's blog, in one transaction. A post the actor owns already is updated in place, any other is created. An image the actor uploaded under that name before is not uploaded again.

func (*Service) List

func (s *Service) List(ctx context.Context, actor *core.User, in ListInput) (*Listing, error)

List returns a page of the actor's posts, drafts included.

func (*Service) PostURL

func (s *Service) PostURL(postID string) string

PostURL is the public address of a post.

func (*Service) PromptFor

func (s *Service) PromptFor(ctx context.Context, actor *core.User, promptID string) (*postops.PostPrompt, error)

PromptFor returns the prompt with the given ID if it is addressed to the actor, and nil otherwise.

func (*Service) Save

func (s *Service) Save(ctx context.Context, actor *core.User, in SaveInput) (*Saved, error)

Save creates or changes the actor's post, or deletes it. Publishing notifies the author's direct connections, and the asker of the prompt the post answers, in the same transaction.

func (*Service) SendPrompt

func (s *Service) SendPrompt(ctx context.Context, actor, recipient *core.User, message string) error

SendPrompt asks a user to write a post on a subject, and tells them by mail. The recipient must be a direct connection of the actor; anyone else is refused with the wording the prompt form always used.

func (*Service) TextLimits

func (s *Service) TextLimits() TextLimits

TextLimits returns the service's text length limits. Forms read them to check their fields; the service enforces them on save.

func (*Service) UploadImage

func (s *Service) UploadImage(ctx context.Context, actor *core.User, r io.Reader) (string, error)

UploadImage stores an image for the actor and returns its file name. The file lands in the media storage, so it is not part of a transaction.

type TextLimits

type TextLimits struct {
	CommentMaxLength     int
	PostBodyMaxLength    int
	PostSubjectMaxLength int
	PromptMaxLength      int
}

TextLimits are the most characters the texts of this service may have.

Jump to

Keyboard shortcuts

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