config

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Mar 3, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package config handles loading, validating, and merging notification pipeline configurations.

Index

Constants

View Source
const (
	DefaultVoiceName  = "nova"
	DefaultVoiceModel = "tts-1"
	DefaultVoiceSpeed = 1.0
)

Voice generation defaults.

View Source
const DefaultAFKThreshold = 300

DefaultAFKThreshold is the default idle-time threshold in seconds.

View Source
const DefaultMaxDesktops = 4

DefaultMaxDesktops is the default upper bound for the virtual desktop index.

View Source
const DefaultVolume = 100

DefaultVolume is the default playback volume (0-100).

Variables

This section is empty.

Functions

func FindPath added in v0.2.12

func FindPath(explicitPath string) (string, error)

FindPath resolves the config file path using the same resolution order as Load. Returns the resolved path or an error if no config file is found.

func MatchProfile added in v0.2.17

func MatchProfile(cfg Config, dir string) string

MatchProfile returns the first profile whose match rule is satisfied by the given working directory, or "default" if none match. Profiles are checked alphabetically for deterministic tiebreaking. Profiles without a match rule are skipped.

func Validate added in v0.2.4

func Validate(cfg Config) error

Validate checks a parsed Config for common mistakes and returns a multi-line error listing all problems found, or nil if valid.

Types

type Action

type Action struct {
	CooldownSeconds int    `json:"cooldown_seconds,omitempty"`
	Steps           []Step `json:"steps"`
}

Action holds an ordered list of steps to execute.

func Resolve

func Resolve(cfg Config, profile, action string) (string, *Action, error)

Resolve looks up an action by profile and action name. Returns the canonical profile name (resolving aliases), the action, and an error. Checks direct match first, then alias match, then falls back to the "default" profile.

type Config

type Config struct {
	Options  Options            `json:"config"`
	Profiles map[string]Profile `json:"profiles"`
	Builtin  bool               `json:"-"` // true when using built-in defaults (no config file)
}

Config holds the top-level configuration: global options and profiles.

func DefaultConfig added in v0.2.25

func DefaultConfig() Config

DefaultConfig returns a built-in config with a "default" profile containing four basic actions (ready, error, done, attention) using only local audio steps. Used as a fallback when no config file exists so that basic commands work out of the box without any setup.

func Load

func Load(explicitPath string) (Config, error)

Load reads and parses a config file. It tries, in order:

  1. explicitPath (if non-empty)
  2. notify-config.json next to the running binary
  3. ~/.config/notify/notify-config.json

When no config file is found and explicitPath is empty, Load returns DefaultConfig() so that basic commands work without any setup.

func (*Config) UnmarshalJSON

func (c *Config) UnmarshalJSON(data []byte) error

UnmarshalJSON sets defaults then decodes the JSON structure. Go's json.Unmarshal merges into existing struct fields, so only values present in JSON override the defaults.

type Credentials

type Credentials struct {
	DiscordWebhook string `json:"discord_webhook,omitempty"`
	SlackWebhook   string `json:"slack_webhook,omitempty"`
	TelegramToken  string `json:"telegram_token,omitempty"`
	TelegramChatID string `json:"telegram_chat_id,omitempty"`
	OpenAIAPIKey   string `json:"openai_api_key,omitempty"`
	MQTTUsername   string `json:"mqtt_username,omitempty"`
	MQTTPassword   string `json:"mqtt_password,omitempty"`
}

Credentials holds secret values for remote notification actions.

func MergeCredentials added in v0.2.13

func MergeCredentials(global Credentials, profile *Credentials) Credentials

MergeCredentials returns global credentials with any non-empty profile fields overriding. A nil profile returns global unchanged. The profile parameter is a pointer so callers can pass nil to indicate "no profile-level overrides" without needing a zero-value Credentials.

type MatchRule added in v0.2.17

type MatchRule struct {
	Dir string `json:"dir,omitempty"`
	Env string `json:"env,omitempty"`
}

MatchRule defines conditions for automatic profile selection. All non-empty fields must match (AND logic). Dir is a substring check against the working directory (forward-slash normalized). Env is a KEY=VALUE check against an environment variable.

type Options

type Options struct {
	AFKThresholdSeconds int               `json:"afk_threshold_seconds,omitempty"`
	DefaultVolume       int               `json:"default_volume,omitempty"`
	Log                 bool              `json:"log,omitempty"`
	Echo                bool              `json:"echo,omitempty"`
	Cooldown            bool              `json:"cooldown,omitempty"`
	CooldownSeconds     int               `json:"cooldown_seconds,omitempty"`
	ExitCodes           map[string]string `json:"exit_codes,omitempty"`
	OutputLines         int               `json:"output_lines,omitempty"`
	HeartbeatSeconds    int               `json:"heartbeat_seconds,omitempty"`
	ShellHookThreshold  int               `json:"shell_hook_threshold,omitempty"`
	Storage             string            `json:"storage,omitempty"`        // "sqlite" (default) or "file"
	RetentionDays       int               `json:"retention_days,omitempty"` // 0 = keep forever, >0 = auto-prune
	MaxDesktops         int               `json:"max_desktops,omitempty"`   // 0 = default (4)
	Voice               VoiceConfig       `json:"openai_voice,omitempty"`
	Credentials         Credentials       `json:"credentials,omitempty"`
}

Options holds global settings parsed from the "config" key.

func (*Options) MaxDesktopsLimit added in v0.2.40

func (o *Options) MaxDesktopsLimit() int

MaxDesktops returns the effective desktop limit from config, falling back to DefaultMaxDesktops.

type Profile

type Profile struct {
	Extends     string            `json:"-"`
	Aliases     []string          `json:"-"`
	Desktop     *int              `json:"-"` // 1-4, virtual desktop to switch to on toast click
	Credentials *Credentials      `json:"-"`
	Match       *MatchRule        `json:"-"`
	Actions     map[string]Action `json:"-"`
}

Profile holds a set of actions and an optional parent profile name. When "extends" is set, the profile inherits all actions from the parent, with its own actions taking priority on conflicts. Aliases provide shorthand names for the profile. Credentials override global credentials field-by-field (nil = use global only). Match defines conditions for automatic profile selection (nil = never auto-selected).

func (Profile) MarshalJSON added in v0.2.20

func (p Profile) MarshalJSON() ([]byte, error)

MarshalJSON serializes a Profile back to the flat JSON format used by UnmarshalJSON. Without this, json.Marshal produces {} because all fields have json:"-" tags.

func (*Profile) UnmarshalJSON added in v0.2.11

func (p *Profile) UnmarshalJSON(data []byte) error

UnmarshalJSON extracts the optional "extends" key and parses all remaining keys as actions. This keeps the JSON format flat:

{ "extends": "default", "ready": { "steps": [...] } }

type Step

type Step struct {
	Type    string            `json:"type"`              // "sound" | "say" | "toast" | "discord" | "discord_voice" | "slack" | "telegram" | "telegram_audio" | "telegram_voice" | "webhook" | "plugin" | "mqtt"
	Sound   string            `json:"sound,omitempty"`   // type=sound
	Text    string            `json:"text,omitempty"`    // type=say, discord, discord_voice, slack, telegram, telegram_audio, webhook, plugin, mqtt
	Title   string            `json:"title,omitempty"`   // type=toast
	Message string            `json:"message,omitempty"` // type=toast
	URL     string            `json:"url,omitempty"`     // type=webhook
	Headers map[string]string `json:"headers,omitempty"` // type=webhook
	Command string            `json:"command,omitempty"` // type=plugin
	Timeout *int              `json:"timeout,omitempty"` // type=plugin (seconds, default 10)
	Broker  string            `json:"broker,omitempty"`  // type=mqtt
	Topic   string            `json:"topic,omitempty"`   // type=mqtt
	Retain  bool              `json:"retain,omitempty"`  // type=mqtt (default false)
	QoS     *int              `json:"qos,omitempty"`     // type=mqtt (0, 1, or 2; default 0)
	Volume  *int              `json:"volume,omitempty"`  // per-step override, nil = use default
	When    string            `json:"when,omitempty"`    // "" | "never" | "afk" | "present" | "run" | "direct" | "hours:X-Y" | "long:DURATION"
}

Step is a single unit of work within an action.

type VoiceConfig added in v0.2.25

type VoiceConfig struct {
	Provider string  `json:"provider,omitempty"` // "openai" (default, only option)
	Model    string  `json:"model,omitempty"`    // "tts-1" or "tts-1-hd"
	Voice    string  `json:"voice,omitempty"`    // alloy|echo|fable|onyx|nova|shimmer
	Speed    float64 `json:"speed,omitempty"`    // 0.25-4.0, default 1.0
	MinUses  int     `json:"min_uses,omitempty"` // minimum event log occurrences before generating (default 3)
}

VoiceConfig holds settings for AI voice generation.

Jump to

Keyboard shortcuts

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