Files
goget/cmd/goget/flags.go
T

317 lines
17 KiB
Go

//go:build linux || freebsd
// +build linux freebsd
package main
import (
"flag"
"strings"
"time"
"codeberg.org/petrbalvin/goget/internal/config"
)
// headerFlags accumulates multiple --header values.
type headerFlags []string
func (h *headerFlags) String() string { return strings.Join(*h, ", ") }
func (h *headerFlags) Set(v string) error {
*h = append(*h, v)
return nil
}
// formFlags accumulates multiple --form values.
type formFlags []string
func (f *formFlags) String() string { return strings.Join(*f, ", ") }
func (f *formFlags) Set(v string) error {
*f = append(*f, v)
return nil
}
// Flags holds all CLI flag values.
type Flags struct {
URL *string
Output *string
Resume *bool
Overwrite *bool
Restart *bool
Verbose *bool
Quiet *bool
NoProgress *bool
JSON *bool
Debug *bool
Timeout *time.Duration
Proxy *string
NoIPv4 *bool
NoRedirect *bool
MaxRetries *int
DNSServers *string
Checksum *string
ChecksumAlgo *string
ChecksumFile *string
NoDecompress *bool
Parallel *int
MaxSpeed *string
Username *string
Password *string
PasswordFile *string
AuthType *string
CookieJar *string
ContentDisp *bool
ShowHeaders *bool
KeepTimestamps *bool
Recursive *bool
RecursiveParallel *int
MaxDepth *int
FollowExternal *bool
Mirror *bool
NoConvertLinks *bool
NoMirrorAssets *bool
NoRobots *bool
RateLimit *string
ExcludePattern *string
Extract *bool
ExtractDir *string
StripComponents *int
Upload *bool
UploadMethod *string
UploadFile *string
UploadFormData *string
UploadFileField *string
PGPDecrypt *bool
PGPVerify *bool
PGPSignature *string
PGPKey *string
PGPPassphrase *string
PGPPassphraseFile *string
OAuthClientID *string
OAuthClientSecret *string
OAuthTokenURL *string
OAuthAuthURL *string
OAuthRedirectURI *string
OAuthScopes *string
OAuthGrantType *string
OAuthAccessToken *string
OAuthRefreshToken *string
Metalink *bool
MetalinkFile *string
Queue *bool
QueueList *bool
QueueProcess *bool
QueueClear *bool
QueueFile *string
QueuePriority *int
BatchFile *string
InitConfig *bool
ConfigGet *string
ConfigSet *string
ConfigList *bool
ConfigUnset *string
Completion *string
Info *string
Benchmark *string
Schedule *string
BindInterface *string
KnownHosts *string
SSHInsecure *bool
DryRun *bool
OnComplete *string
GenManPage *bool
Help *bool
Version *bool
// curl/wget compatible flags
Headers headerFlags
Cookies headerFlags // --cookie, repeatable
Insecure *bool
CertFile *string
KeyFile *string
SSLKeyLogFile *string
Data *string
MaxTime *time.Duration
MaxFileSize *string
Accept *string
NoParent *bool
Spider *bool
WriteOut *string
ProgressStyle *string
WarcFile *string
TraceTime *bool
Form formFlags
PageRequisites *bool
SpanHosts *bool
AdjustExt *bool
NoPrivate *bool // deprecated, use AllowPrivate inversely
Wait *string
RandomWait *bool
ConvertLinks *bool
Fail *bool
Compressed *bool
Referer *string
RetryDelay *time.Duration
PinnedCert *string
AllowPrivate *bool
Range *string
ConnectTimeout *time.Duration
Domains *string
Reject *string
CutDirs *int
PostFile *string
CACertificate *string
NoClobber *bool
RetryHTTPError *string
RetryAllErrors *bool
Glob *bool
InputFile *string
Timestamping *bool
BackupConverted *bool
Continue *bool
ProtoDirs *bool
HSTSFile *string
CreateDirs *bool
}
// defineFlags registers all CLI flags on the given FlagSet and returns them.
func defineFlags(fs *flag.FlagSet, cfg *config.Config) *Flags {
f := &Flags{
URL: fs.String("url", "", "URL to download (can be specified multiple times)"),
Output: fs.String("output", "", "Output file path"),
Resume: fs.Bool("resume", cfg.AutoResume, "Resume interrupted download"),
Overwrite: fs.Bool("overwrite", false, "Overwrite existing file"),
Restart: fs.Bool("restart", false, "Delete existing file and restart download from scratch"),
Verbose: fs.Bool("verbose", cfg.Verbose, "Verbose output"),
Quiet: fs.Bool("quiet", false, "Suppress all output except errors"),
NoProgress: fs.Bool("no-progress", false, "Hide progress bar (keep other output)"),
JSON: fs.Bool("json", false, "Output machine-readable progress as JSON lines"),
Debug: fs.Bool("debug", cfg.Debug, "Debug mode"),
Timeout: fs.Duration("timeout", 0, "Timeout (0 = auto)"),
Proxy: fs.String("proxy", cfg.Proxy, "Proxy server URL (http://, https://, socks5://, socks5h://)"),
NoIPv4: fs.Bool("no-ipv4", !cfg.IPv4Fallback, "Disable IPv4 fallback"),
NoRedirect: fs.Bool("no-redirect", false, "Disable following HTTP redirects"),
MaxRetries: fs.Int("max-retries", 0, "Maximum number of retries on failure (0 = default)"),
DNSServers: fs.String("dns-servers", "", "Custom DNS servers (comma-separated, e.g. 1.1.1.1,8.8.8.8)"),
Checksum: fs.String("checksum", "", "Expected checksum value"),
ChecksumAlgo: fs.String("checksum-algo", cfg.ChecksumAlgo, "Checksum algorithm (sha256, sha512, blake2b, sha3-256, sha3-512, md5)"),
ChecksumFile: fs.String("checksum-file", "", "Read checksum from file (SHA256SUMS format)"),
NoDecompress: fs.Bool("no-decompress", !cfg.AutoDecompress, "Disable automatic decompression"),
Parallel: fs.Int("parallel", cfg.Parallel, "Number of parallel connections (0 = auto)"),
MaxSpeed: fs.String("max-speed", "", "Max speed (e.g., 10MB/s, 0 = unlimited)"),
Username: fs.String("username", cfg.Auth.Username, "Username for HTTP Basic/Digest Auth"),
Password: fs.String("password", "", "Password for HTTP Basic/Digest Auth"),
PasswordFile: fs.String("password-file", "", "Read password from file"),
AuthType: fs.String("auth-type", cfg.Auth.AuthType, "Auth type: basic, digest, auto"),
CookieJar: fs.String("cookie-jar", cfg.CookieJar, "File for loading/saving cookies"),
ContentDisp: fs.Bool("content-disposition", false, "Use server-provided filename from Content-Disposition header"),
ShowHeaders: fs.Bool("show-headers", false, "Print HTTP response headers during download"),
KeepTimestamps: fs.Bool("keep-timestamps", false, "Set file modification time from Last-Modified header"),
Recursive: fs.Bool("recursive", cfg.Recursive.Enabled, "Recursive downloading"),
RecursiveParallel: fs.Int("recursive-parallel", cfg.Recursive.Parallel, "Number of concurrent file downloads in recursive mode (0 = sequential)"),
MaxDepth: fs.Int("max-depth", cfg.Recursive.MaxDepth, "Maximum recursion depth"),
FollowExternal: fs.Bool("follow-external", cfg.Recursive.FollowExternal, "Follow external domains"),
Mirror: fs.Bool("mirror", false, "Mirror entire website (infinite depth, convert links)"),
NoConvertLinks: fs.Bool("no-convert-links", false, "Don't convert links for local viewing in mirror mode"),
NoMirrorAssets: fs.Bool("no-mirror-assets", false, "Don't download assets (CSS, JS, images) in mirror mode"),
NoRobots: fs.Bool("no-robots", false, "Don't respect robots.txt in mirror mode"),
RateLimit: fs.String("rate-limit", "", "Rate limit (e.g., 100KB/s, 1MB/s, 0 = unlimited)"),
ExcludePattern: fs.String("exclude-pattern", strings.Join(cfg.Recursive.ExcludePatterns, ","), "Exclude URL patterns (comma-separated)"),
Extract: fs.Bool("extract", cfg.Extract.Enabled, "Auto-extract archive after download"),
ExtractDir: fs.String("extract-dir", cfg.Extract.OutputDir, "Directory for extracted files"),
StripComponents: fs.Int("strip-components", cfg.Extract.StripComponents, "Strip N path components during extraction"),
Upload: fs.Bool("upload", false, "Upload file instead of downloading"),
UploadMethod: fs.String("upload-method", "PUT", "Upload method: PUT or POST"),
UploadFile: fs.String("upload-file", "", "File to upload"),
UploadFormData: fs.String("form-data", "", "Form data (key=value, comma-separated)"),
UploadFileField: fs.String("file-field", "file", "Form field name for file upload"),
PGPDecrypt: fs.Bool("pgp-decrypt", false, "Decrypt PGP encrypted file after download"),
PGPVerify: fs.Bool("pgp-verify", false, "Verify PGP signature after download"),
PGPSignature: fs.String("pgp-sig", "", "Path to PGP signature file (.asc, .sig)"),
PGPKey: fs.String("pgp-key", "", "Path to PGP key file (public or private)"),
PGPPassphrase: fs.String("pgp-passphrase", "", "Passphrase for PGP private key"),
PGPPassphraseFile: fs.String("pgp-passphrase-file", "", "Read PGP passphrase from file"),
OAuthClientID: fs.String("oauth-client-id", cfg.Auth.OAuth.ClientID, "OAuth 2.0 Client ID"),
OAuthClientSecret: fs.String("oauth-client-secret", cfg.Auth.OAuth.ClientSecret, "OAuth 2.0 Client Secret"),
OAuthTokenURL: fs.String("oauth-token-url", cfg.Auth.OAuth.TokenURL, "OAuth 2.0 Token URL"),
OAuthAuthURL: fs.String("oauth-auth-url", cfg.Auth.OAuth.AuthURL, "OAuth 2.0 Authorization URL"),
OAuthRedirectURI: fs.String("oauth-redirect-uri", cfg.Auth.OAuth.RedirectURI, "OAuth 2.0 Redirect URI"),
OAuthScopes: fs.String("oauth-scopes", strings.Join(cfg.Auth.OAuth.Scopes, ","), "OAuth 2.0 Scopes (comma-separated)"),
OAuthGrantType: fs.String("oauth-grant-type", cfg.Auth.OAuth.GrantType, "OAuth 2.0 Grant Type (client_credentials, authorization_code, password, refresh_token)"),
OAuthAccessToken: fs.String("oauth-access-token", cfg.Auth.OAuth.AccessToken, "OAuth 2.0 Access Token (direct)"),
OAuthRefreshToken: fs.String("oauth-refresh-token", cfg.Auth.OAuth.RefreshToken, "OAuth 2.0 Refresh Token"),
Metalink: fs.Bool("metalink", false, "Treat URL as Metalink (multi-source download)"),
MetalinkFile: fs.String("metalink-file", "", "Path to local Metalink file"),
Queue: fs.Bool("queue", false, "Add to download queue instead of downloading immediately"),
QueueList: fs.Bool("queue-list", false, "List items in download queue"),
QueueProcess: fs.Bool("queue-process", false, "Process download queue"),
QueueClear: fs.Bool("queue-clear", false, "Clear completed items from queue"),
QueueFile: fs.String("queue-file", "", "Custom queue file path"),
QueuePriority: fs.Int("queue-priority", 5, "Priority for queue item (1-10)"),
BatchFile: fs.String("batch-file", "", "Download multiple URLs from a file (one per line)"),
InitConfig: fs.Bool("init-config", false, "Generate default config file"),
ConfigGet: fs.String("config-get", "", "Get a config value (e.g. --config-get timeout)"),
ConfigSet: fs.String("config-set", "", "Set a config value (e.g. --config-set timeout 5m)"),
ConfigList: fs.Bool("config-list", false, "List all config values"),
ConfigUnset: fs.String("config-unset", "", "Unset a config value (e.g. --config-unset timeout)"),
Completion: fs.String("completion", "", "Generate shell completion script (bash, zsh, fish)"),
Info: fs.String("info", "", "Show file information without downloading"),
Benchmark: fs.String("benchmark", "", "Benchmark download speed from URL (downloads first 10MB)"),
Schedule: fs.String("schedule", "", "Schedule download at specified time (e.g. '2026-06-01 02:00' or cron '0 2 * * *')"),
BindInterface: fs.String("bind-interface", "", "Bind to specific network interface"),
KnownHosts: fs.String("known-hosts", "", "Path to SSH known_hosts file for SFTP (default: ~/.ssh/known_hosts)"),
SSHInsecure: fs.Bool("ssh-insecure", false, "Skip SSH host key verification for SFTP"),
DryRun: fs.Bool("dry-run", false, "List URLs without saving files in recursive/mirror mode"),
OnComplete: fs.String("on-complete", "", "Run command after successful download"),
GenManPage: fs.Bool("generate-man-page", false, "Generate man page and exit"),
Help: fs.Bool("help", false, "Show help"),
Version: fs.Bool("version", false, "Show version"),
// curl/wget compatible flags
Insecure: fs.Bool("insecure", false, "Skip TLS certificate verification"),
CertFile: fs.String("cert", "", "Client certificate file (PEM, for mTLS)"),
KeyFile: fs.String("key", "", "Client private key file (PEM)"),
SSLKeyLogFile: fs.String("ssl-key-log", "", "File to log TLS session keys to (SSLKEYLOGFILE for Wireshark)"),
Data: fs.String("data", "", "Send POST data (e.g., --data 'key=value')"),
MaxTime: fs.Duration("max-time", 0, "Maximum total transfer time (0 = unlimited)"),
MaxFileSize: fs.String("max-filesize", "", "Maximum file size to download (e.g., 100MB)"),
Accept: fs.String("accept", "", "Accept patterns for recursive download (e.g., '*.pdf,*.html')"),
NoParent: fs.Bool("no-parent", false, "Do not ascend to parent directory in recursive download"),
Spider: fs.Bool("spider", false, "Check URL existence only (HEAD request, no download)"),
WriteOut: fs.String("write-out", "", "Output metadata after download (curl format: %{http_code}, %{size_download}, %{time_total})"),
ProgressStyle: fs.String("progress", "", "Progress display style: bar (default) or dot"),
WarcFile: fs.String("warc-file", "", "Write WARC output file for web archiving"),
TraceTime: fs.Bool("trace-time", false, "Print HTTP timing breakdown after download"),
PageRequisites: fs.Bool("page-requisites", false, "Download all assets (CSS, JS, images) needed to display the page"),
SpanHosts: fs.Bool("span-hosts", false, "Follow links to external domains in recursive download"),
AdjustExt: fs.Bool("adjust-extension", false, "Append .html extension to downloaded HTML files"),
Wait: fs.String("wait", "", "Wait between requests in recursive/mirror mode (e.g., 1s, 500ms)"),
RandomWait: fs.Bool("random-wait", false, "Randomize wait time (0.5x to 1.5x) in recursive/mirror mode"),
ConvertLinks: fs.Bool("convert-links", false, "Convert links for local viewing in recursive mode"),
Fail: fs.Bool("fail", false, "Exit with error on HTTP 4xx/5xx status codes"),
Compressed: fs.Bool("compressed", false, "Send Accept-Encoding header for auto-decompression"),
Referer: fs.String("referer", "", "Send Referer header"),
RetryDelay: fs.Duration("retry-delay", 0, "Delay between retry attempts"),
PinnedCert: fs.String("pinned-cert", "", "SHA-256 hash of server certificate for pinning"),
AllowPrivate: fs.Bool("allow-private", false, "Allow connections to private/internal IPs (disables SSRF protection)"),
Range: fs.String("range", "", "Download only a range of bytes (e.g., 0-1000)"),
ConnectTimeout: fs.Duration("connect-timeout", 0, "Timeout for connection establishment"),
Domains: fs.String("domains", "", "Only follow these domains in recursive mode (comma-separated)"),
Reject: fs.String("reject", "", "Reject URL patterns in recursive mode (glob, comma-separated)"),
CutDirs: fs.Int("cut-dirs", 0, "Strip N directory levels when saving files"),
PostFile: fs.String("post-file", "", "Send file contents as POST body"),
CACertificate: fs.String("ca-certificate", "", "Path to custom CA certificate"),
NoClobber: fs.Bool("no-clobber", false, "Skip download if output file already exists"),
RetryHTTPError: fs.String("retry-on-http-error", "", "Retry on these HTTP status codes (comma-separated, e.g. 503,429)"),
RetryAllErrors: fs.Bool("retry-all-errors", false, "Retry on any HTTP error (4xx/5xx) instead of just selected codes"),
Glob: fs.Bool("glob", false, "Expand [1-3], {a,b} patterns in URL"),
Timestamping: fs.Bool("timestamping", false, "Download only if remote file is newer"),
BackupConverted: fs.Bool("backup-converted", false, "Backup original file before link conversion"),
Continue: fs.Bool("continue", false, "Auto-resume download if output file exists"),
ProtoDirs: fs.Bool("protocol-directories", false, "Create .http/, .ftp/ subdirectories in recursive mode"),
InputFile: fs.String("input-file", "", "Read URLs from file (use - for stdin)"),
HSTSFile: fs.String("hsts-file", "", "HSTS cache file (default: ~/.config/goget/hsts)"),
CreateDirs: fs.Bool("create-dirs", true, "Create missing parent directories of --output (curl --create-dirs)"),
}
fs.Var(&f.Headers, "header", "Custom HTTP header (repeatable, e.g. --header 'Key: Value')")
fs.Var(&f.Cookies, "cookie", "Set cookie (repeatable, e.g. --cookie 'name=value')")
fs.Var(&f.Form, "form", "Multipart form data (repeatable, e.g. --form 'field=value' or --form 'field=@file')")
return f
}