unpackerr

package
v0.13.1 Latest Latest
Warning

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

Go to latest
Published: Jan 21, 2024 License: MIT Imports: 45 Imported by: 0

Documentation

Index

Constants

View Source
const (
	WAITING = ExtractStatus(iota)
	QUEUED
	EXTRACTING
	EXTRACTFAILED
	EXTRACTED
	IMPORTED
	DELETING
	DELETEFAILED // unused
	DELETED
	EXTRACTEDNOTHING
)

Extract Statuses.

View Source
const DefaultQueuePageSize = 2000

DefaultQueuePageSize is how many items we request from Lidarr and Readarr. Once we have better support for Sonarr/Radarr v3 this will apply to those as well. If you have more than this many items queued.. oof. As the queue goes away, more things should get picked up.

View Source
const (
	FolderString = "Folder"
)

These are the names used to identify each app.

View Source
const WebhookTemplateDiscord = `` /* 1727-byte string literal not displayed */

WebhookTemplateDiscord is used when sending a webhook to discord.com.

View Source
const WebhookTemplateGotify = `` /* 858-byte string literal not displayed */

The extra spaces before the newlines here are required to make this look good on web and on android.

View Source
const WebhookTemplateNotifiarr = `` /* 871-byte string literal not displayed */

WebhookTemplateNotifiarr is the default template when not using discord.com (below), or a custom template file.

View Source
const WebhookTemplatePushover = `token={{token}}&user={{channel}}&html=1&title={{formencode .Event.Desc}}&` +
	`{{if nickname}}device={{nickname}}&{{end}}message=<pre><b>App</b>: {{.App}}
<b>Name</b>: {{formencode (index .IDs "title")}}
<b>Path</b>: {{formencode .Path}}
{{ if .Data -}}
{{ if .Data.Elapsed.Duration}}<b>Time</b>: {{.Data.Elapsed}}
{{end}}{{ if .Data.Archives}}<b>RARs</b>: {{len .Data.Archives}}
{{end}}{{ if .Data.Files}}<b>Files</b>: {{len .Data.Files}}
{{end}}{{ if .Data.Bytes}}<b>Bytes</b>: {{humanbytes .Data.Bytes}}
{{end}}{{ if and (gt .Event 1) (lt .Event 5)}}<b>Queue</b>: {{.Data.Queue}}
{{end}}{{ if .Data.Error}}
<font color="#FF0000"><b>ERROR</b>: {{formencode .Data.Error}}</font>
{{end}}{{end -}}</pre>`
View Source
const WebhookTemplateSlack = `` /* 1866-byte string literal not displayed */

WebhookTemplateSlack is a built-in template for sending a message to Slack.

View Source
const WebhookTemplateTelegram = `` /* 819-byte string literal not displayed */

Variables

View Source
var (
	ErrInvalidURL = fmt.Errorf("provided application URL is invalid")
	ErrInvalidKey = fmt.Errorf("provided application API Key is invalid, must be %d characters", apiKeyLength)
)

Application validation errors.

View Source
var (
	ErrInvalidStatus = fmt.Errorf("invalid HTTP status reply")
	ErrWebhookNoURL  = fmt.Errorf("webhook without a URL configured; fix it")
)

Errors produced by this file.

View Source
var (
	ErrCmdhookNoCmd = fmt.Errorf("cmdhook without a command configured; fix it")
)

Errors produced by this file.

Functions

func Index added in v0.12.0

func Start

func Start() (err error)

Start runs the app.

Types

type AllowedIPs added in v0.12.0

type AllowedIPs struct {
	Input []string
	Nets  []*net.IPNet
}

AllowedIPs determines who can set x-forwarded-for.

func MakeIPs added in v0.12.0

func MakeIPs(upstreams []string) AllowedIPs

MakeIPs turns a list of CIDR strings (or plain IPs) into a list of net.IPNet. This "allowed" list is later used to check incoming IPs from web requests.

func (AllowedIPs) Contains added in v0.12.0

func (n AllowedIPs) Contains(ip string) bool

Contains returns true if an IP is allowed.

func (AllowedIPs) String added in v0.12.0

func (n AllowedIPs) String() (s string)

String turns a list of allowedIPs into a printable masterpiece.

type Config

type Config struct {
	Debug       bool             `json:"debug" toml:"debug" xml:"debug" yaml:"debug"`
	Quiet       bool             `json:"quiet" toml:"quiet" xml:"quiet" yaml:"quiet"`
	Activity    bool             `json:"activity" toml:"activity" xml:"activity" yaml:"activity"`
	Parallel    uint             `json:"parallel" toml:"parallel" xml:"parallel" yaml:"parallel"`
	ErrorStdErr bool             `json:"errorStderr" toml:"error_stderr" xml:"error_stderr" yaml:"errorStderr"`
	LogFile     string           `json:"logFile" toml:"log_file" xml:"log_file" yaml:"logFile"`
	LogFiles    int              `json:"logFiles" toml:"log_files" xml:"log_files" yaml:"logFiles"`
	LogFileMb   int              `json:"logFileMb" toml:"log_file_mb" xml:"log_file_mb" yaml:"logFileMb"`
	MaxRetries  uint             `json:"maxRetries" toml:"max_retries" xml:"max_retries" yaml:"maxRetries"`
	FileMode    string           `json:"fileMode" toml:"file_mode" xml:"file_mode" yaml:"fileMode"`
	DirMode     string           `json:"dirMode" toml:"dir_mode" xml:"dir_mode" yaml:"dirMode"`
	LogQueues   cnfg.Duration    `json:"logQueues" toml:"log_queues" xml:"log_queues" yaml:"logQueues"`
	Interval    cnfg.Duration    `json:"interval" toml:"interval" xml:"interval" yaml:"interval"`
	Timeout     cnfg.Duration    `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
	DeleteDelay cnfg.Duration    `json:"deleteDelay" toml:"delete_delay" xml:"delete_delay" yaml:"deleteDelay"`
	StartDelay  cnfg.Duration    `json:"startDelay" toml:"start_delay" xml:"start_delay" yaml:"startDelay"`
	RetryDelay  cnfg.Duration    `json:"retryDelay" toml:"retry_delay" xml:"retry_delay" yaml:"retryDelay"`
	Buffer      uint             `json:"buffer" toml:"buffer" xml:"buffer" yaml:"buffer"`                       //nolint:lll // undocumented.
	KeepHistory uint             `json:"keepHistory" toml:"keep_history" xml:"keep_history" yaml:"keepHistory"` //nolint:lll // undocumented.
	Passwords   StringSlice      `json:"passwords" toml:"passwords" xml:"password" yaml:"passwords"`
	Webserver   *WebServer       `json:"webserver" toml:"webserver" xml:"webserver" yaml:"webserver"`
	Lidarr      []*LidarrConfig  `json:"lidarr,omitempty" toml:"lidarr" xml:"lidarr" yaml:"lidarr,omitempty"`
	Radarr      []*RadarrConfig  `json:"radarr,omitempty" toml:"radarr" xml:"radarr" yaml:"radarr,omitempty"`
	Whisparr    []*RadarrConfig  `json:"whisparr,omitempty" toml:"whisparr" xml:"whisparr" yaml:"whisparr,omitempty"`
	Readarr     []*ReadarrConfig `json:"readarr,omitempty" toml:"readarr" xml:"readarr" yaml:"readarr,omitempty"`
	Sonarr      []*SonarrConfig  `json:"sonarr,omitempty" toml:"sonarr" xml:"sonarr" yaml:"sonarr,omitempty"`
	Folders     []*FolderConfig  `json:"folder,omitempty" toml:"folder" xml:"folder" yaml:"folder,omitempty"`
	Webhook     []*WebhookConfig `json:"webhook,omitempty" toml:"webhook" xml:"webhook" yaml:"webhook,omitempty"`
	Cmdhook     []*WebhookConfig `json:"cmdhook,omitempty" toml:"cmdhook" xml:"cmdhook" yaml:"cmdhook,omitempty"`
	Folder      struct {
		Interval cnfg.Duration `json:"interval" toml:"interval" xml:"interval" yaml:"interval"` // undocumented.
	} `json:"folders,omitempty" toml:"folders" xml:"folders" yaml:"folders,omitempty"` // undocumented.
}

Config defines the configuration data used to start the application.

type Extract

type Extract struct {
	Syncthing   bool
	Retries     uint
	Path        string
	App         starr.App
	URL         string
	Updated     time.Time
	DeleteDelay time.Duration
	DeleteOrig  bool
	Status      ExtractStatus
	IDs         map[string]interface{}
	Resp        *xtractr.Response
}

Extract holds data for files being extracted.

type ExtractStatus

type ExtractStatus uint8

ExtractStatus is our enum for an extract's status.

func (ExtractStatus) Desc

func (status ExtractStatus) Desc() string

Desc makes ExtractStatus human readable.

func (ExtractStatus) MarshalText

func (status ExtractStatus) MarshalText() ([]byte, error)

MarshalText turns a status into a word, for a json identifier.

func (ExtractStatus) String

func (status ExtractStatus) String() string

String turns a status into a short string.

type ExtractStatuses added in v0.11.2

type ExtractStatuses []ExtractStatus

ExtractStatuses allows us to create a custom environment variable unmarshaller.

func (ExtractStatuses) MarshalENV added in v0.11.2

func (statuses ExtractStatuses) MarshalENV(tag string) (map[string]string, error)

func (*ExtractStatuses) UnmarshalENV added in v0.11.2

func (statuses *ExtractStatuses) UnmarshalENV(tag, envval string) error

UnmarshalENV turns environment variables into extraction statuses.

type Flags

type Flags struct {
	ConfigFile string
	EnvPrefix  string
	// contains filtered or unexported fields
}

Flags are our CLI input flags.

type Folder

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

Folder is a "new" watched folder.

type FolderConfig

type FolderConfig struct {
	DeleteOrig       bool          `json:"delete_original" toml:"delete_original" xml:"delete_original" yaml:"delete_original"`
	DeleteFiles      bool          `json:"delete_files" toml:"delete_files" xml:"delete_files" yaml:"delete_files"`
	DisableLog       bool          `json:"disable_log" toml:"disable_log" xml:"disable_log" yaml:"disable_log"`
	MoveBack         bool          `json:"move_back" toml:"move_back" xml:"move_back" yaml:"move_back"`
	DeleteAfter      cnfg.Duration `json:"delete_after" toml:"delete_after" xml:"delete_after" yaml:"delete_after"`
	ExtractPath      string        `json:"extract_path" toml:"extract_path" xml:"extract_path" yaml:"extract_path"`
	ExtractISOs      bool          `json:"extract_isos" toml:"extract_isos" xml:"extract_isos" yaml:"extract_isos"`
	DisableRecursion bool          `json:"disableRecursion" toml:"disable_recursion" xml:"disable_recursion" yaml:"disableRecursion"`
	Path             string        `json:"path" toml:"path" xml:"path" yaml:"path"`
}

FolderConfig defines the input data for a watched folder.

type Folders

type Folders struct {
	Interval time.Duration
	Config   []*FolderConfig
	Folders  map[string]*Folder
	Events   chan *eventData
	Updates  chan *xtractr.Response
	Printf   func(msg string, v ...interface{})
	Errorf   func(msg string, v ...interface{})
	Debugf   func(msg string, v ...interface{})
	FSNotify *fsnotify.Watcher
	Watcher  *watcher.Watcher
}

Folders holds all known (created) folders in all watch paths.

func (*Folders) Add

func (f *Folders) Add(folder string) error

Add uses either fsnotify or watcher.

func (*Folders) Remove

func (f *Folders) Remove(folder string)

Remove uses either fsnotify or watcher.

type History

type History struct {
	Items    []string
	Finished uint
	Retries  uint
	Map      map[string]*Extract
}

History holds the history of extracted items.

type LidarrConfig

type LidarrConfig struct {
	starr.Config
	StarrConfig
	Queue          *lidarr.Queue `json:"-" toml:"-" xml:"-" yaml:"-"`
	*lidarr.Lidarr `json:"-" toml:"-" xml:"-" yaml:"-"`
	sync.RWMutex   `json:"-" toml:"-" xml:"-" yaml:"-"`
}

LidarrConfig represents the input data for a Lidarr server.

type Logger

type Logger struct {
	HTTP  *log.Logger
	Info  *log.Logger
	Error *log.Logger
	Debug *log.Logger
}

Logger provides a struct we can pass into other packages.

func (*Logger) Debugf

func (l *Logger) Debugf(msg string, v ...interface{})

Debugf writes Debug log lines... to stdout and/or a file.

func (*Logger) Errorf added in v0.12.0

func (l *Logger) Errorf(msg string, v ...interface{})

Errorf writes log errors... to stdout and/or a file.

func (*Logger) Printf

func (l *Logger) Printf(msg string, v ...interface{})

Printf writes log lines... to stdout and/or a file.

type MetricsCollector added in v0.12.0

type MetricsCollector struct {
	*Unpackerr
	// contains filtered or unexported fields
}

MetricsCollector is used to plug into a custom Prometheus metrics collector.

func (*MetricsCollector) Collect added in v0.12.0

func (c *MetricsCollector) Collect(ch chan<- prometheus.Metric)

Collect satisfies the Prometheus custom metrics collector.

func (*MetricsCollector) Describe added in v0.12.0

func (c *MetricsCollector) Describe(ch chan<- *prometheus.Desc)

Describe satisfies the Prometheus custom metrics collector.

type RadarrConfig

type RadarrConfig struct {
	starr.Config
	StarrConfig
	Queue          *radarr.Queue `json:"-" toml:"-" xml:"-" yaml:"-"`
	sync.RWMutex   `json:"-" toml:"-" xml:"-" yaml:"-"`
	*radarr.Radarr `json:"-" toml:"-" xml:"-" yaml:"-"`
}

RadarrConfig represents the input data for a Radarr server.

type ReadarrConfig

type ReadarrConfig struct {
	starr.Config
	StarrConfig
	Queue            *readarr.Queue `json:"-" toml:"-" xml:"-" yaml:"-"`
	sync.RWMutex     `json:"-" toml:"-" xml:"-" yaml:"-"`
	*readarr.Readarr `json:"-" toml:"-" xml:"-" yaml:"-"`
}

ReadarrConfig represents the input data for a Readarr server.

type SonarrConfig

type SonarrConfig struct {
	starr.Config
	StarrConfig
	Queue          *sonarr.Queue `json:"-" toml:"-" xml:"-" yaml:"-"`
	sync.RWMutex   `json:"-" toml:"-" xml:"-" yaml:"-"`
	*sonarr.Sonarr `json:"-" toml:"-" xml:"-" yaml:"-"`
}

SonarrConfig represents the input data for a Sonarr server.

type StarrConfig

type StarrConfig struct {
	Path        string        `json:"path" toml:"path" xml:"path" yaml:"path"`
	Paths       StringSlice   `json:"paths" toml:"paths" xml:"paths" yaml:"paths"`
	Protocols   string        `json:"protocols" toml:"protocols" xml:"protocols" yaml:"protocols"`
	DeleteOrig  bool          `json:"delete_orig" toml:"delete_orig" xml:"delete_orig" yaml:"delete_orig"`
	DeleteDelay cnfg.Duration `json:"delete_delay" toml:"delete_delay" xml:"delete_delay" yaml:"delete_delay"`
	Syncthing   bool          `json:"syncthing" toml:"syncthing" xml:"syncthing" yaml:"syncthing"`
	ValidSSL    bool          `json:"valid_ssl" toml:"valid_ssl" xml:"valid_ssl" yaml:"valid_ssl"`
	Timeout     cnfg.Duration `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
}

Shared config items for all starr apps.

type Stats added in v0.12.0

type Stats struct {
	Waiting    uint
	Queued     uint
	Extracting uint
	Failed     uint
	Extracted  uint
	Imported   uint
	Deleted    uint
	HookOK     uint
	HookFail   uint
	CmdOK      uint
	CmdFail    uint
}

Stats is filled and returned when a stats request is issued.

type StringSlice added in v0.11.2

type StringSlice []string

StringSlice allows a special environment variable unmarshaller for a lot of strings.

func (StringSlice) MarshalENV added in v0.11.2

func (slice StringSlice) MarshalENV(tag string) (map[string]string, error)

func (*StringSlice) UnmarshalENV added in v0.11.2

func (slice *StringSlice) UnmarshalENV(_, envval string) error

UnmarshalENV turns environment variables into a string slice.

type Unpackerr

type Unpackerr struct {
	*Flags
	*Config
	*History
	*xtractr.Xtractr

	*Logger
	// contains filtered or unexported fields
}

Unpackerr stores all the running data.

func New

func New() *Unpackerr

New returns an UnpackerPoller struct full of defaults. An empty struct will surely cause you pain, so use this!

func (*Unpackerr) CmdhookCounts

func (u *Unpackerr) CmdhookCounts() (total uint, fails uint)

CmdhookCounts returns the total count of requests and errors for all webhooks.

func (*Unpackerr) ParseFlags

func (u *Unpackerr) ParseFlags() *Unpackerr

ParseFlags turns CLI args into usable data.

func (*Unpackerr) PollFolders

func (u *Unpackerr) PollFolders()

PollFolders begins the routines to watch folders for changes. if those changes include the addition of compressed files, they are processed for exctraction.

func (*Unpackerr) Run

func (u *Unpackerr) Run()

Run starts the loop that does the work.

func (*Unpackerr) WebhookCounts

func (u *Unpackerr) WebhookCounts() (total uint, fails uint)

WebhookCounts returns the total count of requests and errors for all webhooks.

type WebServer added in v0.12.0

type WebServer struct {
	Metrics    bool        `toml:"metrics" json:"metrics" xml:"metrics" yaml:"metrics"`
	LogFiles   int         `json:"logFiles" toml:"log_files" xml:"log_files" yaml:"logFiles"`
	LogFileMb  int         `json:"logFileMb" toml:"log_file_mb" xml:"log_file_mb" yaml:"logFileMb"`
	ListenAddr string      `toml:"listen_addr" json:"listenAddr" xml:"listen_addr" yaml:"listenAddr"`
	LogFile    string      `json:"logFile" toml:"log_file" xml:"log_file" yaml:"logFile"`
	SSLCrtFile string      `json:"sslCertFile" toml:"ssl_cert_file" xml:"ssl_cert_file" yaml:"sslCertFile"`
	SSLKeyFile string      `json:"sslKeyFile" toml:"ssl_key_file" xml:"ssl_key_file" yaml:"sslKeyFile"`
	URLBase    string      `json:"urlbase" toml:"urlbase" xml:"urlbase" yaml:"urlbase"`
	Upstreams  StringSlice `json:"upstreams" toml:"upstreams" xml:"upstreams" yaml:"upstreams"`
	// contains filtered or unexported fields
}

func (*WebServer) Enabled added in v0.12.0

func (w *WebServer) Enabled() bool

type WebhookConfig

type WebhookConfig struct {
	Name      string          `json:"name" toml:"name" xml:"name" yaml:"name"`
	URL       string          `json:"url" toml:"url" xml:"url,omitempty" yaml:"url"`
	Command   string          `json:"command" toml:"command" xml:"command,omitempty" yaml:"command"`
	CType     string          `json:"contentType" toml:"content_type" xml:"content_type,omitempty" yaml:"contentType"`
	TmplPath  string          `json:"templatePath" toml:"template_path" xml:"template_path,omitempty" yaml:"templatePath"`
	TempName  string          `json:"template" toml:"template" xml:"template,omitempty" yaml:"template"`
	Timeout   cnfg.Duration   `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
	Shell     bool            `json:"shell" toml:"shell" xml:"shell" yaml:"shell"`
	IgnoreSSL bool            `json:"ignoreSsl" toml:"ignore_ssl" xml:"ignore_ssl,omitempty" yaml:"ignoreSsl"`
	Silent    bool            `json:"silent" toml:"silent" xml:"silent" yaml:"silent"`
	Events    ExtractStatuses `json:"events" toml:"events" xml:"events" yaml:"events"`
	Exclude   StringSlice     `json:"exclude" toml:"exclude" xml:"exclude" yaml:"exclude"`
	Nickname  string          `json:"nickname" toml:"nickname" xml:"nickname,omitempty" yaml:"nickname"`
	Token     string          `json:"token" toml:"token" xml:"token,omitempty" yaml:"token"`
	Channel   string          `json:"channel" toml:"channel" xml:"channel,omitempty" yaml:"channel"`

	sync.Mutex `json:"-" toml:"-" xml:"-" yaml:"-"`
	// contains filtered or unexported fields
}

WebhookConfig defines the data to send webhooks to a server.

func (*WebhookConfig) Counts

func (w *WebhookConfig) Counts() (uint, uint)

Counts returns the total count of requests and failures for a webhook.

func (*WebhookConfig) Excluded

func (w *WebhookConfig) Excluded(app starr.App) bool

Excluded returns true if an app is in the Exclude slice.

func (*WebhookConfig) HasEvent

func (w *WebhookConfig) HasEvent(e ExtractStatus) bool

HasEvent returns true if a status event is in the Events slice. Also returns true if the Events slice has only one value of WAITING.

func (*WebhookConfig) Send

func (w *WebhookConfig) Send(body io.Reader) ([]byte, error)

Send marshals an interface{} into json and POSTs it to a URL.

func (*WebhookConfig) Template

func (w *WebhookConfig) Template() (*template.Template, error)

Template returns a template specific to this webhook.

type WebhookPayload

type WebhookPayload struct {
	Path   string                 `json:"path"`                // Path for the extracted item.
	App    starr.App              `json:"app"`                 // Application Triggering Event
	IDs    map[string]interface{} `json:"ids,omitempty"`       // Arbitrary IDs from each app.
	Event  ExtractStatus          `json:"unpackerr_eventtype"` // The type of the event.
	Time   time.Time              `json:"time"`                // Time of this event.
	Data   *XtractPayload         `json:"data,omitempty"`      // Payload from extraction process.
	Config *WebhookConfig         `json:"-"`                   // Payload from extraction process.
	// Application Metadata.
	Go       string    `json:"go"`       // Version of go compiled with
	OS       string    `json:"os"`       // Operating system: linux, windows, darwin
	Arch     string    `json:"arch"`     // Architecture: amd64, armhf
	Version  string    `json:"version"`  // Application Version
	Revision string    `json:"revision"` // Application Revision
	Branch   string    `json:"branch"`   // Branch built from.
	Started  time.Time `json:"started"`  // App start time.
}

WebhookPayload defines the data sent to notifarr.com (and other) webhooks.

type XtractPayload

type XtractPayload struct {
	Error    string        `json:"error,omitempty"`    // error only during extractfailed
	Archive  []string      `json:"archive,omitempty"`  // list of all archive files extracted
	Archives StringSlice   `json:"archives,omitempty"` // list of all archive files extracted
	Files    StringSlice   `json:"files,omitempty"`    // list of all files extracted
	File     []string      `json:"file,omitempty"`     // list of all files extracted
	Start    time.Time     `json:"start,omitempty"`    // start time of extraction
	Output   string        `json:"output,omitempty"`   // temporary items folder
	Bytes    int64         `json:"bytes,omitempty"`    // Bytes written
	Elapsed  cnfg.Duration `json:"elapsed,omitempty"`  // Duration as a string: 5m32s
	Queue    int           `json:"queue,omitempty"`    // Extraction Queue Size
}

XtractPayload is a rewrite of xtractr.Response.

Jump to

Keyboard shortcuts

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