kinds

package
v0.93.0 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package kinds is the site's content model as configuration: content kinds, group kinds, tiers, restrictions, site scopes and content filters. One Config drives storage, routes, media kinds, search and URLs (ContentKit #117).

Index

Constants

View Source
const (
	// DownloadPages is a zip of the version's pages (the media kind's
	// Publish.Download), the default of readers.
	DownloadPages = "pages"
	// DownloadOriginal is the version's video as uploaded (the upload its HLS
	// ladder encodes), the default of players.
	DownloadOriginal = "original"
)

What a download serves.

View Source
const (
	ShowDescription = "description" // the content's and versions' descriptions
	ShowCover       = "cover"
	ShowGroups      = "entities"
	ShowAttributes  = "attributes" // the content's and versions' attributes
	ShowLength      = "length"     // versions' page counts, durations and segments
	ShowReactions   = "reactions"  // like and dislike counts; locked viewers may react
	ShowFavorites   = "favorites"  // favorite counts
	ShowViews       = "views"      // view counts
	ShowComments    = "comments"   // comments and their counts; locked viewers may comment
)

Properties a Locked view may show.

Variables

DefaultLocked shows a kind's metadata and cover: no preview, counts or comments.

View Source
var ErrInvalid = errors.New("kinds: invalid config")

ErrInvalid is a Config that cannot be served.

Shown are the properties a Locked view may show.

Functions

func ValidateAttributes

func ValidateAttributes(declared map[string]Attribute, values map[string]any) (map[string]any, error)

ValidateAttributes checks values against the declared attributes and returns them normalized: ints as int64, times as RFC 3339 UTC. A nil value drops the attribute; an undeclared one or a value of the wrong type is ErrInvalid.

Types

type Attribute

type Attribute struct {
	// Type is string, int, bool, enum or time.
	Type       string   `json:"type" yaml:"type"`
	Values     []string `json:"values,omitempty" yaml:"values"`
	Filterable bool     `json:"filterable,omitempty" yaml:"filterable"`
	Sortable   bool     `json:"sortable,omitempty" yaml:"sortable"`
}

Attribute is one declared per-kind field.

type Config

type Config struct {
	Languages      []string             `json:"languages" yaml:"languages"`
	Tiers          []string             `json:"tiers,omitempty" yaml:"tiers"`
	TokenClaims    []string             `json:"token_claims,omitempty" yaml:"token_claims"`
	Restrictions   []string             `json:"restrictions,omitempty" yaml:"restrictions"`
	Sites          []Site               `json:"sites,omitempty" yaml:"sites"`
	ContentFilters []ContentFilter      `json:"content_filters,omitempty" yaml:"content_filters"`
	Kinds          map[string]Kind      `json:"kinds" yaml:"kinds"`
	GroupKinds     map[string]GroupKind `json:"entity_kinds,omitempty" yaml:"group_kinds"`
}

Config is the site's content model.

func (Config) Routes

func (c Config) Routes() map[string]string

Routes maps every content kind and group kind with a route to it: the first path segment of its pages (contenturl.Routes).

func (Config) SiteFor

func (c Config) SiteFor(host string) (Site, bool)

SiteFor returns the site serving host, ignoring case and port; the first site when none matches. Host is the request host, not an authority selector.

func (Config) Validate

func (c Config) Validate() error

Validate refuses a Config that names unknown kinds, languages, tiers or restrictions, or repeats a route.

type ContentFilter

type ContentFilter struct {
	Group          GroupRef          `json:"entity" yaml:"group"`
	DefaultVisible bool              `json:"default_visible" yaml:"default_visible"`
	Labels         map[string]string `json:"labels,omitempty" yaml:"labels"`
}

ContentFilter is a group viewers may hide; DefaultVisible is the default before a viewer's own override.

type ContentFilterDefault added in v0.90.0

type ContentFilterDefault struct {
	Group   GroupRef `json:"entity" yaml:"group"`
	Visible bool     `json:"visible" yaml:"visible"`
}

ContentFilterDefault sets the visibility of one declared ContentFilter on a site. Unspecified filters retain their app-wide default.

type Download added in v0.90.0

type Download struct {
	// Off: the kind's versions have no download.
	Off bool `json:"off,omitempty" yaml:"off"`
	// Serve is DownloadPages, DownloadOriginal or a private MP4 preset of the
	// kind's media ("mp4-1080"); empty is the presentation's default.
	Serve string `json:"serve,omitempty" yaml:"serve"`
}

Download is what a kind's version download serves. Whether a viewer may download, and which pages are marked, is the host's DownloadPolicy.

type GroupKind

type GroupKind struct {
	Route string `json:"route,omitempty" yaml:"route"`
	// Ordered members carry positions (series, playlists, rails).
	Ordered bool `json:"ordered,omitempty" yaml:"ordered"`
	// Parent is the group kind a group may sit under (series under series).
	Parent string `json:"parent,omitempty" yaml:"parent"`
	// ScopedBy makes slugs unique within a group of that kind (character
	// within series).
	ScopedBy string `json:"scoped_by,omitempty" yaml:"scoped_by"`
	// Owner is "site" (staff-managed) or "user" (channels, playlists): a
	// signed-in person creates a user-owned group and owns it.
	Owner string `json:"owner,omitempty" yaml:"owner"`
	// MaxPerOwner caps the active groups of the kind one person owns; 0 is
	// no cap. Staff are not capped.
	MaxPerOwner int `json:"max_per_owner,omitempty" yaml:"max_per_owner"`
	// Uploads limit what editors other than staff upload to a user-owned
	// group's media.
	Uploads UploadLimits `json:"uploads,omitzero" yaml:"uploads"`
	// Sellable groups carry offers; their key unlocks every member.
	Sellable bool `json:"sellable,omitempty" yaml:"sellable"`
	// AuthScope groups name an AuthKit group whose permissions govern their
	// content (OnlyDemo channels).
	AuthScope bool `json:"auth_scope,omitempty" yaml:"auth_scope"`
	// Windows lets memberships carry active_from/active_until (rails).
	Windows bool `json:"windows,omitempty" yaml:"windows"`
	// VersionLevel lets memberships target one version (voice actors).
	VersionLevel bool `json:"version_level,omitempty" yaml:"version_level"`
	// Roles are membership roles (publisher on an artist group).
	Roles      []string             `json:"roles,omitempty" yaml:"roles"`
	Attributes map[string]Attribute `json:"attributes,omitempty" yaml:"attributes"`
}

GroupKind is one kind of grouping: tag, artist, series, channel, rail, ...

type GroupRef

type GroupRef struct {
	Kind string `json:"kind" yaml:"kind"`
	Slug string `json:"slug" yaml:"slug"`
}

GroupRef names a group by kind and slug.

type Kind

type Kind struct {
	// Route is the URL segment: /{lang}/{route}/{CODE}/{slug}.
	Route string `json:"route" yaml:"route"`
	// Presentation tells contentkit-ui how to show it: reader, player or post.
	Presentation string       `json:"presentation" yaml:"presentation"`
	Versions     VersionRules `json:"versions" yaml:"versions"`
	// Segments enables ordered, individually released ranges (chapters).
	Segments bool `json:"segments,omitempty" yaml:"segments"`
	// Groups are the group kinds content of this kind may join.
	Groups     []string             `json:"entities,omitempty" yaml:"groups"`
	Attributes map[string]Attribute `json:"attributes,omitempty" yaml:"attributes"`
	// Sort is the default list order.
	Sort string `json:"sort,omitempty" yaml:"sort"`
	// Locked is what a viewer who does not open its content sees of it;
	// nil is DefaultLocked.
	Locked *Locked `json:"locked,omitempty" yaml:"locked"`
	// DraftTTL expires drafts that never went live this long after their
	// creation: they are deleted, media included. Zero keeps them.
	DraftTTL time.Duration `json:"draft_ttl,omitempty" yaml:"draft_ttl"`
	// Download is what a version's download serves; nil serves its
	// presentation's default (Download.Serves).
	Download *Download `json:"download,omitempty" yaml:"download"`
}

Kind is one content kind: a gallery, a movie, a creator post, a blog post.

func (Kind) LockedView added in v0.90.0

func (k Kind) LockedView() Locked

LockedView is k's Locked, else DefaultLocked.

func (Kind) Serves added in v0.90.0

func (k Kind) Serves() string

Serves is what k's download serves: its Serve, else its presentation's default; "" serves none.

type Locked added in v0.90.0

type Locked struct {
	Show []string `json:"show" yaml:"show"`
	// Preview is the free part when its access rule names none; nil is none.
	Preview *Preview `json:"preview,omitempty" yaml:"preview"`
}

Locked is what a viewer who does not open content (or a version) still sees of it: the properties Show names and the free part Preview names. Its id, code, path, title, languages, traits, owner, creators and paywall always show; its body and private media never do.

func (Locked) Shows added in v0.90.0

func (l Locked) Shows(p string) bool

Shows reports whether l shows property p.

type Preview added in v0.86.0

type Preview struct {
	Pages    int `json:"pages,omitempty" yaml:"pages"`
	Segments int `json:"segments,omitempty" yaml:"segments"`
}

Preview is the free part of locked content: its first Pages pages or first Segments segments (chapters).

func (Preview) Validate added in v0.86.0

func (p Preview) Validate() error

Validate refuses a preview of nothing or of negative parts.

type Site

type Site struct {
	Name                string     `json:"name" yaml:"name"`
	Hosts               []string   `json:"hosts" yaml:"hosts"`
	ExcludeRestrictions []string   `json:"exclude_restrictions,omitempty" yaml:"exclude_restrictions"`
	RequireGroups       []GroupRef `json:"require_groups,omitempty" yaml:"require_groups"`
	// ContentFilterDefaults override app defaults for this entrypoint. A
	// reader's explicit saved preference still wins; these are not access rules.
	ContentFilterDefaults []ContentFilterDefault `json:"content_filter_defaults,omitempty" yaml:"content_filter_defaults"`
}

Site is one deployment's slice of the catalog, matched by request host. The first site is the default for unmatched hosts.

func (Site) DefaultVisible added in v0.90.0

func (s Site) DefaultVisible(filter ContentFilter) bool

DefaultVisible resolves a filter's default for this site before any saved reader override. It does not change RequireGroups or other access rules.

type UploadLimits

type UploadLimits struct {
	// FilesPerHour and BytesPerDay limit each uploader.
	FilesPerHour int   `json:"files_per_hour,omitempty" yaml:"files_per_hour"`
	BytesPerDay  int64 `json:"bytes_per_day,omitempty" yaml:"bytes_per_day"`
	// QuotaBytes caps the group's stored originals.
	QuotaBytes int64 `json:"quota_bytes,omitempty" yaml:"quota_bytes"`
}

UploadLimits bound a user-owned group's uploads; zero fields are off.

type VersionRules

type VersionRules struct {
	// Languages is "one" (a version serves one language) or "many".
	Languages string `json:"languages" yaml:"languages"`
	// Traits are the declared version traits (colored, uncensored, ...).
	Traits []string `json:"traits,omitempty" yaml:"traits"`
	// Hidden kinds have exactly one version that clients never see.
	Hidden bool `json:"hidden,omitempty" yaml:"hidden"`
}

VersionRules shape a kind's versions.

Jump to

Keyboard shortcuts

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