├── .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 | GitHub Readme Stats 11 |

JS SHELL

12 |

自动化一键完成JS库管理

13 |

14 |

15 | GitHub 16 | Issues 17 | GitHub 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` Docker Built 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 | 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 |
48 |
49 |
50 |
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 |
47 |
48 |
49 |
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 |
44 |

在线编辑工具

45 | 47 | 48 | 49 | 52 | 53 |
54 |

配置文件  温馨提示:每次保存都会在 config/bak 目录下生成备份文件 55 |

56 |
57 | 58 |
59 |
60 |
61 | 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 | 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 |
72 |
73 | 74 |
75 | 77 |  

78 | 温馨提示:只能手动执行的活动名,执行其他请进入终端操作。若执行活动脚本期间卡住或想停止运行,刷新页面即可。 79 | 80 |

81 |
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 |
25 |
26 |
27 |
28 | 42 |
43 | 45 |

日志查询

46 | 47 |
48 |
49 | 50 |
51 | 62 |
63 |
64 | 65 |
66 |
67 |
68 |
69 |
70 |
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 |
25 |
26 |
27 |
28 | 42 |
43 | 45 |

查看脚本

46 | 47 |
48 |
49 | 50 |
51 | 62 |
63 |
64 | 65 |
66 |
67 |
68 |
69 |
70 |
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)} --------------------------------------------------------------------------------