web

package
v0.25.9 Latest Latest
Warning

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

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Overview

Optional, removable backup feed. Keep this file isolated from the rest of the web package so deleting it (plus the routes / clear-cache wiring in web.go and the BEGIN/END telemirror block in static/index.html) is enough to drop the feature.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActiveList added in v0.14.0

type ActiveList struct {
	Name      string   `json:"name"`
	Resolvers []string `json:"resolvers"`
	LastUsed  int64    `json:"lastUsed,omitempty"`
}

ActiveList is a named subset of the resolver bank that the user can switch between — e.g., "Home", "Office", "Mobile". The currently selected list is what the fetcher uses; switching to a different list hot-swaps the active resolvers without rescanning.

type Config

type Config struct {
	Domain string `json:"domain"`
	// ExtraDomains are additional sub-domains the server also answers feed
	// queries on; the client spreads block fetches across the main domain +
	// these (main stays canonical for relay paths). From the d= URI field.
	ExtraDomains []string `json:"extraDomains,omitempty"`
	Key          string   `json:"key"`
	Resolvers    []string `json:"resolvers"`
	// ServerKey is the pinned server signing public key (base64url, the sk=
	// field of a thefeed:// URI). When set, the client verifies feed content
	// against the server's signed ExtraBlocks. Empty = unverified (old config).
	ServerKey string  `json:"serverKey,omitempty"`
	QueryMode string  `json:"queryMode"`
	RateLimit float64 `json:"rateLimit"`
	// Timeout is the per-query DNS timeout in seconds (0 = default 15 s).
	// Also used as the resolver health-check probe timeout.
	Timeout float64 `json:"timeout,omitempty"`
	// Scatter is the number of resolvers queried simultaneously per DNS block request
	// (0 or 1 = sequential, 4 = default parallel pair).
	Scatter int `json:"scatter,omitempty"`
	// AutoScan enables hourly automatic resolver health-check scans.
	// nil means enabled (default); set to a false pointer to disable.
	AutoScan *bool `json:"autoScan,omitempty"`
}

Config holds the client configuration saved in the data directory.

type Profile added in v0.2.0

type Profile struct {
	ID                 string   `json:"id"`
	Nickname           string   `json:"nickname"`
	Config             Config   `json:"config"`
	AutoUpdate         []string `json:"autoUpdate,omitempty"`
	AutoUpdateInterval int      `json:"autoUpdateInterval,omitempty"`
	// PinnedChannels stores the user's pinned channel names (stripped of @).
	// Pinned channels render at the top of each section in the sidebar.
	PinnedChannels []string `json:"pinnedChannels,omitempty"`
}

Profile wraps a Config with a user-chosen nickname and a unique ID.

type ProfileList added in v0.2.0

type ProfileList struct {
	Active   string    `json:"active"` // ID of active profile
	Profiles []Profile `json:"profiles"`
	// FontSize stores user's preferred font size (0 = default 14).
	FontSize int    `json:"fontSize,omitempty"`
	Debug    bool   `json:"debug,omitempty"`
	Theme    string `json:"theme,omitempty"`
	Lang     string `json:"lang,omitempty"`
	// SkipUpdateVersion is the latest release the user dismissed.
	SkipUpdateVersion string `json:"skipUpdateVersion,omitempty"`
	// ResolverBank is the shared pool of DNS resolvers used by all profiles.
	ResolverBank []string `json:"resolverBank,omitempty"`
	// ResolverScores stores accumulated performance data for bank resolvers.
	ResolverScores map[string]*SavedResolverScore `json:"resolverScores,omitempty"`
	// ActiveLists holds named resolver subsets so the user can keep one
	// list per situation (home, office, mobile data) and switch by name
	// instead of rescanning. The currently-selected list is named in
	// SelectedList; its resolvers are what the fetcher uses.
	//
	// Migration: legacy installs without ActiveLists are upgraded on
	// first load — their last_scan.json (or current bank) becomes a
	// single list named "Default".
	ActiveLists  []ActiveList `json:"activeLists,omitempty"`
	SelectedList string       `json:"selectedList,omitempty"`
	// ScanPromptOff suppresses the startup "scan resolvers?" prompt.
	// Persisted server-side so it survives Android's per-launch port
	// changes (each launch picks a fresh port → different localStorage
	// origin → flag was lost on every restart).
	ScanPromptOff bool `json:"scanPromptOff,omitempty"`

	// ProfilePicsEnabled enables fetching avatars over DNS when the
	// GitHub relay can't serve them. Off by default.
	ProfilePicsEnabled bool `json:"profilePicsEnabled,omitempty"`

	// Connection settings (formerly per-profile). 0 = use default.
	QueryMode string  `json:"queryMode,omitempty"` // "single" or "double"
	RateLimit float64 `json:"rateLimit,omitempty"` // parallel block fetches
	Scatter   int     `json:"scatter,omitempty"`   // resolvers per block
	Timeout   float64 `json:"timeout,omitempty"`   // DNS query timeout (s)

	// ResolverCacheShare gates the shared-resolver-cache feature. Pointer
	// (not plain bool) so we can tell "user never set it" (nil → default
	// on) apart from "user explicitly disabled" (false). New installs and
	// upgrades from before this field existed get the feature on; an
	// explicit opt-out persists across restarts.
	ResolverCacheShare *bool `json:"resolverCacheShare,omitempty"`

	// SeenIDs maps channel name → last-seen message ID. It's the baseline
	// for the per-channel unread-count badge. Persisted server-side so the
	// counts survive the client's loopback port changing (which wipes the
	// WebView localStorage these markers used to live in).
	SeenIDs map[string]int64 `json:"seenIds,omitempty"`
	// SeenHashes maps channel name → last-seen content hash, used for the
	// X/Twitter "NEW" badge where message IDs aren't sequential.
	SeenHashes map[string]int64 `json:"seenHashes,omitempty"`
}

ProfileList is the on-disk structure for profiles.json.

func (*ProfileList) ShareEnabled added in v0.19.0

func (pl *ProfileList) ShareEnabled() bool

ShareEnabled returns whether the shared-resolver-cache feature is on. Default is on; only an explicit *false disables it.

type SavedResolverScore added in v0.10.0

type SavedResolverScore struct {
	Success int64 `json:"success"`
	Failure int64 `json:"failure"`
	TotalMs int64 `json:"totalMs"`
}

SavedResolverScore stores persistent resolver performance data.

type Server

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

Server is the web UI server for thefeed client.

func New

func New(dataDir string, port int, host string, password string) (*Server, error)

New creates a new web server.

func (*Server) Run

func (s *Server) Run() error

Run starts the web server, binding to s.host:s.port.

func (*Server) Serve added in v0.17.4

func (s *Server) Serve(ln net.Listener) error

Serve runs the web server on an already-bound listener. Used by the mobile entry where the listener is opened first to discover the kernel-assigned port.

func (*Server) SetNewMessageHandler added in v0.25.9

func (s *Server) SetNewMessageHandler(fn func(count int))

SetNewMessageHandler registers a callback invoked (off the UI path) whenever the background chat poll loop discovers new messages. Pass nil to clear.

func (*Server) SetSharedBackend added in v0.22.0

func (s *Server) SetSharedBackend(v bool)

SetSharedBackend toggles multi-user mode. When on, /api/seen reports shared:true and refuses writes, so the client falls back to per-browser localStorage and connected users don't share (and clobber) seen markers.

Jump to

Keyboard shortcuts

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