mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 07:23:06 +00:00
137 lines
3.9 KiB
Bash
Executable File
137 lines
3.9 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
set -u
|
|
|
|
say() {
|
|
printf '%s\n' "$*"
|
|
}
|
|
|
|
warn() {
|
|
printf '错误: %s\n' "$*" >&2
|
|
}
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
用法:
|
|
./search_config.sh
|
|
./search_config.sh --tavily KEY --exa KEY --keenable KEY
|
|
|
|
选项:
|
|
--tavily KEY 配置 TAVILY_API_KEY
|
|
--exa KEY 配置 EXA_API_KEY
|
|
--keenable KEY 配置 KEENABLE_API_KEY
|
|
--config FILE 覆盖配置文件路径
|
|
-h, --help 显示帮助
|
|
|
|
不传 key 参数时进入隐藏输入的交互模式;传入任意 key 参数时不交互,
|
|
未指定的服务保留已有值。配置文件默认是 ~/.config/my-pi/search.env。
|
|
EOF
|
|
}
|
|
|
|
CONFIG_FILE=${MY_PI_SEARCH_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/my-pi/search.env}
|
|
mode=interactive
|
|
tavily_set=0
|
|
exa_set=0
|
|
keenable_set=0
|
|
tavily_value=
|
|
exa_value=
|
|
keenable_value=
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case $1 in
|
|
--tavily)
|
|
[ "$#" -ge 2 ] || { warn "--tavily 缺少 KEY"; exit 2; }
|
|
tavily_value=$2; tavily_set=1; mode=noninteractive; shift 2 ;;
|
|
--exa)
|
|
[ "$#" -ge 2 ] || { warn "--exa 缺少 KEY"; exit 2; }
|
|
exa_value=$2; exa_set=1; mode=noninteractive; shift 2 ;;
|
|
--keenable)
|
|
[ "$#" -ge 2 ] || { warn "--keenable 缺少 KEY"; exit 2; }
|
|
keenable_value=$2; keenable_set=1; mode=noninteractive; shift 2 ;;
|
|
--config)
|
|
[ "$#" -ge 2 ] || { warn "--config 缺少 FILE"; exit 2; }
|
|
CONFIG_FILE=$2; shift 2 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) warn "未知参数:$1"; usage >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
valid_key() {
|
|
case $1 in
|
|
''|*[!A-Za-z0-9._-]*) return 1 ;;
|
|
*) return 0 ;;
|
|
esac
|
|
}
|
|
|
|
read_existing() {
|
|
existing_name=$1
|
|
[ -f "$CONFIG_FILE" ] || return 0
|
|
awk -v name="$existing_name" '
|
|
$1 == "export" { sub(/^export[ \t]+/, "") }
|
|
index($0, name "=") == 1 { print substr($0, length(name) + 2); exit }
|
|
' "$CONFIG_FILE"
|
|
}
|
|
|
|
prompt_key() {
|
|
prompt_label=$1
|
|
prompt_current=$2
|
|
if [ ! -t 0 ]; then
|
|
warn "交互模式需要终端;请改用 --tavily/--exa/--keenable 参数。"
|
|
return 2
|
|
fi
|
|
if [ -n "$prompt_current" ]; then
|
|
printf '%s API key(回车保留现有值): ' "$prompt_label" >&2
|
|
else
|
|
printf '%s API key(回车跳过): ' "$prompt_label" >&2
|
|
fi
|
|
stty -echo
|
|
IFS= read -r prompt_value || prompt_status=$?
|
|
stty echo
|
|
printf '\n' >&2
|
|
[ "${prompt_status:-0}" -eq 0 ] || return "$prompt_status"
|
|
printf '%s\n' "$prompt_value"
|
|
}
|
|
|
|
current_tavily=$(read_existing TAVILY_API_KEY)
|
|
current_exa=$(read_existing EXA_API_KEY)
|
|
current_keenable=$(read_existing KEENABLE_API_KEY)
|
|
|
|
if [ "$mode" = interactive ]; then
|
|
tavily_value=$(prompt_key Tavily "$current_tavily") || exit $?
|
|
exa_value=$(prompt_key Exa "$current_exa") || exit $?
|
|
keenable_value=$(prompt_key Keenable "$current_keenable") || exit $?
|
|
[ -n "$tavily_value" ] && tavily_set=1
|
|
[ -n "$exa_value" ] && exa_set=1
|
|
[ -n "$keenable_value" ] && keenable_set=1
|
|
fi
|
|
|
|
[ "$tavily_set" -eq 1 ] || tavily_value=$current_tavily
|
|
[ "$exa_set" -eq 1 ] || exa_value=$current_exa
|
|
[ "$keenable_set" -eq 1 ] || keenable_value=$current_keenable
|
|
|
|
for key_value in "$tavily_value" "$exa_value" "$keenable_value"; do
|
|
[ -z "$key_value" ] || valid_key "$key_value" || {
|
|
warn "API key 只能包含字母、数字、点、下划线和连字符。"
|
|
exit 2
|
|
}
|
|
done
|
|
|
|
config_dir=${CONFIG_FILE%/*}
|
|
[ "$config_dir" = "$CONFIG_FILE" ] && config_dir=.
|
|
umask 077
|
|
mkdir -p "$config_dir" || exit 1
|
|
config_tmp=$(mktemp "$config_dir/.search.env.XXXXXX") || exit 1
|
|
trap 'rm -f "$config_tmp"' EXIT HUP INT TERM
|
|
{
|
|
printf '# Generated by my-pi/search_config.sh. Do not commit this file.\n'
|
|
[ -z "$tavily_value" ] || printf 'export TAVILY_API_KEY=%s\n' "$tavily_value"
|
|
[ -z "$exa_value" ] || printf 'export EXA_API_KEY=%s\n' "$exa_value"
|
|
[ -z "$keenable_value" ] || printf 'export KEENABLE_API_KEY=%s\n' "$keenable_value"
|
|
} > "$config_tmp" || exit 1
|
|
chmod 600 "$config_tmp" || exit 1
|
|
mv "$config_tmp" "$CONFIG_FILE" || exit 1
|
|
trap - EXIT HUP INT TERM
|
|
|
|
say "搜索 API key 已安全写入 ${CONFIG_FILE}(权限 600)。"
|
|
say "重启 Pi 后生效;显式环境变量仍优先于该文件。"
|