├── .github
├── ISSUE_TEMPLATE
│ ├── New_Funtion.md
│ └── bug_report.md
├── textbook
│ └── Panel1.png
└── workflows
│ ├── Built_JD_Shell_To_Docker.yml
│ ├── Sync_JD_Shell_A1_From_Gitee.yml
│ ├── Sync_JD_Shell_To_Gitee.yml
│ ├── Sync_JD_Shell_v3_From_Gitee.yml
│ └── Sync_JD_Shell_v3_To_Gitee.yml
├── .gitignore
├── README.md
├── docker
├── Dockerfile
├── docker-compose.yml
├── docker-entrypoint.sh
└── proc_file.sh
├── export_sharecodes.sh
├── git_pull.sh
├── install_scripts
├── docker_install_jd.sh
└── linux_install_jd.sh
├── jd.sh
├── panel
├── ecosystem.config.js
├── package.json
├── public
│ ├── auth.html
│ ├── crontab.html
│ ├── css
│ │ ├── codemirror.min.css
│ │ ├── dracula.css
│ │ ├── main.css
│ │ ├── merge.css
│ │ ├── normalize.min.css
│ │ ├── style.css
│ │ └── twilight.css
│ ├── diff.html
│ ├── diy.html
│ ├── helpcode.html
│ ├── home.html
│ ├── js
│ │ ├── codemirror.min.js
│ │ ├── comment.js
│ │ ├── diff_match_patch.js
│ │ ├── javascript.js
│ │ ├── jquery.min.js
│ │ ├── merge.js
│ │ ├── qrcode.min.js
│ │ ├── shell.js
│ │ ├── sublime.js
│ │ └── sweetalert2.js
│ ├── pwd.html
│ ├── robots.txt
│ ├── run.html
│ ├── tasklog.html
│ ├── terminal.html
│ └── viewScripts.html
├── server.js
└── webshellbinary
│ ├── ttyd.aarch64
│ ├── ttyd.arm
│ ├── ttyd.armhf
│ ├── ttyd.i686
│ ├── ttyd.mips
│ ├── ttyd.mips64
│ ├── ttyd.mips64el
│ ├── ttyd.mipsel
│ └── ttyd.x86_64
├── repair.sh
├── rm_log.sh
├── sample
├── auth.json
├── config.sh.sample
├── crontab.list.sample
└── diy.sh
└── update.js
/.github/ISSUE_TEMPLATE/New_Funtion.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 功能需求
3 | about: 想要增加什么样的功能?
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 |
10 | ### 想要增加什么样的功能或者哪里存在不足之处呢?
11 |
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: BUG 反馈
3 | about: 出现bug
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 | ## 1.关于你要提交的问题
27 |
28 | Q:是否搜索了issue(包括已关闭的issue)
29 | - [ ] 没有类似的issue
30 |
31 | Q:是否阅读了常见问题
32 | - [ ] 已阅读常见问题,未找到相关说明
33 |
34 | Q:是否仔细阅读了教程
35 |
36 | - [ ] 已仔细阅读教程
37 |
38 |
39 | ## 2. 使用什么平台?
40 |
41 | - [ ] Linux
42 | - [ ] Docker
43 |
44 | ## 3. 是否用一键脚本部署的?
45 |
46 | - [ ] Yes
47 | - [ ] No
48 |
49 | ## 4. 有没有试过用修复脚本来修复过?
50 |
51 | - [ ] Yes
52 | - [ ] No
53 |
54 |
55 | ## 5. 详细叙述
56 | ### (1) 具体问题
57 | A:
58 |
59 |
60 | ### (2) 详细日志
61 | A:
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/.github/textbook/Panel1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/.github/textbook/Panel1.png
--------------------------------------------------------------------------------
/.github/workflows/Built_JD_Shell_To_Docker.yml:
--------------------------------------------------------------------------------
1 | name: Built_JD_Shell_To_Docker
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: '30 * * * *'
6 |
7 | jobs:
8 | docker:
9 | runs-on: ubuntu-latest
10 | timeout-minutes: 10
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@v2
14 |
15 | - name: Set up QEMU
16 | uses: docker/setup-qemu-action@v1
17 |
18 | - name: Set up Docker Buildx
19 | uses: docker/setup-buildx-action@v1
20 |
21 | - name: Login to DockerHub
22 | uses: docker/login-action@v1
23 | with:
24 | username: ${{ secrets.DockerHub_ID }}
25 | password: ${{ secrets.DockerHub_PASSWORD }}
26 |
27 | - name: Build & Push
28 | uses: docker/build-push-action@v2
29 | with:
30 | context: ./docker/
31 | platforms: linux/amd64,linux/arm64/v8,linux/arm/v7,linux/arm/v6,linux/ppc64le,linux/s390x
32 | push: true
33 | tags: lantianxiang1/jd_shell:v3
34 | - name: Delete Workflow Runs
35 | uses: Mattraks/delete-workflow-runs@main
36 | with:
37 | token: ${{ github.token }}
38 | repository: ${{ github.repository }}
39 | retain_days: 1
40 | keep_minimum_runs: 0
41 |
42 |
--------------------------------------------------------------------------------
/.github/workflows/Sync_JD_Shell_A1_From_Gitee.yml:
--------------------------------------------------------------------------------
1 | name: Sync_JD_Shell_A1_From_Gitee
2 | on:
3 | push:
4 | branches:
5 | - A1
6 | workflow_dispatch:
7 | schedule:
8 | - cron: '*/8 * * * *'
9 | jobs:
10 | sync:
11 | runs-on: ubuntu-18.04
12 | if: github.repository == 'lan-tianxiang/jd_shell'
13 | timeout-minutes: 3
14 | steps:
15 | - name: Init Build Dependencies
16 | env:
17 | DEBIAN_FRONTEND: noninteractive
18 | run: |
19 | sudo -E rm -rf /etc/apt/sources.list.d
20 | sudo -E apt-get update -y
21 | sudo -E apt-get install -y build-essential git git-core curl wget
22 | sudo -E apt-get clean -y
23 | git config --global user.name 'lan-tianxiang' && git config --global user.email 'highdimen@github.com'
24 | - name: Prepare Key
25 | run: |
26 | mkdir -p ~/.ssh
27 | echo -e "${{ secrets.RSA_PRIVATE_KEY }}" > ~/.ssh/id_rsa
28 | chmod 600 ~/.ssh/id_rsa
29 | ssh-keyscan gitee.com > ~/.ssh/known_hosts
30 | - name: Clone Master
31 | run: |
32 | git clone -b A1 git@gitee.com:highdimen/jd_shell.git A1
33 | - name: Push Master
34 | uses: ad-m/github-push-action@master
35 | with:
36 | directory: A1
37 | github_token: ${{ secrets.HUB_TOKEN }}
38 | branch: A1
39 | force : true
40 | - name: Delete Workflow Runs
41 | uses: Mattraks/delete-workflow-runs@main
42 | with:
43 | token: ${{ github.token }}
44 | repository: ${{ github.repository }}
45 | retain_days: 1
46 | keep_minimum_runs: 0
47 |
--------------------------------------------------------------------------------
/.github/workflows/Sync_JD_Shell_To_Gitee.yml:
--------------------------------------------------------------------------------
1 | name: Sync_JD_Shell_To_Gitee
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: '1,6,11,16,21,26,31,36,41,46,51,55 * * * *'
6 | jobs:
7 | sync:
8 | runs-on: ubuntu-latest
9 | timeout-minutes: 3
10 | steps:
11 | - name: Sync to Gitee
12 | uses: wearerequired/git-mirror-action@master
13 | env:
14 | # 注意在 Settings->Secrets 配置 GITEE_RSA_PRIVATE_KEY
15 | SSH_PRIVATE_KEY: ${{ secrets.RSA_PRIVATE_KEY }}
16 | with:
17 | # 注意替换为你的 GitHub 源仓库地址
18 | source-repo: git@github.com:lan-tianxiang/jd_shell.git
19 | # 注意替换为你的 Gitee 目标仓库地址
20 | destination-repo: git@gitee.com:highdimen/jd_shell.git
21 |
22 | - name: Delete Workflow Runs
23 | uses: Mattraks/delete-workflow-runs@main
24 | with:
25 | token: ${{ github.token }}
26 | repository: ${{ github.repository }}
27 | retain_days: 1
28 | keep_minimum_runs: 0
29 |
30 |
--------------------------------------------------------------------------------
/.github/workflows/Sync_JD_Shell_v3_From_Gitee.yml:
--------------------------------------------------------------------------------
1 | name: Sync_JD_Shell_v3_From_Gitee
2 | on:
3 | push:
4 | branches:
5 | - v3
6 | workflow_dispatch:
7 | schedule:
8 | - cron: '*/10 * * * *'
9 | jobs:
10 | sync:
11 | runs-on: ubuntu-18.04
12 | if: github.repository == 'lan-tianxiang/jd_shell'
13 | timeout-minutes: 3
14 | steps:
15 | - name: Init Build Dependencies
16 | env:
17 | DEBIAN_FRONTEND: noninteractive
18 | run: |
19 | sudo -E rm -rf /etc/apt/sources.list.d
20 | sudo -E apt-get update -y
21 | sudo -E apt-get install -y build-essential git git-core curl wget
22 | sudo -E apt-get clean -y
23 | git config --global user.name 'lan-tianxiang' && git config --global user.email 'highdimen@github.com'
24 | - name: Prepare Key
25 | run: |
26 | mkdir -p ~/.ssh
27 | echo -e "${{ secrets.RSA_PRIVATE_KEY }}" > ~/.ssh/id_rsa
28 | chmod 600 ~/.ssh/id_rsa
29 | ssh-keyscan gitee.com > ~/.ssh/known_hosts
30 | - name: Clone Master
31 | run: |
32 | git clone -b v3 git@gitee.com:highdimen/jd_shell.git v3
33 | - name: Push Master
34 | uses: ad-m/github-push-action@master
35 | with:
36 | directory: v3
37 | github_token: ${{ secrets.HUB_TOKEN }}
38 | branch: v3
39 | force : true
40 | - name: Delete Workflow Runs
41 | uses: Mattraks/delete-workflow-runs@main
42 | with:
43 | token: ${{ github.token }}
44 | repository: ${{ github.repository }}
45 | retain_days: 1
46 | keep_minimum_runs: 0
47 |
--------------------------------------------------------------------------------
/.github/workflows/Sync_JD_Shell_v3_To_Gitee.yml:
--------------------------------------------------------------------------------
1 | name: Sync_JD_Shell_v3_To_Gitee
2 | on:
3 | push:
4 | branches:
5 | - v3
6 | workflow_dispatch:
7 | jobs:
8 | sync:
9 | runs-on: ubuntu-18.04
10 | if: github.repository == 'lan-tianxiang/jd_shell'
11 | timeout-minutes: 3
12 | steps:
13 | - name: Init Build Dependencies
14 | env:
15 | DEBIAN_FRONTEND: noninteractive
16 | run: |
17 | sudo -E rm -rf /etc/apt/sources.list.d
18 | sudo -E apt-get update -y
19 | sudo -E apt-get install -y build-essential git git-core curl wget
20 | sudo -E apt-get clean -y
21 | git config --global user.name 'lan-tianxiang' && git config --global user.email 'highdimen@gitee.com'
22 | - name: Prepare Key
23 | run: |
24 | mkdir -p ~/.ssh
25 | echo -e "${{ secrets.RSA_PRIVATE_KEY }}" > ~/.ssh/id_rsa
26 | chmod 600 ~/.ssh/id_rsa
27 | ssh-keyscan github.com > ~/.ssh/known_hosts
28 | - name: Clone Master
29 | run: |
30 | git clone -b v3 git@github.com:lan-tianxiang/jd_shell.git v3
31 | - name: Prepare Key
32 | run: |
33 | mkdir -p ~/.ssh
34 | echo -e "${{ secrets.RSA_PRIVATE_KEY }}" > ~/.ssh/id_rsa
35 | chmod 600 ~/.ssh/id_rsa
36 | ssh-keyscan gitee.com > ~/.ssh/known_hosts
37 | - name: push Master
38 | run: |
39 | cd v3
40 | perl -i -pe "s|url \= git\@github.com:lan-tianxiang\/jd_shell.git|url \= git\@gitee.com:highdimen\/jd_shell.git|g" .git/config
41 | cat .git/config
42 | echo "## UpdateTime: "$(date) >> jd.sh
43 | git add .
44 | git commit -m "update"
45 | git push -f
46 | - name: Delete Workflow Runs
47 | uses: Mattraks/delete-workflow-runs@main
48 | with:
49 | token: ${{ github.token }}
50 | repository: ${{ github.repository }}
51 | retain_days: 1
52 | keep_minimum_runs: 0
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | panel/node_modules*
2 | panel/yarn.lock
3 | panel/package-lock.json
4 | scripts*
5 | log*
6 | config*
7 | version
8 | old_crontab
9 | new_task
10 | drop_task
11 | send_count
12 | jd.sh.*
13 | export_sharecodes.sh.*
14 | run_all.sh
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | ### 旧版暂停更新,忙不过来 答疑交流QQ群967451175
6 | A1版(新版) https://github.com/lan-tianxiang/js_tool
7 |
8 |
9 |
10 |
11 |
JS SHELL
12 | 自动化一键完成JS库管理
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | 查看 Demo
30 | ·
31 | 报告 Bug
32 | ·
33 | 请求增加功能
34 |
35 |
36 | 喜欢这个项目?请考虑捐赠❤来帮助它完善!
37 |
38 |
当然,觉得默默关注也是鼓励的话,也可以在右上角给颗⭐!你的支持是我最大的动力😎!
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | ## 必要声明:
48 | * 本仓库发布的SHELL项目,是用于对第三方js库进行自动更新,管理和运行的一体化软件.
49 | * 本项目内所有资源文件,禁止任何公众号、自媒体进行任何形式的转载、发布。
50 | * 本仓库发布的SHELL项目中涉及的任何脚本,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断.
51 | * 所有使用者在使用SHELL项目的任何部分时,需先遵守法律法规。对于一切使用不当所造成的后果,需自行承担.对任何脚本问题概不负责,包括但不限于由任何脚本错误导致的任何损失或损害.
52 | * 间接使用SHELL项目的任何用户,包括但不限于建立VPS或在某些行为违反国家/地区法律或相关法规的情况下进行传播, 本人对于由此引起的任何隐私泄漏或其他后果概不负责.
53 | * 如果任何单位或个人认为该项目可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关文件.
54 | * 任何以任何方式查看此项目的人或直接或间接使用该SHELL项目的任何脚本的使用者都应仔细阅读此声明。本人保留随时更改或补充此免责声明的权利。一旦使用并复制了任何相关脚本或SHELL项目的规则,则视为您已接受此免责声明.
55 |
56 | **您必须在下载后的24小时内从计算机或手机中完全删除以上内容.**
57 | > ***您使用或者复制了本仓库且本人制作的任何脚本,则视为`已接受`此声明,请仔细阅读***
58 |
59 | ##### ☣请各位不要传播!!☣
60 |
61 | ### 通知
62 | - __2021/3/31 9:00 `Docker重要通知`__
63 | 修复Docker遗留的隐藏BUG,为了保持docker和linux修复脚本的一致,请所有使用`Docker`重新安装一键脚本,选择删除已部署的镜像即可。
64 |
65 | - __2021/3/30 9:00 `长期`__
66 | ㅤ有好用的第三方脚本欢迎提交到https://github.com/lan-tianxiang/jd_scripts
67 |
68 | ## 开发行程
69 |
70 | - __2021/4/5 12:00 `完成多账户并发运行任务功能`__
71 | - __2021/4/10 12:00 `对结构优化,减少执行文件`__
72 | - __2021/4/15 12:00 `不知道要更什么功能,你们来提!!!`__
73 | - __2021/4/15 12:00 `尚待继续!!!`__
74 |
75 | ## 适用于以下系统
76 |
77 | ### 如何部署?
78 |
79 | (推荐使用docker安装),有点如下:
80 | 一、安全方面,暴露主机端口很危险,docker被入侵不影响主机。
81 | 二、docker类似虚拟机,不用在主机安装软件,影响环境,且Bug少,面板自启功能
82 | [Docker](https://github.com/lan-tianxiang/js_tool/wiki/Docker)
83 |
84 | ## `Linux`
85 |
86 | - [Debian/Ubuntu/Armbian/OpenMediaVault等Debian系](https://github.com/lan-tianxiang/jd_shell/wiki/Linux) 🔻
87 |
88 | - [CentOS/RedHat/Fedora等红帽系](https://github.com/lan-tianxiang/jd_shell/wiki/Linux) 🔻
89 |
90 | - [Android等使用Termux模拟Linux的系统](https://github.com/lan-tianxiang/jd_shell/wiki/Android) 🔻
91 |
92 | - [OpenWRT、MacOs等类UNIX系统](https://github.com/lan-tianxiang/jd_shell/wiki/Unix) 🔻
93 |
94 | ## `Docker`
95 |
96 | - [Docker](https://github.com/lan-tianxiang/jd_shell/wiki/Docker) 🔻
97 |
98 | ## `Windows10`
99 |
100 | - [Win10安装 WSL Ubuntu](https://github.com/lan-tianxiang/jd_shell/wiki/Win10) 🔻
101 |
102 |
103 | ***
104 |
105 | ### [WIKI](https://github.com/lan-tianxiang/jd_shell/wiki/Instruction) 和各文件注释都含有大量教程,请自行翻阅❗❗
106 |
107 |
108 |
109 |
110 | ##### 小彩蛋
111 |
112 | ##### 默认隐藏,欢迎加入交流
113 |
118 |
119 |
120 |
121 | ## 更新日志
122 |
123 | > 只记录大的更新,小修小改不记录。
124 |
125 | 2021-04-01, 新增在线SHELL调试功能,具体查看WIKI,Docker用户不支持
126 |
127 | 2021-03-30, 修复Docker遗留的隐藏BUG,保持docker和linux修复脚本的一致
128 |
129 | 2021-03-29, 增加超时关闭,以防因网络等未知原因卡住而不断消耗系统资源(默认关闭)
130 |
131 | 2021-03-28, 自动配置并填写助力码,在config最后的专区内,无需人工干预(默认关闭)
132 |
133 | 2021-02-19,面板功能集成至jd.sh内,运行jd.sh会出现操作提示
134 |
135 | 2021-01-23,控制面板增加日志查看功能,Docker重启容器后可以使用`docker restart jd`,非Docker如果是pm2方式的请重启pm2进程`pm2 resatrt server.js`。
136 |
137 | 2020-01-21,增加shylocks/Loon脚本。
138 |
139 | 2021-01-15,如果本机上安装了pm2,则挂机程序以pm2启动,否则以nohup启动。
140 |
141 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:lts-alpine
2 | LABEL maintainer="LanTianXiang "
3 | ARG JD_BASE_URL=https://gitee.com/highdimen/jd_shell
4 | ARG JD_BASE_BRANCH=v3
5 | ARG JD_SCRIPTS_URL=https://gitee.com/highdimen/clone_scripts
6 | ARG JD_SCRIPTS_BRANCH=master
7 | ARG JD_SCRIPTS2_URL=https://gitee.com/highdimen/jd_scripts
8 | ARG JD_SCRIPTS2_BRANCH=master
9 | ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
10 | LANG=zh_CN.UTF-8 \
11 | SHELL=/bin/bash \
12 | PS1="\u@\h:\w \$ " \
13 | JD_DIR=/root/jd \
14 | ENABLE_HANGUP=true \
15 | ENABLE_WEB_PANEL=true
16 | RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
17 | && apk update -f \
18 | && apk upgrade \
19 | && apk --no-cache add -f bash \
20 | coreutils \
21 | moreutils \
22 | git \
23 | wget \
24 | curl \
25 | nano \
26 | tzdata \
27 | perl \
28 | openssl \
29 | && rm -rf /var/cache/apk/* \
30 | && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
31 | && echo "Asia/Shanghai" > /etc/timezone \
32 | && git clone -b ${JD_BASE_BRANCH} ${JD_BASE_URL} ${JD_DIR} \
33 | && cd ${JD_DIR}/panel \
34 | && npm install \
35 | && git clone -b ${JD_SCRIPTS_BRANCH} ${JD_SCRIPTS_URL} ${JD_DIR}/scripts \
36 | && cd ${JD_DIR}/scripts \
37 | && npm install \
38 | && npm install -g pm2 \
39 | && git clone -b ${JD_SCRIPTS2_BRANCH} ${JD_SCRIPTS2_URL} ${JD_DIR}/scripts2 \
40 | && rm -rf /root/.npm
41 | WORKDIR ${JD_DIR}
42 | ENTRYPOINT bash ${JD_DIR}/docker/docker-entrypoint.sh
43 |
--------------------------------------------------------------------------------
/docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.0"
2 | services:
3 | # 第1个容器
4 | jd1:
5 | image: lan-tianxiang/jd_shell:gitee # 如果要从gitee更新脚本,则为:lan-tianxiang/jd_shell:gitee
6 | container_name: jd1
7 | restart: always
8 | tty: true
9 | network_mode: "bridge"
10 | hostname: jd1
11 | volumes:
12 | - ./jd1/config:/jd/config
13 | - ./jd1/log:/jd/log
14 | - ./jd1/scripts:/jd/scripts # 如果想要看到lxk0301大佬的js脚本,以方便的添加额外脚本,可以解除本行注释,下同
15 | ports:
16 | - 5678:5678
17 | environment:
18 | - ENABLE_HANGUP=true # 是否在启动容器时自动启动挂机程序
19 | - ENABLE_WEB_PANEL=true # 是否在启动容器时自动启动控制面板
20 |
21 | # 第2个容器
22 | jd2:
23 | image: lan-tianxiang/jd_shell:gitee # 如果要从gitee更新脚本,则为:lan-tianxiang/jd_shell:gitee
24 | container_name: jd2
25 | restart: always
26 | tty: true
27 | network_mode: "bridge"
28 | hostname: jd2
29 | volumes:
30 | - ./jd2/config:/jd/config
31 | - ./jd2/log:/jd/log
32 | ports:
33 | - 5679:5678
34 | environment:
35 | - ENABLE_HANGUP=true # 是否在启动容器时自动启动挂机程序
36 | - ENABLE_WEB_PANEL=true # 是否在启动容器时自动启动控制面板
37 |
38 | # 第3个容器,以此类推
39 | jd3:
40 | image: lan-tianxiang/jd_shell:gitee # 如果要从gitee更新脚本,则为:lan-tianxiang/jd_shell:gitee
41 | container_name: jd3
42 | restart: always
43 | tty: true
44 | network_mode: "bridge"
45 | hostname: jd3
46 | volumes:
47 | - ./jd3/config:/jd/config
48 | - ./jd3/log:/jd/log
49 | ports:
50 | - 5680:5678
51 | environment:
52 | - ENABLE_HANGUP=true # 是否在启动容器时自动启动挂机程序
53 | - ENABLE_WEB_PANEL=true # 是否在启动容器时自动启动控制面板
54 |
--------------------------------------------------------------------------------
/docker/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | echo -e "======================1. 检测配置文件========================\n"
5 | [ ! -d ${JD_DIR}/config ] && mkdir -p ${JD_DIR}/config
6 |
7 | if [ ! -s ${JD_DIR}/config/crontab.list ]
8 | then
9 | echo -e "检测到config配置目录下不存在crontab.list或存在但文件为空,从示例文件复制一份用于初始化...\n"
10 | cp -fv ${JD_DIR}/sample/crontab.list.sample ${JD_DIR}/config/crontab.list
11 | sed -i "s,MY_PATH,${JD_DIR},g" ${JD_DIR}/config/crontab.list
12 | sed -i "s,ENV_PATH=,PATH=$PATH,g" ${JD_DIR}/config/crontab.list
13 | fi
14 |
15 | if [ ! -s ${JD_DIR}/config/config.sh ]; then
16 | echo -e "检测到config配置目录下不存在config.sh,从示例文件复制一份用于初始化...\n"
17 | cp -fv ${JD_DIR}/sample/config.sh.sample ${JD_DIR}/config/config.sh
18 | echo
19 | fi
20 |
21 | if [ ! -s ${JD_DIR}/config/auth.json ]; then
22 | echo -e "检测到config配置目录下不存在auth.json,从示例文件复制一份用于初始化...\n"
23 | cp -fv ${JD_DIR}/sample/auth.json ${JD_DIR}/config/auth.json
24 | echo
25 | fi
26 |
27 | echo -e "======================2. 更新源代码========================\n"
28 | bash ${JD_DIR}/git_pull.sh
29 | echo
30 |
31 |
32 | echo -e "========================3. 启动挂机程序========================\n"
33 | if [[ ${ENABLE_HANGUP} == true ]]; then
34 | . ${JD_DIR}/config/config.sh
35 | if [ -n "${Cookie1}" ]; then
36 | bash ${JD_DIR}/jd.sh hangup
37 | echo -e "挂机程序启动成功...\n"
38 | else
39 | echo -e "config.sh中还未填入有效的Cookie,可能是首次部署容器,因此不启动挂机程序...\n"
40 | fi
41 | elif [[ ${ENABLE_HANGUP} == false ]]; then
42 | echo -e "已设置为不自动启动挂机程序,跳过...\n"
43 | fi
44 |
45 | echo -e "========================4. 启动控制面板========================\n"
46 | if [[ ${ENABLE_WEB_PANEL} == true ]]; then
47 | bash ${JD_DIR}/jd.sh panelon
48 | echo -e "控制面板启动成功...\n"
49 | echo -e "如未修改用户名密码,则初始用户名为:admin,初始密码为:adminadmin\n"
50 | echo -e "请访问 http://:5678 登陆并修改配置...\n"
51 | elif [[ ${ENABLE_WEB_PANEL} == false ]]; then
52 | echo -e "已设置为不自动启动控制面板,跳过...\n"
53 | fi
54 | echo -e "容器启动成功...\n"
55 |
56 | crond -f
57 |
58 | exec "$@"
59 |
--------------------------------------------------------------------------------
/docker/proc_file.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "整理各个日志文件里面的互助码相关信息。。。"
4 | echo "==========================================================================="
5 | logdDir="/scripts/logs"
6 | sharecodeFile="${logdDir}/sharecode.log"
7 | jdzzFile="${logdDir}/jd_jdzz.log"
8 | jdfactoryFile="${logdDir}/jd_jdfactory.log"
9 | jxFactoryFile="${logdDir}/jd_dreamFactory.log"
10 | plantBean="${logdDir}/jd_plantBean.log"
11 | jdfruit="${logdDir}/jd_fruit.log"
12 | jdpet="${logdDir}/jd_pet.log"
13 | jdcrazyJoy="${logdDir}/jd_crazy_joy.log"
14 |
15 | sed -n '/京东赚赚好友互助码】.*/'p $jdzzFile | awk '{print $4,$5}' | sort | uniq >>$sharecodeFile
16 | echo "提取京东赚赚助力码完成"
17 |
18 | sed -n '/东东工厂好友互助码】.*/'p $jdfactoryFile | awk '{print $4,$5}' | sort | uniq >>$sharecodeFile
19 | echo "提取东东工厂助力码完成"
20 |
21 | sed -n '/京喜工厂好友互助码.*/'p $jxFactoryFile | awk '{print $4,$5}' | sort | uniq >>$sharecodeFile
22 | echo "提取京喜工厂助力码完成"
23 |
24 | sed -n '/京东种豆得豆好友互助码】.*/'p $plantBean | awk '{print $4,$5}' | sort | uniq >>$sharecodeFile
25 | echo "提取京东种豆助力码完成"
26 |
27 | sed -n '/东东农场好友互助码】.*/'p $jdfruit | awk '{print $4,$5}' | sort | uniq >>$sharecodeFile
28 | echo "提取京东农场助力码完成"
29 |
30 | sed -n '/东东萌宠好友互助码】.*/'p $jdpet | awk '{print $4,$5}' | sort | uniq >>$sharecodeFile
31 | echo "提取东东萌宠助力码完成"
32 |
33 | sed -n '/crazyJoy任务好友互助码】.*/'p $jdcrazyJoy | awk '{print $4,$5}' | sort | uniq >>$sharecodeFile
34 | echo "提取crazyJoy任务助力码完成"
35 |
36 | cp $sharecodeFile ${sharecodeFile}.tmp
37 | sed -i 's/ //' ${sharecodeFile}.tmp
38 | cat ${sharecodeFile}.tmp | sort | uniq >$sharecodeFile
39 | rm ${sharecodeFile}.tmp
40 | echo "互助码排序和去重完成"
41 |
42 | echo "==========================================================================="
43 | echo "整理完成,具体结果请查看${sharecodeFile}文件"
44 |
45 | echo "处理jd_crazy_joy_coin任务。。。"
46 | if [ ! $CRZAY_JOY_COIN_ENABLE ]; then
47 | echo "默认启用jd_crazy_joy_coin杀掉jd_crazy_joy_coin任务,并重启"
48 | eval $(ps -ef | grep "jd_crazy" | awk '{print "kill "$1}')
49 | echo '' >/scripts/logs/jd_crazy_joy_coin.log
50 | node /scripts/jd_crazy_joy_coin.js | ts >>/scripts/logs/jd_crazy_joy_coin.log 2>&1 &
51 | echo "默认jd_crazy_joy_coin重启完成"
52 | else
53 | if [ $CRZAY_JOY_COIN_ENABLE = "Y" ]; then
54 | echo "配置启用jd_crazy_joy_coin,杀掉jd_crazy_joy_coin任务,并重启"
55 | eval $(ps -ef | grep "jd_crazy" | awk '{print "kill "$1}')
56 | echo '' >/scripts/logs/jd_crazy_joy_coin.log
57 | node /scripts/jd_crazy_joy_coin.js | ts >>/scripts/logs/jd_crazy_joy_coin.log 2>&1 &
58 | echo "配置jd_crazy_joy_coin重启完成"
59 | else
60 | eval $(ps -ef | grep "jd_crazy" | awk '{print "kill "$1}')
61 | echo "已配置不启用jd_crazy_joy_coin任务,不处理"
62 | fi
63 | fi
64 |
--------------------------------------------------------------------------------
/export_sharecodes.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ## 路径、环境判断
4 | ShellDir=${JD_DIR:-$(
5 | cd $(dirname $0)
6 | pwd
7 | )}
8 | LogDir=${ShellDir}/log
9 | ConfigDir=${ShellDir}/config
10 | FileConf=${ConfigDir}/config.sh
11 | [[ ${ANDROID_RUNTIME_ROOT}${ANDROID_ROOT} ]] && Opt="P" || Opt="E"
12 | Tips="从日志中未找到任何互助码"
13 |
14 | ## 所有有互助码的活动,只需要把脚本名称去掉前缀 jd_ 后列在 Name1 中,将其中文名称列在 Name2 中,对应 config.sh 中互助码后缀列在 Name3 中即可。
15 | ## Name1、Name2 和 Name3 中的三个名称必须一一对应。
16 | Name1=(fruit pet plantBean dreamFactory jdfactory crazy_joy jdzz jxnc cash sgmh cfd carnivalcity health)
17 | Name2=(东东农场 东东萌宠 京东种豆得豆 京喜工厂 东东工厂 crazyJoy任务 京东赚赚 京喜农场 签到领现金 闪购盲盒 京喜财富岛 京东手机狂欢城 东东健康社区)
18 | Name3=(Fruit Pet Bean DreamFactory JdFactory Joy Jdzz Jxnc Cash Sgmh Cfd Carnivalcity Health)
19 |
20 | ## 导入 config.sh
21 | function Import_Conf() {
22 | if [ -f ${FileConf} ]; then
23 | . ${FileConf}
24 | if [ -z "${Cookie1}" ]; then
25 | echo -e "## 请先在 config.sh 中配置好 Cookie\n"
26 | exit 1
27 | fi
28 | else
29 | echo -e "## 配置文件 ${FileConf} 不存在,请先按教程配置好该文件\n"
30 | exit 1
31 | fi
32 | }
33 |
34 | ## 用户数量 UserSum
35 | function Count_UserSum() {
36 | for ((i = 1; i <= 1000; i++)); do
37 | Tmp=Cookie$i
38 | CookieTmp=${!Tmp}
39 | [[ ${CookieTmp} ]] && UserSum=$i || break
40 | done
41 | }
42 |
43 | ## 导出互助码的通用程序
44 | function Cat_Scodes() {
45 | if [ -d ${LogDir}/jd_$1 ] && [[ $(ls ${LogDir}/jd_$1) != "" ]]; then
46 | cd ${LogDir}/jd_$1
47 |
48 | ## 导出助力码变量(My)
49 | for log in $(ls -r); do
50 | case $# in
51 | 2)
52 | codes=$(cat ${log} | grep -${Opt} "开始【京东账号|您的(好友)?助力码为" | uniq | perl -0777 -pe "{s|\*||g; s|开始||g; s|\n您的(好友)?助力码为(:)?:?|:|g; s|,.+||g}" | sed -r "s/【京东账号/My$2/;s/】.*?:/='/;s/】.*?/='/;s/$/'/;s/\(每次运行都变化,不影响\)//")
53 | ;;
54 | 3)
55 | codes=$(grep -${Opt} $3 ${log} | uniq | sed -r "s/【京东账号/My$2/;s/(.*?】/='/;s/$/'/")
56 | ;;
57 | esac
58 | if [[ ${codes} ]]; then
59 | ## 添加判断,若未找到该用户互助码,则设置为空值
60 | for ((user_num = 1; user_num <= ${UserSum}; user_num++)); do
61 | echo -e "${codes}" | grep -${Opt}q "My$2${user_num}="
62 | if [ $? -eq 1 ]; then
63 | if [ $user_num == 1 ]; then
64 | codes=$(echo "${codes}" | sed -r "1i My${2}1=''")
65 | else
66 | codes=$(echo "${codes}" | sed -r "/My$2$(expr ${user_num} - 1)=/a\My$2${user_num}=''")
67 | fi
68 | fi
69 | done
70 | break
71 | fi
72 | done
73 |
74 | ## 导出为他人助力变量(ForOther)
75 | if [[ ${codes} ]]; then
76 | help_code=""
77 | for ((user_num = 1; user_num <= ${UserSum}; user_num++)); do
78 | echo -e "${codes}" | grep -${Opt}q "My$2${user_num}=''"
79 | if [ $? -eq 1 ]; then
80 | help_code=${help_code}"\${My"$2${user_num}"}@"
81 | fi
82 | done
83 | ## 生成互助规则模板
84 | for_other_codes=""
85 | case $HelpType in
86 | 0) ### 统一优先级助力模板
87 | new_code=$(echo ${help_code} | sed "s/@$//")
88 | for ((user_num = 1; user_num <= ${UserSum}; user_num++)); do
89 | if [ $user_num == 1 ]; then
90 | for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\""${new_code}"\"\n"
91 | else
92 | for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\"\${ForOther"${2}1"}\"\n"
93 | fi
94 | done
95 | ;;
96 | 1) ### 均匀助力模板
97 | for ((user_num = 1; user_num <= ${UserSum}; user_num++)); do
98 | echo ${help_code} | grep "\${My"$2${user_num}"}@" >/dev/null
99 | if [ $? -eq 0 ]; then
100 | left_str=$(echo ${help_code} | sed "s/\${My$2${user_num}}@/ /g" | awk '{print $1}')
101 | right_str=$(echo ${help_code} | sed "s/\${My$2${user_num}}@/ /g" | awk '{print $2}')
102 | mark="\${My$2${user_num}}@"
103 | else
104 | left_str=$(echo ${help_code} | sed "s/${mark}/ /g" | awk '{print $1}')${mark}
105 | right_str=$(echo ${help_code} | sed "s/${mark}/ /g" | awk '{print $2}')
106 | fi
107 | new_code=$(echo ${right_str}${left_str} | sed "s/@$//")
108 | for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\""${new_code}"\"\n"
109 | done
110 | ;;
111 | *) ### 普通优先级助力模板
112 | for ((user_num = 1; user_num <= ${UserSum}; user_num++)); do
113 | new_code=$(echo ${help_code} | sed "s/\${My"$2${user_num}"}@//;s/@$//")
114 | for_other_codes=${for_other_codes}"ForOther"$2${user_num}"=\""${new_code}"\"\n"
115 | done
116 | ;;
117 | esac
118 | echo -e "${codes}\n\n${for_other_codes}" | sed s/[[:space:]]//g
119 | else
120 | echo ${Tips}
121 | fi
122 | else
123 | echo "## 未运行过 jd_$1 脚本,未产生日志"
124 | fi
125 | }
126 |
127 | ## 汇总
128 | function Cat_All() {
129 | echo -e "\n# 从最后一个日志提取互助码,受日志内容影响,仅供参考。"
130 | echo -e "\n# 手动填写用法: 检查无误后,将以下内容直接复制到config.sh的最后面专区中!!!"
131 | echo -e "\n# 开启自动助力的用户请勿理会以上内容!!!"
132 | echo -e "\n################################"
133 | for ((i = 0; i < ${#Name1[*]}; i++)); do
134 | echo -e "\n# ${Name2[i]}:"
135 | [[ $(Cat_Scodes "${Name1[i]}" "${Name3[i]}" "的${Name2[i]}好友互助码") == ${Tips} ]] && Cat_Scodes "${Name1[i]}" "${Name3[i]}" || Cat_Scodes "${Name1[i]}" "${Name3[i]}" "的${Name2[i]}好友互助码"
136 | done
137 | }
138 |
139 | ## 执行并写入日志
140 | #LogTime=$(date "+%Y-%m-%d-%H-%M-%S")
141 | #LogFile="${LogDir}/export_sharecodes/${LogTime}.log"
142 | LogFile="${LogDir}/export_sharecodes/export_sharecodes.log"
143 | [ ! -d "${LogDir}/export_sharecodes" ] && mkdir -p ${LogDir}/export_sharecodes
144 | Import_Conf && Count_UserSum && Cat_All | perl -pe "{s|京东种豆|种豆|; s|crazyJoy任务|疯狂的JOY|}" | tee ${LogFile}
145 |
--------------------------------------------------------------------------------
/git_pull.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ## Author: lan-tianxiang
4 | ## Source: https://github.com/lan-tianxiang/jd_shell
5 | ## Modified: 2021-03-29
6 | ## Version: v3.6.3
7 |
8 | ## 文件路径、脚本网址、文件版本以及各种环境的判断
9 | ShellDir=${JD_DIR:-$(
10 | cd $(dirname $0)
11 | pwd
12 | )}
13 | [[ ${JD_DIR} ]] && ShellJd=${ShellDir}/jd.sh || ShellJd=${ShellDir}/jd.sh
14 | LogDir=${ShellDir}/log
15 | [ ! -d ${LogDir} ] && mkdir -p ${LogDir}
16 | ScriptsDir=${ShellDir}/scripts
17 | Scripts2Dir=${ShellDir}/.scripts2
18 | oldScripts2Dir=${ShellDir}/scripts2
19 | ConfigDir=${ShellDir}/config
20 | FileConf=${ConfigDir}/config.sh
21 | FileConftemp=${ConfigDir}/config.sh.temp
22 | FileDiy=${ConfigDir}/diy.sh
23 | FileDiySample=${ShellDir}/sample/diy.sh
24 | FileConfSample=${ShellDir}/sample/config.sh.sample
25 | ListCron=${ConfigDir}/crontab.list
26 | FileListCronSample=${ShellDir}/sample/crontab.list.sample
27 | ListCronLxk=${ScriptsDir}/docker/crontab_list.sh
28 | ListCronShylocks=${Scripts2Dir}/docker/crontab_list.sh
29 | ListTask=${LogDir}/task.list
30 | ListJs=${LogDir}/js.list
31 | ListJsAdd=${LogDir}/js-add.list
32 | ListJsDrop=${LogDir}/js-drop.list
33 | ContentVersion=${ShellDir}/version
34 | ContentNewTask=${ShellDir}/new_task
35 | ContentDropTask=${ShellDir}/drop_task
36 | SendCount=${ShellDir}/send_count
37 | isTermux=${ANDROID_RUNTIME_ROOT}${ANDROID_ROOT}
38 | WhichDep=$(grep "/jd_shell" "${ShellDir}/.git/config")
39 | Scripts2URL=https://gitee.com/highdimen/jd_scripts
40 | PanelDir=${ShellDir}/panel
41 | panelpwd=${ConfigDir}/auth.json
42 | panelpwdSample=${ShellDir}/sample/auth.json
43 |
44 | if [[ ${WhichDep} == *github* ]]; then
45 | ScriptsURL=https://gitee.com/highdimen/clone_scripts
46 | ShellURL=https://gitee.com/highdimen/jd_shell
47 | else
48 | ScriptsURL=https://gitee.com/highdimen/clone_scripts
49 | ShellURL=https://gitee.com/highdimen/jd_shell
50 | fi
51 |
52 | function SourceUrl_Update {
53 | if [ -s ${ScriptsDir}/.git/config ]; then
54 | strAttttt=$(grep "url" ${ScriptsDir}/.git/config)
55 | strBttttt="highdimen"
56 | if [[ $strAttttt =~ $strBttttt ]]; then
57 | echo "1"
58 | else
59 | rm -rf ${ScriptsDir}
60 | fi
61 | fi
62 |
63 | if [ -s ${Scripts2Dir}/.git/config ]; then
64 | strAttttt=$(grep "url" ${Scripts2Dir}/.git/config)
65 | strBttttt="highdimen"
66 | if [[ $strAttttt =~ $strBttttt ]]; then
67 | echo "1"
68 | else
69 | rm -rf ${ScriptsDir}
70 | fi
71 | fi
72 |
73 | strAttttt=$(grep "url" ${ShellDir}/.git/config)
74 | strBttttt="highdimen"
75 | if [[ $strAttttt =~ $strBttttt ]]; then
76 | echo "3"
77 | else
78 | perl -i -pe "s|url \= https\:\/\/github.com\/lan-tianxiang\/jd_shell|url \= https\:\/\/gitee.com\/highdimen\/jd_shell|g" ${ShellDir}/.git/config
79 | perl -i -pe "s|url \= https\:\/\/gitee.com\/tianxiang-lan\/jd_shell|url \= https\:\/\/gitee.com\/highdimen\/jd_shell|g" ${ShellDir}/.git/config
80 | perl -i -pe "s|url \= http\:\/\/github.com\/lan-tianxiang\/jd_shell|url \= https\:\/\/gitee.com\/highdimen\/jd_shell|g" ${ShellDir}/.git/config
81 | perl -i -pe "s|url \= http\:\/\/gitee.com\/tianxiang-lan\/jd_shell|url \= https\:\/\/gitee.com\/highdimen\/jd_shell|g" ${ShellDir}/.git/config
82 | # sed -i "s/url \= https\:\/\/github.com\/lan-tianxiang\/jd_shell/url \= https\:\/\/gitee.com\/highdimen\/jd_shell/g" ${ShellDir}/.git/config
83 | # sed -i "s/url \= https\:\/\/gitee.com\/tianxiang-lan\/jd_shell/url \= https\:\/\/gitee.com\/highdimen\/jd_shell/g" ${ShellDir}/.git/config
84 | fi
85 | }
86 |
87 | fix_config() {
88 | #crontab -r
89 | #rm -rf ${ListCron}
90 | #cp -f $FileListCronSample $ListCron
91 | perl -i -pe "{
92 | s|.+(jd(\.sh)? jd_zoo)|0 \*\/2 \* \* \* \1|g;
93 | s|.+(jd(\.sh)? jd_zooCollect)|20,40 \* \* \* \* \1|g;
94 | }" ${ListCron}
95 | crontab ${ListCron}
96 | }
97 |
98 | fix_files() {
99 | [ ! -d ${ShellDir}/config ] && mkdir -p ${ShellDir}/config
100 | [ -d $oldScripts2Dir ] && rm -rf $oldScripts2Dir
101 | [ ! -f $FileConf ] && cp -f $FileConfSample $FileConf
102 | [ ! -f $ListCron ] && cp -f $FileListCronSample $ListCron
103 | [ ! -f $FileDiy ] && cp -f $FileDiySample $FileDiy
104 | }
105 |
106 | ## 更新crontab,gitee服务器同一时间限制5个链接,因此每个人更新代码必须错开时间,每次执行git_pull随机生成。
107 | ## 每天次数随机,更新时间随机,更新秒数随机,至少6次,至多12次,大部分为8-10次,符合正态分布。
108 | function Update_Cron() {
109 | if [ -f ${ListCron} ]; then
110 | local random_min=$((${RANDOM} % 60))
111 | local random_sleep=$((${RANDOM} % 100))
112 | local random_hour_array[0]=$((${RANDOM} % 3))
113 | local random_hour=${random_hour_array[0]}
114 | local i j tmp
115 |
116 | for ((i = 1; i < 14; i++)); do
117 | j=$(($i - 1))
118 | tmp=$(($((${RANDOM} % 3)) + ${random_hour_array[j]} + 4))
119 | [[ $tmp -lt 24 ]] && random_hour_array[i]=$tmp || break
120 | done
121 |
122 | for ((i = 1; i < ${#random_hour_array[*]}; i++)); do
123 | random_hour="$random_hour,${random_hour_array[i]}"
124 | done
125 | perl -i -pe "s|.+(bash.+git_pull.+log.*)|22,44 \* \* \* \* sleep ${random_sleep} && \1|" ${ListCron}
126 | crontab ${ListCron}
127 | fi
128 | }
129 |
130 | ## 更新shell脚本
131 | function Git_PullShell {
132 | echo -e "更新shell脚本,原地址:${ShellURL}\n"
133 | cd ${ShellDir}
134 | git fetch --all
135 | ExitStatusShell=$?
136 | git reset --hard origin/v3
137 | }
138 |
139 | ## 克隆scripts
140 | function Git_CloneScripts {
141 | echo -e "克隆LXK9301脚本,原地址:${ScriptsURL}\n"
142 | git clone -b master ${ScriptsURL} ${ScriptsDir}
143 | ExitStatusScripts=$?
144 | echo
145 | }
146 |
147 | ## 更新scripts
148 | function Git_PullScripts {
149 | echo -e "更新LXK9301脚本,原地址:${ScriptsURL}\n"
150 | cd ${ScriptsDir}
151 | git fetch --all
152 | ExitStatusScripts=$?
153 | git reset --hard origin/master
154 | echo
155 | }
156 |
157 | ## 克隆scripts2
158 | function Git_CloneScripts2 {
159 | git clone -b master ${Scripts2URL} ${Scripts2Dir} >/dev/null 2>&1
160 | ExitStatusScripts2=$?
161 | }
162 |
163 | ## 更新scripts2
164 | function Git_PullScripts2 {
165 | cd ${Scripts2Dir}
166 | git fetch --all >/dev/null 2>&1
167 | ExitStatusScripts2=$?
168 | git reset --hard origin/master >/dev/null 2>&1
169 | }
170 |
171 | ## 用户数量UserSum
172 | function Count_UserSum {
173 | i=1
174 | while [ $i -le 1000 ]; do
175 | Tmp=Cookie$i
176 | CookieTmp=${!Tmp}
177 | [[ ${CookieTmp} ]] && UserSum=$i || break
178 | let i++
179 | done
180 | }
181 |
182 | ## 把config.sh中提供的所有账户的PIN附加在jd_joy_run.js中,让各账户相互进行宠汪汪赛跑助力
183 | ## 你的账号将按Cookie顺序被优先助力,助力完成再助力我的账号和lxk0301大佬的账号
184 | function Change_JoyRunPins {
185 | j=${UserSum}
186 | PinALL=""
187 | while [[ $j -ge 1 ]]; do
188 | Tmp=Cookie$j
189 | CookieTemp=${!Tmp}
190 | PinTemp=$(echo ${CookieTemp} | perl -pe "{s|.*pt_pin=(.+);|\1|; s|%|\\\x|g}")
191 | PinTempFormat=$(printf ${PinTemp})
192 | PinALL="${PinTempFormat},${PinALL}"
193 | let j--
194 | done
195 | PinEvine="jd_620b506d07889,"
196 | PinALL="${PinALL}${PinEvine}"
197 | perl -i -pe "{s|(let invite_pins = \[\")(.+\"\];?)|\1${PinALL}\2|; s|(let run_pins = \[\")(.+\"\];?)|\1${PinALL}\2|}" ${ScriptsDir}/jd_joy_run.js
198 | }
199 |
200 | ## 修改lxk0301大佬js文件的函数汇总
201 | function Change_ALL {
202 | if [ -f ${FileConf} ]; then
203 | . ${FileConf}
204 | if [ -n "${Cookie1}" ]; then
205 | Count_UserSum
206 | Change_JoyRunPins
207 | fi
208 | fi
209 | }
210 |
211 | ## 检测文件:LXK9301/jd_scripts 仓库中的 docker/crontab_list.sh,和 shylocks/Loon 仓库中的 docker/crontab_list.sh
212 | ## 检测定时任务是否有变化,此函数会在Log文件夹下生成四个文件,分别为:
213 | ## task.list crontab.list中的所有任务清单,仅保留脚本名
214 | ## js.list 上述检测文件中用来运行js脚本的清单(去掉后缀.js,非运行脚本的不会包括在内)
215 | ## js-add.list 如果上述检测文件增加了定时任务,这个文件内容将不为空
216 | ## js-drop.list 如果上述检测文件删除了定时任务,这个文件内容将不为空
217 | function Diff_Cron {
218 | if [ -f ${ListCron} ]; then
219 | if [ -n "${JD_DIR}" ]; then
220 | grep -E " j[drx]_\w+" ${ListCron} | perl -pe "s|.+ (j[drx]_\w+).*|\1|" | uniq | sort >${ListTask}
221 | else
222 | grep "${ShellDir}/" ${ListCron} | grep -E " j[drx]_\w+" | perl -pe "s|.+ (j[drx]_\w+).*|\1|" | uniq | sort >${ListTask}
223 | fi
224 | cat ${ListCronLxk} ${ListCronShylocks} | grep -E "j[drx]_\w+\.js" | perl -pe "s|.+(j[drx]_\w+)\.js.+|\1|" | sort >${ListJs}
225 | grep -vwf ${ListTask} ${ListJs} >${ListJsAdd}
226 | grep -vwf ${ListJs} ${ListTask} >${ListJsDrop}
227 | else
228 | echo -e "${ListCron} 文件不存在,请先定义你自己的crontab.list...\n"
229 | fi
230 | }
231 |
232 | ## 发送删除失效定时任务的消息
233 | function Notify_DropTask {
234 | cd ${ShellDir}
235 | node update.js
236 | [ -f ${ContentDropTask} ] && rm -f ${ContentDropTask}
237 | }
238 |
239 | ## 发送新的定时任务消息
240 | function Notify_NewTask {
241 | cd ${ShellDir}
242 | node update.js
243 | [ -f ${ContentNewTask} ] && rm -f ${ContentNewTask}
244 | }
245 |
246 | ## 检测配置文件版本
247 | function Notify_Version {
248 | ## 识别出两个文件的版本号
249 | VerConfSample=$(grep " Version: " ${FileConfSample} | perl -pe "s|.+v((\d+\.?){3})|\1|")
250 | [ -f ${FileConf} ] && VerConf=$(grep " Version: " ${FileConf} | perl -pe "s|.+v((\d+\.?){3})|\1|")
251 |
252 | ## 删除旧的发送记录文件
253 | [ -f "${SendCount}" ] && [[ $(cat ${SendCount}) != ${VerConfSample} ]] && rm -f ${SendCount}
254 |
255 | ## 识别出更新日期和更新内容
256 | UpdateDate=$(grep " Date: " ${FileConfSample} | awk -F ": " '{print $2}')
257 | UpdateContent=$(grep " Update Content: " ${FileConfSample} | awk -F ": " '{print $2}')
258 |
259 | ## 如果是今天,并且版本号不一致,则发送通知
260 | if [ -f ${FileConf} ] && [[ "${VerConf}" != "${VerConfSample}" ]] && [[ ${UpdateDate} == $(date "+%Y-%m-%d") ]]; then
261 | if [ ! -f ${SendCount} ]; then
262 | echo -e "日期: ${UpdateDate}\n版本: ${VerConf} -> ${VerConfSample}\n内容: ${UpdateContent}\n\n" | tee ${ContentVersion}
263 | echo -e "如需更新请手动操作,仅更新当天通知一次!" >>${ContentVersion}
264 | cd ${ShellDir}
265 | node update.js
266 | if [ $? -eq 0 ]; then
267 | echo "${VerConfSample}" >${SendCount}
268 | [ -f ${ContentVersion} ] && rm -f ${ContentVersion}
269 | fi
270 | fi
271 | else
272 | [ -f ${ContentVersion} ] && rm -f ${ContentVersion}
273 | [ -f ${SendCount} ] && rm -f ${SendCount}
274 | fi
275 | }
276 |
277 | ## npm install 子程序,判断是否为安卓,判断是否安装有yarn
278 | function Npm_InstallSub {
279 | if [ -n "${isTermux}" ]; then
280 | npm install --no-bin-links || npm install --no-bin-links --registry=https://registry.npm.taobao.org
281 | elif ! type yarn >/dev/null 2>&1; then
282 | npm install || npm install --registry=https://registry.npm.taobao.org
283 | else
284 | echo -e "检测到本机安装了 yarn,使用 yarn 替代 npm...\n"
285 | yarn install || yarn install --registry=https://registry.npm.taobao.org
286 | fi
287 | }
288 |
289 | ## npm install
290 | function Npm_Install {
291 | cd ${ScriptsDir}
292 | if [[ "${PackageListOld}" != "$(cat package.json)" ]]; then
293 | echo -e "检测到package.json有变化,运行 npm install...\n"
294 | Npm_InstallSub
295 | if [ $? -ne 0 ]; then
296 | echo -e "\nnpm install 运行不成功,自动删除 ${ScriptsDir}/node_modules 后再次尝试一遍..."
297 | rm -rf ${ScriptsDir}/node_modules
298 | fi
299 | echo
300 | fi
301 |
302 | if [ ! -d ${ScriptsDir}/node_modules ]; then
303 | echo -e "运行 npm install...\n"
304 | Npm_InstallSub
305 | if [ $? -ne 0 ]; then
306 | echo -e "\nnpm install 运行不成功,自动删除 ${ScriptsDir}/node_modules...\n"
307 | echo -e "请进入 ${ScriptsDir} 目录后按照wiki教程手动运行 npm install...\n"
308 | echo -e "当 npm install 失败时,如果检测到有新任务或失效任务,只会输出日志,不会自动增加或删除定时任务...\n"
309 | echo -e "3...\n"
310 | sleep 1
311 | echo -e "2...\n"
312 | sleep 1
313 | echo -e "1...\n"
314 | sleep 1
315 | rm -rf ${ScriptsDir}/node_modules
316 | fi
317 | fi
318 | }
319 |
320 | ## 输出是否有新的定时任务
321 | function Output_ListJsAdd {
322 | if [ -s ${ListJsAdd} ]; then
323 | echo -e "检测到有新的定时任务:\n"
324 | cat ${ListJsAdd}
325 | echo
326 | fi
327 | }
328 |
329 | ## 输出是否有失效的定时任务
330 | function Output_ListJsDrop {
331 | if [ ${ExitStatusScripts} -eq 0 ] && [ -s ${ListJsDrop} ]; then
332 | echo -e "检测到有失效的定时任务:\n"
333 | cat ${ListJsDrop}
334 | echo
335 | fi
336 | }
337 |
338 | ## 自动删除失效的脚本与定时任务,需要5个条件:1.AutoDelCron 设置为 true;2.正常更新js脚本,没有报错;3.js-drop.list不为空;4.crontab.list存在并且不为空;5.已经正常运行过npm install
339 | ## 检测文件:LXK9301/jd_scripts 仓库中的 docker/crontab_list.sh,和 shylocks/Loon 仓库中的 docker/crontab_list.sh
340 | ## 如果检测到某个定时任务在上述检测文件中已删除,那么在本地也删除对应定时任务
341 | function Del_Cron {
342 | if [ "${AutoDelCron}" = "true" ] && [ -s ${ListJsDrop} ] && [ -s ${ListCron} ] && [ -d ${ScriptsDir}/node_modules ]; then
343 | echo -e "开始尝试自动删除定时任务如下:\n"
344 | cat ${ListJsDrop}
345 | echo
346 | JsDrop=$(cat ${ListJsDrop})
347 | for Cron in ${JsDrop}; do
348 | perl -i -ne "{print unless / ${Cron}( |$)/}" ${ListCron}
349 | done
350 | crontab ${ListCron}
351 | echo -e "成功删除失效的脚本与定时任务,当前的定时任务清单如下:\n\n--------------------------------------------------------------\n"
352 | crontab -l
353 | echo -e "\n--------------------------------------------------------------\n"
354 | if [ -d ${ScriptsDir}/node_modules ]; then
355 | echo -e "jd-base脚本成功删除失效的定时任务:\n\n${JsDrop}\n\n脚本地址:${ShellURL}" >${ContentDropTask}
356 | Notify_DropTask
357 | fi
358 | fi
359 | }
360 |
361 | ## 自动增加新的定时任务,需要5个条件:1.AutoAddCron 设置为 true;2.正常更新js脚本,没有报错;3.js-add.list不为空;4.crontab.list存在并且不为空;5.已经正常运行过npm install
362 | ## 检测文件:LXK9301/jd_scripts 仓库中的 docker/crontab_list.sh,和 shylocks/Loon 仓库中的 docker/crontab_list.sh
363 | ## 如果检测到检测文件中增加新的定时任务,那么在本地也增加
364 | ## 本功能生效时,会自动从检测文件新增加的任务中读取时间,该时间为北京时间
365 | function Add_Cron {
366 | if [ "${AutoAddCron}" = "true" ] && [ -s ${ListJsAdd} ] && [ -s ${ListCron} ] && [ -d ${ScriptsDir}/node_modules ]; then
367 | echo -e "开始尝试自动添加定时任务如下:\n"
368 | cat ${ListJsAdd}
369 | echo
370 | JsAdd=$(cat ${ListJsAdd})
371 |
372 | for Cron in ${JsAdd}; do
373 | if [[ ${Cron} == jd_bean_sign ]]; then
374 | echo "4 0,9 * * * bash ${ShellJd} ${Cron}" >>${ListCron}
375 | else
376 | cat ${ListCronLxk} ${ListCronShylocks} | grep -E "\/${Cron}\." | perl -pe "s|(^.+)node */scripts/(j[drx]_\w+)\.js.+|\1bash ${ShellJd} \2|" >>${ListCron}
377 | fi
378 | done
379 |
380 | if [ $? -eq 0 ]; then
381 | crontab ${ListCron}
382 | echo -e "成功添加新的定时任务,当前的定时任务清单如下:\n\n--------------------------------------------------------------\n"
383 | crontab -l
384 | echo -e "\n--------------------------------------------------------------\n"
385 | if [ -d ${ScriptsDir}/node_modules ]; then
386 | echo -e "jd-base脚本成功添加新的定时任务:\n\n${JsAdd}\n\n脚本地址:${ShellURL}" >${ContentNewTask}
387 | Notify_NewTask
388 | fi
389 | else
390 | echo -e "添加新的定时任务出错,请手动添加...\n"
391 | if [ -d ${ScriptsDir}/node_modules ]; then
392 | echo -e "jd-base脚本尝试自动添加以下新的定时任务出错,请手动添加:\n\n${JsAdd}" >${ContentNewTask}
393 | Notify_NewTask
394 | fi
395 | fi
396 | fi
397 | }
398 |
399 | ## 自定义脚本功能
400 | function ExtraShell() {
401 | ## 自动同步用户自定义的diy.sh
402 | if [[ ${EnableExtraShellUpdate} == true ]]; then
403 | wget -q $EnableExtraShellURL -O ${FileDiy}
404 | if [ $? -eq 0 ]; then
405 | echo -e "自定义 DIY 脚本同步完成......"
406 | echo -e ''
407 | sleep 2s
408 | else
409 | echo -e "\033[31m自定义 DIY 脚本同步失败!\033[0m"
410 | echo -e ''
411 | sleep 2s
412 | fi
413 | fi
414 |
415 | ## 调用用户自定义的diy.sh
416 | if [[ ${EnableExtraShell} == true ]]; then
417 | if [ -f ${FileDiy} ]; then
418 | . ${FileDiy}
419 | else
420 | echo -e "${FileDiy} 文件不存在,跳过执行自定义 DIY 脚本...\n"
421 | echo -e ''
422 | fi
423 | fi
424 | }
425 |
426 | ## 一键执行所有活动脚本
427 | function Run_All() {
428 | ## 临时删除以旧版脚本
429 | rm -rf ${ShellDir}/run-all.sh
430 | ## 默认将 "jd、jx、jr" 开头的活动脚本加入其中
431 | rm -rf ${ShellDir}/run_all.sh
432 | bash ${ShellDir}/jd.sh | grep -io 'j[drx]_[a-z].*' | grep -v 'bean_change' >${ShellDir}/run_all.sh
433 | sed -i "1i\jd_bean_change.js" ${ShellDir}/run_all.sh ## 置顶京豆变动通知
434 | sed -i "s#^#bash ${ShellDir}/jd.sh g" ${ShellDir}/run_all.sh
435 | sed -i 's#.js# now#g' ${ShellDir}/run_all.sh
436 | sed -i '1i\#!/bin/env bash' ${ShellDir}/run_all.sh
437 | ## 自定义添加脚本
438 | ## 例:echo "bash ${ShellDir}/jd.sh xxx now" >>${ShellDir}/run_all.sh
439 |
440 | ## 将挂机活动移至末尾从而最后执行
441 | ## 目前仅有 "疯狂的JOY" 这一个活动
442 | ## 模板如下 :
443 | ## cat run_all.sh | grep xxx -wq
444 | ## if [ $? -eq 0 ];then
445 | ## sed -i '/xxx/d' ${ShellDir}/run_all.sh
446 | ## echo "bash jd.sh xxx now" >>${ShellDir}/run_all.sh
447 | ## fi
448 | cat ${ShellDir}/run_all.sh | grep jd_crazy_joy_coin -wq
449 | if [ $? -eq 0 ]; then
450 | sed -i '/jd_crazy_joy_coin/d' ${ShellDir}/run_all.sh
451 | echo "bash ${ShellDir}/jd.sh jd_crazy_joy_coin now" >>${ShellDir}/run_all.sh
452 | fi
453 |
454 | ## 去除不想加入到此脚本中的活动
455 | ## 例:sed -i '/xxx/d' ${ShellDir}/run_all.sh
456 | sed -i '/jd_delCoupon/d' ${ShellDir}/run_all.sh ## 不执行 "京东家庭号" 活动
457 | sed -i '/jd_family/d' ${ShellDir}/run_all.sh ## 不执行 "删除优惠券" 活动
458 | sed -i '/jd_exit/d' ${ShellDir}/run_all.sh ## 不执行 "删除优惠券" 活动
459 |
460 | ## 去除脚本中的空行
461 | sed -i '/^\s*$/d' ${ShellDir}/run_all.sh
462 | ## 赋权
463 | chmod 777 ${ShellDir}/run_all.sh
464 | }
465 |
466 | function panelinit {
467 | [ -f ${PanelDir}/package.json ] && PackageListOld=$(cat ${PanelDir}/package.json)
468 | cd ${PanelDir}
469 | if [[ "${PackageListOld}" != "$(cat package.json)" ]]; then
470 | echo -e "检测到package.json有变化,运行 npm install...\n"
471 | Npm_InstallSub
472 | if [ $? -ne 0 ]; then
473 | echo -e "\nnpm install 运行不成功,自动删除 ${ScriptsDir}/node_modules 后再次尝试一遍..."
474 | rm -rf ${PanelDir}/node_modules
475 | fi
476 | echo
477 | fi
478 |
479 | if [ ! -d ${PanelDir}/node_modules ]; then
480 | echo -e "运行 npm install...\n"
481 | Npm_InstallSub
482 | if [ $? -ne 0 ]; then
483 | echo -e "\nnpm install 运行不成功,自动删除 ${ScriptsDir}/node_modules...\n"
484 | echo -e "请进入 ${ScriptsDir} 目录后按照wiki教程手动运行 npm install...\n"
485 | echo -e "当 npm install 失败时,如果检测到有新任务或失效任务,只会输出日志,不会自动增加或删除定时任务...\n"
486 | echo -e "3...\n"
487 | sleep 1
488 | echo -e "2...\n"
489 | sleep 1
490 | echo -e "1...\n"
491 | sleep 1
492 | rm -rf ${PanelDir}/node_modules
493 | fi
494 | fi
495 | echo -e "控制面板检查&更新完成"
496 | sleep 1
497 | if [ ! -s ${panelpwd} ]; then
498 | cp -f ${panelpwdSample} ${panelpwd}
499 | echo -e "检测到未设置密码,用户名:admin,密码:adminadmin\n"
500 | fi
501 | }
502 |
503 | ## 在日志中记录时间与路径
504 | echo -e ''
505 | echo -e "+----------------- 开 始 执 行 更 新 脚 本 -----------------+"
506 | echo -e ''
507 | echo -e " 活动脚本目录:${ScriptsDir}"
508 | echo -e ''
509 | echo -e " 当前系统时间:$(date "+%Y-%m-%d %H:%M")"
510 | echo -e ''
511 | echo -e "+-----------------------------------------------------------+"
512 | ## 检测配置文件链接
513 | SourceUrl_Update
514 | fix_files
515 | ## 更新shell脚本、检测配置文件版本并将sample/config.sh.sample复制到config目录下
516 | Git_PullShell && Update_Cron
517 | VerConfSample=$(grep " Version: " ${FileConfSample} | perl -pe "s|.+v((\d+\.?){3})|\1|")
518 | [ -f ${FileConf} ] && VerConf=$(grep " Version: " ${FileConf} | perl -pe "s|.+v((\d+\.?){3})|\1|")
519 | if [ ${ExitStatusShell} -eq 0 ]; then
520 | echo -e "\nshell脚本更新完成...\n"
521 | if [ -n "${JD_DIR}" ] && [ -d ${ConfigDir} ]; then
522 | cp -f ${FileConfSample} ${ConfigDir}/config.sh.sample
523 | fi
524 | else
525 | echo -e "\nshell脚本更新失败,请检查原因后再次运行git_pull.sh,或等待定时任务自动再次运行git_pull.sh...\n"
526 | fi
527 |
528 | ## 克隆或更新js脚本
529 | if [ ${ExitStatusShell} -eq 0 ]; then
530 | echo -e "--------------------------------------------------------------\n"
531 | [ -f ${ScriptsDir}/package.json ] && PackageListOld=$(cat ${ScriptsDir}/package.json)
532 | [ -d ${ScriptsDir}/.git ] && Git_PullScripts || Git_CloneScripts
533 | #测试自写脚本
534 | [ -d ${Scripts2Dir}/.git ] && Git_PullScripts2 || Git_CloneScripts2
535 | cp -f ${Scripts2Dir}/jd_*.js ${ScriptsDir}
536 | [ -f ${Scripts2Dir}/ZooFaker.js ] && cp -f ${Scripts2Dir}/ZooFaker.js ${ScriptsDir}
537 | cp -rf ${Scripts2Dir}/sendNotify.js ${ScriptsDir}/sendNotify.js
538 | fi
539 |
540 | ## 执行各函数
541 | if [[ ${ExitStatusScripts} -eq 0 ]]; then
542 | Change_ALL
543 | [ -d ${ScriptsDir}/node_modules ] && Notify_Version
544 | Diff_Cron
545 | Npm_Install
546 | Output_ListJsAdd
547 | Output_ListJsDrop
548 | Del_Cron
549 | Add_Cron
550 | ExtraShell
551 | Run_All
552 | panelinit
553 | echo -e "活动脚本更新完成......\n"
554 | else
555 | echo -e "\033[31m活动脚本更新失败,请检查原因或再次运行 git_pull.sh ......\033[0m"
556 | Change_ALL
557 | fi
558 |
559 | #fix_config
560 | ## 清除配置缓存
561 | [ -f ${FileConftemp} ] && rm -rf ${FileConftemp}
562 |
563 | echo -e "脚本目录:${ShellDir}"
564 |
--------------------------------------------------------------------------------
/install_scripts/docker_install_jd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # 以 Docker 容器的方式一键安装 jd-base。
4 | #
5 | clear
6 |
7 | DockerImage="lantianxiang1/jd_shell:v3"
8 | ShellName=$0
9 | ShellDir=$(cd "$(dirname "$0")";pwd)
10 | ContainerName=""
11 | PanelPort=""
12 | WorkDir="${ShellDir}/jd-docker-workdir"
13 | JdDir=""
14 | ConfigDir=""
15 | LogDir=""
16 | ScriptsDir=""
17 |
18 | GetImageType="Online"
19 | HasImage=false
20 | NewImage=true
21 | DelContainer=false
22 |
23 | NeedDirConfig=""
24 | NeedDirLog=""
25 | NeedDirScripts=""
26 |
27 | log() {
28 | echo -e "\e[32m$1 \e[0m"
29 | }
30 |
31 | inp() {
32 | echo -e "\e[33m$1 \e[0m"
33 | }
34 |
35 | warn() {
36 | echo -e "\e[31m$1 \e[0m"
37 | }
38 |
39 |
40 | # 检查 Docker 环境
41 | Install_Docker() {
42 | if [ -x "$(command -v docker)" ]; then
43 | log "Docker 已安装!"
44 | else
45 | warn "请自行安装好 Docker !"
46 | exit 1
47 | fi
48 | }
49 | Install_Docker
50 |
51 | warn "\n注意如果你什么都不清楚,建议所有选项都直接回车,使用默认选择!!!\n"
52 |
53 | #
54 | # 收集配置信息
55 | #
56 |
57 | # 选择镜像获取方式
58 | Choose_GetImageType() {
59 | inp "\n选择镜像获取方式:\n1) 在线获取[默认]\n2 本地生成) "
60 | echo -n -e "\e[33m输入您的选择->\e[0m"
61 | read update
62 | if [ "$update" = "2" ]; then
63 | GetImageType="Local"
64 | fi
65 | }
66 |
67 | # 检测镜像是否存在
68 | Check_Image() {
69 | if [ ! -z "$(docker images -q $DockerImage 2> /dev/null)" ]; then
70 | HasImage=true
71 | inp "检测到先前已经存在的镜像,是否创建新的镜像:\n1) 是[默认]\n2) 不需要"
72 | echo -n -e "\e[33m输入您的选择->\e[0m"
73 | read update
74 | if [ "$update" = "2" ]; then
75 | NewImage=false
76 | else
77 | Choose_GetImageType
78 | fi
79 | else
80 | Choose_GetImageType
81 | fi
82 | }
83 | Check_Image
84 |
85 | # 检测容器是否存在
86 | Check_ContainerName() {
87 | if [ ! -z "$(docker ps -a --format "{{.Names}}" | grep -w $ContainerName 2> /dev/null)" ]; then
88 | inp "\n检测到先前已经存在的容器,是否删除先前的容器:\n1) 是[默认]\n2) 不要"
89 | echo -n -e "\e[33m输入您的选择->\e[0m"
90 | read update
91 | if [ "$update" = "2" ]; then
92 | log "选择了不删除先前的容器,需要重新输入容器名称"
93 | Input_ContainerName
94 | else
95 | DelContainer=true
96 | fi
97 | fi
98 | }
99 |
100 | # 输入容器名称
101 | Input_ContainerName() {
102 | echo -n -e "\n\e[33m请输入要创建的Docker容器名称[默认为:jd]->\e[0m"
103 | read container_name
104 | if [ -z "$container_name" ]; then
105 | ContainerName="jd"
106 | else
107 | ContainerName=$container_name
108 | fi
109 | Check_ContainerName
110 | }
111 | Input_ContainerName
112 |
113 | # 输入端口号
114 | Input_PanelPort() {
115 | echo -n -e "\n\e[33m请输入控制面板端口号[默认为:5678]->\e[0m"
116 | read panel_port
117 | if [ -z "$panel_port" ]; then
118 | PanelPort="5678"
119 | else
120 | PanelPort=$panel_port
121 | fi
122 | inp "如发现端口冲突,请自行检查端口占用情况!"
123 | }
124 | Input_PanelPort
125 |
126 | # 配置文件目录
127 |
128 | Need_ConfigDir() {
129 | inp "\n是否需要映射配置文件目录:\n1) 是[默认]\n2) 否"
130 | echo -n -e "\e[33m输入您的选择->\e[0m"
131 | read need_config_dir
132 | if [ "$need_config_dir" = "2" ]; then
133 | NeedDirConfig=''
134 | else
135 | NeedDirConfig="-v $ConfigDir:/root/jd/config"
136 | echo -e "\n\e[33m如果有用于存放配置文件的远程 Git 仓库,请输入地址,否则直接回车(看不懂也回车):\e[0m"
137 | read remote_config
138 | if [ -n "$remote_config" ]; then
139 | git clone $remote_config ${JdDir}/config
140 | else
141 | mkdir -p $ConfigDir
142 | fi
143 | fi
144 | }
145 |
146 | Need_LogDir() {
147 | inp "\n是否需要映射日志文件目录:\n1) 是[默认]\n2) 否"
148 | echo -n -e "\e[33m输入您的选择->\e[0m"
149 | read need_log_dir
150 | if [ "$need_log_dir" = "2" ]; then
151 | NeedDirLog=''
152 | else
153 | NeedDirLog="-v $LogDir:/root/jd/log"
154 | mkdir -p $LogDir
155 | fi
156 | }
157 |
158 | Need_ScriptsDir() {
159 | inp "\n是否需要映射js脚本目录:\n1) 是\n2) 否[默认]"
160 | echo -n -e "\e[33m输入您的选择->\e[0m"
161 | read need_scripts_dir
162 | if [ "$need_scripts_dir" = "1" ]; then
163 | NeedDirScripts="-v $ScriptsDir:/root/jd/scripts"
164 | mkdir -p $ScriptsDir
165 | fi
166 | }
167 |
168 | Need_Dir() {
169 | inp "\n是否需要映射文件目录:\n1) 是[默认]\n2) 否"
170 | echo -n -e "\e[33m输入您的选择->\e[0m"
171 | read need_dir
172 | if [ "$need_dir" = "2" ]; then
173 | log "选择了不映射文件目录"
174 | else
175 | echo -e "\n\e[33m请输入配置文件保存的绝对路径,直接回车为 $ShellDir/jd-docker :\e[0m"
176 | read jd_dir
177 | if [ -z "$jd_dir" ]; then
178 | JdDir=$ShellDir/jd-docker
179 | else
180 | JdDir=$jd_dir
181 | fi
182 | ConfigDir=$JdDir/config
183 | LogDir=$JdDir/log
184 | ScriptsDir=$JdDir/scripts
185 | Need_ConfigDir
186 | Need_LogDir
187 | Need_ScriptsDir
188 | fi
189 | }
190 | Need_Dir
191 |
192 | #
193 | # 配置信息收集完成,开始安装
194 | #
195 |
196 | if [ $NewImage = true ]; then
197 | log "\n正在获取新镜像..."
198 | if [ $HasImage = true ]; then
199 | docker stop jd
200 | docker rm jd
201 | docker rmi $(docker images lantianxiang1/jd_shell -q) -f
202 | # docker image rm -f $DockerImage
203 | fi
204 | if [ $GetImageType = "Local" ]; then
205 | rm -fr $WorkDir
206 | mkdir -p $WorkDir
207 | wget -q https://cdn.jsdelivr.net/gh/lan-tianxiang/jd_shell/docker/Dockerfile -O $WorkDir/Dockerfile
208 | sed -i 's,github.com,github.com.cnpmjs.org,g' $WorkDir/Dockerfile
209 | sed -i 's,npm install,npm install --registry=https://registry.npm.taobao.org,g' $WorkDir/Dockerfile
210 | docker build -t $DockerImage $WorkDir > $ShellDir/build_jd_image.log
211 | rm -fr $WorkDir
212 | else
213 | docker pull $DockerImage
214 | fi
215 | fi
216 |
217 | if [ $DelContainer = true ]; then
218 | log "\n2.2.删除先前的容器"
219 | docker stop $ContainerName > /dev/null
220 | docker rm $ContainerName > /dev/null
221 | fi
222 |
223 | clear
224 |
225 | log "\n创建容器并运行"
226 | docker run -dit \
227 | $NeedDirConfig \
228 | $NeedDirLog \
229 | $NeedDirScripts \
230 | -p $PanelPort:5678 \
231 | --name $ContainerName \
232 | --hostname jd \
233 | --restart always \
234 | $DockerImage
235 |
236 | log "\n下面列出所有容器"
237 | docker ps
238 |
239 | log "\n安装已经完成。\n请访问 http://:${PanelPort} 进行配置\n初始用户名:admin,初始密码:adminadmin"
240 | rm -f $ShellDir/$ShellName
241 | echo "进入容器命令为########docker exec -it jd /bin/bash"
242 | # 更新于5/26
243 |
--------------------------------------------------------------------------------
/install_scripts/linux_install_jd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | clear
3 | echo -e "\n"
4 | echo -e "\n[开始部署jd_shell\n"
5 |
6 | ShellDir=$(cd "$(dirname "$0")";pwd)
7 | ShellName=$0
8 | JdDir=${ShellDir}/jd
9 |
10 | function Welcome() {
11 | echo -e "除了安卓,由于其它系统安装软件需要sudo,本脚本除安装环境外不会调用再次任何root的执行权限\n"
12 | echo -e "若担心安全风险,可选择自行安装环境!!\n"
13 | echo -e ''
14 | echo -e '#####################################################'
15 | echo -e ''
16 | echo -e "\n正在为您安装环境(依赖):\ngit wget curl perl moreutils node.js npm\n\n"
17 | echo -e ''
18 | echo -e " 请输入开头序号选择当前的操作系统 :\n"
19 | echo -e " 1 debian/ubuntu/armbian/OpenMediaVault,以及其他debian系\n"
20 | echo -e " 2 CentOS/RedHat/Fedora等红帽系\n"
21 | echo -e " 3 Termux为主的安卓系\n"
22 | echo -e " 4 环境已安装,直接开始部署脚本\n"
23 | echo -e " 5 自己手动安装环境(退出)\n"
24 | echo -e " 当前系统时间 $(date +%Y-%m-%d) $(date +%H:%M)"
25 | echo -e ''
26 | echo -e '#####################################################'
27 | echo -e ''
28 | read -n1 LINUX_TYPE
29 | case $LINUX_TYPE in
30 | 1 )
31 | echo " debian/ubuntu/armbian/OpenMediaVault,以及其他debian系"
32 | sudo apt update && sudo apt install -y git wget curl nodejs npm perl
33 | if [ ! -x "$(command -v node)" ] || [ ! -x "$(command -v npm)" ] || [ ! -x "$(command -v git)" ] || [ ! -x "$(command -v curl)" ] || [ ! -x "$(command -v wget)" ] || [ ! -x "$(command -v perl)" ]; then
34 | echo -e "\n依赖未安装完整,请重新运行该脚本且切换良好的网络环境!\n"
35 | exit 1
36 | else
37 | echo -e "\n依赖安装完成,按任意键开始部署脚本,否则按 Ctrl + C 退出!\n"
38 | read BEGINTOINSTALL
39 | INSTALLATION_CLONE
40 | fi
41 | ;;
42 | 2 )
43 | echo " CentOS/RedHat/Fedora等红帽系"
44 | sudo yum update && sudo yum install -y git wget curl perl nodejs
45 | if [ ! -x "$(command -v node)" ] || [ ! -x "$(command -v npm)" ] || [ ! -x "$(command -v git)" ] || [ ! -x "$(command -v curl)" ] || [ ! -x "$(command -v wget)" ] || [ ! -x "$(command -v perl)" ]; then
46 | echo -e "\n依赖未安装完整,请重新运行该脚本且切换良好的网络环境!\n"
47 | exit 1
48 | else
49 | echo -e "\n依赖安装完成,按任意键开始部署脚本,否则按 Ctrl + C 退出!\n"
50 | read BEGINTOINSTALL
51 | INSTALLATION_CLONE
52 | fi
53 | ;;
54 | 3 )
55 | echo " Termux为主的安卓系"
56 | pkg update && pkg install -y git perl nodejs-lts wget curl nano cronie
57 | if [ ! -x "$(command -v node)" ] || [ ! -x "$(command -v npm)" ] || [ ! -x "$(command -v git)" ] || [ ! -x "$(command -v curl)" ] || [ ! -x "$(command -v wget)" ] || [ ! -x "$(command -v perl)" ]; then
58 | echo -e "\n依赖未安装完整,请重新运行该脚本且切换良好的网络环境!\n"
59 | exit 1
60 | else
61 | echo -e "\n依赖安装完成,按任意键开始部署脚本,否则按 Ctrl + C 退出!\n"
62 | read BEGINTOINSTALL
63 | INSTALLATION_CLONE
64 | fi
65 | ;;
66 | 4 )
67 | echo " 已安装(继续)"
68 | if [ ! -x "$(command -v node)" ] || [ ! -x "$(command -v npm)" ] || [ ! -x "$(command -v git)" ] || [ ! -x "$(command -v curl)" ] || [ ! -x "$(command -v wget)" ] || [ ! -x "$(command -v perl)" ]; then
69 | echo -e "\n依赖未安装完整!\n"
70 | exit 1
71 | else
72 | echo -e "\n依赖已安装,按任意键开始部署脚本,否则按 Ctrl + C 退出!\n"
73 | read BEGINTOINSTALL
74 | INSTALLATION_CLONE
75 | fi
76 | ;;
77 | * )
78 | echo " 自己手动安装环境(退出)";;
79 | esac
80 | }
81 |
82 | function INSTALLATION_CLONE() {
83 | echo -e "\n1. 获取源码"
84 | [ -d ${JdDir} ] && mv ${JdDir} ${JdDir}.bak && echo "检测到已有 ${JdDir} 目录,已备份为 ${JdDir}.bak"
85 | git clone -b v3 https://gitee.com/highdimen/jd_shell ${JdDir}
86 |
87 | echo -e "\n2. 检查配置文件"
88 | [ ! -d ${JdDir}/config ] && mkdir -p ${JdDir}/config
89 |
90 | if [ ! -s ${JdDir}/config/crontab.list ]
91 | then
92 | cp -fv ${JdDir}/sample/crontab.list.sample ${JdDir}/config/crontab.list
93 | sed -i "s,MY_PATH,${JdDir},g" ${JdDir}/config/crontab.list
94 | sed -i "s,ENV_PATH=,PATH=$PATH,g" ${JdDir}/config/crontab.list
95 | fi
96 | crontab -l > ${JdDir}/old_crontab
97 | crontab ${JdDir}/config/crontab.list
98 |
99 | [ ! -s ${JdDir}/config/config.sh ] && cp -fv ${JdDir}/sample/config.sh.sample ${JdDir}/config/config.sh
100 |
101 | echo -e "\n3. 执行 git_pull.sh 进行脚本更新以及定时文件更新"
102 | bash ${JdDir}/git_pull.sh
103 |
104 | echo -e "\n注意:原有定时任务已备份在 ${JdDir}/old_crontab"
105 | rm -f ${ShellDir}/${ShellName}
106 |
107 | echo -e "\n安装完成!!!!"
108 | }
109 | Welcome
110 |
--------------------------------------------------------------------------------
/jd.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ## Author: lan-tianxiang
4 | ## Source: https://github.com/lan-tianxiang/jd_shell
5 | ## Modified: 2021-07-07
6 | ## Version: v3.66.0
7 |
8 | ## 路径
9 | ShellDir=${JD_DIR:-$(
10 | cd $(dirname $0)
11 | pwd
12 | )}
13 | [ ${JD_DIR} ] && HelpJd=jd.sh || HelpJd=jd.sh
14 | ScriptsDir=${ShellDir}/scripts
15 | PanelDir=${ShellDir}/panel
16 | WebshellDir=${ShellDir}/webshell
17 | ConfigDir=${ShellDir}/config
18 | FileConf=${ConfigDir}/config.sh
19 | FileConftemp=${ConfigDir}/config.sh.temp
20 | FileConfSample=${ShellDir}/sample/config.sh.sample
21 | panelpwd=${ConfigDir}/auth.json
22 | LogDir=${ShellDir}/log
23 | ListScripts=($(
24 | cd ${ScriptsDir}
25 | ls *.js | grep -E "j[drx]_"
26 | ))
27 | ListCron=${ConfigDir}/crontab.list
28 |
29 | ## 常量
30 | AutoHelpme=false
31 | TasksTerminateTime=0
32 | NodeType="nohup"
33 | IsWebShell="false"
34 |
35 | ## 导入config.sh
36 | function Import_Conf() {
37 | if [ -f ${FileConf} ]; then
38 | . ${FileConf}
39 | if [ -z "${Cookie1}" ]; then
40 | echo -e "请先在config.sh中配置好Cookie...\n"
41 | exit 1
42 | fi
43 | else
44 | echo -e "配置文件 ${FileConf} 不存在,请先按教程配置好该文件...\n"
45 | exit 1
46 | fi
47 | }
48 |
49 | ## 更新crontab
50 | function Detect_Cron() {
51 | if [[ $(cat ${ListCron}) != $(crontab -l) ]]; then
52 | crontab ${ListCron}
53 | fi
54 | }
55 |
56 | ## 用户数量UserSum
57 | function Count_UserSum() {
58 | for ((i = 1; i <= 1000; i++)); do
59 | Tmp=Cookie$i
60 | CookieTmp=${!Tmp}
61 | [[ ${CookieTmp} ]] && UserSum=$i || break
62 | done
63 | }
64 |
65 | ## 判断使用系统
66 | detect_system() {
67 | SYSTEM=UnKnow
68 | Platform="虚拟机"
69 | SYSTEMTYPE=$(uname -m)
70 | [[ -n $(uname -m | grep arm) ]] && SYSTEMTYPE=arm
71 | [[ -n $(uname -a | grep Android) ]] && SYSTEM=Android
72 | [[ -n $(uname -s | grep Darwin) ]] && SYSTEM=Macos
73 | [[ -n $(ls /etc | grep lsb-release) ]] && SYSTEM=Ubuntu
74 | [[ -n $(ls /etc | grep debian_version) ]] && SYSTEM=Debian
75 | [[ -n $(ls /etc | grep redhat-release) ]] && SYSTEM=Centos
76 | [ -f /proc/1/cgroup ] && [[ -n $(cat /proc/1/cgroup | grep cpuset | grep scope) ]] && SYSTEM=Docker
77 | [ -f /proc/version ] && [[ -n $(cat /proc/version | grep Openwar) ]] && SYSTEM=Openwar
78 | #[[ -n $(dmesg|grep -i virtual) ]] && Platform="虚拟机"
79 | }
80 |
81 | ## 组合Cookie和互助码子程序
82 | function Combin_Sub() {
83 | CombinAll=""
84 | for ((i = 1; i <= ${UserSum}; i++)); do
85 | for num in ${TempBlockCookie}; do
86 | if [[ $i -eq $num ]]; then
87 | continue 2
88 | fi
89 | done
90 | Tmp1=$1$i
91 | Tmp2=${!Tmp1}
92 | case $# in
93 | 1)
94 | CombinAll="${CombinAll}&${Tmp2}"
95 | ;;
96 | 2)
97 | CombinAll="${CombinAll}&${Tmp2}@$2"
98 | ;;
99 | 3)
100 | if [ $(($i % 2)) -eq 1 ]; then
101 | CombinAll="${CombinAll}&${Tmp2}@$2"
102 | else
103 | CombinAll="${CombinAll}&${Tmp2}@$3"
104 | fi
105 | ;;
106 | 4)
107 | case $(($i % 3)) in
108 | 1)
109 | CombinAll="${CombinAll}&${Tmp2}@$2"
110 | ;;
111 | 2)
112 | CombinAll="${CombinAll}&${Tmp2}@$3"
113 | ;;
114 | 0)
115 | CombinAll="${CombinAll}&${Tmp2}@$4"
116 | ;;
117 | esac
118 | ;;
119 | esac
120 | done
121 | echo ${CombinAll} | perl -pe "{s|^&||; s|^@+||; s|&@|&|g; s|@+&|&|g; s|@+|@|g; s|@+$||}"
122 | }
123 |
124 | ## 组合Cookie、Token与互助码
125 | function Combin_All() {
126 | export JD_COOKIE=$(Combin_Sub Cookie)
127 | ## 东东农场(jd_fruit.js)
128 | export FRUITSHARECODES=$(Combin_Sub ForOtherFruit "588e4dd7ba134ad5aa255d9b9e1a38e3@520b92a9f0c34b34a0833f6c3bb41cac@e124f1c465554bf485983257743233d3" "7363f89a9d7248ae91a439794f854614@07b3cd1495524fa2b0f768e7639eab9f")
129 | ## 东东萌宠(jd_pet.js)
130 | export PETSHARECODES=$(Combin_Sub ForOtherPet "MTE1NDAxNzgwMDAwMDAwMzk3NDIzODc=@MTAxODEyMjkyMDAwMDAwMDQwMTEzNzA3@MTE1NDUyMjEwMDAwMDAwNDM3NDQzMzU=" "MTEzMzI0OTE0NTAwMDAwMDA0Mzc0NjgzOQ==")
131 | ## 种豆得豆(jd_plantBean.js)
132 | export PLANT_BEAN_SHARECODES=$(Combin_Sub ForOtherBean "olmijoxgmjutzeajdig5vec453deq25pz7msb7i@okj5ibnh3onz6mkpbt6natnj7xdxeqeg53kjbsi@7oivz2mjbmnx4cbdwoeomdbqrr6bwbgsrhybhxa" "yvppbgio53ya5quolmjz6hiwlhu6yge7i7six5y@ebxm5lgxoknqdfx75eycfx6vy5n2tuflqhuhfia")
133 | ## 东东工厂(jd_jdfactory.js)
134 | export DDFACTORY_SHARECODES=$(Combin_Sub ForOtherJdFactory "T0225KkcRhwZp1HXJk70k_8CfQCjVWnYaS5kRrbA@T0205KkcAVhorA6EfG6dwb9ACjVWnYaS5kRrbA@T0205KkcG1tgqh22f1-s54tXCjVWnYaS5kRrbA" "T019__l2QBYe_UneIRj9lv8CjVWnYaS5kRrbA@T0205KkcNFd5nz6dXnCV4r9gCjVWnYaS5kRrbA")
135 | ## 京喜工厂(jd_dreamFactory.js)
136 | export DREAM_FACTORY_SHARE_CODES=$(Combin_Sub ForOtherDreamFactory "piDVq-y7O_2SyEzi5ZxxYw==@IzYimRViEUHMiUDFhPPLOg==@ieXM8XzpopOaevcW0f1OwA==" "y0k9IDhCNqQvEov0x2ugNQ==")
137 | ## 京东赚赚(jd_jdzz.js)
138 | export JDZZ_SHARECODES=$(Combin_Sub ForOtherJdzz "S5KkcRhwZp1HXJk70k_8CfQ@S5KkcAVhorA6EfG6dwb9A@S5KkcG1tgqh22f1-s54tX")
139 | ## 疯狂的Joy(jd_crazy_joy.js)
140 | export JDJOY_SHARECODES=$(Combin_Sub ForOtherJoy "N1ihLmXRx9ahdnutDzc1Vqt9zd5YaBeE@o8k-j4vfLXWhsdA5HoPq-w==@zw2aNaUUBen1acOglloXVw==")
141 | ## 口袋书店(jd_bookshop.js)
142 | export BOOKSHOP_SHARECODES=$(Combin_Sub ForOtherBookShop)
143 | ## 签到领现金(jd_cash.js)
144 | export JD_CASH_SHARECODES=$(Combin_Sub ForOtherCash "eU9Yau6yNPkm9zrVzHsb3w@eU9YLarDP6Z1rRq8njtZ@eU9YN6nLObVHriuNuA9O")
145 | ## 京喜农场(jd_jxnc.js)
146 | export JXNC_SHARECODES=$(Combin_Sub ForOtherJxnc)
147 | ## 闪购盲盒(jd_sgmh.js)
148 | export JDSGMH_SHARECODES=$(Combin_Sub ForOtherSgmh)
149 | ## 京喜财富岛(jd_cfd.js)
150 | export JDCFD_SHARECODES=$(Combin_Sub ForOtherCfd)
151 | ## 环球挑战赛(jd_global.js)
152 | export JDGLOBAL_SHARECODES=$(Combin_Sub ForOtherGlobal "MjNtTnVxbXJvMGlWTHc5Sm9kUXZ3VUM4R241aDFjblhybHhTWFYvQmZUOD0")
153 | ## 京东手机狂欢城(jd_carnivalcity.js)
154 | export JD818_SHARECODES=$(Combin_Sub ForOtherCarnivalcity "5443fec1-7dbc-4d92-a09b-b7eb0a01199f@8c2a0d3a-b4d7-4bbf-bccc-4e7efc18f849")
155 |
156 | export JDHEALTH_SHARECODES=$(Combin_Sub ForOtherHealth)
157 | }
158 |
159 | ## 转换JD_BEAN_SIGN_STOP_NOTIFY或JD_BEAN_SIGN_NOTIFY_SIMPLE
160 | function Trans_JD_BEAN_SIGN_NOTIFY() {
161 | case ${NotifyBeanSign} in
162 | 0)
163 | export JD_BEAN_SIGN_STOP_NOTIFY="true"
164 | ;;
165 | 1)
166 | export JD_BEAN_SIGN_NOTIFY_SIMPLE="true"
167 | ;;
168 | esac
169 | }
170 |
171 | ## 转换UN_SUBSCRIBES
172 | function Trans_UN_SUBSCRIBES() {
173 | export UN_SUBSCRIBES="${goodPageSize}\n${shopPageSize}\n${jdUnsubscribeStopGoods}\n${jdUnsubscribeStopShop}"
174 | }
175 |
176 | ## 申明全部变量
177 | function Set_Env() {
178 | Count_UserSum
179 | Combin_All
180 | Trans_JD_BEAN_SIGN_NOTIFY
181 | Trans_UN_SUBSCRIBES
182 | }
183 |
184 | ## 随机延迟
185 | function Random_Delay() {
186 | if [[ -n ${RandomDelay} ]] && [[ ${RandomDelay} -gt 0 ]]; then
187 | CurMin=$(date "+%-M")
188 | if [[ ${CurMin} -gt 2 && ${CurMin} -lt 30 ]] || [[ ${CurMin} -gt 31 && ${CurMin} -lt 59 ]]; then
189 | CurDelay=$((${RANDOM} % ${RandomDelay} + 1))
190 | echo -e "\n命令未添加 \"now\",随机延迟 ${CurDelay} 秒后再执行任务,如需立即终止,请按 CTRL+C...\n"
191 | sleep ${CurDelay}
192 | fi
193 | fi
194 | }
195 |
196 | ## 使用说明
197 | function Help() {
198 | echo -e "本脚本的用法为:"
199 | echo -e "bash ${HelpJd} jd_xxx # 如果设置了随机延迟并且当时时间不在0-2、30-31、59分内,将随机延迟一定秒数"
200 | echo -e "bash ${HelpJd} jd_xxx now # 无论是否设置了随机延迟,均立即运行"
201 | echo -e "bash ${HelpJd} hangup # 重启挂机程序"
202 | echo -e "bash ${HelpJd} panelon # 开启控制面板"
203 | echo -e "bash ${HelpJd} paneloff # 关闭控制面板"
204 | echo -e "bash ${HelpJd} resetpwd # 重置控制面板用户名和密码"
205 | echo
206 | cd ${ScriptsDir}
207 | for ((i = 0; i < ${#ListScripts[*]}; i++)); do
208 | Name=$(grep "new Env" ${ListScripts[i]} | awk -F "'|\"" '{print $2}')
209 | echo -e "$(($i + 1)).${Name}:${ListScripts[i]}"
210 | done
211 | }
212 |
213 | ## nohup
214 | function Run_Nohup() {
215 | for js in ${HangUpJs}; do
216 | if [[ $(ps -ef | grep "${js}" | grep -v "grep") != "" ]]; then
217 | ps -ef | grep "${js}" | grep -v "grep" | awk '{print $2}' | xargs kill -9
218 | fi
219 | done
220 |
221 | for js in ${HangUpJs}; do
222 | [ ! -d ${LogDir}/${js} ] && mkdir -p ${LogDir}/${js}
223 | LogTime=$(date "+%Y-%m-%d-%H-%M-%S")
224 | LogFile="${LogDir}/${js}/${LogTime}.log"
225 | nohup node ${js}.js >${LogFile} &
226 | done
227 | }
228 |
229 | ## pm2
230 | function Run_Pm2() {
231 | pm2 flush
232 | for js in ${HangUpJs}; do
233 | pm2 restart ${js}.js || pm2 start ${js}.js
234 | done
235 | }
236 |
237 | ## 运行挂机脚本
238 | function Run_HangUp() {
239 | Import_Conf && Detect_Cron && Set_Env
240 | HangUpJs="jd_crazy_joy_coin"
241 | cd ${ScriptsDir}
242 | if type pm2 >/dev/null 2>&1; then
243 | Run_Pm2 2>/dev/null
244 | else
245 | Run_Nohup >/dev/null 2>&1
246 | fi
247 | }
248 |
249 | ## npm install 子程序,判断是否为安卓,判断是否安装有yarn
250 | function Npm_InstallSub() {
251 | if [ -n "${isTermux}" ]; then
252 | npm install --no-bin-links || npm install --no-bin-links --registry=https://registry.npm.taobao.org
253 | elif ! type yarn >/dev/null 2>&1; then
254 | npm install || npm install --registry=https://registry.npm.taobao.org
255 | else
256 | echo -e "检测到本机安装了 yarn,使用 yarn 替代 npm...\n"
257 | yarn install || yarn install --registry=https://registry.npm.taobao.org
258 | fi
259 | }
260 |
261 | ## panel install
262 | function panelon() {
263 | if [ ! -d ${PanelDir}/node_modules ]; then
264 | echo -e "运行 npm install...\n"
265 | Npm_InstallSub
266 | if [ $? -ne 0 ]; then
267 | echo -e "\nnpm install 运行不成功,自动删除 ${ScriptsDir}/node_modules 后再次尝试一遍..."
268 | rm -rf ${PanelDir}/node_modules
269 | fi
270 | fi
271 |
272 | [ -f ${PanelDir}/package.json ] && PackageListOld=$(cat ${PanelDir}/package.json)
273 | cd ${PanelDir}
274 | if [[ "${PackageListOld}" != "$(cat package.json)" ]]; then
275 | echo -e "检测到package.json有变化,运行 npm install...\n"
276 | Npm_InstallSub
277 | if [ $? -ne 0 ]; then
278 | echo -e "\nnpm install 运行不成功,自动删除 ${ScriptsDir}/node_modules 后再次尝试一遍..."
279 | rm -rf ${PanelDir}/node_modules
280 | fi
281 | echo
282 | fi
283 |
284 | echo -e "记得开启前先认真看Wiki中,功能页里关于控制面板的事项\n"
285 |
286 | if [ ! -f "$panelpwd" ]; then
287 | cp -f ${ShellDir}/sample/auth.json ${ConfigDir}/auth.json
288 | echo -e "检测到未设置密码,用户名:admin,密码:adminadmin\n"
289 | fi
290 | ## 安装pm2
291 | [ ! $NodeType = nohup ] && [ ! -x "$(command -v pm2)" ] && npm install pm2@latest -g
292 |
293 | ## 复制ttyd
294 | cd ${PanelDir}
295 | [ $SYSTEMTYPE = arm ] && [ ! -f ${PanelDir}/ttyd ] && cp -f ${PanelDir}/webshellbinary/ttyd.arm ${PanelDir}/ttyd && [ ! -x ${PanelDir}/ttyd ] && chmod +x ${PanelDir}/ttyd && echo 1
296 | [ ! $SYSTEM = Android ] && [ ! -f ${PanelDir}/ttyd ] && cp -f ${PanelDir}/webshellbinary/ttyd.$(uname -m) ${PanelDir}/ttyd && [ ! -x ${PanelDir}/ttyd ] && chmod +x ${PanelDir}/ttyd echo 1
297 |
298 | paneloff
299 | cd ${PanelDir}
300 | [ ! $NodeType = nohup ] && [ $IsWebShell = true ] && pm2 start ${PanelDir}/ttyd --name="WebShell" -- -p 9999 -t fontSize=14 -t disableLeaveAlert=true -t rendererType=webgl bash >/dev/null 2>&1 &
301 | [ ! $NodeType = nohup ] && pm2 start ${PanelDir}/server.js && echo "成功,按回车继续" &
302 |
303 | [ $NodeType = nohup ] && [ $IsWebShell = true ] && nohup ./ttyd -p 9999 -t fontSize=14 -t disableLeaveAlert=true -t rendererType=webgl bash >/dev/null 2>&1 &
304 | [ $NodeType = nohup ] && nohup node ${PanelDir}/server.js >/dev/null 2>&1 &
305 |
306 | if [ $? -ne 0 ]; then
307 | echo -e "开启失败,请截图并复制错误代码并提交Issues!\n"
308 | else
309 | echo -e "确认看过WIKI,打开浏览器,地址为你的127.0.0.1:5678\n"
310 | fi
311 | }
312 |
313 | ## 关闭面板
314 | function paneloff() {
315 | cd ${PanelDir}
316 | pm2 delete all >/dev/null 2>&1
317 | pkill -9 ttyd >/dev/null 2>&1
318 | pkill -9 node >/dev/null 2>&1
319 | }
320 |
321 | ## 重置密码
322 | function Reset_Pwd() {
323 | cp -f ${ShellDir}/sample/auth.json ${ConfigDir}/auth.json
324 | echo -e "控制面板重置成功,用户名:admin,密码:adminadmin\n"
325 | }
326 |
327 | ## 运行京东脚本
328 | function Run_Normal() {
329 | Import_Conf && Detect_Cron && Set_Env
330 |
331 | if [ ${AutoHelpme} = true ]; then
332 | if [ -f ${LogDir}/export_sharecodes/export_sharecodes.log ]; then
333 | [ ! -s ${FileConftemp} ] && cp -f ${FileConf} ${ConfigDir}/config.sh.temp && cat ${LogDir}/export_sharecodes/export_sharecodes.log >>${ConfigDir}/config.sh.temp
334 | FileConf=${ConfigDir}/config.sh.temp
335 | Import_Conf && Detect_Cron && Set_Env
336 | else
337 | echo "暂时没有助力码"
338 | fi
339 | else
340 | echo "0000"
341 | fi
342 |
343 | FileNameTmp1=$(echo $1 | perl -pe "s|\.js||")
344 | FileNameTmp2=$(echo $1 | perl -pe "{s|jd_||; s|\.js||; s|^|jd_|}")
345 | SeekDir="${ScriptsDir} ${ScriptsDir}/backUp ${ConfigDir}"
346 | FileName=""
347 | WhichDir=""
348 |
349 | for dir in ${SeekDir}; do
350 | if [ -f ${dir}/${FileNameTmp1}.js ]; then
351 | FileName=${FileNameTmp1}
352 | WhichDir=${dir}
353 | break
354 | elif [ -f ${dir}/${FileNameTmp2}.js ]; then
355 | FileName=${FileNameTmp2}
356 | WhichDir=${dir}
357 | break
358 | fi
359 | done
360 |
361 | if [ -n "${FileName}" ] && [ -n "${WhichDir}" ]; then
362 | [ $# -eq 1 ] && Random_Delay
363 | LogTime=$(date "+%Y-%m-%d-%H-%M-%S")
364 | LogFile="${LogDir}/${FileName}/${LogTime}.log"
365 | [ ! -d ${LogDir}/${FileName} ] && mkdir -p ${LogDir}/${FileName}
366 | cd ${WhichDir}
367 | # env
368 | [ ${TasksTerminateTime} = 0 ] && node ${FileName}.js | tee ${LogFile}
369 | [ ${TasksTerminateTime} -ne 0 ] && timeout ${TasksTerminateTime} node ${FileName}.js | tee ${LogFile}
370 | else
371 | echo -e "\n在${ScriptsDir}、${ScriptsDir}/backUp、${ConfigDir}三个目录下均未检测到 $1 脚本的存在,请确认...\n"
372 | Help
373 | fi
374 | }
375 |
376 |
377 |
378 |
379 | detect_system
380 | ## 命令检测
381 | case $# in
382 | 0)
383 | echo
384 | Help
385 | ;;
386 | 1)
387 | if [[ $1 == hangup ]]; then
388 | Run_HangUp
389 | elif [[ $1 == resetpwd ]]; then
390 | Reset_Pwd
391 | elif [[ $1 == panelon ]]; then
392 | panelon
393 | elif [[ $1 == paneloff ]]; then
394 | paneloff
395 | else
396 | Run_Normal $1
397 | fi
398 | ;;
399 | 2)
400 | if [[ $2 == now ]]; then
401 | Run_Normal $1 $2
402 | else
403 | echo -e "\n命令输入错误...\n"
404 | Help
405 | fi
406 | ;;
407 | *)
408 | echo -e "\n命令过多...\n"
409 | Help
410 | ;;
411 | esac
412 | echo "您的操作系统为:$SYSTEM 架构:$SYSTEMTYPE"
413 | ## Update Time 2021-04-06 12:35:48
414 |
--------------------------------------------------------------------------------
/panel/ecosystem.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | apps: [
3 | {
4 | name: 'server',
5 | script: './server.js',
6 | watch: ['server.js'],
7 | // Delay between restart
8 | watch_delay: 2000,
9 | ignore_watch: ['node_modules', 'public'],
10 | watch_options: {
11 | followSymlinks: false,
12 | },
13 | },
14 | ],
15 | };
16 |
--------------------------------------------------------------------------------
/panel/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "panel",
3 | "version": "1.0.0",
4 | "description": "web panel",
5 | "main": "server.js",
6 | "dependencies": {
7 | "body-parser": "^1.19.0",
8 | "compression": "^1.7.4",
9 | "express": "^4.17.1",
10 | "express-session": "^1.17.1",
11 | "got": "^11.8.1",
12 | "http-proxy-middleware": "^1.0.6"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/panel/public/auth.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | JDSHELL控制面板
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
JDSHELL控制面板-V3
19 |
24 |
25 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/panel/public/crontab.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 定时设定 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
42 |
43 | 在线编辑工具
44 |
46 |
47 |
定时任务清单
48 |
49 |
50 |
51 |
52 |
53 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/panel/public/css/codemirror.min.css:
--------------------------------------------------------------------------------
1 | .CodeMirror {
2 | font-family: monospace;
3 | height: 300px;
4 | color: black
5 | }
6 |
7 | .CodeMirror-lines {
8 | padding: 4px 0
9 | }
10 |
11 | .CodeMirror pre {
12 | padding: 0 4px
13 | }
14 |
15 | .CodeMirror-scrollbar-filler,
16 | .CodeMirror-gutter-filler {
17 | background-color: white
18 | }
19 |
20 | .CodeMirror-gutters {
21 | border-right: 1px solid #ddd;
22 | background-color: #f7f7f7;
23 | white-space: nowrap
24 | }
25 |
26 | .CodeMirror-linenumber {
27 | padding: 0 3px 0 5px;
28 | min-width: 20px;
29 | text-align: right;
30 | color: #999;
31 | white-space: nowrap
32 | }
33 |
34 | .CodeMirror-guttermarker {
35 | color: black
36 | }
37 |
38 | .CodeMirror-guttermarker-subtle {
39 | color: #999
40 | }
41 |
42 | .CodeMirror-cursor {
43 | border-left: 1px solid black;
44 | border-right: 0;
45 | width: 0
46 | }
47 |
48 | .CodeMirror div.CodeMirror-secondarycursor {
49 | border-left: 1px solid silver
50 | }
51 |
52 | .cm-fat-cursor .CodeMirror-cursor {
53 | width: auto;
54 | border: 0;
55 | background: #7e7
56 | }
57 |
58 | .cm-fat-cursor div.CodeMirror-cursors {
59 | z-index: 1
60 | }
61 |
62 | .cm-animate-fat-cursor {
63 | width: auto;
64 | border: 0;
65 | -webkit-animation: blink 1.06s steps(1) infinite;
66 | -moz-animation: blink 1.06s steps(1) infinite;
67 | animation: blink 1.06s steps(1) infinite;
68 | background-color: #7e7
69 | }
70 |
71 | @-moz-keyframes blink {
72 | 50% {
73 | background-color: transparent
74 | }
75 | }
76 |
77 | @-webkit-keyframes blink {
78 | 50% {
79 | background-color: transparent
80 | }
81 | }
82 |
83 | @keyframes blink {
84 | 50% {
85 | background-color: transparent
86 | }
87 | }
88 |
89 | .cm-tab {
90 | display: inline-block;
91 | text-decoration: inherit
92 | }
93 |
94 | .CodeMirror-ruler {
95 | border-left: 1px solid #ccc;
96 | position: absolute
97 | }
98 |
99 | .cm-s-default .cm-header {
100 | color: blue
101 | }
102 |
103 | .cm-s-default .cm-quote {
104 | color: #090
105 | }
106 |
107 | .cm-negative {
108 | color: #d44
109 | }
110 |
111 | .cm-positive {
112 | color: #292
113 | }
114 |
115 | .cm-header,
116 | .cm-strong {
117 | font-weight: bold
118 | }
119 |
120 | .cm-em {
121 | font-style: italic
122 | }
123 |
124 | .cm-link {
125 | text-decoration: underline
126 | }
127 |
128 | .cm-strikethrough {
129 | text-decoration: line-through
130 | }
131 |
132 | .cm-s-default .cm-keyword {
133 | color: #708
134 | }
135 |
136 | .cm-s-default .cm-atom {
137 | color: #219
138 | }
139 |
140 | .cm-s-default .cm-number {
141 | color: #164
142 | }
143 |
144 | .cm-s-default .cm-def {
145 | color: #00f
146 | }
147 |
148 | .cm-s-default .cm-variable-2 {
149 | color: #05a
150 | }
151 |
152 | .cm-s-default .cm-variable-3 {
153 | color: #085
154 | }
155 |
156 | .cm-s-default .cm-comment {
157 | color: #a50
158 | }
159 |
160 | .cm-s-default .cm-string {
161 | color: #a11
162 | }
163 |
164 | .cm-s-default .cm-string-2 {
165 | color: #f50
166 | }
167 |
168 | .cm-s-default .cm-meta {
169 | color: #555
170 | }
171 |
172 | .cm-s-default .cm-qualifier {
173 | color: #555
174 | }
175 |
176 | .cm-s-default .cm-builtin {
177 | color: #30a
178 | }
179 |
180 | .cm-s-default .cm-bracket {
181 | color: #997
182 | }
183 |
184 | .cm-s-default .cm-tag {
185 | color: #170
186 | }
187 |
188 | .cm-s-default .cm-attribute {
189 | color: #00c
190 | }
191 |
192 | .cm-s-default .cm-hr {
193 | color: #999
194 | }
195 |
196 | .cm-s-default .cm-link {
197 | color: #00c
198 | }
199 |
200 | .cm-s-default .cm-error {
201 | color: red
202 | }
203 |
204 | .cm-invalidchar {
205 | color: red
206 | }
207 |
208 | .CodeMirror-composing {
209 | border-bottom: 2px solid
210 | }
211 |
212 | div.CodeMirror span.CodeMirror-matchingbracket {
213 | color: #0f0
214 | }
215 |
216 | div.CodeMirror span.CodeMirror-nonmatchingbracket {
217 | color: #f22
218 | }
219 |
220 | .CodeMirror-matchingtag {
221 | background: rgba(255, 150, 0, .3)
222 | }
223 |
224 | .CodeMirror-activeline-background {
225 | background: #e8f2ff
226 | }
227 |
228 | .CodeMirror {
229 | position: relative;
230 | overflow: hidden;
231 | background: white
232 | }
233 |
234 | .CodeMirror-scroll {
235 | overflow: scroll !important;
236 | margin-bottom: -30px;
237 | margin-right: -30px;
238 | padding-bottom: 30px;
239 | height: 100%;
240 | outline: 0;
241 | position: relative
242 | }
243 |
244 | .CodeMirror-sizer {
245 | position: relative;
246 | border-right: 30px solid transparent
247 | }
248 |
249 | .CodeMirror-vscrollbar,
250 | .CodeMirror-hscrollbar,
251 | .CodeMirror-scrollbar-filler,
252 | .CodeMirror-gutter-filler {
253 | position: absolute;
254 | z-index: 6;
255 | display: none
256 | }
257 |
258 | .CodeMirror-vscrollbar {
259 | right: 0;
260 | top: 0;
261 | overflow-x: hidden;
262 | overflow-y: scroll
263 | }
264 |
265 | .CodeMirror-hscrollbar {
266 | bottom: 0;
267 | left: 0;
268 | overflow-y: hidden;
269 | overflow-x: scroll
270 | }
271 |
272 | .CodeMirror-scrollbar-filler {
273 | right: 0;
274 | bottom: 0
275 | }
276 |
277 | .CodeMirror-gutter-filler {
278 | left: 0;
279 | bottom: 0
280 | }
281 |
282 | .CodeMirror-gutters {
283 | position: absolute;
284 | left: 0;
285 | top: 0;
286 | z-index: 3
287 | }
288 |
289 | .CodeMirror-gutter {
290 | white-space: normal;
291 | height: 100%;
292 | display: inline-block;
293 | margin-bottom: -30px;
294 | *zoom: 1;
295 | *display: inline
296 | }
297 |
298 | .CodeMirror-gutter-wrapper {
299 | position: absolute;
300 | z-index: 4;
301 | background: none !important;
302 | border: none !important
303 | }
304 |
305 | .CodeMirror-gutter-background {
306 | position: absolute;
307 | top: 0;
308 | bottom: 0;
309 | z-index: 4
310 | }
311 |
312 | .CodeMirror-gutter-elt {
313 | position: absolute;
314 | cursor: default;
315 | z-index: 4
316 | }
317 |
318 | .CodeMirror-gutter-wrapper {
319 | -webkit-user-select: none;
320 | -moz-user-select: none;
321 | user-select: none
322 | }
323 |
324 | .CodeMirror-lines {
325 | cursor: text;
326 | min-height: 1px
327 | }
328 |
329 | .CodeMirror pre {
330 | -moz-border-radius: 0;
331 | -webkit-border-radius: 0;
332 | border-radius: 0;
333 | border-width: 0;
334 | background: transparent;
335 | font-family: inherit;
336 | font-size: inherit;
337 | margin: 0;
338 | white-space: pre;
339 | word-wrap: normal;
340 | line-height: inherit;
341 | color: inherit;
342 | z-index: 2;
343 | position: relative;
344 | overflow: visible;
345 | -webkit-tap-highlight-color: transparent
346 | }
347 |
348 | .CodeMirror-wrap pre {
349 | word-wrap: break-word;
350 | white-space: pre-wrap;
351 | word-break: normal
352 | }
353 |
354 | .CodeMirror-linebackground {
355 | position: absolute;
356 | left: 0;
357 | right: 0;
358 | top: 0;
359 | bottom: 0;
360 | z-index: 0
361 | }
362 |
363 | .CodeMirror-linewidget {
364 | position: relative;
365 | z-index: 2;
366 | overflow: auto
367 | }
368 |
369 | .CodeMirror-code {
370 | outline: 0
371 | }
372 |
373 | .CodeMirror-scroll,
374 | .CodeMirror-sizer,
375 | .CodeMirror-gutter,
376 | .CodeMirror-gutters,
377 | .CodeMirror-linenumber {
378 | -moz-box-sizing: content-box;
379 | box-sizing: content-box
380 | }
381 |
382 | .CodeMirror-measure {
383 | position: absolute;
384 | width: 100%;
385 | height: 0;
386 | overflow: hidden;
387 | visibility: hidden
388 | }
389 |
390 | .CodeMirror-cursor {
391 | position: absolute
392 | }
393 |
394 | .CodeMirror-measure pre {
395 | position: static
396 | }
397 |
398 | div.CodeMirror-cursors {
399 | visibility: hidden;
400 | position: relative;
401 | z-index: 3
402 | }
403 |
404 | div.CodeMirror-dragcursors {
405 | visibility: visible
406 | }
407 |
408 | .CodeMirror-focused div.CodeMirror-cursors {
409 | visibility: visible
410 | }
411 |
412 | .CodeMirror-selected {
413 | background: #d9d9d9
414 | }
415 |
416 | .CodeMirror-focused .CodeMirror-selected {
417 | background: #d7d4f0
418 | }
419 |
420 | .CodeMirror-crosshair {
421 | cursor: crosshair
422 | }
423 |
424 | .CodeMirror-line::selection,
425 | .CodeMirror-line>span::selection,
426 | .CodeMirror-line>span>span::selection {
427 | background: #d7d4f0
428 | }
429 |
430 | .CodeMirror-line::-moz-selection,
431 | .CodeMirror-line>span::-moz-selection,
432 | .CodeMirror-line>span>span::-moz-selection {
433 | background: #d7d4f0
434 | }
435 |
436 | .cm-searching {
437 | background: #ffa;
438 | background: rgba(255, 255, 0, .4)
439 | }
440 |
441 | .CodeMirror span {
442 | *vertical-align: text-bottom
443 | }
444 |
445 | .cm-force-border {
446 | padding-right: .1px
447 | }
448 |
449 | @media print {
450 | .CodeMirror div.CodeMirror-cursors {
451 | visibility: hidden
452 | }
453 | }
454 |
455 | .cm-tab-wrap-hack:after {
456 | content: ''
457 | }
458 |
459 | span.CodeMirror-selectedtext {
460 | background: 0
461 | }
462 |
--------------------------------------------------------------------------------
/panel/public/css/dracula.css:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Name: dracula
4 | Author: Michael Kaminsky (http://github.com/mkaminsky11)
5 |
6 | Original dracula color scheme by Zeno Rocha (https://github.com/zenorocha/dracula-theme)
7 |
8 | */
9 |
10 |
11 | .cm-s-dracula.CodeMirror, .cm-s-dracula .CodeMirror-gutters {
12 | background-color: #202020 !important;
13 | color: #f8f8f2 !important;
14 | border: none;
15 | }
16 | .cm-s-dracula .CodeMirror-gutters { color: #282a36; }
17 | .cm-s-dracula .CodeMirror-cursor { border-left: solid thin #f8f8f0; }
18 | .cm-s-dracula .CodeMirror-linenumber { color: white; }
19 | .cm-s-dracula .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
20 | .cm-s-dracula .CodeMirror-line::selection, .cm-s-dracula .CodeMirror-line > span::selection, .cm-s-dracula .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
21 | .cm-s-dracula .CodeMirror-line::-moz-selection, .cm-s-dracula .CodeMirror-line > span::-moz-selection, .cm-s-dracula .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
22 | .cm-s-dracula span.cm-comment { color: #cccccc; }
23 | .cm-s-dracula span.cm-string, .cm-s-dracula span.cm-string-2 { color: #f1fa8c; }
24 | .cm-s-dracula span.cm-number { color: #bd93f9; }
25 | .cm-s-dracula span.cm-variable { color: #50fa7b; }
26 | .cm-s-dracula span.cm-variable-2 { color: white; }
27 | .cm-s-dracula span.cm-def { color: #50fa7b; }
28 | .cm-s-dracula span.cm-operator { color: #ff79c6; }
29 | .cm-s-dracula span.cm-keyword { color: #0099ff; }
30 | .cm-s-dracula span.cm-atom { color: #bd93f9; }
31 | .cm-s-dracula span.cm-meta { color: #f8f8f2; }
32 | .cm-s-dracula span.cm-tag { color: #ff79c6; }
33 | .cm-s-dracula span.cm-attribute { color: #50fa7b; }
34 | .cm-s-dracula span.cm-qualifier { color: #50fa7b; }
35 | .cm-s-dracula span.cm-property { color: #66d9ef; }
36 | .cm-s-dracula span.cm-builtin { color: #50fa7b; }
37 | .cm-s-dracula span.cm-variable-3, .cm-s-dracula span.cm-type { color: #ffb86c; }
38 |
39 | .cm-s-dracula .CodeMirror-activeline-background { background: rgba(255,255,255,0.1); }
40 | .cm-s-dracula .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
41 |
--------------------------------------------------------------------------------
/panel/public/css/main.css:
--------------------------------------------------------------------------------
1 | body,
2 | html {
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | h1,
8 | ul {
9 | color: #000000;
10 | margin: 0.2em 0 0.4em 0;
11 | margin-left: 0.5em;
12 | font-size: 1.5rem;
13 | padding-right: 1rem;
14 | }
15 |
16 | h4 {
17 | margin-top: 0.5em;
18 | margin-left: 0.8em;
19 | margin-bottom: 0.5em;
20 | color: rgb(0, 0, 0);
21 | }
22 |
23 | nav ul {
24 | margin: 0;
25 | padding: 0;
26 | }
27 |
28 | nav ul li {
29 | display: inline;
30 | }
31 |
32 | nav ul li a:link,
33 | nav ul li a:visited,
34 | nav ul li a:active {
35 | font-size: 0.875rem;
36 | padding: 0.5rem 1.4rem;
37 | color: white;
38 | text-decoration: none;
39 | background-color: #1A3D22;
40 | transition: background-color 200ms;
41 | }
42 |
43 | nav ul li a:hover {
44 | background-color: #000000;
45 | }
46 |
47 | nav .active a {
48 | background-color: #1A3D22 !important;
49 | }
50 |
51 | .footer {
52 | color: rgb(185, 185, 185);
53 | left: 0px;
54 | bottom: 0px;
55 | width: 100%;
56 | height: 100px;
57 | position: absolute;
58 | z-index: 9999;
59 | width: 100%;
60 | margin: 0 auto;
61 | text-align: center;
62 | }
63 |
64 |
65 | .container {
66 | display: flex;
67 | flex-direction: column;
68 | height: 100vh;
69 | width: 100%;
70 | height: 100%;
71 | top: 0px;
72 | left: 0px;
73 | position: absolute;
74 |
75 | }
76 |
77 | .container p {
78 | font-size: 0.875rem;
79 | margin: 0;
80 | line-height: 1.5em;
81 | }
82 |
83 | .container .right {
84 | top: 0px;
85 | left: 0px;
86 | position: absolute;
87 | float: left;
88 | width: 250px;
89 | height: 50px;
90 | border: 1px solid #F00;
91 | }
92 |
93 | .diffs {
94 | flex: 1 1 auto;
95 | display: flex;
96 | flex-direction: column;
97 | }
98 |
99 | .diffs header {
100 | margin-top: 1rem;
101 | }
102 |
103 | .diffs header * {
104 | display: inline-block;
105 | vertical-align: middle;
106 | }
107 |
108 | .diffs .compare-wrapper,
109 | .diffs .wrapper {
110 | flex: 1 1 auto;
111 | position: relative;
112 | }
113 |
114 | .diffs .compare-wrapper #compare {
115 | display: flex;
116 | flex-direction: column;
117 | position: absolute;
118 | top: 0;
119 | left: 0;
120 | bottom: 0;
121 | right: 0;
122 | }
123 |
124 | /* Auto-height fix */
125 |
126 | .wrapper .CodeMirror {
127 | position: absolute;
128 | height: calc(100% - 0.5em);
129 | width: 100%
130 | }
131 |
132 | .mergely-column .CodeMirror {
133 | height: 100%;
134 | }
135 |
136 | .sources a {
137 | font-size: 1rem;
138 | }
139 |
140 | /* Login page */
141 | .login-form {
142 | width: 300px;
143 | height: 450px;
144 | position: absolute;
145 | top: 0;
146 | left: 0;
147 | right: 0;
148 | bottom: 0;
149 | margin: auto;
150 | font-family: Tahoma, Geneva, sans-serif;
151 | }
152 |
153 | .login-form h1 {
154 | text-align: center;
155 | color: #000000;
156 | font-size: 24px;
157 | padding: 20px 0 20px 0;
158 | }
159 |
160 | .login-form input[type="password"],
161 | .login-form input[type="text"] {
162 | width: 100%;
163 | padding: 15px;
164 | border: 1px solid #dddddd;
165 | margin-bottom: 15px;
166 | box-sizing: border-box;
167 | border-radius: 11px 11px 11px 11px;
168 | -moz-border-radius: 11px 11px 11px 11px;
169 | -webkit-border-radius: 11px 11px 11px 11px;
170 | }
171 |
172 | .login-form input[type="submit"] {
173 | width: 100%;
174 | padding: 15px;
175 | background-color: #6D8A88;
176 | border: 0;
177 | box-sizing: border-box;
178 | cursor: pointer;
179 | font-weight: bold;
180 | color: #ffffff;
181 | border-radius: 11px 11px 11px 11px;
182 | -moz-border-radius: 11px 11px 11px 11px;
183 | -webkit-border-radius: 11px 11px 11px 11px;
184 | }
185 |
186 | #qrcontainer {
187 | position: fixed;
188 | width: 100%;
189 | height: 100%;
190 | left: 0;
191 | top: 0;
192 | z-index: 1000;
193 | display: flex;
194 | align-items: center;
195 | justify-content: center;
196 | background: rgba(255, 255, 255, .8);
197 | text-align: center;
198 | transition: all 0.3s;
199 | }
200 |
201 | #qrcontainer.hidden {
202 | opacity: 0;
203 | visibility: hidden;
204 | }
205 |
206 | #qrcontainer .qframe {
207 | background-color: #ffffff;
208 | padding: 1rem;
209 | border-radius: 0.5rem;
210 | border: #6D8A88 1px solid;
211 | -webkit-box-shadow: 0px 0px 7px 3px rgba(0, 0, 0, 0.2);
212 | box-shadow: 0px 0px 7px 3px rgba(0, 0, 0, 0.2);
213 | position: relative;
214 | }
215 |
216 | #qrcontainer .qframe #refresh_qrcode {
217 | width: 256px;
218 | height: 256px;
219 | position: absolute;
220 | background-color: rgba(0, 0, 0, 0.5);
221 | left: 1rem;
222 | top: 1rem;
223 | color: #ffffff;
224 | display: flex;
225 | justify-content: center;
226 | align-items: center;
227 | }
228 |
229 | #qrcontainer .qframe #refresh_qrcode.hidden {
230 | opacity: 0;
231 | visibility: hidden;
232 | }
233 |
234 | #qrcontainer .qframe #refresh_qrcode h3 {
235 | font-weight: normal;
236 | }
237 |
238 | #qrcontainer .qframe #refresh_qrcode .refresh {
239 | display: block;
240 | background: #e4393c;
241 | width: 80px;
242 | height: 30px;
243 | margin: 0 auto;
244 | line-height: 30px;
245 | opacity: 1;
246 | z-index: 19;
247 | color: #fbfbfb;
248 | text-decoration: none;
249 | cursor: pointer;
250 | }
251 |
252 | #qrcontainer .qframe .info {
253 | padding: 1rem 0 0 0;
254 | }
255 |
256 | #qrcontainer .qframe .qframe-close {
257 | font-size: 20px;
258 | color: #f00;
259 | cursor: pointer;
260 | }
261 |
262 | @media screen and (max-width: 480px) {
263 |
264 | nav ul li a:link,
265 | nav ul li a:visited,
266 | nav ul li a:active {
267 | font-size: 0.75rem;
268 | padding: 0.5rem 0.5rem;
269 | margin: 0;
270 |
271 | }
272 |
273 | .container p {
274 | font-size: 0.75rem;
275 | margin: 0;
276 | line-height: 1.5em;
277 | }
278 | }
279 |
280 | .log-container {
281 | display: flex;
282 | flex-direction: column;
283 | height: 100vh;
284 | margin: 0 .5em;
285 | }
286 |
287 | @media (min-width: 992px) {
288 | .elk-app {
289 | height: 100%;
290 | }
291 |
292 | .elk-side {
293 | width: 20rem;
294 | }
295 |
296 | .elk-container,
297 | .elk-main,
298 | .elk-side {
299 | overflow-y: auto;
300 | }
301 | }
302 |
303 | .bg-light {
304 | background-color: #f8f9fa !important;
305 | }
306 |
307 | .left-list {
308 | overflow: auto;
309 | z-index: 100;
310 | }
311 |
312 | .text-dark {
313 | color: #343a40 !important;
314 | }
315 |
316 | .nav-link {
317 | font-size: 18px;
318 | color: #007bff;
319 | text-decoration: none;
320 | background-color: transparent;
321 | }
322 |
323 | /* diff页面 */
324 | .CodeMirror-merge {
325 | flex: 1;
326 | width: 100%;
327 | height: auto;
328 | display: flex;
329 | overflow: hidden;
330 | }
331 |
332 | .CodeMirror-merge .CodeMirror {
333 | height: 100%;
334 | }
335 |
336 | .CodeMirror-merge-2pane .CodeMirror-merge-pane {
337 | width: calc(50% - 15px);
338 | }
339 |
340 | .CodeMirror-merge-2pane .CodeMirror-merge-gap {
341 | width: 30px;
342 | background: #1E411F
343 | }
344 |
345 | .CodeMirror-merge-2pane .CodeMirror-merge-scrolllock {
346 | display: none;
347 | }
348 |
349 | .CodeMirror-merge-pane-rightmost {
350 | position: static;
351 | }
352 |
353 | /* 更新工具差异处颜色 */
354 | .CodeMirror-merge-r-chunk {
355 | background: #1E411F
356 | }
357 |
358 | .CodeMirror-merge-r-chunk-start {
359 | border-top: 1px solid #1E411F;
360 | }
361 |
362 | .CodeMirror-merge-r-chunk-end {
363 | border-bottom: 1px solid #1E411F;
364 | }
365 |
366 | .CodeMirror-merge-r-connect {
367 | fill: #ebdc5c;
368 | stroke: rgb(148, 238, 136);
369 | stroke-width: 1px;
370 | }
371 |
372 | /* 手动执行脚本页面 */
373 | .run-cmd-form {
374 | margin-top: 6px;
375 | }
376 |
377 | .cmd-section {
378 | border-color: #1e90ff;
379 | -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px #1e90ff;
380 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px #1e90ff;
381 |
382 | }
383 |
384 | .cmd-section input {
385 | width: 150px;
386 | height: 20px;
387 | -moz-animation: glow 800ms ease-out infinite alternate;
388 | -o-animation: glow 800ms ease-out infinite alternate;
389 | -ms-animation: glow 800ms ease-out infinite alternate;
390 | animation: glow 800ms ease-out infinite alternate;
391 | background: #222922;
392 | background: -webkit-linear-gradient(#333933, #222922);
393 | background: -moz-linear-gradient(#333933, #222922);
394 | background: -o-linear-gradient(#333933, #222922);
395 | background: -ms-linear-gradient(#333933, #222922);
396 | background: linear-gradient(#333933, #222922);
397 | color: #efe;
398 | outline: none;
399 | }
400 |
401 |
402 | /* 按钮配置 */
403 | button {
404 | /* 静态背景颜色 */
405 | background: #000000;
406 | /* 静态字体颜色 */
407 | color: rgb(255, 255, 255);
408 | border: none;
409 | position: relative;
410 | height: 30px;
411 | font-size: 0.6em;
412 | padding: 0 1em;
413 | cursor: pointer;
414 | transition: 200ms ease all;
415 | outline: none;
416 | }
417 |
418 | button:hover {
419 | /* 静态字体颜色 */
420 | color: #000000;
421 | /* 点击背景颜色 */
422 | background: rgb(255, 255, 255);
423 |
424 | }
425 |
426 | button:before,
427 | button:after {
428 | content: '';
429 | position: absolute;
430 | top: 0;
431 | right: 0;
432 | height: 0px;
433 | width: 0;
434 | /* 线条动画颜色 */
435 | background: #535252;
436 | transition: 400ms ease all;
437 | }
438 |
439 | button:after {
440 | right: inherit;
441 | top: inherit;
442 | left: 0;
443 | bottom: 0;
444 | }
445 |
446 | button:hover:before,
447 | button:hover:after {
448 | width: 100%;
449 | transition: 500ms ease all;
450 | }
451 |
452 | .ant-btn {
453 | line-height: 1.499;
454 | position: relative;
455 | display: inline-block;
456 | font-weight: 400;
457 | white-space: nowrap;
458 | text-align: center;
459 | background-image: none;
460 | border: 1px solid transparent;
461 | -webkit-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
462 | box-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
463 | cursor: pointer;
464 | -webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1);
465 | transition: all .3s cubic-bezier(.645, .045, .355, 1);
466 | -webkit-user-select: none;
467 | -moz-user-select: none;
468 | -ms-user-select: none;
469 | user-select: none;
470 | -ms-touch-action: manipulation;
471 | touch-action: manipulation;
472 | height: 32px;
473 | padding: 0 15px;
474 | font-size: 14px;
475 | border-radius: 4px;
476 | color: rgba(0, 0, 0, 0.65);
477 | background-color: #fff;
478 | border-color: #d9d9d9;
479 | }
480 |
481 | .ant-btn-primary {
482 | color: #fff;
483 | background-color: #1890ff;
484 | border-color: #1890ff;
485 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
486 | -webkit-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
487 | box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
488 | }
489 |
490 | .ant-btn-red {
491 | color: #fff;
492 | background-color: #FF5A44;
493 | border-color: #FF5A44;
494 | border-radius: 6px 6px 6px 6px;
495 | -moz-border-radius: 6px 6px 6px 6px;
496 | -webkit-border-radius: 6px 6px 6px 6px;
497 | }
498 |
--------------------------------------------------------------------------------
/panel/public/css/merge.css:
--------------------------------------------------------------------------------
1 | .CodeMirror-merge {
2 | position: relative;
3 | border: 1px solid #ddd;
4 | white-space: pre;
5 | }
6 |
7 | .CodeMirror-merge, .CodeMirror-merge .CodeMirror {
8 | height: 350px;
9 | }
10 |
11 | .CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
12 | .CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
13 | .CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
14 | .CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
15 |
16 | .CodeMirror-merge-pane {
17 | display: inline-block;
18 | white-space: normal;
19 | vertical-align: top;
20 | }
21 | .CodeMirror-merge-pane-rightmost {
22 | position: absolute;
23 | right: 0px;
24 | z-index: 1;
25 | }
26 |
27 | .CodeMirror-merge-gap {
28 | z-index: 2;
29 | display: inline-block;
30 | height: 100%;
31 | -moz-box-sizing: border-box;
32 | box-sizing: border-box;
33 | overflow: hidden;
34 | border-left: 1px solid #ddd;
35 | border-right: 1px solid #ddd;
36 | position: relative;
37 | background: #f8f8f8;
38 | }
39 |
40 | .CodeMirror-merge-scrolllock-wrap {
41 | position: absolute;
42 | bottom: 0; left: 50%;
43 | }
44 | .CodeMirror-merge-scrolllock {
45 | position: relative;
46 | left: -50%;
47 | cursor: pointer;
48 | color: #555;
49 | line-height: 1;
50 | }
51 | .CodeMirror-merge-scrolllock:after {
52 | content: "\21db\00a0\00a0\21da";
53 | }
54 | .CodeMirror-merge-scrolllock.CodeMirror-merge-scrolllock-enabled:after {
55 | content: "\21db\21da";
56 | }
57 |
58 | .CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
59 | position: absolute;
60 | left: 0; top: 0;
61 | right: 0; bottom: 0;
62 | line-height: 1;
63 | }
64 |
65 | .CodeMirror-merge-copy {
66 | position: absolute;
67 | cursor: pointer;
68 | color: #44c;
69 | z-index: 3;
70 | }
71 |
72 | .CodeMirror-merge-copy-reverse {
73 | position: absolute;
74 | cursor: pointer;
75 | color: #44c;
76 | }
77 |
78 | .CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
79 | .CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
80 |
81 | .CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
82 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
83 | background-position: bottom left;
84 | background-repeat: repeat-x;
85 | }
86 |
87 | .CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
88 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
89 | background-position: bottom left;
90 | background-repeat: repeat-x;
91 | }
92 |
93 | .CodeMirror-merge-r-chunk { background: #ffffe0; }
94 | .CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
95 | .CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
96 | .CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
97 |
98 | .CodeMirror-merge-l-chunk { background: #eef; }
99 | .CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
100 | .CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
101 | .CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
102 |
103 | .CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
104 | .CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
105 | .CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
106 |
107 | .CodeMirror-merge-collapsed-widget:before {
108 | content: "(...)";
109 | }
110 | .CodeMirror-merge-collapsed-widget {
111 | cursor: pointer;
112 | color: #88b;
113 | background: #eef;
114 | border: 1px solid #ddf;
115 | font-size: 90%;
116 | padding: 0 3px;
117 | border-radius: 4px;
118 | }
119 | .CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
120 |
--------------------------------------------------------------------------------
/panel/public/css/normalize.min.css:
--------------------------------------------------------------------------------
1 | button,
2 | hr,
3 | input {
4 | overflow: visible
5 | }
6 |
7 | audio,
8 | canvas,
9 | progress,
10 | video {
11 | display: inline-block
12 | }
13 |
14 | progress,
15 | sub,
16 | sup {
17 | vertical-align: baseline
18 | }
19 |
20 | html {
21 | font-family: sans-serif;
22 | line-height: 1.15;
23 | -ms-text-size-adjust: 100%;
24 | -webkit-text-size-adjust: 100%
25 | }
26 |
27 | body {
28 | margin: 0
29 | }
30 |
31 | menu,
32 | article,
33 | aside,
34 | details,
35 | footer,
36 | header,
37 | nav,
38 | section {
39 | display: block
40 | }
41 |
42 | h1 {
43 | font-size: 2em;
44 | margin: .67em 0
45 | }
46 |
47 | figcaption,
48 | figure,
49 | main {
50 | display: block
51 | }
52 |
53 | figure {
54 | margin: 1em 40px
55 | }
56 |
57 | hr {
58 | box-sizing: content-box;
59 | height: 0
60 | }
61 |
62 | code,
63 | kbd,
64 | pre,
65 | samp {
66 | font-family: monospace, monospace;
67 | font-size: 1em
68 | }
69 |
70 | a {
71 | background-color: transparent;
72 | -webkit-text-decoration-skip: objects
73 | }
74 |
75 | a:active,
76 | a:hover {
77 | outline-width: 0
78 | }
79 |
80 | abbr[title] {
81 | border-bottom: none;
82 | text-decoration: underline;
83 | text-decoration: underline dotted
84 | }
85 |
86 | b,
87 | strong {
88 | font-weight: bolder
89 | }
90 |
91 | dfn {
92 | font-style: italic
93 | }
94 |
95 | mark {
96 | background-color: #ff0;
97 | color: #000
98 | }
99 |
100 | small {
101 | font-size: 80%
102 | }
103 |
104 | sub,
105 | sup {
106 | font-size: 75%;
107 | line-height: 0;
108 | position: relative
109 | }
110 |
111 | sub {
112 | bottom: -.25em
113 | }
114 |
115 | sup {
116 | top: -.5em
117 | }
118 |
119 | audio:not([controls]) {
120 | display: none;
121 | height: 0
122 | }
123 |
124 | img {
125 | border-style: none
126 | }
127 |
128 | svg:not(:root) {
129 | overflow: hidden
130 | }
131 |
132 | button,
133 | input,
134 | optgroup,
135 | select,
136 | textarea {
137 | font-family: sans-serif;
138 | font-size: 100%;
139 | line-height: 1.15;
140 | margin: 0
141 | }
142 |
143 | button,
144 | select {
145 | text-transform: none
146 | }
147 |
148 | [type=submit],
149 | [type=reset],
150 | button,
151 | html [type=button] {
152 | -webkit-appearance: button
153 | }
154 |
155 | [type=button]::-moz-focus-inner,
156 | [type=reset]::-moz-focus-inner,
157 | [type=submit]::-moz-focus-inner,
158 | button::-moz-focus-inner {
159 | border-style: none;
160 | padding: 0
161 | }
162 |
163 | [type=button]:-moz-focusring,
164 | [type=reset]:-moz-focusring,
165 | [type=submit]:-moz-focusring,
166 | button:-moz-focusring {
167 | outline: ButtonText dotted 1px
168 | }
169 |
170 | fieldset {
171 | border: 1px solid silver;
172 | margin: 0 2px;
173 | padding: .35em .625em .75em
174 | }
175 |
176 | legend {
177 | box-sizing: border-box;
178 | color: inherit;
179 | display: table;
180 | max-width: 100%;
181 | padding: 0;
182 | white-space: normal
183 | }
184 |
185 |
186 |
187 | textarea {
188 | overflow: auto
189 | }
190 |
191 | [type=checkbox],
192 | [type=radio] {
193 | box-sizing: border-box;
194 | padding: 0
195 | }
196 |
197 | [type=number]::-webkit-inner-spin-button,
198 | [type=number]::-webkit-outer-spin-button {
199 | height: auto
200 | }
201 |
202 | [type=search] {
203 | -webkit-appearance: textfield;
204 | outline-offset: -2px
205 | }
206 |
207 | [type=search]::-webkit-search-cancel-button,
208 | [type=search]::-webkit-search-decoration {
209 | -webkit-appearance: none
210 | }
211 |
212 | ::-webkit-file-upload-button {
213 | -webkit-appearance: button;
214 | font: inherit
215 | }
216 |
217 | summary {
218 | display: list-item
219 | }
220 |
221 | [hidden],
222 | template {
223 | display: none
224 | }
225 |
226 | /*# sourceMappingURL=normalize.min.css.map */
--------------------------------------------------------------------------------
/panel/public/css/style.css:
--------------------------------------------------------------------------------
1 | /*Sakura animation using WebGL. No images are used. The framerate might be slow or the demo might not play at all in some older systems so you can watch this video: http://www.screenr.com/BFZ8. Let me make it clear that I did not make this and just thought is was very cool and wanted to share it.
2 | */
3 |
4 | body {
5 | padding: 0;
6 | margin: 0;
7 | overflow: hidden;
8 | height: 600px;
9 | }
10 |
11 | canvas {
12 | padding: 0;
13 | margin: 0;
14 | }
--------------------------------------------------------------------------------
/panel/public/css/twilight.css:
--------------------------------------------------------------------------------
1 | .cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/
2 | .cm-s-twilight div.CodeMirror-selected { background: #323232; } /**/
3 | .cm-s-twilight .CodeMirror-line::selection, .cm-s-twilight .CodeMirror-line > span::selection, .cm-s-twilight .CodeMirror-line > span > span::selection { background: rgba(50, 50, 50, 0.99); }
4 | .cm-s-twilight .CodeMirror-line::-moz-selection, .cm-s-twilight .CodeMirror-line > span::-moz-selection, .cm-s-twilight .CodeMirror-line > span > span::-moz-selection { background: rgba(50, 50, 50, 0.99); }
5 |
6 | .cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; }
7 | .cm-s-twilight .CodeMirror-guttermarker { color: white; }
8 | .cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; }
9 | .cm-s-twilight .CodeMirror-linenumber { color: #aaa; }
10 | .cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white; }
11 |
12 | .cm-s-twilight .cm-keyword { color: #f9ee98; } /**/
13 | .cm-s-twilight .cm-atom { color: #FC0; }
14 | .cm-s-twilight .cm-number { color: #ca7841; } /**/
15 | .cm-s-twilight .cm-def { color: #8DA6CE; }
16 | .cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/
17 | .cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def, .cm-s-twilight span.cm-type { color: #607392; } /**/
18 | .cm-s-twilight .cm-operator { color: #cda869; } /**/
19 | .cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/
20 | .cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/
21 | .cm-s-twilight .cm-string-2 { color:#bd6b18; } /*?*/
22 | .cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/
23 | .cm-s-twilight .cm-builtin { color: #cda869; } /*?*/
24 | .cm-s-twilight .cm-tag { color: #997643; } /**/
25 | .cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/
26 | .cm-s-twilight .cm-header { color: #FF6400; }
27 | .cm-s-twilight .cm-hr { color: #AEAEAE; }
28 | .cm-s-twilight .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } /**/
29 | .cm-s-twilight .cm-error { border-bottom: 1px solid red; }
30 |
31 | .cm-s-twilight .CodeMirror-activeline-background { background: #27282E; }
32 | .cm-s-twilight .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }
33 |
--------------------------------------------------------------------------------
/panel/public/diff.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 在线更新工具 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
39 |
40 | 在线对比合并工具
41 |
42 |
43 |
44 |
45 |
46 |
左侧为 config.sh ,右侧为 config.sh.sample
47 |
51 |
52 |
查看源文件,注意将浏览器编码切换为 UTF-8 。
53 |
57 |
58 |
59 |
60 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/panel/public/diy.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 自定义脚本 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
42 |
43 | 在线编辑工具
44 |
45 |
46 |
47 |
自定义脚本 温馨提示:此脚本的用途为收集并添加第三方作者编写的活动脚本,关于如何启用该功能详见配置文件中的《DIY脚本功能设置》模块。
48 |
49 |
50 |
51 |
52 |
53 |
54 |
97 |
98 |
99 |
100 |
101 |
--------------------------------------------------------------------------------
/panel/public/helpcode.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 手动互助码填写区域 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
38 |
39 | 在线对比合并工具
40 |
41 |
42 |
43 |
44 |
45 |
左侧为 sharecode.sh ,右侧为 sharecode.sh.sample
46 |
50 |
51 |
查看源文件,注意将浏览器编码切换为 UTF-8 。
52 |
56 |
57 |
58 |
59 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/panel/public/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 用户设定 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
43 |
54 |
配置文件 温馨提示:每次保存都会在 config/bak 目录下生成备份文件
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
69 |
70 |
请使用手机京东APP扫码
71 |
✖
72 |
73 |
74 |
235 |
236 |
237 |
238 |
239 |
--------------------------------------------------------------------------------
/panel/public/js/comment.js:
--------------------------------------------------------------------------------
1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 | // Distributed under an MIT license: https://codemirror.net/LICENSE
3 |
4 | (function(mod) {
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS
6 | mod(require("../../lib/codemirror"));
7 | else if (typeof define == "function" && define.amd) // AMD
8 | define(["../../lib/codemirror"], mod);
9 | else // Plain browser env
10 | mod(CodeMirror);
11 | })(function(CodeMirror) {
12 | "use strict";
13 |
14 | var noOptions = {};
15 | var nonWS = /[^\s\u00a0]/;
16 | var Pos = CodeMirror.Pos, cmp = CodeMirror.cmpPos;
17 |
18 | function firstNonWS(str) {
19 | var found = str.search(nonWS);
20 | return found == -1 ? 0 : found;
21 | }
22 |
23 | CodeMirror.commands.toggleComment = function(cm) {
24 | cm.toggleComment();
25 | };
26 |
27 | CodeMirror.defineExtension("toggleComment", function(options) {
28 | if (!options) options = noOptions;
29 | var cm = this;
30 | var minLine = Infinity, ranges = this.listSelections(), mode = null;
31 | for (var i = ranges.length - 1; i >= 0; i--) {
32 | var from = ranges[i].from(), to = ranges[i].to();
33 | if (from.line >= minLine) continue;
34 | if (to.line >= minLine) to = Pos(minLine, 0);
35 | minLine = from.line;
36 | if (mode == null) {
37 | if (cm.uncomment(from, to, options)) mode = "un";
38 | else { cm.lineComment(from, to, options); mode = "line"; }
39 | } else if (mode == "un") {
40 | cm.uncomment(from, to, options);
41 | } else {
42 | cm.lineComment(from, to, options);
43 | }
44 | }
45 | });
46 |
47 | // Rough heuristic to try and detect lines that are part of multi-line string
48 | function probablyInsideString(cm, pos, line) {
49 | return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
50 | }
51 |
52 | function getMode(cm, pos) {
53 | var mode = cm.getMode()
54 | return mode.useInnerComments === false || !mode.innerMode ? mode : cm.getModeAt(pos)
55 | }
56 |
57 | CodeMirror.defineExtension("lineComment", function(from, to, options) {
58 | if (!options) options = noOptions;
59 | var self = this, mode = getMode(self, from);
60 | var firstLine = self.getLine(from.line);
61 | if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
62 |
63 | var commentString = options.lineComment || mode.lineComment;
64 | if (!commentString) {
65 | if (options.blockCommentStart || mode.blockCommentStart) {
66 | options.fullLines = true;
67 | self.blockComment(from, to, options);
68 | }
69 | return;
70 | }
71 |
72 | var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
73 | var pad = options.padding == null ? " " : options.padding;
74 | var blankLines = options.commentBlankLines || from.line == to.line;
75 |
76 | self.operation(function() {
77 | if (options.indent) {
78 | var baseString = null;
79 | for (var i = from.line; i < end; ++i) {
80 | var line = self.getLine(i);
81 | var whitespace = line.slice(0, firstNonWS(line));
82 | if (baseString == null || baseString.length > whitespace.length) {
83 | baseString = whitespace;
84 | }
85 | }
86 | for (var i = from.line; i < end; ++i) {
87 | var line = self.getLine(i), cut = baseString.length;
88 | if (!blankLines && !nonWS.test(line)) continue;
89 | if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
90 | self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
91 | }
92 | } else {
93 | for (var i = from.line; i < end; ++i) {
94 | if (blankLines || nonWS.test(self.getLine(i)))
95 | self.replaceRange(commentString + pad, Pos(i, 0));
96 | }
97 | }
98 | });
99 | });
100 |
101 | CodeMirror.defineExtension("blockComment", function(from, to, options) {
102 | if (!options) options = noOptions;
103 | var self = this, mode = getMode(self, from);
104 | var startString = options.blockCommentStart || mode.blockCommentStart;
105 | var endString = options.blockCommentEnd || mode.blockCommentEnd;
106 | if (!startString || !endString) {
107 | if ((options.lineComment || mode.lineComment) && options.fullLines != false)
108 | self.lineComment(from, to, options);
109 | return;
110 | }
111 | if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return
112 |
113 | var end = Math.min(to.line, self.lastLine());
114 | if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
115 |
116 | var pad = options.padding == null ? " " : options.padding;
117 | if (from.line > end) return;
118 |
119 | self.operation(function() {
120 | if (options.fullLines != false) {
121 | var lastLineHasText = nonWS.test(self.getLine(end));
122 | self.replaceRange(pad + endString, Pos(end));
123 | self.replaceRange(startString + pad, Pos(from.line, 0));
124 | var lead = options.blockCommentLead || mode.blockCommentLead;
125 | if (lead != null) for (var i = from.line + 1; i <= end; ++i)
126 | if (i != end || lastLineHasText)
127 | self.replaceRange(lead + pad, Pos(i, 0));
128 | } else {
129 | var atCursor = cmp(self.getCursor("to"), to) == 0, empty = !self.somethingSelected()
130 | self.replaceRange(endString, to);
131 | if (atCursor) self.setSelection(empty ? to : self.getCursor("from"), to)
132 | self.replaceRange(startString, from);
133 | }
134 | });
135 | });
136 |
137 | CodeMirror.defineExtension("uncomment", function(from, to, options) {
138 | if (!options) options = noOptions;
139 | var self = this, mode = getMode(self, from);
140 | var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
141 |
142 | // Try finding line comments
143 | var lineString = options.lineComment || mode.lineComment, lines = [];
144 | var pad = options.padding == null ? " " : options.padding, didSomething;
145 | lineComment: {
146 | if (!lineString) break lineComment;
147 | for (var i = start; i <= end; ++i) {
148 | var line = self.getLine(i);
149 | var found = line.indexOf(lineString);
150 | if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
151 | if (found == -1 && nonWS.test(line)) break lineComment;
152 | if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
153 | lines.push(line);
154 | }
155 | self.operation(function() {
156 | for (var i = start; i <= end; ++i) {
157 | var line = lines[i - start];
158 | var pos = line.indexOf(lineString), endPos = pos + lineString.length;
159 | if (pos < 0) continue;
160 | if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
161 | didSomething = true;
162 | self.replaceRange("", Pos(i, pos), Pos(i, endPos));
163 | }
164 | });
165 | if (didSomething) return true;
166 | }
167 |
168 | // Try block comments
169 | var startString = options.blockCommentStart || mode.blockCommentStart;
170 | var endString = options.blockCommentEnd || mode.blockCommentEnd;
171 | if (!startString || !endString) return false;
172 | var lead = options.blockCommentLead || mode.blockCommentLead;
173 | var startLine = self.getLine(start), open = startLine.indexOf(startString)
174 | if (open == -1) return false
175 | var endLine = end == start ? startLine : self.getLine(end)
176 | var close = endLine.indexOf(endString, end == start ? open + startString.length : 0);
177 | var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1)
178 | if (close == -1 ||
179 | !/comment/.test(self.getTokenTypeAt(insideStart)) ||
180 | !/comment/.test(self.getTokenTypeAt(insideEnd)) ||
181 | self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
182 | return false;
183 |
184 | // Avoid killing block comments completely outside the selection.
185 | // Positions of the last startString before the start of the selection, and the first endString after it.
186 | var lastStart = startLine.lastIndexOf(startString, from.ch);
187 | var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
188 | if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
189 | // Positions of the first endString after the end of the selection, and the last startString before it.
190 | firstEnd = endLine.indexOf(endString, to.ch);
191 | var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
192 | lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
193 | if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
194 |
195 | self.operation(function() {
196 | self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
197 | Pos(end, close + endString.length));
198 | var openEnd = open + startString.length;
199 | if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
200 | self.replaceRange("", Pos(start, open), Pos(start, openEnd));
201 | if (lead) for (var i = start + 1; i <= end; ++i) {
202 | var line = self.getLine(i), found = line.indexOf(lead);
203 | if (found == -1 || nonWS.test(line.slice(0, found))) continue;
204 | var foundEnd = found + lead.length;
205 | if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
206 | self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
207 | }
208 | });
209 | return true;
210 | });
211 | });
212 |
--------------------------------------------------------------------------------
/panel/public/js/qrcode.min.js:
--------------------------------------------------------------------------------
1 | var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j=0?p.get(q):0}}for(var r=0,m=0;mm;m++)for(var j=0;jm;m++)for(var j=0;j=0;)b^=f.G15<=0;)b^=f.G18<>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;cf;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=[''],h=0;d>h;h++){g.push("");for(var i=0;d>i;i++)g.push(' | ');g.push("
")}g.push("
"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}();
--------------------------------------------------------------------------------
/panel/public/js/shell.js:
--------------------------------------------------------------------------------
1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 | // Distributed under an MIT license: https://codemirror.net/LICENSE
3 |
4 | (function(mod) {
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS
6 | mod(require("../../lib/codemirror"));
7 | else if (typeof define == "function" && define.amd) // AMD
8 | define(["../../lib/codemirror"], mod);
9 | else // Plain browser env
10 | mod(CodeMirror);
11 | })(function(CodeMirror) {
12 | "use strict";
13 |
14 | CodeMirror.defineMode('shell', function() {
15 |
16 | var words = {};
17 | function define(style, dict) {
18 | for(var i = 0; i < dict.length; i++) {
19 | words[dict[i]] = style;
20 | }
21 | };
22 |
23 | var commonAtoms = ["true", "false"];
24 | var commonKeywords = ["if", "then", "do", "else", "elif", "while", "until", "for", "in", "esac", "fi",
25 | "fin", "fil", "done", "exit", "set", "unset", "export", "function"];
26 | var commonCommands = ["ab", "awk", "bash", "beep", "cat", "cc", "cd", "chown", "chmod", "chroot", "clear",
27 | "cp", "curl", "cut", "diff", "echo", "find", "gawk", "gcc", "get", "git", "grep", "hg", "kill", "killall",
28 | "ln", "ls", "make", "mkdir", "openssl", "mv", "nc", "nl", "node", "npm", "ping", "ps", "restart", "rm",
29 | "rmdir", "sed", "service", "sh", "shopt", "shred", "source", "sort", "sleep", "ssh", "start", "stop",
30 | "su", "sudo", "svn", "tee", "telnet", "top", "touch", "vi", "vim", "wall", "wc", "wget", "who", "write",
31 | "yes", "zsh"];
32 |
33 | CodeMirror.registerHelper("hintWords", "shell", commonAtoms.concat(commonKeywords, commonCommands));
34 |
35 | define('atom', commonAtoms);
36 | define('keyword', commonKeywords);
37 | define('builtin', commonCommands);
38 |
39 | function tokenBase(stream, state) {
40 | if (stream.eatSpace()) return null;
41 |
42 | var sol = stream.sol();
43 | var ch = stream.next();
44 |
45 | if (ch === '\\') {
46 | stream.next();
47 | return null;
48 | }
49 | if (ch === '\'' || ch === '"' || ch === '`') {
50 | state.tokens.unshift(tokenString(ch, ch === "`" ? "quote" : "string"));
51 | return tokenize(stream, state);
52 | }
53 | if (ch === '#') {
54 | if (sol && stream.eat('!')) {
55 | stream.skipToEnd();
56 | return 'meta'; // 'comment'?
57 | }
58 | stream.skipToEnd();
59 | return 'comment';
60 | }
61 | if (ch === '$') {
62 | state.tokens.unshift(tokenDollar);
63 | return tokenize(stream, state);
64 | }
65 | if (ch === '+' || ch === '=') {
66 | return 'operator';
67 | }
68 | if (ch === '-') {
69 | stream.eat('-');
70 | stream.eatWhile(/\w/);
71 | return 'attribute';
72 | }
73 | if (ch == "<") {
74 | if (stream.match("<<")) return "operator"
75 | var heredoc = stream.match(/^<-?\s*['"]?([^'"]*)['"]?/)
76 | if (heredoc) {
77 | state.tokens.unshift(tokenHeredoc(heredoc[1]))
78 | return 'string-2'
79 | }
80 | }
81 | if (/\d/.test(ch)) {
82 | stream.eatWhile(/\d/);
83 | if(stream.eol() || !/\w/.test(stream.peek())) {
84 | return 'number';
85 | }
86 | }
87 | stream.eatWhile(/[\w-]/);
88 | var cur = stream.current();
89 | if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
90 | return words.hasOwnProperty(cur) ? words[cur] : null;
91 | }
92 |
93 | function tokenString(quote, style) {
94 | var close = quote == "(" ? ")" : quote == "{" ? "}" : quote
95 | return function(stream, state) {
96 | var next, escaped = false;
97 | while ((next = stream.next()) != null) {
98 | if (next === close && !escaped) {
99 | state.tokens.shift();
100 | break;
101 | } else if (next === '$' && !escaped && quote !== "'" && stream.peek() != close) {
102 | escaped = true;
103 | stream.backUp(1);
104 | state.tokens.unshift(tokenDollar);
105 | break;
106 | } else if (!escaped && quote !== close && next === quote) {
107 | state.tokens.unshift(tokenString(quote, style))
108 | return tokenize(stream, state)
109 | } else if (!escaped && /['"]/.test(next) && !/['"]/.test(quote)) {
110 | state.tokens.unshift(tokenStringStart(next, "string"));
111 | stream.backUp(1);
112 | break;
113 | }
114 | escaped = !escaped && next === '\\';
115 | }
116 | return style;
117 | };
118 | };
119 |
120 | function tokenStringStart(quote, style) {
121 | return function(stream, state) {
122 | state.tokens[0] = tokenString(quote, style)
123 | stream.next()
124 | return tokenize(stream, state)
125 | }
126 | }
127 |
128 | var tokenDollar = function(stream, state) {
129 | if (state.tokens.length > 1) stream.eat('$');
130 | var ch = stream.next()
131 | if (/['"({]/.test(ch)) {
132 | state.tokens[0] = tokenString(ch, ch == "(" ? "quote" : ch == "{" ? "def" : "string");
133 | return tokenize(stream, state);
134 | }
135 | if (!/\d/.test(ch)) stream.eatWhile(/\w/);
136 | state.tokens.shift();
137 | return 'def';
138 | };
139 |
140 | function tokenHeredoc(delim) {
141 | return function(stream, state) {
142 | if (stream.sol() && stream.string == delim) state.tokens.shift()
143 | stream.skipToEnd()
144 | return "string-2"
145 | }
146 | }
147 |
148 | function tokenize(stream, state) {
149 | return (state.tokens[0] || tokenBase) (stream, state);
150 | };
151 |
152 | return {
153 | startState: function() {return {tokens:[]};},
154 | token: function(stream, state) {
155 | return tokenize(stream, state);
156 | },
157 | closeBrackets: "()[]{}''\"\"``",
158 | lineComment: '#',
159 | fold: "brace"
160 | };
161 | });
162 |
163 | CodeMirror.defineMIME('text/x-sh', 'shell');
164 | // Apache uses a slightly different Media Type for Shell scripts
165 | // http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
166 | CodeMirror.defineMIME('application/x-sh', 'shell');
167 |
168 | });
169 |
--------------------------------------------------------------------------------
/panel/public/pwd.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 修改密码 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
35 |
36 |
请输入新的用户名和密码
37 |
42 |
43 |
44 |
45 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/panel/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: Baiduspider
2 | Disallow: /
3 | User-agent: Sosospider
4 | Disallow: /
5 | User-agent: sogou spider
6 | Disallow: /
7 | User-agent: YodaoBot
8 | Disallow: /
9 | User-agent: Googlebot
10 | Disallow: /
11 | User-agent: Bingbot
12 | Disallow: /
13 | User-agent: Slurp
14 | Disallow: /
15 | Disallow: /
16 |
--------------------------------------------------------------------------------
/panel/public/run.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 手动执行脚本 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
40 |
41 | 脚本执行工具
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
279 |
280 |
281 |
282 |
283 |
--------------------------------------------------------------------------------
/panel/public/tasklog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 日志查询 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
162 |
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/panel/public/terminal.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | WebSHELL · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/panel/public/viewScripts.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 查看脚本 · JS-TOOL
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
163 |
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.aarch64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.aarch64
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.arm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.arm
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.armhf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.armhf
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.i686:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.i686
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.mips:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.mips
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.mips64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.mips64
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.mips64el:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.mips64el
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.mipsel:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.mipsel
--------------------------------------------------------------------------------
/panel/webshellbinary/ttyd.x86_64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lan-tianxiang/jd_shell/db86334d03818adb10a782c4ef4326f83d184f46/panel/webshellbinary/ttyd.x86_64
--------------------------------------------------------------------------------
/repair.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ## Author: lan-tianxiang
4 | ## Source: https://github.com/lan-tianxiang/jd_shell
5 | ## Modified: 2021-03-27
6 | ## Version: v0.0.2
7 |
8 | ## 文件路径、脚本网址、文件版本以及各种环境的判断
9 | ShellDir=${JD_DIR:-$(
10 | cd $(dirname $0)
11 | pwd
12 | )}
13 | [[ ${JD_DIR} ]] && ShellJd=jd || ShellJd=${ShellDir}/jd.sh
14 | LogDir=${ShellDir}/log
15 | [ ! -d ${LogDir} ] && mkdir -p ${LogDir}
16 | ScriptsDir=${ShellDir}/scripts
17 | Scripts2Dir=${ShellDir}/scripts2
18 | ConfigDir=${ShellDir}/config
19 | FileConf=${ConfigDir}/config.sh
20 | FileDiy=${ConfigDir}/diy.sh
21 | FileConfSample=${ShellDir}/sample/config.sh.sample
22 | ListCron=${ConfigDir}/crontab.list
23 | ListCronLxk=${ScriptsDir}/docker/crontab_list.sh
24 | ListCronShylocks=${Scripts2Dir}/docker/crontab_list.sh
25 | ListTask=${LogDir}/task.list
26 | ListJs=${LogDir}/js.list
27 | ListJsAdd=${LogDir}/js-add.list
28 | ListJsDrop=${LogDir}/js-drop.list
29 | ContentVersion=${ShellDir}/version
30 | ContentNewTask=${ShellDir}/new_task
31 | ContentDropTask=${ShellDir}/drop_task
32 | SendCount=${ShellDir}/send_count
33 | isTermux=${ANDROID_RUNTIME_ROOT}${ANDROID_ROOT}
34 | WhichDep=$(grep "/jd_shell" "${ShellDir}/.git/config")
35 | Scripts2URL=https://gitee.com/tianxiang-lan/jd_scripts
36 |
37 | cp ${FileConf} $(dirname ${ShellDir})/config.sh
38 | pkill -9 node
39 | bash ${ShellDir}/jd.sh paneloff
40 | rm -rf ${ShellDir}
41 | cd $(dirname ${ShellDir})
42 |
43 | ShellDir_t=$(
44 | cd "$(dirname "$0")"
45 | pwd
46 | )
47 | ShellName_t=$0
48 | JdDir_t=${ShellDir_t}/jd
49 |
50 | function REINSTALLATION() {
51 | echo -e "\n1. 获取源码"
52 | [ -d ${JdDir_t} ] && mv ${JdDir_t} ${JdDir_t}.bak && echo "检测到已有 ${JdDir_t} 目录,已备份为 ${JdDir_t}.bak"
53 | git clone -b v3 https://gitee.com/tianxiang-lan/jd_shell ${JdDir_t}
54 |
55 | echo -e "\n2. 检查配置文件"
56 |
57 | [ ! -d ${JdDir_t}/config ] && mkdir -p ${JdDir_t}/config
58 |
59 | if [ ! -s ${JdDir_t}/config/crontab.list ]; then
60 | cp -fv ${JdDir_t}/sample/crontab.list.sample ${JdDir_t}/config/crontab.list
61 | sed -i "s,MY_PATH,${JdDir_t},g" ${JdDir_t}/config/crontab.list
62 | sed -i "s,ENV_PATH=,PATH=$PATH,g" ${JdDir_t}/config/crontab.list
63 | fi
64 |
65 | crontab ${JdDir_t}/config/crontab.list
66 |
67 | [ -f $(dirname ${ShellDir})/config.sh ] && cp $(dirname ${ShellDir})/config.sh ${ConfigDir}/config.sh && rm -rf $(dirname ${ShellDir})/config.sh
68 | [ ! -s ${JdDir_t}/config/config.sh ] && cp -fv ${JdDir_t}/sample/config.sh.sample ${JdDir_t}/config/config.sh
69 |
70 | echo -e "\n3. 执行 git_pull.sh 进行脚本更新以及定时文件更新"
71 | bash ${JdDir_t}/git_pull.sh
72 |
73 | echo -e "\n修复完成!!!!"
74 | }
75 |
76 | REINSTALLATION
77 |
--------------------------------------------------------------------------------
/rm_log.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ## Author: Evine Deng
4 | ## Source: https://github.com/EvineDeng/jd-base
5 | ## Modified: 2021-01-21
6 | ## Version: v3.2.4
7 |
8 | ## 判断环境
9 | ShellDir=${JD_DIR:-$(
10 | cd $(dirname $0)
11 | pwd
12 | )}
13 | LogDir=${ShellDir}/log
14 |
15 | ## 导入配置文件
16 | . ${ShellDir}/config/config.sh
17 |
18 | ## 删除运行js脚本的旧日志
19 | function Rm_JsLog {
20 | LogFileList=$(ls -l ${LogDir}/*/*.log | awk '{print $9}')
21 | for log in ${LogFileList}; do
22 | LogDate=$(echo ${log} | awk -F "/" '{print $NF}' | cut -c1-10) #文件名比文件属性获得的日期要可靠
23 | if [[ $(uname -s) == Darwin ]]; then
24 | DiffTime=$(($(date +%s) - $(date -j -f "%Y-%m-%d" "${LogDate}" +%s)))
25 | else
26 | DiffTime=$(($(date +%s) - $(date +%s -d "${LogDate}")))
27 | fi
28 | [ ${DiffTime} -gt $((${RmLogDaysAgo} * 86400)) ] && rm -vf ${log}
29 | done
30 | }
31 |
32 | ## 删除git_pull.sh的运行日志
33 | function Rm_GitPullLog {
34 | if [[ $(uname -s) == Darwin ]]; then
35 | DateDelLog=$(date -v-${RmLogDaysAgo}d "+%Y-%m-%d")
36 | else
37 | Stmp=$(($(date "+%s") - 86400 * ${RmLogDaysAgo}))
38 | DateDelLog=$(date -d "@${Stmp}" "+%Y-%m-%d")
39 | fi
40 | LineEndGitPull=$(($(cat ${LogDir}/git_pull.log | grep -n "${DateDelLog} " | head -1 | awk -F ":" '{print $1}') - 3))
41 | [ ${LineEndGitPull} -gt 0 ] && perl -i -ne "{print unless 1 .. ${LineEndGitPull} }" ${LogDir}/git_pull.log
42 | }
43 |
44 | ## 删除空文件夹
45 | function Rm_EmptyDir {
46 | cd ${LogDir}
47 | for dir in $(ls); do
48 | if [ -d ${dir} ] && [[ $(ls ${dir}) == "" ]]; then
49 | rm -rf ${dir}
50 | fi
51 | done
52 | }
53 |
54 | ## 运行
55 | if [ -n "${RmLogDaysAgo}" ]; then
56 | Rm_JsLog
57 | Rm_GitPullLog
58 | Rm_EmptyDir
59 | fi
60 |
--------------------------------------------------------------------------------
/sample/auth.json:
--------------------------------------------------------------------------------
1 | {"user":"admin","password":"adminadmin"}
--------------------------------------------------------------------------------
/sample/crontab.list.sample:
--------------------------------------------------------------------------------
1 | ENV_PATH=
2 |
3 | # 更新lxk0301大佬的js脚本和shell脚本,并替换相关参数:
4 | 22 * * * * bash MY_PATH/git_pull.sh >> MY_PATH/log/git_pull.log 2>&1
5 |
6 | # 删除 RmLogDaysAgo 指定天数以前的旧日志,本行为不记录日志:
7 | 57 13 * * * bash MY_PATH/rm_log.sh >/dev/null 2>&1
8 |
9 | # 导出所有互助码清单,日志在log/export_sharecodes下(可通过面板或者日记查看):
10 | 48 * * * * bash MY_PATH/export_sharecodes.sh
11 |
12 | # 重启挂机脚本:
13 | # 33 13 * * * bash MY_PATH/jd.sh hangup
14 |
15 | # 自定义定时区,添加自己其他想加的定时任务:
16 |
17 |
18 | # 运行lxk0301大佬的js脚本,仅列出长期任务作初始化用,AutoAddCron=true时,将自动添加短期任务。
19 | # 请保留任务名称中的前缀"jd_",去掉后缀".js",如果有些任务你不想运行,注释掉就好了,不要删除。否则会重新添加上。
20 | # 非lxk0301/jd_scripts仓库中的脚本不能以“jd_”、“jr_”、“jx_”开头。请在最后保留一个空行。
21 | 5 9 * * * bash MY_PATH/jd.sh jd_bean_change
22 |
--------------------------------------------------------------------------------
/sample/diy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | ## Modified:2021-3-26
3 | echo "lan-tianxiang暂无推荐的第三方脚本"
4 | ############################## 作 者 昵 称 (必填) ##############################
5 | # 使用空格隔开
6 | # author_list="shylocks whyour 799953468 i-chenzhe"
7 |
8 | ############################## 作 者 脚 本 地 址 URL (必填) ##############################
9 | # 例如:https://raw.sevencdn.com/whyour/hundun/master/quanx/jx_nc.js
10 | # 1.从作者库中随意挑选一个脚本地址,每个作者的地址添加一个即可,无须重复添加
11 | # 2.将地址最后的 “脚本名称+后缀” 剪切到下一个变量里(my_scripts_list_xxx)
12 |
13 | ## 目前使用本人收集的脚本库项目用于代替 CDN 加速
14 | #scripts_base_url_1=https://gitee.com/highdimen/jd_scripts/raw/master/
15 | #scripts_base_url_2=https://gitee.com/highdimen/jd_scripts/raw/master/
16 | #scripts_base_url_3=https://gitee.com/highdimen/jd_scripts/raw/master/
17 | #scripts_base_url_4=https://gitee.com/highdimen/jd_scripts/raw/master/
18 |
19 | ## 添加更多脚本地址URL示例:scripts_base_url_3=https://raw.sevencdn.com/whyour/hundun/master/quanx/
20 |
21 | ############################## 作 者 脚 本 名 称 (必填) ##############################
22 | # 将相应作者的脚本填写到以下变量中
23 | #my_scripts_list_1="jd_jdaxc.js jd_xxl_gh.js"
24 | #my_scripts_list_2="jd_factory_component.js"
25 | #my_scripts_list_3="jd_paopao.js"
26 | #my_scripts_list_4="jd_shake.js jd_marketLottery.js jd_superDay.js jd_xmf.js jd_wish.js jd_lenovo.js jd_oneplus.js jd_mgold.js jd_grassy.js jd_sister.js"
27 |
28 | ## 活动脚本名称1:东东爱消除、个护爱消除
29 | ## 活动脚本名称2:京喜工厂Plus
30 | ## 活动脚本名称3:京东泡泡大战
31 | ## 活动脚本名称4:百变大咖秀、超级摇一摇、京东超市-大转盘、超级品类日、众筹许愿池、科技打造品质生活、一加盲盒、金口碑奖 投票、答题赢京豆、乘风破浪的姐姐
32 |
33 | ## 由于CDN代理无法实时更新文件内容,目前使用本人的脚本收集库以解决不能访问 Github 的问题
34 |
35 | ############################## 随 机 函 数 ##############################
36 | #rand() {
37 | # min=$1
38 | # max=$(($2 - $min + 1))
39 | # num=$(cat /proc/sys/kernel/random/uuid | cksum | awk -F ' ' '{print $1}')
40 | # echo $(($num % $max + $min))
41 | #}
42 | #cd ${ShellDir}
43 | #index=1
44 | #for author in $author_list; do
45 | # echo -e "开始下载 $author 的活动脚本:"
46 | # echo -e ''
47 | # # 下载my_scripts_list中的每个js文件,重命名增加前缀"作者昵称_",增加后缀".new"
48 | # eval scripts_list=\$my_scripts_list_${index}
49 | # #echo $scripts_list
50 | # eval url_list=\$scripts_base_url_${index}
51 | # #echo $url_list
52 | # for js in $scripts_list; do
53 | # eval url=$url_list$js
54 | # echo $url
55 | # eval name=$js
56 | # echo $name
57 | # wget -q --no-check-certificate $url -O scripts/$name.new
58 | #
59 | # # 如果上一步下载没问题,才去掉后缀".new",如果上一步下载有问题,就保留之前正常下载的版本
60 | # # 随机添加个cron到crontab.list
61 | # if [ $? -eq 0 ]; then
62 | # mv -f scripts/$name.new scripts/$name
63 | # echo -e "更新 $name 完成...\n"
64 | # croname=$(echo "$name" | awk -F\. '{print $1}')
65 | # script_date=$(cat scripts/$name | grep "http" | awk '{if($1~/^[0-59]/) print $1,$2,$3,$4,$5}' | sort | uniq | head -n 1)
66 | # if [ -z "${script_date}" ]; then
67 | # cron_min=$(rand 1 59)
68 | # cron_hour=$(rand 7 9)
69 | # [ $(grep -c "$croname" ${ListCron}) -eq 0 ] && sed -i "/hangup/a${cron_min} ${cron_hour} * * * bash ${ShellDir}/jd.sh $croname" ${ListCron}
70 | # else
71 | # [ $(grep -c "$croname" ${ListCron}) -eq 0 ] && sed -i "/hangup/a${script_date} bash ${ShellDir}/jd.sh $croname" ${ListCron}
72 | # fi
73 | # else
74 | # [ -f scripts/$name.new ] && rm -f scripts/$name.new
75 | # echo -e "更新 $name 失败,使用上一次正常的版本...\n"
76 | # fi
77 | # done
78 | # index=$(($index + 1))
79 | #done
80 |
81 | ############################## 删 除 失 效 的 活 动 脚 本 ##############################
82 | ## 删除旧版本失效的活动示例: rm -rf ${ScriptsDir}/jd_test.js
83 | #rm -rf ${ScriptsDir}/jd_axc.js
84 | #rm -rf ${ScriptsDir}/jd_shakeBean.js
85 | #rm -rf ${ScriptsDir}/jd_super5G.js
86 | #rm -rf ${ScriptsDir}/jd_mother_jump.js
87 | #rm -rf ${ScriptsDir}/jd_city_cash.js
88 | #rm -rf ${ScriptsDir}/jd_entertainment.js
89 |
90 | ############################## 修 正 定 时 任 务 ##############################
91 | ## 目前两个版本都做了软链接,但为了 Linux 旧版用户可以使用,继续将软链接更改为具体文件
92 | ## 注意两边修改内容区别在于中间内容"jd"、"${ShellDir}/jd.sh"
93 | ## 修正定时任务示例:sed -i "s|bash jd jd_test|bash ${ShellDir}/jd.sh test|g" ${ListCron}
94 | ## sed -i "s|bash jd jd_ceshi|bash ${ShellDir}/jd.sh ceshi|g" ${ListCron}
95 | #sed -i "s|bash jd jd_jdaxc|bash ${ShellDir}/jd.sh jd_jdaxc|g" ${ListCron}
96 | #sed -i "s|bash jd jd_xxl_gh|bash ${ShellDir}/jd.sh jd_xxl_gh|g" ${ListCron}
97 | #sed -i "s|bash jd jd_factory_component|bash ${ShellDir}/jd.sh jd_factory_component|g" ${ListCron}
98 | #sed -i "s|bash jd jd_paopao|bash ${ShellDir}/jd.sh jd_paopao|g" ${ListCron}
99 | #sed -i "s|bash jd jd_entertainment|bash ${ShellDir}/jd.sh jd_entertainment|g" ${ListCron}
100 | #sed -i "s|bash jd jd_shake|bash ${ShellDir}/jd.sh jd_shake|g" ${ListCron}
101 | #sed -i "s|bash jd jd_marketLottery|bash ${ShellDir}/jd.sh jd_marketLottery|g" ${ListCron}
102 | #sed -i "s|bash jd jd_superDay|bash ${ShellDir}/jd.sh jd_superDay|g" ${ListCron}
103 | #sed -i "s|bash jd jd_xmf|bash ${ShellDir}/jd.sh jd_xmf|g" ${ListCron}
104 | #sed -i "s|bash jd jd_wish|bash ${ShellDir}/jd.sh jd_wish|g" ${ListCron}
105 | #sed -i "s|bash jd jd_lenovo|bash ${ShellDir}/jd.sh jd_lenovo|g" ${ListCron}
106 | #sed -i "s|bash jd jd_mother_jump|bash ${ShellDir}/jd.sh jd_mother_jump|g" ${ListCron}
107 | #sed -i "s|bash jd jd_oneplus|bash ${ShellDir}/jd.sh jd_oneplus|g" ${ListCron}
108 | #sed -i "s|bash jd jd_mgold|bash ${ShellDir}/jd.sh jd_mgold|g" ${ListCron}
109 | #sed -i "s|bash jd jd_city_cash|bash ${ShellDir}/jd.sh jd_city_cash|g" ${ListCron}
110 |
--------------------------------------------------------------------------------
/update.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: lxk0301 https://github.com/lxk0301
3 | * @Date: 2020-12-20 13:50:34
4 | * @Last Modified by: lxk0301
5 | * @Last Modified time: 2020-12-20 13:51:02
6 | */
7 | const $ = new Env('通知');
8 | const notify = require('./scripts/sendNotify');
9 | const fs = require('fs');
10 | !(async() => {
11 | await update();
12 | })()
13 | .catch((e) => $.logErr(e))
14 | .finally(() => $.done())
15 |
16 | async function update() {
17 | try {
18 | if (fs.existsSync('new_task')) {
19 | const newTaskContent = await fs.readFileSync('./new_task', 'utf8');
20 | if (newTaskContent) {
21 | await notify.sendNotify('新增薅羊毛任务通知', newTaskContent);
22 | }
23 | }
24 |
25 | if (fs.existsSync('drop_task')) {
26 | const dropTaskContent = await fs.readFileSync('./drop_task', 'utf8');
27 | if (dropTaskContent) {
28 | await notify.sendNotify('删除失效任务通知', dropTaskContent);
29 | }
30 | }
31 |
32 | if (fs.existsSync('version')) {
33 | const versionContent = await fs.readFileSync('./version', 'utf8');
34 | if (versionContent) {
35 | await notify.sendNotify('配置文件更新通知', versionContent);
36 | }
37 | }
38 | } catch (err) {
39 | console.error(err)
40 | }
41 | }
42 | function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,i)=>{s.call(this,t,(t,s,r)=>{t?i(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}isNode(){return"undefined"!=typeof module&&!!module.exports}isQuanX(){return"undefined"!=typeof $task}isSurge(){return"undefined"!=typeof $httpClient&&"undefined"==typeof $loon}isLoon(){return"undefined"!=typeof $loon}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const i=this.getdata(t);if(i)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,i)=>e(i))})}runScript(t,e){return new Promise(s=>{let i=this.getdata("@chavy_boxjs_userCfgs.httpapi");i=i?i.replace(/\n/g,"").trim():i;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[o,h]=i.split("@"),a={url:`http://${h}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":o,Accept:"*/*"}};this.post(a,(t,e,i)=>s(i))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e);if(!s&&!i)return{};{const i=s?t:e;try{return JSON.parse(this.fs.readFileSync(i))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),i=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):i?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const i=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of i)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,i)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[i+1])>>0==+e[i+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,i]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,i,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,i,r]=/^@(.*?)\.(.*?)$/.exec(e),o=this.getval(i),h=i?"null"===o?null:o||"{}":"{}";try{const e=JSON.parse(h);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),i)}catch(e){const o={};this.lodash_set(o,r,t),s=this.setval(JSON.stringify(o),i)}}else s=this.setval(t,e);return s}getval(t){return this.isSurge()||this.isLoon()?$persistentStore.read(t):this.isQuanX()?$prefs.valueForKey(t):this.isNode()?(this.data=this.loaddata(),this.data[t]):this.data&&this.data[t]||null}setval(t,e){return this.isSurge()||this.isLoon()?$persistentStore.write(t,e):this.isQuanX()?$prefs.setValueForKey(t,e):this.isNode()?(this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0):this.data&&this.data[e]||null}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"]),this.isSurge()||this.isLoon()?(this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)})):this.isQuanX()?(this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t))):this.isNode()&&(this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)}))}post(t,e=(()=>{})){if(t.body&&t.headers&&!t.headers["Content-Type"]&&(t.headers["Content-Type"]="application/x-www-form-urlencoded"),t.headers&&delete t.headers["Content-Length"],this.isSurge()||this.isLoon())this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.post(t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method="POST",this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>e(t));else if(this.isNode()){this.initGotEnv(t);const{url:s,...i}=t;this.got.post(s,i).then(t=>{const{statusCode:s,statusCode:i,headers:r,body:o}=t;e(null,{status:s,statusCode:i,headers:r,body:o},o)},t=>{const{message:s,response:i}=t;e(s,i,i&&i.body)})}}time(t){let e={"M+":(new Date).getMonth()+1,"d+":(new Date).getDate(),"H+":(new Date).getHours(),"m+":(new Date).getMinutes(),"s+":(new Date).getSeconds(),"q+":Math.floor(((new Date).getMonth()+3)/3),S:(new Date).getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,((new Date).getFullYear()+"").substr(4-RegExp.$1.length)));for(let s in e)new RegExp("("+s+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?e[s]:("00"+e[s]).substr((""+e[s]).length)));return t}msg(e=t,s="",i="",r){const o=t=>{if(!t)return t;if("string"==typeof t)return this.isLoon()?t:this.isQuanX()?{"open-url":t}:this.isSurge()?{url:t}:void 0;if("object"==typeof t){if(this.isLoon()){let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}if(this.isQuanX()){let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl;return{"open-url":e,"media-url":s}}if(this.isSurge()){let e=t.url||t.openUrl||t["open-url"];return{url:e}}}};this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r)));let h=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];h.push(e),s&&h.push(s),i&&h.push(i),console.log(h.join("\n")),this.logs=this.logs.concat(h)}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){const s=!this.isSurge()&&!this.isQuanX()&&!this.isLoon();s?this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack):this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t)}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),(this.isSurge()||this.isQuanX()||this.isLoon())&&$done(t)}}(t,e)}
--------------------------------------------------------------------------------