mirror of
https://github.com/whyour/qinglong.git
synced 2026-06-18 19:25:10 +08:00
shell 增加国际化
This commit is contained in:
parent
0ee0b83207
commit
b5a5fb3be6
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -31,3 +31,4 @@ __pycache__
|
||||||
/shell/preload/lang_env.sh
|
/shell/preload/lang_env.sh
|
||||||
|
|
||||||
.deepseek/
|
.deepseek/
|
||||||
|
.claude/
|
||||||
43
AGENTS.md
Normal file
43
AGENTS.md
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!-- gitnexus:start -->
|
||||||
|
# GitNexus — Code Intelligence
|
||||||
|
|
||||||
|
This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||||
|
|
||||||
|
> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
|
||||||
|
|
||||||
|
## Always Do
|
||||||
|
|
||||||
|
- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
|
||||||
|
- **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`.
|
||||||
|
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
|
||||||
|
- When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
|
||||||
|
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`.
|
||||||
|
|
||||||
|
## Never Do
|
||||||
|
|
||||||
|
- NEVER edit a function, class, or method without first running `impact` on it.
|
||||||
|
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
|
||||||
|
- NEVER rename symbols with find-and-replace — use `rename` which understands the call graph.
|
||||||
|
- NEVER commit changes without running `detect_changes()` to check affected scope.
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
| Resource | Use for |
|
||||||
|
|----------|---------|
|
||||||
|
| `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness |
|
||||||
|
| `gitnexus://repo/qinglong/clusters` | All functional areas |
|
||||||
|
| `gitnexus://repo/qinglong/processes` | All execution flows |
|
||||||
|
| `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace |
|
||||||
|
|
||||||
|
## CLI
|
||||||
|
|
||||||
|
| Task | Read this skill file |
|
||||||
|
|------|---------------------|
|
||||||
|
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
|
||||||
|
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
|
||||||
|
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
|
||||||
|
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
|
||||||
|
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
|
||||||
|
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
|
||||||
|
|
||||||
|
<!-- gitnexus:end -->
|
||||||
43
CLAUDE.md
Normal file
43
CLAUDE.md
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!-- gitnexus:start -->
|
||||||
|
# GitNexus — Code Intelligence
|
||||||
|
|
||||||
|
This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
|
||||||
|
|
||||||
|
> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
|
||||||
|
|
||||||
|
## Always Do
|
||||||
|
|
||||||
|
- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
|
||||||
|
- **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`.
|
||||||
|
- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
|
||||||
|
- When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
|
||||||
|
- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`.
|
||||||
|
|
||||||
|
## Never Do
|
||||||
|
|
||||||
|
- NEVER edit a function, class, or method without first running `impact` on it.
|
||||||
|
- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
|
||||||
|
- NEVER rename symbols with find-and-replace — use `rename` which understands the call graph.
|
||||||
|
- NEVER commit changes without running `detect_changes()` to check affected scope.
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
| Resource | Use for |
|
||||||
|
|----------|---------|
|
||||||
|
| `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness |
|
||||||
|
| `gitnexus://repo/qinglong/clusters` | All functional areas |
|
||||||
|
| `gitnexus://repo/qinglong/processes` | All execution flows |
|
||||||
|
| `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace |
|
||||||
|
|
||||||
|
## CLI
|
||||||
|
|
||||||
|
| Task | Read this skill file |
|
||||||
|
|------|---------------------|
|
||||||
|
| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
|
||||||
|
| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
|
||||||
|
| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
|
||||||
|
| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
|
||||||
|
| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
|
||||||
|
| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
|
||||||
|
|
||||||
|
<!-- gitnexus:end -->
|
||||||
24
shell/api.sh
24
shell/api.sh
|
|
@ -50,9 +50,9 @@ add_cron_api() {
|
||||||
code=$(echo "$api" | jq -r .code)
|
code=$(echo "$api" | jq -r .code)
|
||||||
message=$(echo "$api" | jq -r .message)
|
message=$(echo "$api" | jq -r .message)
|
||||||
if [[ $code == 200 ]]; then
|
if [[ $code == 200 ]]; then
|
||||||
echo -e "$name -> 添加成功"
|
t '%s -> 添加成功' "$name"
|
||||||
else
|
else
|
||||||
echo -e "$name -> 添加失败(${message})"
|
t '%s -> 添加失败(%s)' "$name" "$message"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,9 +81,9 @@ update_cron_api() {
|
||||||
code=$(echo "$api" | jq -r .code)
|
code=$(echo "$api" | jq -r .code)
|
||||||
message=$(echo "$api" | jq -r .message)
|
message=$(echo "$api" | jq -r .message)
|
||||||
if [[ $code == 200 ]]; then
|
if [[ $code == 200 ]]; then
|
||||||
echo -e "$name -> 更新成功"
|
t '%s -> 更新成功' "$name"
|
||||||
else
|
else
|
||||||
echo -e "$name -> 更新失败(${message})"
|
t '%s -> 更新失败(%s)' "$name" "$message"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,9 +108,9 @@ update_cron_command_api() {
|
||||||
code=$(echo "$api" | jq -r .code)
|
code=$(echo "$api" | jq -r .code)
|
||||||
message=$(echo "$api" | jq -r .message)
|
message=$(echo "$api" | jq -r .message)
|
||||||
if [[ $code == 200 ]]; then
|
if [[ $code == 200 ]]; then
|
||||||
echo -e "$command -> 更新成功"
|
t '%s -> 更新成功' "$command"
|
||||||
else
|
else
|
||||||
echo -e "$command -> 更新失败(${message})"
|
t '%s -> 更新失败(%s)' "$command" "$message"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,9 +128,9 @@ del_cron_api() {
|
||||||
code=$(echo "$api" | jq -r .code)
|
code=$(echo "$api" | jq -r .code)
|
||||||
message=$(echo "$api" | jq -r .message)
|
message=$(echo "$api" | jq -r .message)
|
||||||
if [[ $code == 200 ]]; then
|
if [[ $code == 200 ]]; then
|
||||||
echo -e "成功"
|
t '成功'
|
||||||
else
|
else
|
||||||
echo -e "失败(${message})"
|
t '失败(%s)' "$message"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,9 +175,9 @@ notify_api() {
|
||||||
code=$(echo "$api" | jq -r .code)
|
code=$(echo "$api" | jq -r .code)
|
||||||
message=$(echo "$api" | jq -r .message)
|
message=$(echo "$api" | jq -r .message)
|
||||||
if [[ $code == 200 ]]; then
|
if [[ $code == 200 ]]; then
|
||||||
echo -e "通知发送成功🎉"
|
t '通知发送成功🎉'
|
||||||
else
|
else
|
||||||
echo -e "通知失败(${message})"
|
t '通知失败(%s)' "$message"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,9 +214,9 @@ update_auth_config() {
|
||||||
code=$(echo "$api" | jq -r .code)
|
code=$(echo "$api" | jq -r .code)
|
||||||
message=$(echo "$api" | jq -r .message)
|
message=$(echo "$api" | jq -r .message)
|
||||||
if [[ $code == 200 ]]; then
|
if [[ $code == 200 ]]; then
|
||||||
echo -e "${tip}成功🎉"
|
t '%s成功🎉' "$tip"
|
||||||
else
|
else
|
||||||
echo -e "${tip}失败(${message})"
|
t '%s失败(%s)' "$tip" "$message"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
18
shell/bot.sh
18
shell/bot.sh
|
|
@ -8,7 +8,7 @@ else
|
||||||
repo_path="${dir_repo}/diybot"
|
repo_path="${dir_repo}/diybot"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\n1、安装bot依赖...\n"
|
t '\n1、安装bot依赖...\n'
|
||||||
os_name="${QL_OS_TYPE:-}"
|
os_name="${QL_OS_TYPE:-}"
|
||||||
if [ -z "$os_name" ]; then
|
if [ -z "$os_name" ]; then
|
||||||
os_name=$(source /etc/os-release && echo "$ID")
|
os_name=$(source /etc/os-release && echo "$ID")
|
||||||
|
|
@ -28,13 +28,13 @@ case "$os_name" in
|
||||||
$SUDO apt-get install -y gcc python3-dev musl-dev zlib1g-dev libjpeg-dev libfreetype-dev
|
$SUDO apt-get install -y gcc python3-dev musl-dev zlib1g-dev libjpeg-dev libfreetype-dev
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo -e "暂不支持此系统 $os_name"
|
t '暂不支持此系统 %s' "$os_name"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo -e "\nbot依赖安装成功...\n"
|
t '\nbot依赖安装成功...\n'
|
||||||
|
|
||||||
echo -e "2、下载bot所需文件...\n"
|
t '2、下载bot所需文件...\n'
|
||||||
if [[ ! -d ${repo_path}/.git ]]; then
|
if [[ ! -d ${repo_path}/.git ]]; then
|
||||||
rm -rf ${repo_path}
|
rm -rf ${repo_path}
|
||||||
git_clone_scripts ${url} ${repo_path} "main"
|
git_clone_scripts ${url} ${repo_path} "main"
|
||||||
|
|
@ -44,9 +44,9 @@ cp -rf "$repo_path/jbot" $dir_data
|
||||||
if [[ ! -f "$dir_config/bot.json" ]]; then
|
if [[ ! -f "$dir_config/bot.json" ]]; then
|
||||||
cp -f "$repo_path/config/bot.json" "$dir_config"
|
cp -f "$repo_path/config/bot.json" "$dir_config"
|
||||||
fi
|
fi
|
||||||
echo -e "\nbot文件下载成功...\n"
|
t '\nbot文件下载成功...\n'
|
||||||
|
|
||||||
echo -e "3、安装python3依赖...\n"
|
t '3、安装python3依赖...\n'
|
||||||
cp -f "$repo_path/jbot/requirements.txt" "$dir_data"
|
cp -f "$repo_path/jbot/requirements.txt" "$dir_data"
|
||||||
|
|
||||||
cd $dir_data
|
cd $dir_data
|
||||||
|
|
@ -56,11 +56,11 @@ cat requirements.txt | while read LREAD; do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
echo -e "\npython3依赖安装成功...\n"
|
t '\npython3依赖安装成功...\n'
|
||||||
|
|
||||||
echo -e "4、启动bot程序...\n"
|
t '4、启动bot程序...\n'
|
||||||
make_dir $dir_log/bot
|
make_dir $dir_log/bot
|
||||||
cd $dir_data
|
cd $dir_data
|
||||||
ps -eo pid,command | grep "python3 -m jbot" | grep -v grep | awk '{print $1}' | xargs kill -9 2>/dev/null
|
ps -eo pid,command | grep "python3 -m jbot" | grep -v grep | awk '{print $1}' | xargs kill -9 2>/dev/null
|
||||||
nohup python3 -m jbot >$dir_log/bot/nohup.log 2>&1 &
|
nohup python3 -m jbot >$dir_log/bot/nohup.log 2>&1 &
|
||||||
echo -e "bot启动成功...\n"
|
t 'bot启动成功...\n'
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,29 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
reset_env() {
|
reset_env() {
|
||||||
echo -e "---> 1. 开始检测配置文件\n"
|
t '---> 1. 开始检测配置文件\n'
|
||||||
fix_config
|
fix_config
|
||||||
echo -e "---> 配置文件检测完成\n"
|
t '---> 配置文件检测完成\n'
|
||||||
|
|
||||||
echo -e "---> 2. 开始安装青龙依赖\n"
|
t '---> 2. 开始安装青龙依赖\n'
|
||||||
npm_install_2 $dir_root
|
npm_install_2 $dir_root
|
||||||
echo -e "---> 青龙依赖安装完成\n"
|
t '---> 青龙依赖安装完成\n'
|
||||||
|
|
||||||
echo -e "---> 脚本依赖安装完成\n"
|
t '---> 脚本依赖安装完成\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_dep() {
|
copy_dep() {
|
||||||
echo -e "---> 1. 复制通知文件\n"
|
t '---> 1. 复制通知文件\n'
|
||||||
echo -e "---> 复制一份 $file_notify_py_sample 为 $file_notify_py\n"
|
t '---> 复制一份 %s 为 %s\n' "$file_notify_py_sample" "$file_notify_py"
|
||||||
cp -fv $file_notify_py_sample $file_notify_py
|
cp -fv $file_notify_py_sample $file_notify_py
|
||||||
echo
|
echo
|
||||||
echo -e "---> 复制一份 $file_notify_js_sample 为 $file_notify_js\n"
|
t '---> 复制一份 %s 为 %s\n' "$file_notify_js_sample" "$file_notify_js"
|
||||||
cp -fv $file_notify_js_sample $file_notify_js
|
cp -fv $file_notify_js_sample $file_notify_js
|
||||||
echo -e "---> 通知文件复制完成\n"
|
t '---> 通知文件复制完成\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
pm2_log() {
|
pm2_log() {
|
||||||
echo -e "---> pm2日志"
|
t '---> pm2日志'
|
||||||
local panelOut="/root/.pm2/logs/qinglong-out.log"
|
local panelOut="/root/.pm2/logs/qinglong-out.log"
|
||||||
local panelError="/root/.pm2/logs/qinglong-error.log"
|
local panelError="/root/.pm2/logs/qinglong-error.log"
|
||||||
tail -n 300 "$panelOut"
|
tail -n 300 "$panelOut"
|
||||||
|
|
@ -32,9 +32,10 @@ pm2_log() {
|
||||||
|
|
||||||
check_ql() {
|
check_ql() {
|
||||||
local api=$(curl -s --noproxy "*" "http://localhost:${ql_port}")
|
local api=$(curl -s --noproxy "*" "http://localhost:${ql_port}")
|
||||||
echo -e "\n=====> 检测面板\n\n$api\n"
|
t '\n=====> 检测面板'
|
||||||
|
echo -e "\n\n$api\n"
|
||||||
if [[ $api =~ "<div id=\"root\"></div>" ]]; then
|
if [[ $api =~ "<div id=\"root\"></div>" ]]; then
|
||||||
echo -e "=====> 面板服务启动正常\n"
|
t '=====> 面板服务启动正常\n'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,14 +50,15 @@ check_pm2() {
|
||||||
-H 'Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7' \
|
-H 'Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7' \
|
||||||
--compressed
|
--compressed
|
||||||
)
|
)
|
||||||
echo -e "\n=====> 检测后台\n\n$api\n"
|
t '\n=====> 检测后台'
|
||||||
|
echo -e "\n\n$api\n"
|
||||||
if [[ $api =~ "{\"code\"" ]]; then
|
if [[ $api =~ "{\"code\"" ]]; then
|
||||||
echo -e "=====> 后台服务启动正常\n"
|
t '=====> 后台服务启动正常\n'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
echo -e "=====> 开始检测"
|
t '=====> 开始检测'
|
||||||
npm i -g pnpm@8.3.1 pm2 ts-node
|
npm i -g pnpm@8.3.1 pm2 ts-node
|
||||||
|
|
||||||
reset_env
|
reset_env
|
||||||
|
|
@ -64,7 +66,7 @@ main() {
|
||||||
check_ql
|
check_ql
|
||||||
check_pm2
|
check_pm2
|
||||||
reload_pm2
|
reload_pm2
|
||||||
echo -e "\n=====> 检测结束\n"
|
t '\n=====> 检测结束\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|
|
||||||
105
shell/lang/en.sh
Normal file
105
shell/lang/en.sh
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# English language pack
|
||||||
|
declare -gA LANG_MESSAGES=(
|
||||||
|
['任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n']='Task delayed %s seconds, will start at %s. Set RandomDelay to empty to cancel delay\n'
|
||||||
|
['开始执行...\n']='Starting execution...\n'
|
||||||
|
['已停止']='Stopped'
|
||||||
|
['完成']='Completed'
|
||||||
|
['失败(退出码 %s)']='Failed (exit code %s)'
|
||||||
|
['安装 %s 依赖包...\n']='Installing %s dependencies...\n'
|
||||||
|
['开始拉取仓库 %s 到 %s\n']='Cloning repository %s to %s\n'
|
||||||
|
['添加成功']='Added successfully'
|
||||||
|
['添加失败(%s)']='Add failed (%s)'
|
||||||
|
['更新成功']='Updated successfully'
|
||||||
|
['更新失败(%s)']='Update failed (%s)'
|
||||||
|
['成功']='Success'
|
||||||
|
['失败(%s)']='Failed (%s)'
|
||||||
|
['通知发送成功🎉']='Notification sent successfully 🎉'
|
||||||
|
['通知失败(%s)']='Notification failed (%s)'
|
||||||
|
['当前有以下脚本可以运行:']='Available scripts:'
|
||||||
|
['暂无脚本可以执行']='No scripts available'
|
||||||
|
['警告:工作目录不存在 %s']='Warning: working directory does not exist: %s'
|
||||||
|
['\n缺少并发运行的环境变量参数']='\nMissing concurrency environment variable'
|
||||||
|
['\n缺少单独运行的参数 task xxx.js desi Test']='\nMissing parameter: task xxx.js desi Test'
|
||||||
|
['暂不支持此系统 %s']='Unsupported system: %s'
|
||||||
|
['检测到 pm2 服务正在运行']='pm2 service is running'
|
||||||
|
['npm 模块位置: %s']='npm module location: %s'
|
||||||
|
['导入数据成功 %s']='Data imported successfully: %s'
|
||||||
|
['导出数据成功 %s']='Data exported successfully: %s'
|
||||||
|
['当前版本: %s / 最新版本: %s']='Current: %s / Latest: %s'
|
||||||
|
['已是最新版本']='Already up to date'
|
||||||
|
['%s 个定时任务正在运行']='%s scheduled tasks running'
|
||||||
|
['执行前置命令\n']='Running pre-command\n'
|
||||||
|
['\n执行前置命令结束\n']='\nPre-command finished\n'
|
||||||
|
['\n执行后置命令\n']='\nRunning post-command\n'
|
||||||
|
['\n执行后置命令结束']='\nPost-command finished'
|
||||||
|
['警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容']='Warning: PM2 start failed (exit code: %s), possibly due to hardware incompatibility'
|
||||||
|
['正在尝试直接使用 Node.js 启动服务...']='Attempting to start service with Node.js directly...'
|
||||||
|
['已使用 Node.js 直接启动服务 (PID: %s)']='Service started with Node.js directly (PID: %s)'
|
||||||
|
['注意: 使用此模式时,部分 PM2 管理功能将不可用']='Note: some PM2 management features are unavailable in this mode'
|
||||||
|
['## 开始执行... %s\n']='## Starting... %s\n'
|
||||||
|
['\n## 已停止 🛑... %s 耗时 %s 秒%s']='\n## Stopped 🛑... %s took %s seconds%s'
|
||||||
|
['\n## 完成 ✅... %s 耗时 %s 秒%s']='\n## Completed ✅... %s took %s seconds%s'
|
||||||
|
['\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s']='\n## Failed ❌(exit code %s)... %s took %s seconds%s'
|
||||||
|
['%s -> 添加成功']='%s -> Added successfully'
|
||||||
|
['%s -> 添加失败(%s)']='%s -> Add failed (%s)'
|
||||||
|
['%s -> 更新成功']='%s -> Updated successfully'
|
||||||
|
['%s -> 更新失败(%s)']='%s -> Update failed (%s)'
|
||||||
|
['%s成功🎉']='%s succeeded 🎉'
|
||||||
|
['%s失败(%s)']='%s failed (%s)'
|
||||||
|
['检测到有%s的定时任务:']='Found %s scheduled tasks:'
|
||||||
|
['\n开始尝试自动删除失效的定时任务...']='\nAttempting to remove invalid scheduled tasks...'
|
||||||
|
['\n开始尝试自动添加定时任务...']='\nAttempting to add scheduled tasks...'
|
||||||
|
['拉取 %s 成功...\n']='Pull %s succeeded...\n'
|
||||||
|
['拉取 %s 失败,请检查日志...\n']='Pull %s failed, check logs...\n'
|
||||||
|
['开始下载:%s 保存路径:%s\n']='Downloading: %s to: %s\n'
|
||||||
|
['下载 %s 成功...\n']='Download %s succeeded...\n'
|
||||||
|
['下载 %s 失败,保留之前正常下载的版本...\n']='Download %s failed, keeping previous version...\n'
|
||||||
|
['%s文件不存在,跳过执行...\n']='%s does not exist, skipping...\n'
|
||||||
|
['使用 %s 源更新...\n']='Updating using %s mirror...\n'
|
||||||
|
['更新青龙源文件成功...\n']='Qinglong source updated successfully\n'
|
||||||
|
['更新青龙源文件失败,请检查网络...\n']='Qinglong source update failed, check network\n'
|
||||||
|
['更新青龙静态资源成功...\n']='Static assets updated successfully\n'
|
||||||
|
['更新青龙静态资源失败,请检查网络...\n']='Static assets update failed, check network\n'
|
||||||
|
['\n开始检测依赖...\n']='\nChecking dependencies...\n'
|
||||||
|
['\n依赖检测安装成功...\n']='\nDependencies installed successfully\n'
|
||||||
|
['更新包下载成功...\n']='Package download succeeded\n'
|
||||||
|
['\n依赖检测安装失败,请检查网络...\n']='\nDependency installation failed, check network\n'
|
||||||
|
['\n1、安装bot依赖...\n']='\n1. Installing bot dependencies...\n'
|
||||||
|
['\nbot依赖安装成功...\n']='\nBot dependencies installed\n'
|
||||||
|
['2、下载bot所需文件...\n']='2. Downloading bot files...\n'
|
||||||
|
['\nbot文件下载成功...\n']='\nBot files downloaded\n'
|
||||||
|
['3、安装python3依赖...\n']='3. Installing python3 dependencies...\n'
|
||||||
|
['\npython3依赖安装成功...\n']='\nPython3 dependencies installed\n'
|
||||||
|
['4、启动bot程序...\n']='4. Starting bot...\n'
|
||||||
|
['bot启动成功...\n']='Bot started successfully\n'
|
||||||
|
# check.sh
|
||||||
|
['---> 1. 开始检测配置文件\n']='---> 1. Checking config...\n'
|
||||||
|
['---> 配置文件检测完成\n']='---> Config check complete\n'
|
||||||
|
['---> 2. 开始安装青龙依赖\n']='---> 2. Installing qinglong dependencies...\n'
|
||||||
|
['---> 青龙依赖安装完成\n']='---> Dependencies installed\n'
|
||||||
|
['---> 脚本依赖安装完成\n']='---> Script dependencies installed\n'
|
||||||
|
['---> 1. 复制通知文件\n']='---> 1. Copying notification files...\n'
|
||||||
|
['---> 复制一份 %s 为 %s\n']='---> Copying %s to %s\n'
|
||||||
|
['---> 通知文件复制完成\n']='---> Notification files copied\n'
|
||||||
|
['---> pm2日志']='---> pm2 log'
|
||||||
|
['\n=====> 检测面板']='\n=====> Checking panel'
|
||||||
|
['=====> 面板服务启动正常\n']='=====> Panel service running normally\n'
|
||||||
|
['\n=====> 检测后台']='\n=====> Checking backend'
|
||||||
|
['=====> 后台服务启动正常\n']='=====> Backend service running normally\n'
|
||||||
|
['=====> 开始检测']='=====> Starting check'
|
||||||
|
['\n=====> 检测结束\n']='\n=====> Check complete\n'
|
||||||
|
# rmlog.sh
|
||||||
|
['查询文件 %s']='Checking file: %s'
|
||||||
|
['删除中~']='Deleting...'
|
||||||
|
['正在被 %s 使用,跳过~']='In use by %s, skipping...'
|
||||||
|
['查找旧日志文件中...\n']='Looking for old log files...\n'
|
||||||
|
['删除旧日志执行完毕\n']='Old log cleanup complete\n'
|
||||||
|
# start.sh
|
||||||
|
['未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装']='Module not found. Run: npm i -g @whyour/qinglong'
|
||||||
|
['请先手动设置 export QL_DIR=%s,环境变量,并手动添加到系统环境变量,然后再次执行命令 qinglong 启动服务']='Set env: export QL_DIR=%s, then run qinglong to start'
|
||||||
|
['请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量']='Set QL_DATA_DIR (absolute path ending with /data, e.g. /ql/data)'
|
||||||
|
['QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data,如果有历史数据,请新建 data 目录,把历史数据放到 data 目录中']='QL_DATA_DIR must end with /data, e.g. /ql/data'
|
||||||
|
['暂不支持此系统部署 %s']='Unsupported system for deployment: %s'
|
||||||
|
# update.sh
|
||||||
|
['命令输入错误...\n']='Invalid command...\n'
|
||||||
|
)
|
||||||
105
shell/lang/zh.sh
Normal file
105
shell/lang/zh.sh
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# 中文语言包(zh key → zh value 恒等,en 包做实际翻译)
|
||||||
|
declare -gA LANG_MESSAGES=(
|
||||||
|
['任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n']='任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n'
|
||||||
|
['开始执行...\n']='开始执行...\n'
|
||||||
|
['已停止']='已停止'
|
||||||
|
['完成']='完成'
|
||||||
|
['失败(退出码 %s)']='失败(退出码 %s)'
|
||||||
|
['安装 %s 依赖包...\n']='安装 %s 依赖包...\n'
|
||||||
|
['开始拉取仓库 %s 到 %s\n']='开始拉取仓库 %s 到 %s\n'
|
||||||
|
['添加成功']='添加成功'
|
||||||
|
['添加失败(%s)']='添加失败(%s)'
|
||||||
|
['更新成功']='更新成功'
|
||||||
|
['更新失败(%s)']='更新失败(%s)'
|
||||||
|
['成功']='成功'
|
||||||
|
['失败(%s)']='失败(%s)'
|
||||||
|
['通知发送成功🎉']='通知发送成功🎉'
|
||||||
|
['通知失败(%s)']='通知失败(%s)'
|
||||||
|
['当前有以下脚本可以运行:']='当前有以下脚本可以运行:'
|
||||||
|
['暂无脚本可以执行']='暂无脚本可以执行'
|
||||||
|
['警告:工作目录不存在 %s']='警告:工作目录不存在 %s'
|
||||||
|
['\n缺少并发运行的环境变量参数']='\n缺少并发运行的环境变量参数'
|
||||||
|
['\n缺少单独运行的参数 task xxx.js desi Test']='\n缺少单独运行的参数 task xxx.js desi Test'
|
||||||
|
['暂不支持此系统 %s']='暂不支持此系统 %s'
|
||||||
|
['检测到 pm2 服务正在运行']='检测到 pm2 服务正在运行'
|
||||||
|
['npm 模块位置: %s']='npm 模块位置: %s'
|
||||||
|
['导入数据成功 %s']='导入数据成功 %s'
|
||||||
|
['导出数据成功 %s']='导出数据成功 %s'
|
||||||
|
['当前版本: %s / 最新版本: %s']='当前版本: %s / 最新版本: %s'
|
||||||
|
['已是最新版本']='已是最新版本'
|
||||||
|
['%s 个定时任务正在运行']='%s 个定时任务正在运行'
|
||||||
|
['执行前置命令\n']='执行前置命令\n'
|
||||||
|
['\n执行前置命令结束\n']='\n执行前置命令结束\n'
|
||||||
|
['\n执行后置命令\n']='\n执行后置命令\n'
|
||||||
|
['\n执行后置命令结束']='\n执行后置命令结束'
|
||||||
|
['警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容']='警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容'
|
||||||
|
['正在尝试直接使用 Node.js 启动服务...']='正在尝试直接使用 Node.js 启动服务...'
|
||||||
|
['已使用 Node.js 直接启动服务 (PID: %s)']='已使用 Node.js 直接启动服务 (PID: %s)'
|
||||||
|
['注意: 使用此模式时,部分 PM2 管理功能将不可用']='注意: 使用此模式时,部分 PM2 管理功能将不可用'
|
||||||
|
['## 开始执行... %s\n']='## 开始执行... %s\n'
|
||||||
|
['\n## 已停止 🛑... %s 耗时 %s 秒%s']='\n## 已停止 🛑... %s 耗时 %s 秒%s'
|
||||||
|
['\n## 完成 ✅... %s 耗时 %s 秒%s']='\n## 完成 ✅... %s 耗时 %s 秒%s'
|
||||||
|
['\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s']='\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s'
|
||||||
|
['%s -> 添加成功']='%s -> 添加成功'
|
||||||
|
['%s -> 添加失败(%s)']='%s -> 添加失败(%s)'
|
||||||
|
['%s -> 更新成功']='%s -> 更新成功'
|
||||||
|
['%s -> 更新失败(%s)']='%s -> 更新失败(%s)'
|
||||||
|
['%s成功🎉']='%s成功🎉'
|
||||||
|
['%s失败(%s)']='%s失败(%s)'
|
||||||
|
['检测到有%s的定时任务:']='检测到有%s的定时任务:'
|
||||||
|
['\n开始尝试自动删除失效的定时任务...']='\n开始尝试自动删除失效的定时任务...'
|
||||||
|
['\n开始尝试自动添加定时任务...']='\n开始尝试自动添加定时任务...'
|
||||||
|
['拉取 %s 成功...\n']='拉取 %s 成功...\n'
|
||||||
|
['拉取 %s 失败,请检查日志...\n']='拉取 %s 失败,请检查日志...\n'
|
||||||
|
['开始下载:%s 保存路径:%s\n']='开始下载:%s 保存路径:%s\n'
|
||||||
|
['下载 %s 成功...\n']='下载 %s 成功...\n'
|
||||||
|
['下载 %s 失败,保留之前正常下载的版本...\n']='下载 %s 失败,保留之前正常下载的版本...\n'
|
||||||
|
['%s文件不存在,跳过执行...\n']='%s文件不存在,跳过执行...\n'
|
||||||
|
['使用 %s 源更新...\n']='使用 %s 源更新...\n'
|
||||||
|
['更新青龙源文件成功...\n']='更新青龙源文件成功...\n'
|
||||||
|
['更新青龙源文件失败,请检查网络...\n']='更新青龙源文件失败,请检查网络...\n'
|
||||||
|
['更新青龙静态资源成功...\n']='更新青龙静态资源成功...\n'
|
||||||
|
['更新青龙静态资源失败,请检查网络...\n']='更新青龙静态资源失败,请检查网络...\n'
|
||||||
|
['\n开始检测依赖...\n']='\n开始检测依赖...\n'
|
||||||
|
['\n依赖检测安装成功...\n']='\n依赖检测安装成功...\n'
|
||||||
|
['更新包下载成功...\n']='更新包下载成功...\n'
|
||||||
|
['\n依赖检测安装失败,请检查网络...\n']='\n依赖检测安装失败,请检查网络...\n'
|
||||||
|
['\n1、安装bot依赖...\n']='\n1、安装bot依赖...\n'
|
||||||
|
['\nbot依赖安装成功...\n']='\nbot依赖安装成功...\n'
|
||||||
|
['2、下载bot所需文件...\n']='2、下载bot所需文件...\n'
|
||||||
|
['\nbot文件下载成功...\n']='\nbot文件下载成功...\n'
|
||||||
|
['3、安装python3依赖...\n']='3、安装python3依赖...\n'
|
||||||
|
['\npython3依赖安装成功...\n']='\npython3依赖安装成功...\n'
|
||||||
|
['4、启动bot程序...\n']='4、启动bot程序...\n'
|
||||||
|
['bot启动成功...\n']='bot启动成功...\n'
|
||||||
|
# check.sh
|
||||||
|
['---> 1. 开始检测配置文件\n']='---> 1. 开始检测配置文件\n'
|
||||||
|
['---> 配置文件检测完成\n']='---> 配置文件检测完成\n'
|
||||||
|
['---> 2. 开始安装青龙依赖\n']='---> 2. 开始安装青龙依赖\n'
|
||||||
|
['---> 青龙依赖安装完成\n']='---> 青龙依赖安装完成\n'
|
||||||
|
['---> 脚本依赖安装完成\n']='---> 脚本依赖安装完成\n'
|
||||||
|
['---> 1. 复制通知文件\n']='---> 1. 复制通知文件\n'
|
||||||
|
['---> 复制一份 %s 为 %s\n']='---> 复制一份 %s 为 %s\n'
|
||||||
|
['---> 通知文件复制完成\n']='---> 通知文件复制完成\n'
|
||||||
|
['---> pm2日志']='---> pm2日志'
|
||||||
|
['\n=====> 检测面板']='\n=====> 检测面板'
|
||||||
|
['=====> 面板服务启动正常\n']='=====> 面板服务启动正常\n'
|
||||||
|
['\n=====> 检测后台']='\n=====> 检测后台'
|
||||||
|
['=====> 后台服务启动正常\n']='=====> 后台服务启动正常\n'
|
||||||
|
['=====> 开始检测']='=====> 开始检测'
|
||||||
|
['\n=====> 检测结束\n']='\n=====> 检测结束\n'
|
||||||
|
# rmlog.sh
|
||||||
|
['查询文件 %s']='查询文件 %s'
|
||||||
|
['删除中~']='删除中~'
|
||||||
|
['正在被 %s 使用,跳过~']='正在被 %s 使用,跳过~'
|
||||||
|
['查找旧日志文件中...\n']='查找旧日志文件中...\n'
|
||||||
|
['删除旧日志执行完毕\n']='删除旧日志执行完毕\n'
|
||||||
|
# start.sh
|
||||||
|
['未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装']='未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装'
|
||||||
|
['请先手动设置 export QL_DIR=%s,环境变量,并手动添加到系统环境变量,然后再次执行命令 qinglong 启动服务']='请先手动设置 export QL_DIR=%s,环境变量,并手动添加到系统环境变量,然后再次执行命令 qinglong 启动服务'
|
||||||
|
['请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量']='请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量'
|
||||||
|
['QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data,如果有历史数据,请新建 data 目录,把历史数据放到 data 目录中']='QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data,如果有历史数据,请新建 data 目录,把历史数据放到 data 目录中'
|
||||||
|
['暂不支持此系统部署 %s']='暂不支持此系统部署 %s'
|
||||||
|
# update.sh
|
||||||
|
['命令输入错误...\n']='命令输入错误...\n'
|
||||||
|
)
|
||||||
|
|
@ -30,7 +30,7 @@ random_delay() {
|
||||||
else
|
else
|
||||||
start_time=$(date -d "+${delay_second} seconds" "+%Y-%m-%d %H:%M:%S")
|
start_time=$(date -d "+${delay_second} seconds" "+%Y-%m-%d %H:%M:%S")
|
||||||
fi
|
fi
|
||||||
echo -e "任务随机延迟 $delay_second 秒,将于 $start_time 开始,配置文件参数 RandomDelay 置空可取消延迟 \n"
|
t '任务随机延迟 %s 秒,将于 %s 开始,配置文件参数 RandomDelay 置空可取消延迟\n' "$delay_second" "$start_time"
|
||||||
sleep $delay_second
|
sleep $delay_second
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ enter_script_workdir() {
|
||||||
fi
|
fi
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo -e "警告:工作目录不存在 ${_target_dir}"
|
t '警告:工作目录不存在 %s' "${_target_dir}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd $dir_scripts
|
cd $dir_scripts
|
||||||
|
|
@ -173,7 +173,7 @@ run_concurrent() {
|
||||||
local env_param="$2"
|
local env_param="$2"
|
||||||
local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|" | awk '{$1=$1};1')
|
local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|" | awk '{$1=$1};1')
|
||||||
if [[ ! $env_param ]]; then
|
if [[ ! $env_param ]]; then
|
||||||
echo -e "\n 缺少并发运行的环境变量参数"
|
t '\n缺少并发运行的环境变量参数'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -210,7 +210,7 @@ run_designated() {
|
||||||
local env_param="$2"
|
local env_param="$2"
|
||||||
local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|" | awk '{$1=$1};1')
|
local num_param=$(echo "$3" | perl -pe "s|.*$2(.*)|\1|" | awk '{$1=$1};1')
|
||||||
if [[ ! $env_param ]]; then
|
if [[ ! $env_param ]]; then
|
||||||
echo -e "\n 缺少单独运行的参数 task xxx.js desi Test"
|
t '\n缺少单独运行的参数 task xxx.js desi Test'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@ remove_js_log() {
|
||||||
if [[ $diff_time -gt $((${days} * 86400)) ]]; then
|
if [[ $diff_time -gt $((${days} * 86400)) ]]; then
|
||||||
local log_path=$(echo "$log" | sed "s,${dir_log}/,,g")
|
local log_path=$(echo "$log" | sed "s,${dir_log}/,,g")
|
||||||
local result=$(find_cron_api "log_path=$log_path")
|
local result=$(find_cron_api "log_path=$log_path")
|
||||||
echo -e "查询文件 $log_path"
|
t '查询文件 %s' "$log_path"
|
||||||
if [[ -z $result ]]; then
|
if [[ -z $result ]]; then
|
||||||
echo -e "删除中~"
|
t '删除中~'
|
||||||
rm -vf $log
|
rm -vf $log
|
||||||
else
|
else
|
||||||
echo -e "正在被 $result 使用,跳过~"
|
t '正在被 %s 使用,跳过~' "$result"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
@ -43,8 +43,8 @@ remove_empty_dir() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ ${days} ]]; then
|
if [[ ${days} ]]; then
|
||||||
echo -e "查找旧日志文件中...\n"
|
t '查找旧日志文件中...\n'
|
||||||
remove_js_log
|
remove_js_log
|
||||||
remove_empty_dir
|
remove_empty_dir
|
||||||
echo -e "删除旧日志执行完毕\n"
|
t '删除旧日志执行完毕\n'
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,15 @@ import_config() {
|
||||||
[[ -f $file_config_user ]] && . $file_config_user
|
[[ -f $file_config_user ]] && . $file_config_user
|
||||||
[[ -f $dir_preload/lang_env.sh ]] && . $dir_preload/lang_env.sh
|
[[ -f $dir_preload/lang_env.sh ]] && . $dir_preload/lang_env.sh
|
||||||
|
|
||||||
|
# 加载语言包(bash 4+ 支持 declare -A,不兼容时回退输出中文 key)
|
||||||
|
local lang=${QL_LANG:-zh}
|
||||||
|
local lang_file="$dir_shell/lang/${lang}.sh"
|
||||||
|
if [[ ${BASH_VERSINFO[0]} -ge 4 ]] && [[ -f $lang_file ]]; then
|
||||||
|
. $lang_file
|
||||||
|
elif [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
|
||||||
|
. "$dir_shell/lang/zh.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
load_ql_envs
|
load_ql_envs
|
||||||
command_timeout_time=${CommandTimeoutTime:-""}
|
command_timeout_time=${CommandTimeoutTime:-""}
|
||||||
file_extensions=${RepoFileExtensions:-"js py"}
|
file_extensions=${RepoFileExtensions:-"js py"}
|
||||||
|
|
@ -92,6 +101,18 @@ import_config() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t() {
|
||||||
|
local key="$1"
|
||||||
|
shift
|
||||||
|
local msg
|
||||||
|
if declare -p LANG_MESSAGES &>/dev/null; then
|
||||||
|
msg="${LANG_MESSAGES["$key"]}"
|
||||||
|
fi
|
||||||
|
[[ -z $msg ]] && msg="$key"
|
||||||
|
# shellcheck disable=SC2059
|
||||||
|
printf "$msg\n" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
set_proxy() {
|
set_proxy() {
|
||||||
local proxy="$1"
|
local proxy="$1"
|
||||||
if [[ $proxy ]]; then
|
if [[ $proxy ]]; then
|
||||||
|
|
@ -226,7 +247,7 @@ npm_install_2() {
|
||||||
local dir_work=$1
|
local dir_work=$1
|
||||||
|
|
||||||
cd $dir_work
|
cd $dir_work
|
||||||
echo -e "安装 $dir_work 依赖包...\n"
|
t '安装 %s 依赖包...\n' "$dir_work"
|
||||||
npm_install_sub
|
npm_install_sub
|
||||||
cd $dir_current
|
cd $dir_current
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +266,7 @@ git_clone_scripts() {
|
||||||
local branch="$3"
|
local branch="$3"
|
||||||
local proxy="$4"
|
local proxy="$4"
|
||||||
[[ $branch ]] && local part_cmd="-b $branch "
|
[[ $branch ]] && local part_cmd="-b $branch "
|
||||||
echo -e "开始拉取仓库 ${uniq_path} 到 $dir\n"
|
t '开始拉取仓库 %s 到 %s\n' "${uniq_path}" "$dir"
|
||||||
|
|
||||||
set_proxy "$proxy"
|
set_proxy "$proxy"
|
||||||
|
|
||||||
|
|
@ -278,8 +299,8 @@ reload_pm2() {
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
local exit_code=$?
|
local exit_code=$?
|
||||||
echo "警告: PM2 启动失败 (退出码: $exit_code),可能是由于硬件不兼容"
|
t '警告: PM2 启动失败 (退出码: %s),可能是由于硬件不兼容' "$exit_code"
|
||||||
echo "正在尝试直接使用 Node.js 启动服务..."
|
t '正在尝试直接使用 Node.js 启动服务...'
|
||||||
|
|
||||||
# Kill any existing node processes for qinglong
|
# Kill any existing node processes for qinglong
|
||||||
pkill -f "node.*static/build/app.js" 2>/dev/null || true
|
pkill -f "node.*static/build/app.js" 2>/dev/null || true
|
||||||
|
|
@ -288,8 +309,8 @@ reload_pm2() {
|
||||||
nohup node static/build/app.js > $dir_log/qinglong.log 2>&1 &
|
nohup node static/build/app.js > $dir_log/qinglong.log 2>&1 &
|
||||||
local node_pid=$!
|
local node_pid=$!
|
||||||
|
|
||||||
echo "已使用 Node.js 直接启动服务 (PID: $node_pid)"
|
t '已使用 Node.js 直接启动服务 (PID: %s)' "$node_pid"
|
||||||
echo "注意: 使用此模式时,部分 PM2 管理功能将不可用"
|
t '注意: 使用此模式时,部分 PM2 管理功能将不可用'
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
@ -361,16 +382,16 @@ handle_task_start() {
|
||||||
error_message=", 任务状态更新失败(${error})"
|
error_message=", 任务状态更新失败(${error})"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo -e "## 开始执行... ${begin_time}${error_message}\n"
|
t '## 开始执行... %s\n' "${begin_time}${error_message}"
|
||||||
}
|
}
|
||||||
|
|
||||||
run_task_before() {
|
run_task_before() {
|
||||||
. $file_task_before "$@"
|
. $file_task_before "$@"
|
||||||
|
|
||||||
if [[ ${task_before:=} ]]; then
|
if [[ ${task_before:=} ]]; then
|
||||||
echo -e "执行前置命令\n"
|
t '执行前置命令\n'
|
||||||
eval "${task_before%;}"
|
eval "${task_before%;}"
|
||||||
echo -e "\n执行前置命令结束\n"
|
t '\n执行前置命令结束\n'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -378,9 +399,9 @@ run_task_after() {
|
||||||
. $file_task_after "$@"
|
. $file_task_after "$@"
|
||||||
|
|
||||||
if [[ ${task_after:=} ]]; then
|
if [[ ${task_after:=} ]]; then
|
||||||
echo -e "\n执行后置命令\n"
|
t '\n执行后置命令\n'
|
||||||
eval "${task_after%;}"
|
eval "${task_after%;}"
|
||||||
echo -e "\n执行后置命令结束"
|
t '\n执行后置命令结束'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -402,11 +423,11 @@ handle_task_end() {
|
||||||
record_cron_stat "$ID" "${exit_code:-0}" "$diff_time"
|
record_cron_stat "$ID" "${exit_code:-0}" "$diff_time"
|
||||||
|
|
||||||
if [[ "${MANUAL:=}" == "true" ]]; then
|
if [[ "${MANUAL:=}" == "true" ]]; then
|
||||||
echo -e "\n## 已停止 🛑... $end_time 耗时 $diff_time 秒${error_message:=} "
|
t '\n## 已停止 🛑... %s 耗时 %s 秒%s' "$end_time" "$diff_time" "${error_message:=} "
|
||||||
elif [[ $exit_code -eq 0 ]]; then
|
elif [[ $exit_code -eq 0 ]]; then
|
||||||
echo -e "\n## 完成 ✅... $end_time 耗时 $diff_time 秒${error_message:=} "
|
t '\n## 完成 ✅... %s 耗时 %s 秒%s' "$end_time" "$diff_time" "${error_message:=} "
|
||||||
else
|
else
|
||||||
echo -e "\n## 失败 ❌(退出码 ${exit_code})... $end_time 耗时 $diff_time 秒${error_message:=} "
|
t '\n## 失败 ❌(退出码 %s)... %s 耗时 %s 秒%s' "$exit_code" "$end_time" "$diff_time" "${error_message:=} "
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,23 +12,23 @@ if [[ ! $QL_DIR ]]; then
|
||||||
elif [[ -d "$pnpm_dir/@whyour/qinglong" ]]; then
|
elif [[ -d "$pnpm_dir/@whyour/qinglong" ]]; then
|
||||||
QL_DIR="$pnpm_dir/@whyour/qinglong"
|
QL_DIR="$pnpm_dir/@whyour/qinglong"
|
||||||
else
|
else
|
||||||
echo -e "未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装"
|
t '未找到 qinglong 模块,请先执行 npm i -g @whyour/qinglong 安装'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $QL_DIR ]]; then
|
if [[ $QL_DIR ]]; then
|
||||||
echo -e "请先手动设置 export QL_DIR=$QL_DIR,环境变量,并手动添加到系统环境变量,然后再次执行命令 qinglong 启动服务"
|
t '请先手动设置 export QL_DIR=%s,环境变量,并手动添加到系统环境变量,然后再次执行命令 qinglong 启动服务' "$QL_DIR"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! $QL_DATA_DIR ]]; then
|
if [[ ! $QL_DATA_DIR ]]; then
|
||||||
echo -e "请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量"
|
t '请先手动设置数据存储目录 export QL_DATA_DIR 环境变量,目录必须以斜杠开头的绝对路径,并且以 /data 结尾,例如 /ql/data 并手动添加到系统环境变量'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $QL_DATA_DIR != */data ]]; then
|
if [[ $QL_DATA_DIR != */data ]]; then
|
||||||
echo -e "QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data,如果有历史数据,请新建 data 目录,把历史数据放到 data 目录中"
|
t 'QL_DATA_DIR 必须以 /data 结尾,例如 /ql/data,如果有历史数据,请新建 data 目录,把历史数据放到 data 目录中'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ if [[ $command != "reload" ]]; then
|
||||||
$SUDO apt-get install -y git curl wget tzdata perl openssl jq nginx procps netcat-openbsd openssh-client
|
$SUDO apt-get install -y git curl wget tzdata perl openssl jq nginx procps netcat-openbsd openssh-client
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo -e "暂不支持此系统部署 $os_name"
|
t '暂不支持此系统部署 %s' "$os_name"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,13 @@ dir_shell=$QL_DIR/shell
|
||||||
. $dir_shell/share.sh
|
. $dir_shell/share.sh
|
||||||
. $dir_shell/api.sh
|
. $dir_shell/api.sh
|
||||||
|
|
||||||
trap "single_hanle" 2 3 20 15 14 19 1
|
trap 'single_hanle SIGINT' INT
|
||||||
|
trap 'single_hanle SIGTERM' TERM
|
||||||
|
trap 'single_hanle SIGHUP' HUP
|
||||||
|
trap 'single_hanle SIGALRM' ALRM
|
||||||
|
trap 'single_hanle SIGTSTP' TSTP
|
||||||
|
trap 'single_hanle SIGQUIT' QUIT
|
||||||
|
|
||||||
single_hanle() {
|
single_hanle() {
|
||||||
_task_exit_code="${_task_exit_code:-$?}"
|
_task_exit_code="${_task_exit_code:-$?}"
|
||||||
[[ "$_task_exit_code" == "0" ]] && _task_exit_code="1"
|
[[ "$_task_exit_code" == "0" ]] && _task_exit_code="1"
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ output_list_add_drop() {
|
||||||
local list=$1
|
local list=$1
|
||||||
local type=$2
|
local type=$2
|
||||||
if [[ -s $list ]]; then
|
if [[ -s $list ]]; then
|
||||||
echo -e "检测到有${type}的定时任务:"
|
t '检测到有%s的定时任务:' "$type"
|
||||||
cat $list
|
cat $list
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +45,7 @@ del_cron() {
|
||||||
local path=$2
|
local path=$2
|
||||||
local detail=""
|
local detail=""
|
||||||
local ids=""
|
local ids=""
|
||||||
echo -e "\n开始尝试自动删除失效的定时任务..."
|
t '\n开始尝试自动删除失效的定时任务...'
|
||||||
for cron in $(cat $list_drop); do
|
for cron in $(cat $list_drop); do
|
||||||
local id=$(cat $list_crontab_user | grep -E "$cmd_task.* $cron" | perl -pe "s|.*ID=(.*) $cmd_task.* $cron\.*|\1|" | head -1 | awk -F " " '{print $1}')
|
local id=$(cat $list_crontab_user | grep -E "$cmd_task.* $cron" | perl -pe "s|.*ID=(.*) $cmd_task.* $cron\.*|\1|" | head -1 | awk -F " " '{print $1}')
|
||||||
if [[ $ids ]]; then
|
if [[ $ids ]]; then
|
||||||
|
|
@ -76,7 +76,7 @@ del_cron() {
|
||||||
add_cron() {
|
add_cron() {
|
||||||
local list_add=$1
|
local list_add=$1
|
||||||
local path=$2
|
local path=$2
|
||||||
echo -e "\n开始尝试自动添加定时任务..."
|
t '\n开始尝试自动添加定时任务...'
|
||||||
local detail=""
|
local detail=""
|
||||||
cd $dir_scripts
|
cd $dir_scripts
|
||||||
for file in $(cat $list_add); do
|
for file in $(cat $list_add); do
|
||||||
|
|
@ -136,10 +136,10 @@ update_repo() {
|
||||||
git_clone_scripts "${formatUrl}" ${repo_path} "${branch}" "${proxy}"
|
git_clone_scripts "${formatUrl}" ${repo_path} "${branch}" "${proxy}"
|
||||||
|
|
||||||
if [[ $exit_status -eq 0 ]]; then
|
if [[ $exit_status -eq 0 ]]; then
|
||||||
echo -e "拉取 ${uniq_path} 成功...\n"
|
t '拉取 %s 成功...\n' "${uniq_path}"
|
||||||
diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions" "$autoAddCron" "$autoDelCron"
|
diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions" "$autoAddCron" "$autoDelCron"
|
||||||
else
|
else
|
||||||
echo -e "拉取 ${uniq_path} 失败,请检查日志...\n"
|
t '拉取 %s 失败,请检查日志...\n' "${uniq_path}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,7 +160,7 @@ update_raw() {
|
||||||
local raw_url="$url"
|
local raw_url="$url"
|
||||||
local suffix="${raw_url##*.}"
|
local suffix="${raw_url##*.}"
|
||||||
local raw_file_name="${uniq_path}.${suffix}"
|
local raw_file_name="${uniq_path}.${suffix}"
|
||||||
echo -e "开始下载:${raw_url} \n\n保存路径:$dir_raw/${raw_file_name}\n"
|
t '开始下载:%s 保存路径:%s\n' "${raw_url}" "$dir_raw/${raw_file_name}"
|
||||||
|
|
||||||
set_proxy "$proxy"
|
set_proxy "$proxy"
|
||||||
wget -q --no-check-certificate -O "$dir_raw/${raw_file_name}.new" ${raw_url}
|
wget -q --no-check-certificate -O "$dir_raw/${raw_file_name}.new" ${raw_url}
|
||||||
|
|
@ -169,7 +169,7 @@ update_raw() {
|
||||||
|
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
mv "$dir_raw/${raw_file_name}.new" "$dir_raw/${raw_file_name}"
|
mv "$dir_raw/${raw_file_name}.new" "$dir_raw/${raw_file_name}"
|
||||||
echo -e "下载 ${raw_file_name} 成功...\n"
|
t '下载 %s 成功...\n' "${raw_file_name}"
|
||||||
cd $dir_raw
|
cd $dir_raw
|
||||||
local filename="raw_${raw_file_name}"
|
local filename="raw_${raw_file_name}"
|
||||||
local cron_id=$(cat $list_crontab_user | grep -E "$cmd_task.* $filename" | perl -pe "s|.*ID=(.*) $cmd_task.* $filename\.*|\1|" | head -1 | awk -F " " '{print $1}')
|
local cron_id=$(cat $list_crontab_user | grep -E "$cmd_task.* $filename" | perl -pe "s|.*ID=(.*) $cmd_task.* $filename\.*|\1|" | head -1 | awk -F " " '{print $1}')
|
||||||
|
|
@ -196,7 +196,7 @@ update_raw() {
|
||||||
# update_cron_api "$cron_line:$cmd_task $filename:$cron_name:$cron_id"
|
# update_cron_api "$cron_line:$cmd_task $filename:$cron_name:$cron_id"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "下载 ${raw_file_name} 失败,保留之前正常下载的版本...\n"
|
t '下载 %s 失败,保留之前正常下载的版本...\n' "${raw_file_name}"
|
||||||
[[ -f "$dir_raw/${raw_file_name}.new" ]] && rm -f "$dir_raw/${raw_file_name}.new"
|
[[ -f "$dir_raw/${raw_file_name}.new" ]] && rm -f "$dir_raw/${raw_file_name}.new"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -207,13 +207,13 @@ run_extra_shell() {
|
||||||
if [[ -f $file_extra_shell ]]; then
|
if [[ -f $file_extra_shell ]]; then
|
||||||
. $file_extra_shell
|
. $file_extra_shell
|
||||||
else
|
else
|
||||||
echo -e "$file_extra_shell文件不存在,跳过执行...\n"
|
t '%s文件不存在,跳过执行...\n' "$file_extra_shell"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
## 脚本用法
|
## 脚本用法
|
||||||
usage() {
|
usage() {
|
||||||
echo -e "$cmd_update 命令使用方法:"
|
t "$cmd_update 命令使用方法:"
|
||||||
echo -e "1. $cmd_update update # 更新并重启青龙"
|
echo -e "1. $cmd_update update # 更新并重启青龙"
|
||||||
echo -e "2. $cmd_update extra # 运行自定义脚本"
|
echo -e "2. $cmd_update extra # 运行自定义脚本"
|
||||||
echo -e "3. $cmd_update raw <fileurl> # 更新单个脚本文件"
|
echo -e "3. $cmd_update raw <fileurl> # 更新单个脚本文件"
|
||||||
|
|
@ -268,7 +268,7 @@ update_qinglong() {
|
||||||
downloadQLUrl="https://github.com/whyour/qinglong/archive/refs/heads"
|
downloadQLUrl="https://github.com/whyour/qinglong/archive/refs/heads"
|
||||||
downloadStaticUrl="https://github.com/whyour/qinglong-static/archive/refs/heads"
|
downloadStaticUrl="https://github.com/whyour/qinglong-static/archive/refs/heads"
|
||||||
fi
|
fi
|
||||||
echo -e "使用 ${mirror} 源更新...\n"
|
t '使用 %s 源更新...\n' "${mirror}"
|
||||||
|
|
||||||
local primary_branch="master"
|
local primary_branch="master"
|
||||||
if [[ "${QL_BRANCH}" == "develop" ]] || [[ "${QL_BRANCH}" == "debian" ]] || [[ "${QL_BRANCH}" == "debian-dev" ]]; then
|
if [[ "${QL_BRANCH}" == "develop" ]] || [[ "${QL_BRANCH}" == "debian" ]] || [[ "${QL_BRANCH}" == "debian-dev" ]]; then
|
||||||
|
|
@ -279,13 +279,13 @@ update_qinglong() {
|
||||||
exit_status=$?
|
exit_status=$?
|
||||||
|
|
||||||
if [[ $exit_status -eq 0 ]]; then
|
if [[ $exit_status -eq 0 ]]; then
|
||||||
echo -e "更新青龙源文件成功...\n"
|
t '更新青龙源文件成功...\n'
|
||||||
|
|
||||||
unzip -oq ${dir_tmp}/ql.zip -d ${dir_tmp}
|
unzip -oq ${dir_tmp}/ql.zip -d ${dir_tmp}
|
||||||
|
|
||||||
update_qinglong_static
|
update_qinglong_static
|
||||||
else
|
else
|
||||||
echo -e "更新青龙源文件失败,请检查网络...\n"
|
t '更新青龙源文件失败,请检查网络...\n'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,30 +294,30 @@ update_qinglong_static() {
|
||||||
exit_status=$?
|
exit_status=$?
|
||||||
|
|
||||||
if [[ $exit_status -eq 0 ]]; then
|
if [[ $exit_status -eq 0 ]]; then
|
||||||
echo -e "更新青龙静态资源成功...\n"
|
t '更新青龙静态资源成功...\n'
|
||||||
unzip -oq ${dir_tmp}/static.zip -d ${dir_tmp}
|
unzip -oq ${dir_tmp}/static.zip -d ${dir_tmp}
|
||||||
|
|
||||||
check_update_dep
|
check_update_dep
|
||||||
else
|
else
|
||||||
echo -e "更新青龙静态资源失败,请检查网络...\n"
|
t '更新青龙静态资源失败,请检查网络...\n'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
check_update_dep() {
|
check_update_dep() {
|
||||||
echo -e "\n开始检测依赖...\n"
|
t '\n开始检测依赖...\n'
|
||||||
if [[ $(diff $dir_root/package.json ${dir_tmp}/qinglong-${primary_branch}/package.json) ]]; then
|
if [[ $(diff $dir_root/package.json ${dir_tmp}/qinglong-${primary_branch}/package.json) ]]; then
|
||||||
npm_install_2 "${dir_tmp}/qinglong-${primary_branch}"
|
npm_install_2 "${dir_tmp}/qinglong-${primary_branch}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $exit_status -eq 0 ]]; then
|
if [[ $exit_status -eq 0 ]]; then
|
||||||
echo -e "\n依赖检测安装成功...\n"
|
t '\n依赖检测安装成功...\n'
|
||||||
echo -e "更新包下载成功..."
|
t '更新包下载成功...\n'
|
||||||
|
|
||||||
if [[ "$needRestart" == 'true' ]]; then
|
if [[ "$needRestart" == 'true' ]]; then
|
||||||
reload_qinglong "system"
|
reload_qinglong "system"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "\n依赖检测安装失败,请检查网络...\n"
|
t '\n依赖检测安装失败,请检查网络...\n'
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -514,7 +514,7 @@ main() {
|
||||||
if [[ -n $p2 ]]; then
|
if [[ -n $p2 ]]; then
|
||||||
update_repo "$p2" "$p3" "$p4" "$p5" "$p6" "$p7" "$p8" "$p9" "$p10"
|
update_repo "$p2" "$p3" "$p4" "$p5" "$p6" "$p7" "$p8" "$p9" "$p10"
|
||||||
else
|
else
|
||||||
eval echo -e "命令输入错误...\\\n" $cmd
|
t '命令输入错误...\n'
|
||||||
eval usage $cmd
|
eval usage $cmd
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
@ -523,7 +523,7 @@ main() {
|
||||||
if [[ -n $p2 ]]; then
|
if [[ -n $p2 ]]; then
|
||||||
update_raw "$p2" "$p3" "$p4" "$p5"
|
update_raw "$p2" "$p3" "$p4" "$p5"
|
||||||
else
|
else
|
||||||
eval echo -e "命令输入错误...\\\n" $cmd
|
t '命令输入错误...\n'
|
||||||
eval usage $cmd
|
eval usage $cmd
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
@ -549,7 +549,7 @@ main() {
|
||||||
eval update_auth_config "\\\"username\\\":\\\"$p2\\\"" "重置用户名" $cmd
|
eval update_auth_config "\\\"username\\\":\\\"$p2\\\"" "重置用户名" $cmd
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
eval echo -e "命令输入错误...\\\n" $cmd
|
t '命令输入错误...\n'
|
||||||
eval usage $cmd
|
eval usage $cmd
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ export default function () {
|
||||||
if (code === 200 && data.username) {
|
if (code === 200 && data.username) {
|
||||||
setUser(data);
|
setUser(data);
|
||||||
if (location.pathname === '/') {
|
if (location.pathname === '/') {
|
||||||
history.push('/crontab');
|
history.push('/dashboard');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
needLoading && setLoading(false);
|
needLoading && setLoading(false);
|
||||||
|
|
@ -218,7 +218,7 @@ export default function () {
|
||||||
|
|
||||||
if (['/login', '/initialization', '/error'].includes(location.pathname)) {
|
if (['/login', '/initialization', '/error'].includes(location.pathname)) {
|
||||||
if (systemInfo?.isInitialized && location.pathname === '/initialization') {
|
if (systemInfo?.isInitialized && location.pathname === '/initialization') {
|
||||||
history.push('/crontab');
|
history.push('/dashboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (systemInfo || location.pathname === '/error') {
|
if (systemInfo || location.pathname === '/error') {
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ const Error = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user && user.username) {
|
if (user && user.username) {
|
||||||
history.push('/crontab');
|
history.push('/dashboard');
|
||||||
}
|
}
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user