Initial release
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gitea.dcglab.co.uk/steve/arrman/cmd"
|
||||
"gitea.dcglab.co.uk/steve/arrman/radarr"
|
||||
"gitea.dcglab.co.uk/steve/arrman/sonarr"
|
||||
)
|
||||
|
||||
// Version is set at build time via -ldflags.
|
||||
var Version = "dev"
|
||||
|
||||
func main() {
|
||||
loadEnv()
|
||||
|
||||
if len(os.Args) >= 2 && os.Args[1] == "version" {
|
||||
fmt.Println(Version)
|
||||
return
|
||||
}
|
||||
|
||||
// Extract global --json flag from any position in args
|
||||
filteredArgs, jsonOutput := extractFlag(os.Args[1:], "--json")
|
||||
if len(filteredArgs) < 2 {
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
domain := filteredArgs[0]
|
||||
action := filteredArgs[1]
|
||||
rest := filteredArgs[2:]
|
||||
|
||||
tlsSkip := strings.EqualFold(os.Getenv("ARRMAN_TLS_SKIP_VERIFY"), "true")
|
||||
|
||||
var err error
|
||||
|
||||
switch domain {
|
||||
case "tv":
|
||||
sonarrURL := requireEnv("SONARR_URL")
|
||||
sonarrKey := requireEnv("SONARR_API_KEY")
|
||||
client := sonarr.NewClient(sonarrURL, sonarrKey, tlsSkip)
|
||||
err = runTV(client, action, rest, jsonOutput)
|
||||
|
||||
case "film", "films":
|
||||
radarrURL := requireEnv("RADARR_URL")
|
||||
radarrKey := requireEnv("RADARR_API_KEY")
|
||||
client := radarr.NewClient(radarrURL, radarrKey, tlsSkip)
|
||||
err = runFilm(client, action, rest, jsonOutput)
|
||||
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Unknown domain: %s\n", domain)
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func extractFlag(args []string, flag string) ([]string, bool) {
|
||||
var remaining []string
|
||||
found := false
|
||||
for _, a := range args {
|
||||
if a == flag {
|
||||
found = true
|
||||
} else {
|
||||
remaining = append(remaining, a)
|
||||
}
|
||||
}
|
||||
return remaining, found
|
||||
}
|
||||
|
||||
func runTV(client cmd.SonarrClient, action string, args []string, jsonOutput bool) error {
|
||||
switch action {
|
||||
case "list":
|
||||
rest, inclExt := extractFlag(args, "--include-external")
|
||||
term := strings.Join(rest, " ")
|
||||
return cmd.TVList(client, term, inclExt, jsonOutput)
|
||||
case "add":
|
||||
return cmd.TVAdd(client, args, jsonOutput)
|
||||
case "summary":
|
||||
term := strings.Join(args, " ")
|
||||
return cmd.TVSummary(client, term, jsonOutput)
|
||||
case "profiles":
|
||||
return cmd.TVProfiles(client, jsonOutput)
|
||||
case "rootfolders":
|
||||
return cmd.TVRootFolders(client, jsonOutput)
|
||||
default:
|
||||
return fmt.Errorf("unknown tv action: %s", action)
|
||||
}
|
||||
}
|
||||
|
||||
func runFilm(client cmd.RadarrClient, action string, args []string, jsonOutput bool) error {
|
||||
switch action {
|
||||
case "list":
|
||||
rest, inclExt := extractFlag(args, "--include-external")
|
||||
term := strings.Join(rest, " ")
|
||||
return cmd.FilmList(client, term, inclExt, jsonOutput)
|
||||
case "add":
|
||||
return cmd.FilmAdd(client, args, jsonOutput)
|
||||
case "summary":
|
||||
term := strings.Join(args, " ")
|
||||
return cmd.FilmSummary(client, term, jsonOutput)
|
||||
case "profiles":
|
||||
return cmd.FilmProfiles(client, jsonOutput)
|
||||
case "rootfolders":
|
||||
return cmd.FilmRootFolders(client, jsonOutput)
|
||||
default:
|
||||
return fmt.Errorf("unknown film action: %s", action)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintln(os.Stderr, `Usage: arrman [--json] <domain> <action> [args...]
|
||||
|
||||
Domains: tv, film, films
|
||||
|
||||
Actions:
|
||||
list [title] [--include-external] List/search library (add flag to include external sources)
|
||||
add <term> --profile <id> --rootfolder <path> Add new
|
||||
summary <term> Show details
|
||||
profiles List quality profiles
|
||||
rootfolders List root folders
|
||||
|
||||
Global flags:
|
||||
--json Output results as structured JSON`)
|
||||
}
|
||||
|
||||
func loadEnv() {
|
||||
f, err := os.Open(".env")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(line, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(parts[0])
|
||||
val := strings.TrimSpace(parts[1])
|
||||
if os.Getenv(key) == "" {
|
||||
os.Setenv(key, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func requireEnv(key string) string {
|
||||
val := os.Getenv(key)
|
||||
if val == "" {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s is not set. Check your .env file.\n", key)
|
||||
os.Exit(1)
|
||||
}
|
||||
return val
|
||||
}
|
||||
Reference in New Issue
Block a user