178 lines
6.9 KiB
Go
178 lines
6.9 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"io"
|
||
"strings"
|
||
)
|
||
|
||
const rootHelp = `ufile-cli — 面向自动化与 Agent 的 ufile 命令行客户端
|
||
|
||
用法:
|
||
ufile-cli [全局选项] <命令> [命令选项]
|
||
|
||
Agent 快速开始:
|
||
printf '%s\n' "$UFILE_PASSWORD" | ufile-cli -H https://ufile.example.com auth login -U agent --password-stdin
|
||
ufile-cli upload ./result.zip -R 1d -D 5
|
||
ufile-cli download Ab3dE8xP -C 123456 -O ./result.zip
|
||
|
||
命令:
|
||
auth login 登录并安全保存 30 天 Cookie 会话
|
||
auth whoami 输出当前登录用户和权限
|
||
auth logout 注销当前会话并清除本地凭据
|
||
upload 上传文件;默认自动生成 6 位取件码
|
||
download 下载文件;直接下载,不执行额外的取件校验
|
||
version 输出版本、提交和构建时间
|
||
help [命令] 显示根帮助或指定命令的详细帮助
|
||
|
||
全局选项(必须写在命令之前):
|
||
-H, --host URL ufile 服务地址;--server 是等价别名
|
||
--config PATH 配置文件路径
|
||
--timeout TIME 单次请求超时,默认 10m;0 表示不限制
|
||
--help 显示帮助
|
||
-V, --version 输出版本信息
|
||
|
||
环境变量:
|
||
UFILE_HOST 服务地址;UFILE_SERVER 是兼容别名
|
||
UFILE_SESSION 临时覆盖配置文件中的会话 Cookie
|
||
UFILE_USERNAME auth login 的默认用户名
|
||
UFILE_PASSWORD auth login 的非交互密码;优先使用密钥管理器注入
|
||
UFILE_CONFIG 默认配置文件路径
|
||
|
||
输出契约:
|
||
成功结果以单个 JSON 对象写入 stdout。
|
||
错误以单个 JSON 对象写入 stderr,并返回非零退出码。
|
||
download -O - 是唯一例外:stdout 只包含原始文件字节,不输出 JSON。
|
||
Agent 应以退出码判断成功,不要解析本地化的 message 文案。
|
||
|
||
错误 JSON:
|
||
{"error":{"code":"permission_denied","message":"没有上传权限","httpStatus":403}}
|
||
|
||
退出码:
|
||
0 成功
|
||
1 未分类错误
|
||
2 参数或用法错误
|
||
3 未登录、会话过期或认证失败
|
||
4 权限不足、缺少取件码或业务限制
|
||
5 文件不存在、已失效或取件码错误
|
||
6 服务端输入校验失败
|
||
7 网络错误或服务端内部错误
|
||
8 本地配置或文件读写错误
|
||
|
||
安全约定:
|
||
upload 默认生成取件码;只有显式传入 --no-pickup-code 才公开文件。
|
||
错误或缺失的取件码累计 5 次会使服务端删除整个文件。
|
||
download 不会预先调用校验接口,避免一次操作产生多次校验请求。
|
||
密码不能作为命令行参数传入,避免出现在进程列表和 Agent 日志中。
|
||
pickupCode 和 downloadUrl 可能包含访问凭据,不应写入公开日志。
|
||
|
||
详细帮助:
|
||
ufile-cli help auth
|
||
ufile-cli help upload
|
||
ufile-cli help download
|
||
`
|
||
|
||
const authHelp = `ufile-cli auth — 管理 Cookie 会话
|
||
|
||
用法:
|
||
ufile-cli [全局选项] auth <login|whoami|logout> [选项]
|
||
|
||
登录:
|
||
ufile-cli -H https://ufile.example.com auth login -U USER
|
||
printf '%s\n' "$UFILE_PASSWORD" | ufile-cli -H https://ufile.example.com auth login -U USER --password-stdin
|
||
|
||
login 选项:
|
||
-U, --username USER 用户名;也可使用 UFILE_USERNAME
|
||
--password-stdin 从标准输入读取一行密码,适合 Agent 和 CI
|
||
--help 显示本帮助
|
||
|
||
密码来源优先级:
|
||
1. --password-stdin
|
||
2. UFILE_PASSWORD
|
||
3. 交互式终端中的隐藏输入
|
||
|
||
说明:
|
||
会话 Cookie 有效期由服务端决定,目前为 30 天。
|
||
密码永远不会写入配置文件。
|
||
首次登录后必须改密的账号,需要先在 Web 界面完成密码修改。
|
||
`
|
||
|
||
const uploadHelp = `ufile-cli upload — 上传文件并输出分享信息
|
||
|
||
用法:
|
||
ufile-cli [全局选项] upload <文件路径> [选项]
|
||
command | ufile-cli [全局选项] upload - -N <文件名> [选项]
|
||
|
||
示例:
|
||
ufile-cli upload ./report.zip -R 1d -D 5
|
||
ufile-cli upload ./public.txt -R 1h -D 1 --no-pickup-code
|
||
ufile-cli upload ./secret.pdf -P 123456
|
||
command | ufile-cli upload - -N result.txt -R 8h
|
||
|
||
选项:
|
||
-R, --retention VALUE 保留时间:1h、8h、1d、3d、forever;默认 1d
|
||
-D, --downloads VALUE 下载次数:1-99 或 unlimited;默认 5
|
||
-P, --pickup-code CODE 使用指定的 6 位数字取件码
|
||
--no-pickup-code 明确创建无需取件码的公开分享
|
||
-N, --name NAME 从标准输入上传时必需的文件名
|
||
--content-type TYPE 覆盖根据扩展名推断的 MIME 类型
|
||
--help 显示本帮助
|
||
|
||
安全与权限:
|
||
未指定 -P 或 --no-pickup-code 时,会使用密码学安全随机数自动生成取件码。
|
||
-P 与 --no-pickup-code 不能同时使用。
|
||
普通上传单文件最大 10 MiB,且最多保留 10 个有效文件。
|
||
forever、unlimited 和超过 10 MiB 的文件需要高级上传权限。
|
||
|
||
成功 JSON 字段:
|
||
hash、name、size、expiresAt、maxDownloads、pickupCode、downloadUrl、previewUrl
|
||
|
||
示例输出:
|
||
{"hash":"Ab3dE8xP","name":"report.zip","size":1024,"expiresAt":"2026-09-21T12:00:00Z","maxDownloads":5,"pickupCode":"123456","downloadUrl":"https://ufile.example.com/uf/Ab3dE8xP?code=123456","previewUrl":"https://ufile.example.com/uf/Ab3dE8xP?code=123456&preview=true"}
|
||
`
|
||
|
||
const downloadHelp = `ufile-cli download — 下载一个公开分享文件
|
||
|
||
用法:
|
||
ufile-cli [全局选项] download <8位文件码> -O <输出路径> [选项]
|
||
|
||
示例:
|
||
ufile-cli download Ab3dE8xP -C 123456 -O ./report.zip
|
||
ufile-cli download Ab3dE8xP -O ./public.txt
|
||
ufile-cli download Ab3dE8xP -C 123456 -O - > report.zip
|
||
|
||
选项:
|
||
-C, --code CODE 6 位数字取件码
|
||
-O, --output PATH 输出路径;使用 - 将原始文件字节写入 stdout
|
||
--force 覆盖已存在的目标文件
|
||
--help 显示本帮助
|
||
|
||
重要副作用:
|
||
每次成功下载都会消耗一次访问次数;次数耗尽后服务端删除文件。
|
||
缺失或错误的取件码也会累计失败;达到 5 次时服务端删除文件。
|
||
为减少风险,本命令直接下载,不会先请求 /api/pickup 校验。
|
||
本地文件先写入同目录临时文件,成功后再重命名。
|
||
|
||
输出:
|
||
普通路径成功时,stdout 输出包含 path、name、size、contentType 的 JSON。
|
||
-O - 成功时,stdout 仅包含文件字节;错误 JSON 仍写入 stderr。
|
||
`
|
||
|
||
func printHelp(out, errOut io.Writer, topic string) int {
|
||
switch strings.TrimSpace(topic) {
|
||
case "", "root":
|
||
_, _ = io.WriteString(out, rootHelp)
|
||
case "auth", "auth login", "auth whoami", "auth logout":
|
||
_, _ = io.WriteString(out, authHelp)
|
||
case "upload":
|
||
_, _ = io.WriteString(out, uploadHelp)
|
||
case "download":
|
||
_, _ = io.WriteString(out, downloadHelp)
|
||
case "version":
|
||
fmt.Fprintln(out, "用法:ufile-cli version\n\n以 JSON 输出 version、commit 和 date。")
|
||
default:
|
||
return writeCommandError(errOut, usageError(fmt.Sprintf("未知帮助主题 %q", topic)))
|
||
}
|
||
return exitOK
|
||
}
|