├── .github ├── pull.yml └── workflows │ ├── 10000.yaml │ ├── bika.yaml │ ├── bilibili.yaml │ ├── iqiyi.yaml │ ├── repo_sync.yml │ ├── tieba.yaml │ ├── v2ex.yaml │ ├── v_video.yaml │ ├── wps.yaml │ └── xiaomi.yaml ├── Env.js ├── Env.min.js ├── LICENSE ├── README.md ├── RepoSync.md ├── backUp ├── TG_PUSH.md └── gitSync.md ├── function ├── 10000 │ └── 10000.js ├── bika │ ├── bika.py │ └── sendNotify.py ├── bilibili │ ├── bilibili.py │ ├── bilibiliapi.py │ └── sendNotify.py ├── iQIYI-DailyBonus │ ├── iQIYI-bak.js │ └── iqiyi.js ├── q_video │ └── q_video.js ├── sendNotify.js ├── sendNotify.py ├── tieba │ └── tieba.js ├── v2ex │ └── v2ex.js ├── wps │ ├── sendNotify.py │ └── wps_invitation.py └── xiaomi_sports │ ├── sendNotify.py │ └── xiaomi.py ├── icon ├── DD_bot.png ├── TG_PUSH1.png ├── TG_PUSH2.png ├── TG_PUSH3.png ├── bark.jpg ├── create_new_sync_yaml.png ├── git1.jpg ├── git10.jpg ├── git11.jpg ├── git12.jpg ├── git13.jpg ├── git14.jpg ├── git2.jpg ├── git3.jpg ├── git4.jpg ├── git5.jpg ├── git6.jpg ├── git7.png ├── git8.jpg ├── git9.jpg ├── new_access_token.png ├── new_repository_secret.png ├── open_actions_permissions.png ├── reposync_result.png ├── run_reposync_actions.png ├── set_sectet_pat.png ├── set_up_workflow.png └── your_new_token.png ├── package.json └── requirements.txt /.github/pull.yml: -------------------------------------------------------------------------------- 1 | version: "1" 2 | rules: # Array of rules 3 | - base: master # Required. Target branch 4 | upstream: BlueskyClouds:master # Required. Must be in the same fork network. 5 | mergeMethod: hardreset # Optional, one of [none, merge, squash, rebase, hardreset], Default: none. 6 | mergeUnstable: true # Optional, merge pull request even when the mergeable_state is not clean. Default: false -------------------------------------------------------------------------------- /.github/workflows/10000.yaml: -------------------------------------------------------------------------------- 1 | name: 中国电信签到 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 */8 * * *" 7 | #电信经常签到不成功所以让他每八小时执行一下,一天三次 8 | watch: 9 | types: [started] 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | if: github.event.repository.owner.id == github.event.sender.id 15 | steps: 16 | - uses: actions/checkout@v1 17 | - name: Use Node.js 10.x 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: 10.x 21 | - name: npm install 22 | run: | 23 | npm install 24 | - name: "运行【中国电信签到】" 25 | run: | 26 | node function/10000/10000.js 27 | env: 28 | TELECOM_MOBILE: ${{ secrets.TELECOM_MOBILE }} 29 | SEND_KEY: ${{ secrets.SEND_KEY }} 30 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 31 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 32 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 33 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 34 | QYWX_AM: ${{ secrets.QYWX_AM}} 35 | QYWX_KEY: ${{ secrets.QYWX_KEY}} 36 | TG_PROXY_HOST: ${{ secrets.TG_PROXY_HOST}} 37 | TG_PROXY_PORT: ${{ secrets.TG_PROXY_PORT}} 38 | IGOT_PUSH_KEY: ${{ secrets.IGOT_PUSH_KEY}} 39 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 40 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 41 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 42 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 43 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 44 | #最后推送 2021年4月09日 45 | -------------------------------------------------------------------------------- /.github/workflows/bika.yaml: -------------------------------------------------------------------------------- 1 | name: 哔咔漫画自动打哔咔 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "01 04 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: "Set up Python" 19 | uses: actions/setup-python@v1 20 | with: 21 | python-version: 3.8 22 | 23 | - name: "安装依赖包" 24 | run: pip install -r ./requirements.txt 25 | 26 | - name: "运行 哔咔漫画自动打哔咔" 27 | run: python3 function/bika/bika.py 28 | env: 29 | BIKA_USER: ${{ secrets.BIKA_USER }} 30 | BIKA_PASS: ${{ secrets.BIKA_PASS }} 31 | SEND_KEY: ${{ secrets.SEND_KEY }} 32 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 33 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 34 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 35 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 36 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 37 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 38 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 39 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 40 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 41 | QYWX_AM: ${{ secrets.QYWX_AM}} 42 | #最后推送 2021年4月22日 43 | -------------------------------------------------------------------------------- /.github/workflows/bilibili.yaml: -------------------------------------------------------------------------------- 1 | name: 哔哩哔哩签到 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "5 16 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: "Set up Python" 19 | uses: actions/setup-python@v1 20 | with: 21 | python-version: 3.8 22 | 23 | - name: "安装依赖包" 24 | run: pip install -r ./requirements.txt 25 | 26 | - name: "运行 哔哩哔哩签到" 27 | run: python3 function/bilibili/bilibili.py 28 | env: 29 | BILI_USER: ${{ secrets.BILI_USER }} 30 | BILI_PASS: ${{ secrets.BILI_PASS }} 31 | BILI_COOKIE: ${{ secrets.BILI_COOKIE }} 32 | BILI_NUM: ${{ secrets.BILI_NUM }} 33 | BILI_TYPE: ${{ secrets.BILI_TYPE }} 34 | SEND_KEY: ${{ secrets.SEND_KEY }} 35 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 36 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 37 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 38 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 39 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 40 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 41 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 42 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 43 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 44 | QYWX_AM: ${{ secrets.QYWX_AM}} 45 | #最后推送 2021年4月22日 -------------------------------------------------------------------------------- /.github/workflows/iqiyi.yaml: -------------------------------------------------------------------------------- 1 | name: 爱奇艺会员签到 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "*/20 16 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js 10.x 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: 10.x 20 | - name: npm install 21 | run: | 22 | npm install 23 | - name: "运行【爱奇艺会员签到】" 24 | run: | 25 | node function/iQIYI-DailyBonus/iqiyi.js 26 | env: 27 | iQIYI_COOKIE: ${{ secrets.iQIYI_COOKIE }} 28 | SEND_KEY: ${{ secrets.SEND_KEY }} 29 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 30 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 31 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 32 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 33 | QYWX_KEY: ${{ secrets.QYWX_KEY}} 34 | QYWX_AM: ${{ secrets.QYWX_AM}} 35 | TG_PROXY_HOST: ${{ secrets.TG_PROXY_HOST}} 36 | TG_PROXY_PORT: ${{ secrets.TG_PROXY_PORT}} 37 | IGOT_PUSH_KEY: ${{ secrets.IGOT_PUSH_KEY}} 38 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 39 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 40 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 41 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 42 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 43 | #最后推送 2021年4月09日 44 | -------------------------------------------------------------------------------- /.github/workflows/repo_sync.yml: -------------------------------------------------------------------------------- 1 | name: 自动同步-Actions 2 | on: 3 | schedule: 4 | - cron: '1 0,8,15 * * *' 5 | workflow_dispatch: 6 | watch: 7 | types: started 8 | repository_dispatch: 9 | types: 同步仓库 10 | jobs: 11 | repo-sync: 12 | env: 13 | PAT: ${{ secrets.PAT || github.event.client_payload.PAT }} #此处PAT需要申请,教程详见:https://www.jianshu.com/p/bb82b3ad1d11 14 | runs-on: ubuntu-latest 15 | if: github.event.repository.owner.id == github.event.sender.id 16 | steps: 17 | - uses: actions/checkout@v2 18 | with: 19 | persist-credentials: false 20 | 21 | - name: sync scripts 22 | uses: repo-sync/github-sync@v2 23 | if: env.PAT 24 | with: 25 | source_repo: "https://github.com/BlueSkyClouds/My-Actions.git" 26 | source_branch: "master" 27 | destination_branch: "master" 28 | github_token: ${{ secrets.PAT || github.event.client_payload.PAT }} 29 | #最后推送 2021年4月09日 -------------------------------------------------------------------------------- /.github/workflows/tieba.yaml: -------------------------------------------------------------------------------- 1 | name: 百度签到 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "30 04 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js 10.x 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: 10.x 20 | - name: npm install 21 | run: | 22 | npm install 23 | - name: "运行【百度签到】" 24 | run: | 25 | node function/tieba/tieba.js 26 | env: 27 | BDUSS: ${{ secrets.BDUSS }} 28 | JUMP: ${{ secrets.BDUSS-JUMP }} 29 | SEND_KEY: ${{ secrets.SEND_KEY }} 30 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 31 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 32 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 33 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 34 | QYWX_KEY: ${{ secrets.QYWX_KEY}} 35 | QYWX_AM: ${{ secrets.QYWX_AM}} 36 | TG_PROXY_HOST: ${{ secrets.TG_PROXY_HOST}} 37 | TG_PROXY_PORT: ${{ secrets.TG_PROXY_PORT}} 38 | IGOT_PUSH_KEY: ${{ secrets.IGOT_PUSH_KEY}} 39 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 40 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 41 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 42 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 43 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 44 | #最后推送 2021年4月09日 -------------------------------------------------------------------------------- /.github/workflows/v2ex.yaml: -------------------------------------------------------------------------------- 1 | name: V2ex签到 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 14 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js 10.x 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: 10.x 20 | - name: npm install 21 | run: | 22 | npm install 23 | - name: "运行【V2ex自动签到】" 24 | run: | 25 | node function/v2ex/v2ex.js 26 | env: 27 | V2EXCK: ${{ secrets.V2EXCK }} 28 | SEND_KEY: ${{ secrets.SEND_KEY }} 29 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 30 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 31 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 32 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 33 | QYWX_KEY: ${{ secrets.QYWX_KEY}} 34 | QYWX_AM: ${{ secrets.QYWX_AM}} 35 | TG_PROXY_HOST: ${{ secrets.TG_PROXY_HOST}} 36 | TG_PROXY_PORT: ${{ secrets.TG_PROXY_PORT}} 37 | IGOT_PUSH_KEY: ${{ secrets.IGOT_PUSH_KEY}} 38 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 39 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 40 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 41 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 42 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 43 | #最后推送 2021年4月09日 44 | -------------------------------------------------------------------------------- /.github/workflows/v_video.yaml: -------------------------------------------------------------------------------- 1 | name: 腾讯视频签到 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "30 14 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - uses: actions/checkout@v1 16 | - name: Use Node.js 10.x 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: 10.x 20 | - name: npm install 21 | run: | 22 | npm install 23 | - name: "运行【腾讯视频签到】" 24 | run: | 25 | node function/q_video/q_video.js 26 | env: 27 | V_REF_URL: ${{ secrets.V_REF_URL }} 28 | V_COOKIE: ${{ secrets.V_COOKIE }} 29 | SEND_KEY: ${{ secrets.SEND_KEY }} 30 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 31 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 32 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 33 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 34 | QYWX_KEY: ${{ secrets.QYWX_KEY}} 35 | QYWX_AM: ${{ secrets.QYWX_AM}} 36 | TG_PROXY_HOST: ${{ secrets.TG_PROXY_HOST}} 37 | TG_PROXY_PORT: ${{ secrets.TG_PROXY_PORT}} 38 | IGOT_PUSH_KEY: ${{ secrets.IGOT_PUSH_KEY}} 39 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 40 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 41 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 42 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 43 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 44 | #最后推送 2021年4月09日 45 | -------------------------------------------------------------------------------- /.github/workflows/wps.yaml: -------------------------------------------------------------------------------- 1 | name: WPS自动邀请 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "45 0 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: "Set up Python" 19 | uses: actions/setup-python@v1 20 | with: 21 | python-version: 3.9 22 | 23 | - name: "安装依赖包" 24 | run: pip install -r ./requirements.txt 25 | 26 | - name: "运行 WPS自动邀请" 27 | run: python3 function/wps/wps_invitation.py 28 | env: 29 | WPS_KEY: ${{ secrets.WPS_KEY }} 30 | SEND_KEY: ${{ secrets.SEND_KEY }} 31 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 32 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 33 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 34 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 35 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 36 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 37 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 38 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 39 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 40 | QYWX_AM: ${{ secrets.QYWX_AM}} 41 | #最后推送 2021年4月22日 42 | -------------------------------------------------------------------------------- /.github/workflows/xiaomi.yaml: -------------------------------------------------------------------------------- 1 | name: 小米自动刷步数 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 10 * * *" 7 | watch: 8 | types: [started] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | if: github.event.repository.owner.id == github.event.sender.id 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v2 17 | 18 | - name: "Set up Python" 19 | uses: actions/setup-python@v1 20 | with: 21 | python-version: 3.9 22 | 23 | - name: "安装依赖包" 24 | run: pip install -r ./requirements.txt 25 | 26 | - name: "运行 小米自动刷步数" 27 | run: python3 function/xiaomi_sports/xiaomi.py 28 | env: 29 | Xiaomi_User: ${{ secrets.Xiaomi_User }} 30 | Xiaomi_Pw: ${{ secrets.Xiaomi_Pw }} 31 | Xiaomi_Bs: ${{ secrets.Xiaomi_Bs }} 32 | SEND_KEY: ${{ secrets.SEND_KEY }} 33 | PUSH_KEY: ${{ secrets.PUSH_KEY }} 34 | BARK_PUSH: ${{ secrets.BARK_PUSH }} 35 | PUSH_PLUS_TOKEN: ${{ secrets.PUSH_PLUS_TOKEN}} 36 | PUSH_PLUS_USER: ${{ secrets.PUSH_PLUS_USER}} 37 | TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} 38 | TG_USER_ID: ${{ secrets.TG_USER_ID }} 39 | BARK_SOUND: ${{ secrets.BARK_SOUND }} 40 | DD_BOT_TOKEN: ${{ secrets.DD_BOT_TOKEN }} 41 | DD_BOT_SECRET: ${{ secrets.DD_BOT_SECRET }} 42 | QYWX_AM: ${{ secrets.QYWX_AM}} 43 | #最后推送 2021年4月22日 44 | -------------------------------------------------------------------------------- /Env.js: -------------------------------------------------------------------------------- 1 | function Env(name, opts) { 2 | class Http { 3 | constructor(env) { 4 | this.env = env 5 | } 6 | 7 | send(opts, method = 'GET') { 8 | opts = typeof opts === 'string' ? { url: opts } : opts 9 | let sender = this.get 10 | if (method === 'POST') { 11 | sender = this.post 12 | } 13 | return new Promise((resolve, reject) => { 14 | sender.call(this, opts, (err, resp, body) => { 15 | if (err) reject(err) 16 | else resolve(resp) 17 | }) 18 | }) 19 | } 20 | 21 | get(opts) { 22 | return this.send.call(this.env, opts) 23 | } 24 | 25 | post(opts) { 26 | return this.send.call(this.env, opts, 'POST') 27 | } 28 | } 29 | 30 | return new (class { 31 | constructor(name, opts) { 32 | this.name = name 33 | this.http = new Http(this) 34 | this.data = null 35 | this.dataFile = 'box.dat' 36 | this.logs = [] 37 | this.isMute = false 38 | this.isNeedRewrite = false 39 | this.logSeparator = '\n' 40 | this.startTime = new Date().getTime() 41 | Object.assign(this, opts) 42 | this.log('', `🔔${this.name}, 开始!`) 43 | } 44 | 45 | isNode() { 46 | return 'undefined' !== typeof module && !!module.exports 47 | } 48 | 49 | isQuanX() { 50 | return 'undefined' !== typeof $task 51 | } 52 | 53 | isSurge() { 54 | return 'undefined' !== typeof $httpClient && 'undefined' === typeof $loon 55 | } 56 | 57 | isLoon() { 58 | return 'undefined' !== typeof $loon 59 | } 60 | 61 | isShadowrocket() { 62 | return 'undefined' !== typeof $rocket 63 | } 64 | 65 | toObj(str, defaultValue = null) { 66 | try { 67 | return JSON.parse(str) 68 | } catch { 69 | return defaultValue 70 | } 71 | } 72 | 73 | toStr(obj, defaultValue = null) { 74 | try { 75 | return JSON.stringify(obj) 76 | } catch { 77 | return defaultValue 78 | } 79 | } 80 | 81 | getjson(key, defaultValue) { 82 | let json = defaultValue 83 | const val = this.getdata(key) 84 | if (val) { 85 | try { 86 | json = JSON.parse(this.getdata(key)) 87 | } catch {} 88 | } 89 | return json 90 | } 91 | 92 | setjson(val, key) { 93 | try { 94 | return this.setdata(JSON.stringify(val), key) 95 | } catch { 96 | return false 97 | } 98 | } 99 | 100 | getScript(url) { 101 | return new Promise((resolve) => { 102 | this.get({ url }, (err, resp, body) => resolve(body)) 103 | }) 104 | } 105 | 106 | runScript(script, runOpts) { 107 | return new Promise((resolve) => { 108 | let httpapi = this.getdata('@chavy_boxjs_userCfgs.httpapi') 109 | httpapi = httpapi ? httpapi.replace(/\n/g, '').trim() : httpapi 110 | let httpapi_timeout = this.getdata('@chavy_boxjs_userCfgs.httpapi_timeout') 111 | httpapi_timeout = httpapi_timeout ? httpapi_timeout * 1 : 20 112 | httpapi_timeout = runOpts && runOpts.timeout ? runOpts.timeout : httpapi_timeout 113 | const [key, addr] = httpapi.split('@') 114 | const opts = { 115 | url: `http://${addr}/v1/scripting/evaluate`, 116 | body: { script_text: script, mock_type: 'cron', timeout: httpapi_timeout }, 117 | headers: { 'X-Key': key, 'Accept': '*/*' } 118 | } 119 | this.post(opts, (err, resp, body) => resolve(body)) 120 | }).catch((e) => this.logErr(e)) 121 | } 122 | 123 | loaddata() { 124 | if (this.isNode()) { 125 | this.fs = this.fs ? this.fs : require('fs') 126 | this.path = this.path ? this.path : require('path') 127 | const curDirDataFilePath = this.path.resolve(this.dataFile) 128 | const rootDirDataFilePath = this.path.resolve(process.cwd(), this.dataFile) 129 | const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath) 130 | const isRootDirDataFile = !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath) 131 | if (isCurDirDataFile || isRootDirDataFile) { 132 | const datPath = isCurDirDataFile ? curDirDataFilePath : rootDirDataFilePath 133 | try { 134 | return JSON.parse(this.fs.readFileSync(datPath)) 135 | } catch (e) { 136 | return {} 137 | } 138 | } else return {} 139 | } else return {} 140 | } 141 | 142 | writedata() { 143 | if (this.isNode()) { 144 | this.fs = this.fs ? this.fs : require('fs') 145 | this.path = this.path ? this.path : require('path') 146 | const curDirDataFilePath = this.path.resolve(this.dataFile) 147 | const rootDirDataFilePath = this.path.resolve(process.cwd(), this.dataFile) 148 | const isCurDirDataFile = this.fs.existsSync(curDirDataFilePath) 149 | const isRootDirDataFile = !isCurDirDataFile && this.fs.existsSync(rootDirDataFilePath) 150 | const jsondata = JSON.stringify(this.data) 151 | if (isCurDirDataFile) { 152 | this.fs.writeFileSync(curDirDataFilePath, jsondata) 153 | } else if (isRootDirDataFile) { 154 | this.fs.writeFileSync(rootDirDataFilePath, jsondata) 155 | } else { 156 | this.fs.writeFileSync(curDirDataFilePath, jsondata) 157 | } 158 | } 159 | } 160 | 161 | lodash_get(source, path, defaultValue = undefined) { 162 | const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.') 163 | let result = source 164 | for (const p of paths) { 165 | result = Object(result)[p] 166 | if (result === undefined) { 167 | return defaultValue 168 | } 169 | } 170 | return result 171 | } 172 | 173 | lodash_set(obj, path, value) { 174 | if (Object(obj) !== obj) return obj 175 | if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [] 176 | path 177 | .slice(0, -1) 178 | .reduce((a, c, i) => (Object(a[c]) === a[c] ? a[c] : (a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] ? [] : {})), obj)[ 179 | path[path.length - 1] 180 | ] = value 181 | return obj 182 | } 183 | 184 | getdata(key) { 185 | let val = this.getval(key) 186 | // 如果以 @ 187 | if (/^@/.test(key)) { 188 | const [, objkey, paths] = /^@(.*?)\.(.*?)$/.exec(key) 189 | const objval = objkey ? this.getval(objkey) : '' 190 | if (objval) { 191 | try { 192 | const objedval = JSON.parse(objval) 193 | val = objedval ? this.lodash_get(objedval, paths, '') : val 194 | } catch (e) { 195 | val = '' 196 | } 197 | } 198 | } 199 | return val 200 | } 201 | 202 | setdata(val, key) { 203 | let issuc = false 204 | if (/^@/.test(key)) { 205 | const [, objkey, paths] = /^@(.*?)\.(.*?)$/.exec(key) 206 | const objdat = this.getval(objkey) 207 | const objval = objkey ? (objdat === 'null' ? null : objdat || '{}') : '{}' 208 | try { 209 | const objedval = JSON.parse(objval) 210 | this.lodash_set(objedval, paths, val) 211 | issuc = this.setval(JSON.stringify(objedval), objkey) 212 | } catch (e) { 213 | const objedval = {} 214 | this.lodash_set(objedval, paths, val) 215 | issuc = this.setval(JSON.stringify(objedval), objkey) 216 | } 217 | } else { 218 | issuc = this.setval(val, key) 219 | } 220 | return issuc 221 | } 222 | 223 | getval(key) { 224 | if (this.isSurge() || this.isLoon()) { 225 | return $persistentStore.read(key) 226 | } else if (this.isQuanX()) { 227 | return $prefs.valueForKey(key) 228 | } else if (this.isNode()) { 229 | this.data = this.loaddata() 230 | return this.data[key] 231 | } else { 232 | return (this.data && this.data[key]) || null 233 | } 234 | } 235 | 236 | setval(val, key) { 237 | if (this.isSurge() || this.isLoon()) { 238 | return $persistentStore.write(val, key) 239 | } else if (this.isQuanX()) { 240 | return $prefs.setValueForKey(val, key) 241 | } else if (this.isNode()) { 242 | this.data = this.loaddata() 243 | this.data[key] = val 244 | this.writedata() 245 | return true 246 | } else { 247 | return (this.data && this.data[key]) || null 248 | } 249 | } 250 | 251 | initGotEnv(opts) { 252 | this.got = this.got ? this.got : require('got') 253 | this.cktough = this.cktough ? this.cktough : require('tough-cookie') 254 | this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar() 255 | if (opts) { 256 | opts.headers = opts.headers ? opts.headers : {} 257 | if (undefined === opts.headers.Cookie && undefined === opts.cookieJar) { 258 | opts.cookieJar = this.ckjar 259 | } 260 | } 261 | } 262 | 263 | get(opts, callback = () => {}) { 264 | if (opts.headers) { 265 | delete opts.headers['Content-Type'] 266 | delete opts.headers['Content-Length'] 267 | } 268 | if (this.isSurge() || this.isLoon()) { 269 | if (this.isSurge() && this.isNeedRewrite) { 270 | opts.headers = opts.headers || {} 271 | Object.assign(opts.headers, { 'X-Surge-Skip-Scripting': false }) 272 | } 273 | $httpClient.get(opts, (err, resp, body) => { 274 | if (!err && resp) { 275 | resp.body = body 276 | resp.statusCode = resp.status 277 | } 278 | callback(err, resp, body) 279 | }) 280 | } else if (this.isQuanX()) { 281 | if (this.isNeedRewrite) { 282 | opts.opts = opts.opts || {} 283 | Object.assign(opts.opts, { hints: false }) 284 | } 285 | $task.fetch(opts).then( 286 | (resp) => { 287 | const { statusCode: status, statusCode, headers, body } = resp 288 | callback(null, { status, statusCode, headers, body }, body) 289 | }, 290 | (err) => callback(err) 291 | ) 292 | } else if (this.isNode()) { 293 | this.initGotEnv(opts) 294 | this.got(opts) 295 | .on('redirect', (resp, nextOpts) => { 296 | try { 297 | if (resp.headers['set-cookie']) { 298 | const ck = resp.headers['set-cookie'].map(this.cktough.Cookie.parse).toString() 299 | if (ck) { 300 | this.ckjar.setCookieSync(ck, null) 301 | } 302 | nextOpts.cookieJar = this.ckjar 303 | } 304 | } catch (e) { 305 | this.logErr(e) 306 | } 307 | // this.ckjar.setCookieSync(resp.headers['set-cookie'].map(Cookie.parse).toString()) 308 | }) 309 | .then( 310 | (resp) => { 311 | const { statusCode: status, statusCode, headers, body } = resp 312 | callback(null, { status, statusCode, headers, body }, body) 313 | }, 314 | (err) => { 315 | const { message: error, response: resp } = err 316 | callback(error, resp, resp && resp.body) 317 | } 318 | ) 319 | } 320 | } 321 | 322 | post(opts, callback = () => {}) { 323 | const method = opts.method ? opts.method.toLocaleLowerCase() : 'post' 324 | // 如果指定了请求体, 但没指定`Content-Type`, 则自动生成 325 | if (opts.body && opts.headers && !opts.headers['Content-Type']) { 326 | opts.headers['Content-Type'] = 'application/x-www-form-urlencoded' 327 | } 328 | if (opts.headers) delete opts.headers['Content-Length'] 329 | if (this.isSurge() || this.isLoon()) { 330 | if (this.isSurge() && this.isNeedRewrite) { 331 | opts.headers = opts.headers || {} 332 | Object.assign(opts.headers, { 'X-Surge-Skip-Scripting': false }) 333 | } 334 | $httpClient[method](opts, (err, resp, body) => { 335 | if (!err && resp) { 336 | resp.body = body 337 | resp.statusCode = resp.status 338 | } 339 | callback(err, resp, body) 340 | }) 341 | } else if (this.isQuanX()) { 342 | opts.method = method 343 | if (this.isNeedRewrite) { 344 | opts.opts = opts.opts || {} 345 | Object.assign(opts.opts, { hints: false }) 346 | } 347 | $task.fetch(opts).then( 348 | (resp) => { 349 | const { statusCode: status, statusCode, headers, body } = resp 350 | callback(null, { status, statusCode, headers, body }, body) 351 | }, 352 | (err) => callback(err) 353 | ) 354 | } else if (this.isNode()) { 355 | this.initGotEnv(opts) 356 | const { url, ..._opts } = opts 357 | this.got[method](url, _opts).then( 358 | (resp) => { 359 | const { statusCode: status, statusCode, headers, body } = resp 360 | callback(null, { status, statusCode, headers, body }, body) 361 | }, 362 | (err) => { 363 | const { message: error, response: resp } = err 364 | callback(error, resp, resp && resp.body) 365 | } 366 | ) 367 | } 368 | } 369 | /** 370 | * 371 | * 示例:$.time('yyyy-MM-dd qq HH:mm:ss.S') 372 | * :$.time('yyyyMMddHHmmssS') 373 | * y:年 M:月 d:日 q:季 H:时 m:分 s:秒 S:毫秒 374 | * 其中y可选0-4位占位符、S可选0-1位占位符,其余可选0-2位占位符 375 | * @param {string} fmt 格式化参数 376 | * @param {number} 可选: 根据指定时间戳返回格式化日期 377 | * 378 | */ 379 | time(fmt, ts = null) { 380 | const date = ts ? new Date(ts) : new Date() 381 | let o = { 382 | 'M+': date.getMonth() + 1, 383 | 'd+': date.getDate(), 384 | 'H+': date.getHours(), 385 | 'm+': date.getMinutes(), 386 | 's+': date.getSeconds(), 387 | 'q+': Math.floor((date.getMonth() + 3) / 3), 388 | 'S': date.getMilliseconds() 389 | } 390 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) 391 | for (let k in o) 392 | if (new RegExp('(' + k + ')').test(fmt)) 393 | fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)) 394 | return fmt 395 | } 396 | 397 | /** 398 | * 系统通知 399 | * 400 | * > 通知参数: 同时支持 QuanX 和 Loon 两种格式, EnvJs根据运行环境自动转换, Surge 环境不支持多媒体通知 401 | * 402 | * 示例: 403 | * $.msg(title, subt, desc, 'twitter://') 404 | * $.msg(title, subt, desc, { 'open-url': 'twitter://', 'media-url': 'https://github.githubassets.com/images/modules/open_graph/github-mark.png' }) 405 | * $.msg(title, subt, desc, { 'open-url': 'https://bing.com', 'media-url': 'https://github.githubassets.com/images/modules/open_graph/github-mark.png' }) 406 | * 407 | * @param {*} title 标题 408 | * @param {*} subt 副标题 409 | * @param {*} desc 通知详情 410 | * @param {*} opts 通知参数 411 | * 412 | */ 413 | msg(title = name, subt = '', desc = '', opts) { 414 | const toEnvOpts = (rawopts) => { 415 | if (!rawopts) return rawopts 416 | if (typeof rawopts === 'string') { 417 | if (this.isLoon()) return rawopts 418 | else if (this.isQuanX()) return { 'open-url': rawopts } 419 | else if (this.isSurge()) return { url: rawopts } 420 | else return undefined 421 | } else if (typeof rawopts === 'object') { 422 | if (this.isLoon()) { 423 | let openUrl = rawopts.openUrl || rawopts.url || rawopts['open-url'] 424 | let mediaUrl = rawopts.mediaUrl || rawopts['media-url'] 425 | return { openUrl, mediaUrl } 426 | } else if (this.isQuanX()) { 427 | let openUrl = rawopts['open-url'] || rawopts.url || rawopts.openUrl 428 | let mediaUrl = rawopts['media-url'] || rawopts.mediaUrl 429 | return { 'open-url': openUrl, 'media-url': mediaUrl } 430 | } else if (this.isSurge()) { 431 | let openUrl = rawopts.url || rawopts.openUrl || rawopts['open-url'] 432 | return { url: openUrl } 433 | } 434 | } else { 435 | return undefined 436 | } 437 | } 438 | if (!this.isMute) { 439 | if (this.isSurge() || this.isLoon()) { 440 | $notification.post(title, subt, desc, toEnvOpts(opts)) 441 | } else if (this.isQuanX()) { 442 | $notify(title, subt, desc, toEnvOpts(opts)) 443 | } 444 | } 445 | if (!this.isMuteLog) { 446 | let logs = ['', '==============📣系统通知📣=============='] 447 | logs.push(title) 448 | subt ? logs.push(subt) : '' 449 | desc ? logs.push(desc) : '' 450 | console.log(logs.join('\n')) 451 | this.logs = this.logs.concat(logs) 452 | } 453 | } 454 | 455 | log(...logs) { 456 | if (logs.length > 0) { 457 | this.logs = [...this.logs, ...logs] 458 | } 459 | console.log(logs.join(this.logSeparator)) 460 | } 461 | 462 | logErr(err, msg) { 463 | const isPrintSack = !this.isSurge() && !this.isQuanX() && !this.isLoon() 464 | if (!isPrintSack) { 465 | this.log('', `❗️${this.name}, 错误!`, err) 466 | } else { 467 | this.log('', `❗️${this.name}, 错误!`, err.stack) 468 | } 469 | } 470 | 471 | wait(time) { 472 | return new Promise((resolve) => setTimeout(resolve, time)) 473 | } 474 | 475 | done(val = {}) { 476 | const endTime = new Date().getTime() 477 | const costTime = (endTime - this.startTime) / 1000 478 | this.log('', `🔔${this.name}, 结束! 🕛 ${costTime} 秒`) 479 | this.log() 480 | if (this.isSurge() || this.isQuanX() || this.isLoon()) { 481 | $done(val) 482 | } 483 | } 484 | })(name, opts) 485 | } -------------------------------------------------------------------------------- /Env.min.js: -------------------------------------------------------------------------------- 1 | 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}isShadowrocket(){return"undefined"!=typeof $rocket}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();s&&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=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";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[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,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:i,...r}=t;this.got[s](i,r).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,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).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}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}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)} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, BlueSkyClouds 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![BlueskyClouds’s github stats](https://github-readme-stats.vercel.app/api?username=BlueskyClouds&show_icons=true&theme=merko) 2 |
3 |

My-Actions

4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 个人收集并适配Github Actions的各类签到大杂烩 12 | 13 | ### 本项目已可以实现自动同步上游更改![具体点击](#自动同步) 14 | 15 | # 使用方式 16 | 1. 右上角fork本仓库 17 | 2. 点击Settings -> Secrets -> 点击绿色按钮 (如无绿色按钮说明已激活。直接到第三步。) 18 | 3. 新增 new secret 并设置 Secrets: 19 | 4. 双击右上角自己仓库Star触发,如有不使用项目请[禁用部分项目](https://cdn.jsdelivr.net/gh/BlueskyClouds/BlueskyClouds.github.io/2020/10/19/img/2020-10-19.jpg) 20 | 6. **必须** - 请随便找个文件(例如`README.md`),加个空格提交一下,否则可能会出现无法定时执行的问题 21 | 7. 由于规则更新,可能会Fork后会默认禁用,请手动点击Actions 选择要签到的项目 `enable workflows`激活 22 | 8. [定时执行](#定时执行) 23 | 24 | # 定时执行 25 | 1. 支持手动执行,具体在Actions中选中要执行的Workflows后再在右侧可以看到Run workflow,点击即可运行此workflow。 26 | 27 | 2. 如果嫌上一步麻烦的,也可以直接点击一下star,你会发现所有的workflow都已执行。 28 | 29 | 3. 如需修改执行时间自行修改`.github\workflows\`下面的yaml内的` cron:` 执行时间为国际标准时间 [时间转换](http://www.timebie.com/cn/universalbeijing.php) 分钟在前 小时在后 尽量提前几分钟,因为下载安装部署环境需要一定时间 30 | 31 | ##### Cookie变量设置 Secrets:** 32 | 33 | | 名称 | 内容 | 说明 | 34 | | -------- | -------------| ----- | 35 | | `PAT` | 自动同步**必须设置** |利用Github Actions自动同步上游仓库或新建仓库[PAT获取教程](RepoSync.md)| 36 | | `IQIYI_COOKIE` | 爱奇艺authcookie |P00001的值 详情[文字教程](https://www.bilibili.com/read/cv7437179) [视频教程](https://www.bilibili.com/video/BV1B541157DE) 电脑版有效期三个月| 37 | | `Xiaomi_User` | 小米运动账号 |小米运动账号,多账号请用#分割 例如:13800138000#13800138001| 38 | | `Xiaomi_Pw` | 小米运动密码 |小米运动密码,多账号请用#分割 例如:abc123qwe#abcqwe2| 39 | | `Xiaomi_Bs` | 小米运动步数 |默认为1w-2w之间随机 或自定义随机范围`[18000-25000]`| 40 | | `BILI_USER` | 哔哩哔哩账号 |B站账号| 41 | | `BILI_PASS` | 哔哩哔哩密码 |B站密码| 42 | | `BILI_COOKIE` | 哔哩哔哩COOKIE`(非必填)` |哔哩哔哩COOKIE,如果账号密码无法登陆就用COOKIE,等一段时间再用账号密码即可.| 43 | | `BILI_NUM` | 哔哩哔哩每日投币数量 |每日投币数量`可不填`默认0 不投币| 44 | | `BILI_TYPE` | 哔哩哔哩每日投币方式 |投币方式`可不填`默认1,只给关注的人投币 0 则随机投币| 45 | | `BIKA_USER` | 哔咔漫画用户名 |哔咔漫画用户名| 46 | | `BIKA_PASS` | 哔咔漫画密码 |哔咔漫画密码| 47 | | `WPS_KEY` | WPS_SID |WPS `COOKIE`中的wps_sid,只要不注销,10年过期| 48 | | `V_REF_URL` | 腾讯视频Request URL |电脑端搜索auth_refresh复制整段Request url[图片教程](https://cdn.jsdelivr.net/gh/BlueskyClouds/BlueskyClouds.github.io/2020/11/1/img/v_1.jpg)| 49 | | `V_COOKIE` | 腾讯视频Cookie |电脑端搜索auth_refresh复制Cookie[图片教程](https://cdn.jsdelivr.net/gh/BlueskyClouds/BlueskyClouds.github.io/2020/11/1/img/v_2.jpg)| 50 | | `TELECOM_MOBILE` | 中国电信手机号 |只需要手机号 单账号 `多账号将会暴露手机号` 自行考虑,多账号使用`,`分割 部分地区或手机号暂无法签到,自行测试使用| 51 | | `V2EXCK` | V2EX的Cookie |V2EX的Cookie| 52 | | `BDUSS` | 百度BDUSS |BDUSS值切勿使用双击复制 (结尾有一个`符号`双击复制可能无法复制完整)| 53 | ##### 推送通知环境变量(目前提供`微信server酱`、`pushplus(推送加)`、`iOS Bark APP`、`telegram机器人`、`钉钉机器人`、`企业微信机器人`、`iGot`等通知方式) 54 | 55 | | Name | 归属 | 属性 | 说明 | 56 | | :---------------------: | :----------: | --------- | ------------------------------------------------------------ | 57 | | `SEND_KEY` | 推送开关 | 非必须 | 仅在Cookie失效时发送推送,值随意| 58 | | `PUSH_KEY` | 微信server酱推送 | 非必须 | server酱的微信通知[更新公告](https://sc.ftqq.com/9.version) | 59 | | `BARK_PUSH` | [BARK推送](https://apps.apple.com/us/app/bark-customed-notifications/id1403753865) | 非必须 | IOS用户下载BARK这个APP,填写内容是app提供的`设备码`,例如:https://api.day.app/123 ,那么此处的设备码就是`123`,再不懂看 [这个图](https://github.com/BlueskyClouds/My-Actions/blob/master/icon/bark.jpg)(注:支持自建填完整链接即可) | 60 | | `BARK_SOUND` | [BARK推送](https://apps.apple.com/us/app/bark-customed-notifications/id1403753865) | 非必须 | bark推送声音设置,例如`choo`,具体值请在`bark`-`推送铃声`-`查看所有铃声` | 61 | | `TG_BOT_TOKEN` | telegram推送 | 非必须 | tg推送(需设备可连接外网),`TG_BOT_TOKEN`和`TG_USER_ID`两者必需,填写自己申请[@BotFather](https://t.me/BotFather)的Token,如`10xxx4:AAFcqxxxxgER5uw` , [具体教程](https://github.com/BlueskyClouds/My-Actions/blob/master/backUp/TG_PUSH.md) | 62 | | `TG_USER_ID` | telegram推送 | 非必须 | tg推送(需设备可连接外网),`TG_BOT_TOKEN`和`TG_USER_ID`两者必需,填写[@getuseridbot](https://t.me/getuseridbot)中获取到的纯数字ID, [具体教程](https://github.com/BlueskyClouds/My-Actions/blob/master/backUp/TG_PUSH.md) | 63 | | `DD_BOT_TOKEN` | 钉钉推送 | 非必须 | 钉钉推送(`DD_BOT_TOKEN`和`DD_BOT_SECRET`两者必需)[官方文档](https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq) ,只需`https://oapi.dingtalk.com/robot/send?access_token=XXX` 等于`=`符号后面的XXX即可 | 64 | | `DD_BOT_SECRET` | 钉钉推送 | 非必须 | (`DD_BOT_TOKEN`和`DD_BOT_SECRET`两者必需) ,密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的`SECXXXXXXXXXX`等字符 , 注:钉钉机器人安全设置只需勾选`加签`即可,其他选项不要勾选,再不懂看 [这个图](https://github.com/BlueskyClouds/My-Actions/blob/master/icon/DD_bot.png) | 65 | | `QYWX_KEY` | 企业微信机器人推送 | 非必须 | 密钥,企业微信推送 webhook 后面的 key [详见官方说明文档](https://work.weixin.qq.com/api/doc/90000/90136/91770) | 66 | | `QYWX_AM` | 企业微信应用推送 | 非必须 | 依次填入 企业id,secret,@all(或者成员id),AgentID,图片id [详见官方说明文档](https://work.weixin.qq.com/api/doc/90000/90135/90236) [详见获取教程文档](https://note.youdao.com/ynoteshare1/index.html?id=351e08a72378206f9dd64d2281e9b83b) | 67 | | `IGOT_PUSH_KEY` | iGot推送 | 非必须 | iGot聚合推送,支持多方式推送,确保消息可达。 [参考文档](https://wahao.github.io/Bark-MP-helper ) | 68 | | `PUSH_PLUS_TOKEN` | pushplus推送 | 非必须 | 微信扫码登录后一对一推送或一对多推送下面的token(您的Token) [官方网站](https://www.pushplus.plus/) | 69 | | `PUSH_PLUS_USER` | pushplus推送 | 非必须 | 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码)注:(1、需订阅者扫描二维码 2、如果您是创建群组所属人,也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送),只填`PUSH_PLUS_TOKEN`默认为一对一推送 | 70 | | `TG_PROXY_HOST` | Telegram 代理的 IP | 非必须 | 代理类型为 http。例子:http代理 http://127.0.0.1:1080 则填写 127.0.0.1 | 71 | | `TG_PROXY_PORT` | Telegram 代理的端口 | 非必须 | 例子:http代理 http://127.0.0.1:1080 则填写 1080 | 72 | 73 | ### 同步Fork后的代码 74 | 75 | #### 手动同步 76 | 77 | [手动同步 https://blog.blueskyclouds.com/jsfx/58.html](https://blog.blueskyclouds.com/jsfx/58.html) 78 | 79 | #### 自动同步 80 | 81 | ##### 方案A - 强制远程分支覆盖自己的分支 82 | 1. 参考[这里](https://github.com/BlueskyClouds/My-Actions/blob/master/backUp/gitSync.md),安装[pull插件](https://github.com/apps/pull),并确认此项目已在pull插件的作用下(参考文中1-d)。 83 | 2. 确保.github/pull.yml文件正常存在,yml内上游作者填写正确(此项目已填好,无需更改)。 84 | 3. 确保pull.yml里面是`mergeMethod: hardreset`(默认就是hardreset)。 85 | 4. ENJOY!上游更改三小时左右就会自动发起同步。 86 | 87 | ##### 方案B - 保留自己分支的修改 88 | 89 | > 上游变动后pull插件会自动发起pr,但如果有冲突需要自行**手动**确认。 90 | > 如果上游更新涉及workflow里的文件内容改动,需要自行**手动**确认。 91 | 92 | 1. 参考[这里](https://github.com/BlueskyClouds/My-Actions/blob/master/backUp/gitSync.md),安装[pull插件](https://github.com/apps/pull),并确认此项目已在pull插件的作用下(参考文中1-d)。 93 | 2. 确保.github/pull.yml文件正常存在,yml内上游作者填写正确(此项目已填好,无需更改)。 94 | 3. 将pull.yml里面的`mergeMethod: hardreset`修改为`mergeMethod: merge`保存。 95 | 4. ENJOY!上游更改三小时左右就会自动发起同步。 96 | 97 | ### 鸣谢 98 | 99 | 特别感谢 [JetBrains](https://www.jetbrains.com/?from=My-Actions) 为开源项目提供免费的 [WebStrom](https://www.jetbrains.com/?from=My-Actions) 等 IDE 的授权 100 | [](https://www.jetbrains.com/?from=My-Actions) 101 | 102 | ### 历史 Star 数 103 | ![](https://starchart.cc/BlueskyClouds/My-Actions.svg) 104 | ### 访问量 105 | 106 | ![](http://profile-counter.glitch.me/BlueSkyClouds/count.svg) 107 | -------------------------------------------------------------------------------- /RepoSync.md: -------------------------------------------------------------------------------- 1 | # 通过reposync方式进行代码同步 2 | 3 | ## Why 4 | 5 | 如果不想fork,通过下面的方法重新创建分支,同步代码 6 | 7 | 此方式亲测可行,请放心食用 8 | 9 | 当然别忘了对源仓库进行*Star* 10 | 11 | ## How 12 | 13 | ### 创建新仓库 14 | 15 | [点击创建自己的仓库](https://github.com/new) 16 | 17 | 填入`Repository name`后点击最下方的`Create repository`即可完成创建 18 | 19 | 如默认分支非`master`请自行修改`repo_sync.yml`的`destination_branch`或新建master分支并设置为默认分支 20 | *Settings* -> *Branch* -> 重命名分支为`master`即可 21 | 22 | ### 自己创建工作流 23 | 24 | 在创建完成页面点击`Actions`再点击`set up a workflow yourself` 25 | 26 | set_up_workflow 27 | 28 | 复制https://github.com/BlueskyClouds/My-Actions/blob/master/.github/workflows/repo_sync.yml 里面的代码 29 | 30 | 复制完毕后直接点击右上角的`Start commit`后直接`Commit new file`即可 31 | 32 | create_new_sync_yaml 33 | 34 | ### 申请PAT 35 | 36 | 点击 GitHub [用户设置页面](https://github.com/settings) 最下方的`Developer setting` ,然后选择 [`Personal access tokens`(点击快捷到达指定页面)](https://github.com/settings/tokens/new) 来生成一个 token,把 `repo`和`workflow` 两部分勾上即可。 37 | 38 | ![image-20201111142402212](icon/new_access_token.png) 39 | 40 | 点击最下面的创建按钮后,图示部分即为你的PAT(图示的已经删除了,仅为演示),复制下来马上就要使用了 41 | 42 | ![image-20201111145314326](icon/your_new_token.png) 43 | 44 | 45 | 46 | ### 填写PAT到Secrets 47 | 48 | 申请完毕后,在分支中点击`Settings`-`Secrets`-`New secret` 49 | 50 | set_up_workflow 51 | 52 | `name`填`PAT`,`Value`填入上方申请到的PAT,保存即可 53 | 54 | ![image-20201111144804807](icon/set_sectet_pat.png) 55 | 56 | 57 | 58 | ### 手动触发一次代码同步 59 | 60 | 点击`Actions`,找到指定的脚本,按图示运行一次 61 | 62 | ![image-20201111145720191](icon/run_reposync_actions.png) 63 | 64 | 等待两分钟左右,能够发现代码全部同步过来了 65 | 66 | ![image-20201111145920788](icon/reposync_result.png) 67 | 68 | ## Enjoy 69 | 70 | 操作到这一步,表示您已经全部完成了 71 | 72 | 剩下的去配置cookie等secrets就好啦 -------------------------------------------------------------------------------- /backUp/TG_PUSH.md: -------------------------------------------------------------------------------- 1 | **TG_PUSH教程** 2 | 3 | 利用Telegram机器人推送通知,需要在环境变量填入正确的```TG_BOT_TOKEN```以及```TG_USER_ID```,以下教程简明阐述如何获取token以及UserID 4 | 5 | Ⅰ.首先在Telegram上搜索[BotFather](https://t.me/BotFather)机器人
6 | 7 | ![TG_PUSH1](../icon/TG_PUSH1.png) 8 | 9 | Ⅱ.利用[BotFather](https://t.me/BotFather)创建一个属于自己的通知机器人,按照下图中的1、2、3步骤拿到token,格式形如```10xxx4:AAFcqxxxxgER5uw```。填入```TG_BOT_TOKEN```
10 | 11 | ![TG_PUSH2](../icon/TG_PUSH2.png)
12 | 13 | **新创建的机器人需要跟它发一条消息来开启对话,否则可能会遇到secret填对了但是收不到消息的情况**
14 | 15 | Ⅲ.再次在Telegram上搜索[getuserIDbot](https://t.me/getuserIDbot)机器人,获取UserID。填入```TG_USER_ID```
16 | 17 | ![TG_PUSH3](../icon/TG_PUSH3.png) 18 | 19 | 至此,获取**TG_BOT_TOKEN**以及**TG_USER_ID**的教程结束 20 | -------------------------------------------------------------------------------- /backUp/gitSync.md: -------------------------------------------------------------------------------- 1 | ## 保持自己github的forks自动和上游仓库同步的教程 2 | - 信息来源于 [https://github.com/wei/pull](https://github.com/wei/pull) 3 | - 以下教程仅是出于个人爱好,不保证本教程的完全正确性,最终请以作者 [https://github.com/wei/pull](https://github.com/wei/pull) 的描述为准。 4 | - 注:此教程由telegram用户@wukongdada提供 5 | ### 1、只同步默认分支的教程 6 | 7 | > 当上游的仓库仅有一个默认分支。或者上游仓库有两个分支,我们仅需要同步他的默认分支,其他分支对内容对我们来说无关紧要。 8 | 9 | 10 | ![git1.jpg](../icon/git1.jpg) 11 | 12 | 13 | 14 | a) 登录自己的github账号,另开网页打开 [https://github.com/wei/pull](https://github.com/wei/pull) 15 | 16 | 17 | 18 | b) 点击Pull app进行安装。 19 | 20 | ![../icon/git2.jpg](../icon/git2.jpg) 21 | 22 | 23 | 24 | c) 安装过程中会让你选择要选择那一种方式,All repositories(就是同步已经frok的仓库以及未来fork的仓库),Only select repositories(仅选择要自己需要同步的仓库,其他fork的仓库不会被同步),根据自己需求选择,实在不知道怎么选择,就选All repositories;点击install,完成安装。 25 | 26 | ![../icon/git3.jpg](../icon/git3.jpg) 27 | 28 | 29 | 30 | d) 后续,如果要调整1.c中的选项,打开 [https://github.com/apps/pull](https://github.com/apps/pull) ,点击Configure,输入github密码进入pull的相关设置。 31 | 32 | ![../icon/git4.jpg](../icon/git4.jpg) 33 | 34 | 35 | 36 | e) 进入后,找到Repository access,根据自己的需求,重新选择:All repositories(就是同步已经frok的仓库以及未来fork的仓库),Only select repositories(仅选择要自己需要同步的仓库,其他fork的仓库不会被同步),Save后保存生效。 37 | 38 | ![../icon/git5.jpg](../icon/git5.jpg) 39 | 40 | 41 | 42 | f) Pull app作者虽然在项目中写道keeps your forks up-to-date with upstream via automated pull requests,但当上游仓库有更改时,自己的仓库会在3个小时内完成与上游的同步,3个小时是Pull app作者说的最长时间。当然也可以通过手动触发同步上游仓库,手动触发方式:`https://pull.git.ci/process/你的GitHub名字/你的仓库名字` (例如:`https://pull.git.ci/process/xxxxx/test` ),手动触发可能会进行人机验证,验证通过后会显示Success。 43 | 44 | ![../icon/git12.jpg](../icon/git6.jpg) 45 | 46 | ![../icon/git13.jpg](../icon/git7.png) 47 | 48 | ### 2、同步其他分支的教程 49 | 50 | ![../icon/git8.jpg](../icon/git8.jpg) 51 | 52 | 53 | 54 | a) 假设你fork了上游仓库后,你fork后的地址为 `https://github.com/你的仓库名字/test` ,首先设置完成第1部分内容,注意在1.c步骤没有设置全部同步的,要回到1.e步,确认是否设置同步了 `你的仓库名字/test`,如果没有,请添加上。 55 | 56 | ![../icon/git9.jpg](../icon/git9.jpg) 57 | 58 | 59 | 60 | b) 在默认分支下添加一个文件。 61 | 62 | ![../icon/git10.jpg](../icon/git10.jpg) 63 | 64 | 65 | 66 | c) 复制 ``.github/pull.yml`` 粘贴后看到以下页面,注意github前面的那个.别漏掉了。 67 | 68 | ![../icon/git11.jpg](../icon/git11.jpg) 69 | 70 | 71 | 72 | d) 请在https://github.com/wei/pull#most-common 页复制代码, 73 | 74 | 注意:upstream处要修改为上游仓库作者名字。 75 | 76 | ![../icon/git12.jpg](../icon/git12.jpg) 77 | 78 | ![../icon/git13.jpg](../icon/git13.jpg) 79 | 80 | 81 | 82 | e) 最终的示例如下,假设上游作者是zhangsan,所有的注意点都用红线圈出来了,保存后生效。 83 | 84 | ![../icon/git14.jpg](../icon/git14.jpg) 85 | 86 | 87 | 88 | f) Pull app作者虽然在项目中写道keeps your forks up-to-date with upstream via automated pull requests,但当上游仓库有更改时,自己的仓库会在3个小时内完成与上游的同步,3个小时是Pull app作者说的最长时间。当然也可以通过手动触发同步上游仓库,手动触发方式:`https://pull.git.ci/process/你的GitHub名字/你的仓库名字` (例如:`https://pull.git.ci/process/xxxxx/test`),手动触发可能会进行人机验证,验证通过后会显示Success。具体见1.f提供的图片。 89 | 90 | 91 | 92 | g) 本人仅测试过forks一个仓库只有2个分支的项目,如果有多个分支,不能保证是否可行,请自行测试,或者是使用本教程第3部分高级玩法。 93 | 94 | ### 高级玩法 95 | 96 | >当然,作者还有其他更好的项目用于同步所有分支,例如使用 GitHub actions 进行同步。请参考原作者的项目 97 | - [https://github.com/wei/git-sync](https://github.com/wei/git-sync) 98 | - [https://github.com/repo-sync/github-sync](https://github.com/repo-sync/github-sync) -------------------------------------------------------------------------------- /function/10000/10000.js: -------------------------------------------------------------------------------- 1 | // version v0.0.1 2 | // create by BlueSkyClouds 3 | // detail url: https://github.com/BlueskyClouds/My-Actions 4 | 5 | const exec = require('child_process').execSync 6 | const fs = require('fs') 7 | const download = require('download') 8 | 9 | const $ = new Env('中国电信签到'); 10 | const notify = $.isNode() ? require('../sendNotify') : ''; 11 | // 公共变量 12 | const KEY = process.env.TELECOM_MOBILE 13 | const SEND_KEY = process.env.SEND_KEY 14 | const UTC8 = new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000; 15 | 16 | async function downFile () { 17 | const url = 'https://raw.githubusercontent.com/chavyleung/scripts/master/10000/10000.js' 18 | await download(url, './') 19 | } 20 | 21 | async function changeFiele () { 22 | let content = await fs.readFileSync('./10000.js', 'utf8') 23 | //替换各种无用信息. 24 | content = content.replace("\"\\n\"", "\"\"") 25 | content = content.replace("中国电信", ``) 26 | content = content.replace(/==============\\ud83d\\udce3\\u7cfb\\u7edf\\u901a\\u77e5\\ud83d\\udce3==============/, ``) 27 | content = content.replace("\\ud83d\\udd14${this.name}, \\u5f00\\u59cb!", ``) 28 | content = content.replace("\\ud83d\\udd14${this.name}, \\u7ed3\\u675f! \\ud83d\\udd5b ${e} \\u79d2", ``) 29 | 30 | content = content.replace("const phonedat = $.getdata($.KEY_mobile)", `const phonedat = '${KEY}'`) 31 | await fs.writeFileSync( './10000.js', content, 'utf8') 32 | } 33 | 34 | async function deleteFile(path) { 35 | // 查看文件result.txt是 否存在,如果存在,先删除 36 | const fileExists = await fs.existsSync(path); 37 | // console.log('fileExists', fileExists); 38 | if (fileExists) { 39 | const unlinkRes = await fs.unlinkSync(path); 40 | // console.log('unlinkRes', unlinkRes) 41 | } 42 | } 43 | 44 | async function start() { 45 | if (!KEY) { 46 | console.log('请填写电信号码后再继续') 47 | return 48 | } 49 | // 下载最新代码 50 | await downFile(); 51 | console.log('下载代码完毕') 52 | // 替换变量 53 | await changeFiele(); 54 | console.log('替换变量完毕') 55 | // 执行 56 | await exec("node 10000.js >> result.txt"); 57 | console.log('执行完毕') 58 | const path = "./result.txt"; 59 | let content = ""; 60 | if (fs.existsSync(path)) { 61 | content = fs.readFileSync(path, "utf8"); 62 | } 63 | 64 | if (content.includes("签到成功") | content.includes("已签到")) { 65 | console.log("电信签到-" + content) 66 | }else{ 67 | await notify.sendNotify("中国电信签到-" + timeFormat(UTC8), content); 68 | console.log("中国电信签到-" + content) 69 | } 70 | 71 | //运行完成后,删除下载的文件 72 | console.log('运行完成后,删除下载的文件\n') 73 | await deleteFile(path); 74 | 75 | } 76 | 77 | start() 78 | 79 | function timeFormat(time) { 80 | let date; 81 | if (time) { 82 | date = new Date(time) 83 | } else { 84 | date = new Date(); 85 | } 86 | return date.getFullYear() + '年' + ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1)) + '月' + (date.getDate() >= 10 ? date.getDate() : '0' + date.getDate()) + '日'; 87 | } 88 | // prettier-ignore 89 | 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}isShadowrocket(){return"undefined"!=typeof $rocket}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();s&&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=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";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[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,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:i,...r}=t;this.got[s](i,r).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,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).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}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}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)} 90 | -------------------------------------------------------------------------------- /function/bika/bika.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | import sys 4 | 5 | sys.path.append("My-Actions/function/bika/") 6 | from sendNotify import * 7 | from http import client 8 | 9 | sendNotify = sendNotify() 10 | 11 | SEND_KEY = os.environ['SEND_KEY'] 12 | 13 | msg = '' 14 | 15 | # noinspection SpellCheckingInspection 16 | pica_api_host = "picaapi.picacomic.com" 17 | pica_api_base_url = "https://%s/" % pica_api_host 18 | sign_in_path = "auth/sign-in" 19 | punch_in_path = "users/punch-in" 20 | POST = "POST" 21 | 22 | # noinspection SpellCheckingInspection 23 | api_key = "C69BAF41DA5ABD1FFEDC6D2FEA56B" 24 | api_secret = "~d}$Q7$eIni=V)9\\RK/P.RM4;9[7|@/CA}b~OW!3?EV`:<>M7pddUBL5n|0/*Cn" 25 | # noinspection SpellCheckingInspection 26 | static_headers = { 27 | "api-key": api_key, 28 | "accept": "application/vnd.picacomic.com.v1+json", 29 | "app-channel": "2", 30 | "app-version": "2.2.1.2.3.3", 31 | "app-uuid": "defaultUuid", 32 | "app-platform": "android", 33 | "app-build-version": "44", 34 | "User-Agent": "okhttp/3.8.1", 35 | "image-quality": "original", 36 | } 37 | 38 | 39 | def send_request(path: string, method: string, body: string = None, token: string = None) -> dict: 40 | current_time = str(int(time.time())) 41 | nonce = "".join(random.choices(string.ascii_lowercase + string.digits, k=32)) 42 | raw = path + current_time + nonce + method + api_key 43 | raw = raw.lower() 44 | h = hmac.new(api_secret.encode(), digestmod=hashlib.sha256) 45 | h.update(raw.encode()) 46 | signature = h.hexdigest() 47 | headers = static_headers.copy() 48 | headers["time"] = current_time 49 | headers["nonce"] = nonce 50 | headers["signature"] = signature 51 | if body is not None: 52 | headers["Content-Type"] = "application/json; charset=UTF-8" 53 | if token is not None: 54 | headers["authorization"] = token 55 | connection = client.HTTPSConnection(pica_api_host) 56 | connection.request(method, '/' + path, body, headers) 57 | response = connection.getresponse().read().decode("utf-8") 58 | json_object = json.loads(response) 59 | if json_object["code"] != 200: 60 | if SEND_KEY != '': 61 | sendNotify.send(title=u"哔咔漫画自动打哔咔", msg="登录失败 账号或密码错误") 62 | print(json_object["message"]) 63 | exit(0) 64 | raise RuntimeError(json_object["message"]) 65 | return json_object 66 | 67 | 68 | def sign_in(email: string, password: string) -> string: 69 | body = { 70 | "email": email, 71 | "password": password 72 | } 73 | return send_request(sign_in_path, POST, json.dumps(body))["data"]["token"] 74 | 75 | 76 | def punch_in(token: string): 77 | return send_request(punch_in_path, POST, token=token) 78 | 79 | 80 | if __name__ == '__main__': 81 | if os.environ['BIKA_USER'] == "" or os.environ['BIKA_PASS'] == "": 82 | print("未填写哔咔账号密码 取消运行") 83 | exit(0) 84 | current_token = sign_in(os.environ['BIKA_USER'], os.environ['BIKA_PASS']) 85 | punch_in_response = punch_in(current_token) 86 | result = punch_in_response["data"]["res"] 87 | if result["status"] == "ok": 88 | msg = "打卡成功, 最后一次打卡: %s" % result["punchInLastDay"] 89 | print(msg) 90 | else: 91 | msg = '重复签到 - Already punch-in' 92 | print(msg) 93 | 94 | if SEND_KEY == '': 95 | sendNotify.send(title=u"哔咔漫画自动打哔咔", msg="【哔咔漫画自动签到】\n" + msg) 96 | -------------------------------------------------------------------------------- /function/bika/sendNotify.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import time 3 | import hmac 4 | import hashlib 5 | import base64 6 | import json 7 | import os 8 | import urllib.parse 9 | 10 | 11 | class sendNotify: 12 | # =======================================微信server酱通知设置区域=========================================== 13 | # 此处填你申请的SCKEY. 14 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入PUSH_KEY) 15 | SCKEY = '' 16 | 17 | # =======================================Bark App通知设置区域=========================================== 18 | # 此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) 19 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_PUSH) 20 | BARK_PUSH = '' 21 | # BARK app推送铃声,铃声列表去APP查看复制填写 22 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_SOUND , Value输入app提供的铃声名称,例如:birdsong) 23 | BARK_SOUND = '' 24 | 25 | # =======================================telegram机器人通知设置区域=========================================== 26 | # 此处填你telegram bot 的Token,例如:1077xxx4424:AAFjv0FlexboxEMGfi22B4yh15R5uw 27 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_BOT_TOKEN) 28 | TG_BOT_TOKEN = '' 29 | # 此处填你接收通知消息的telegram用户的id,例如:129xxx206 30 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_USER_ID) 31 | TG_USER_ID = '' 32 | 33 | # =======================================钉钉机器人通知设置区域=========================================== 34 | # 此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415assayed 35 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入DD_BOT_TOKEN) 36 | DD_BOT_TOKEN = '' 37 | # 密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 38 | DD_BOT_SECRET = '' 39 | 40 | # =======================================企业微信机器人通知设置区域=========================================== 此处填你企业微信机器人的 41 | # webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 42 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QYWX_KEY) 43 | # QYWX_KEY = '' 44 | 45 | # =======================================企业微信应用消息通知设置区域=========================================== 此处填你企业微信应用消息的 46 | # 第一个值是企业id,第二个值是secret,第三个值@all(或者成员id),第四个值是AgentID 中间以逗号隔开 47 | # 详情查看https://note.youdao.com/ynoteshare1/index.html?id=351e08a72378206f9dd64d2281e9b83b&type=note#/ 48 | # B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat 49 | QYWX_AM = '' 50 | 51 | # =======================================QQ酷推通知设置区域=========================================== 52 | # 此处填你申请的SKEY(具体详见文档 https://cp.xuthus.cc/) 53 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QQ_SKEY) 54 | # QQ_SKEY = '' 55 | # #此处填写私聊或群组推送,默认私聊(send或group或者wx) 56 | # QQ_MODE = 'send' 57 | 58 | # =======================================push+设置区域======================================= 59 | # 官方文档:https://www.pushplus.plus/ 60 | # PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 61 | PUSH_PLUS_TOKEN = '' 62 | # PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) 63 | PUSH_PLUS_USER = '' 64 | 65 | # Server酱 66 | if os.environ['PUSH_KEY'] != "": 67 | SCKEY = os.environ['PUSH_KEY'] 68 | 69 | # Bark App 70 | if os.environ['BARK_PUSH'] != "": 71 | if os.environ['BARK_PUSH'].find("https") != -1 or os.environ['BARK_PUSH'].find("http") != -1: 72 | BARK_PUSH = os.environ['PUSH_KEY'] 73 | else: 74 | BARK_PUSH = "https://api.day.app/" + os.environ['BARK_PUSH'] 75 | elif os.environ['BARK_SOUND'] != "": 76 | BARK_SOUND = os.environ['BARK_SOUND'] 77 | elif BARK_PUSH != "" or BARK_PUSH.find("https") != -1 or BARK_PUSH.find("http") != -1: 78 | BARK_PUSH = "https://api.day.app/" + BARK_PUSH 79 | 80 | # telegram 81 | if os.environ['TG_BOT_TOKEN'] != "": 82 | TG_BOT_TOKEN = os.environ['TG_BOT_TOKEN'] 83 | if os.environ['TG_USER_ID'] != "": 84 | TG_USER_ID = os.environ['TG_USER_ID'] 85 | 86 | # 钉钉机器人 87 | if os.environ['DD_BOT_TOKEN'] != "": 88 | DD_BOT_TOKEN = os.environ['DD_BOT_TOKEN'] 89 | if os.environ['DD_BOT_SECRET'] != "": 90 | DD_BOT_SECRET = os.environ['DD_BOT_SECRET'] 91 | 92 | # QQ酷推 93 | # if os.environ['QQ_SKEY'] != "": 94 | # QQ_SKEY = os.environ['QQ_SKEY'] 95 | # if os.environ['QQ_MODE'] != "": 96 | # QQ_MODE = os.environ['QQ_MODE'] 97 | 98 | # 企业微信 99 | # if os.environ['QYWX_KEY'] != "": 100 | # QQ_SKEY = os.environ['QYWX_KEY'] 101 | if os.environ['QYWX_AM'] != "": 102 | QYWX_AM = os.environ['QYWX_AM'] 103 | 104 | # push+ 105 | if os.environ['PUSH_PLUS_TOKEN'] != "": 106 | PUSH_PLUS_TOKEN = os.environ['PUSH_PLUS_TOKEN'] 107 | if os.environ['PUSH_PLUS_USER'] != "": 108 | PUSH_PLUS_USER = os.environ['PUSH_PLUS_USER'] 109 | 110 | def serverNotify(self, text, desp): 111 | if sendNotify.SCKEY != '': 112 | url = 'https://sctapi.ftqq.com/' + sendNotify.SCKEY + '.send' 113 | if "\n" in desp: 114 | desp = desp.replace("\n", "\n\n") 115 | data = { 116 | 'text': text, 117 | 'desp': desp 118 | } 119 | response = json.dumps(requests.post(url, data).json(), ensure_ascii=False) 120 | datas = json.loads(response) 121 | # print(datas) 122 | if datas['code'] == 0: 123 | print('\nserver酱发送通知消息成功\n') 124 | elif datas['code'] == 40001: 125 | print('\nPUSH_KEY 错误\n') 126 | else: 127 | print('\n发送通知调用API失败!!\n') 128 | else: 129 | print('\n您未提供server酱的SCKEY,取消微信推送消息通知\n') 130 | pass 131 | 132 | def BarkNotify(self, text, desp): 133 | if sendNotify.BARK_PUSH != '': 134 | url = sendNotify.BARK_PUSH + '/' + urllib.parse.quote(text) + '/' + urllib.parse.quote( 135 | desp) + '?sound=' + sendNotify.BARK_SOUND 136 | headers = {'Content-type': "application/x-www-form-urlencoded"} 137 | response = json.dumps(requests.get(url, headers=headers).json(), ensure_ascii=False) 138 | data = json.loads(response) 139 | # print(data) 140 | if data['code'] == 400: 141 | print('\n找不到 Key 对应的 DeviceToken\n') 142 | elif data['code'] == 200: 143 | print('\nBark APP发送通知消息成功\n') 144 | else: 145 | print('\nBark APP发送通知调用API失败!!\n') 146 | print(data) 147 | else: 148 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 149 | pass 150 | 151 | def tgBotNotify(self, text, desp): 152 | if sendNotify.TG_BOT_TOKEN != '' or sendNotify.TG_USER_ID != '': 153 | 154 | url = 'https://api.telegram.org/bot' + sendNotify.TG_BOT_TOKEN + '/sendMessage' 155 | headers = {'Content-type': "application/x-www-form-urlencoded"} 156 | body = 'chat_id=' + sendNotify.TG_USER_ID + '&text=' + urllib.parse.quote( 157 | text) + '\n\n' + urllib.parse.quote(desp) + '&disable_web_page_preview=true' 158 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 159 | 160 | data = json.loads(response) 161 | if data['ok']: 162 | print('\nTelegram发送通知消息完成\n') 163 | elif data['error_code'] == 400: 164 | print('\n请主动给bot发送一条消息并检查接收用户ID是否正确。\n') 165 | elif data['error_code'] == 401: 166 | print('\nTelegram bot token 填写错误。\n') 167 | else: 168 | print('\nTelegram bot发送通知调用API失败!!\n') 169 | print(data) 170 | else: 171 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 172 | pass 173 | 174 | def dingNotify(self, text, desp): 175 | if sendNotify.DD_BOT_TOKEN != '': 176 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN 177 | data = { 178 | "msgtype": "text", 179 | "text": { 180 | 'content': text + desp 181 | } 182 | } 183 | headers = { 184 | 'Content-Type': 'application/json;charset=utf-8' 185 | } 186 | if sendNotify.DD_BOT_SECRET != '': 187 | timestamp = str(round(time.time() * 1000)) 188 | secret = sendNotify.DD_BOT_SECRET 189 | secret_enc = secret.encode('utf-8') 190 | string_to_sign = '{}\n{}'.format(timestamp, secret) 191 | string_to_sign_enc = string_to_sign.encode('utf-8') 192 | hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() 193 | sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) 194 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN + '×tamp=' + timestamp + '&sign=' + sign 195 | 196 | response = requests.post(url=url, data=json.dumps(data), headers=headers).text 197 | if json.loads(response)['errcode'] == 0: 198 | print('\n钉钉发送通知消息成功\n') 199 | else: 200 | print('\n钉钉发送通知失败!!\n') 201 | else: 202 | print('\n您未提供钉钉的有关数据,取消钉钉推送消息通知\n') 203 | pass 204 | 205 | # def coolpush(self, text, desp): 206 | # if sendNotify.QQ_SKEY != '': 207 | # url = "https://push.xuthus.cc/" + sendNotify.QQ_MODE + "/" + sendNotify.QQ_SKEY 208 | # params = {"c": desp, "t": text} 209 | # headers = {'content-type': 'charset=utf8'} 210 | # response = json.dumps(requests.post(url=url, params=params, headers=headers).json(),ensure_ascii=False) 211 | # datas = json.loads(response) 212 | # 213 | # if datas['code'] == 200: 214 | # print('\nQQ推送发送通知消息成功\n') 215 | # elif datas['code'] == 500: 216 | # print('\nQQ推送QQ_SKEY错误\n') 217 | # else: 218 | # print('\n发送通知调用API失败!!\n') 219 | # 220 | # else: 221 | # print('\n您未提供酷推的SKEY,取消QQ推送消息通知\n') 222 | # pass 223 | def pushNotify(self, text, desp): 224 | if sendNotify.PUSH_PLUS_TOKEN != '': 225 | url = 'http://www.pushplus.plus/send' 226 | data = { 227 | "token": sendNotify.PUSH_PLUS_TOKEN, 228 | "title": text, 229 | "content": desp 230 | } 231 | if sendNotify.PUSH_PLUS_USER != '': 232 | data = { 233 | "token": sendNotify.PUSH_PLUS_TOKEN, 234 | "title": text, 235 | "content": desp, 236 | "topic": sendNotify.PUSH_PLUS_USER, 237 | "template": "html" 238 | } 239 | body = json.dumps(data).encode(encoding='utf-8') 240 | headers = {'Content-Type': 'application/json'} 241 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 242 | datas = json.loads(response) 243 | if datas['code'] == 200: 244 | print('\npush+发送通知消息成功\n') 245 | if datas['code'] == 600: 246 | print('\nPUSH_PLUS_TOKEN 错误\n') 247 | else: 248 | print('\npush+发送通知调用API失败!!\n') 249 | else: 250 | print('\n您未提供push+的PUSH_PLUS_TOKEN,取消push+推送消息通知\n') 251 | pass 252 | 253 | # 企业微信推送 254 | def sendWechat(self, desp): 255 | if sendNotify.QYWX_AM != '': 256 | # 获得access_token 257 | url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken' 258 | token_param = '?corpid=' + sendNotify.QYWX_AM.split(',')[0] + '&corpsecret=' + sendNotify.QYWX_AM.split(',')[1] 259 | token_data = requests.get(url + token_param) 260 | token_data.encoding = 'utf-8' 261 | token_data = token_data.json() 262 | access_token = token_data['access_token'] 263 | #发送内容 264 | content = desp 265 | #创建要发送的消息 266 | data = { 267 | "touser": sendNotify.QYWX_AM.split(',')[2], 268 | "msgtype": "text", 269 | "agentid": sendNotify.QYWX_AM.split(',')[3], 270 | "text": {"content": content} 271 | } 272 | send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + access_token 273 | message = requests.post(send_url, json=data) 274 | message.encoding = 'utf-8' 275 | res = message.json() 276 | print('企业微信推送 : ' + res['errmsg']) 277 | else: 278 | print('\n您未提供企业微信的QYWX_AM,取消企业微信推送消息通知\n') 279 | pass 280 | 281 | def send(self, **kwargs): 282 | send = sendNotify() 283 | title = kwargs.get("title", "") 284 | msg = kwargs.get("msg", "") 285 | send.serverNotify(title, msg) 286 | send.BarkNotify(title, msg) 287 | send.tgBotNotify(title, msg) 288 | send.dingNotify(title, msg) 289 | send.pushNotify(title, msg) 290 | send.sendWechat(msg) 291 | # send.coolpush(title,msg) 292 | 293 | # if __name__ == "__main__": 294 | # send(title = '这是标题',msg = '这是内容') 295 | -------------------------------------------------------------------------------- /function/bilibili/bilibili.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | sys.path.append("My-Actions/function/bilibili/") 4 | from bilibiliapi import * 5 | from sendNotify import * 6 | 7 | sendNotify = sendNotify() 8 | SEND_KEY = os.environ['SEND_KEY'] 9 | BILI_COOKIE = os.environ['BILI_COOKIE'].replace(" ", "") 10 | 11 | class BiliBiliCheckIn(object): 12 | # 待测试,需要大会员账号测试领取福利 13 | def __init__(self, bilibili_cookie_list): 14 | self.bilibili_cookie_list = bilibili_cookie_list 15 | 16 | @staticmethod 17 | def get_nav(session): 18 | url = "https://api.bilibili.com/x/web-interface/nav" 19 | ret = session.get(url=url).json() 20 | # print(ret) #取消本段输出 21 | uname = ret.get("data", {}).get("uname") 22 | uid = ret.get("data", {}).get("mid") 23 | is_login = ret.get("data", {}).get("isLogin") 24 | coin = ret.get("data", {}).get("money") 25 | vip_type = ret.get("data", {}).get("vipType") 26 | current_exp = ret.get("data", {}).get("level_info", {}).get("current_exp") 27 | return uname, uid, is_login, coin, vip_type, current_exp 28 | 29 | @staticmethod 30 | def reward(session) -> dict: 31 | """取B站经验信息""" 32 | url = "https://account.bilibili.com/home/reward" 33 | ret = session.get(url=url).json() 34 | return ret 35 | 36 | @staticmethod 37 | def live_sign(session) -> dict: 38 | """B站直播签到""" 39 | try: 40 | url = "https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign" 41 | ret = session.get(url=url).json() 42 | if ret["code"] == 0: 43 | msg = f'签到成功,{ret["data"]["text"]},特别信息:{ret["data"]["specialText"]},本月已签到{ret["data"]["hadSignDays"]}天' 44 | elif ret["code"] == 1011040: 45 | msg = "今日已签到过,无法重复签到" 46 | else: 47 | msg = f'签到失败,信息为: {ret["message"]}' 48 | except Exception as e: 49 | msg = f"签到异常,原因为{str(e)}" 50 | return msg 51 | 52 | @staticmethod 53 | def manga_sign(session, platform="android") -> dict: 54 | """ 55 | 模拟B站漫画客户端签到 56 | """ 57 | try: 58 | url = "https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn" 59 | post_data = {"platform": platform} 60 | ret = session.post(url=url, data=post_data).json() 61 | if ret["code"] == 0: 62 | msg = "签到成功" 63 | elif ret["msg"] == "clockin clockin is duplicate": 64 | msg = "今天已经签到过了" 65 | else: 66 | msg = f'签到失败,信息为({ret["msg"]})' 67 | except Exception as e: 68 | msg = f"签到异常,原因为: {str(e)}" 69 | return msg 70 | 71 | @staticmethod 72 | def vip_privilege_receive(session, bili_jct, receive_type: int = 1) -> dict: 73 | """ 74 | 领取B站大会员权益 75 | receive_type int 权益类型,1为B币劵,2为优惠券 76 | """ 77 | url = "https://api.bilibili.com/x/vip/privilege/receive" 78 | post_data = {"type": receive_type, "csrf": bili_jct} 79 | ret = session.post(url=url, data=post_data).json() 80 | return ret 81 | 82 | @staticmethod 83 | def vip_manga_reward(session) -> dict: 84 | """获取漫画大会员福利""" 85 | url = "https://manga.bilibili.com/twirp/user.v1.User/GetVipReward" 86 | ret = session.post(url=url, json={"reason_id": 1}).json() 87 | return ret 88 | 89 | @staticmethod 90 | def report_task(session, bili_jct, aid: int, cid: int, progres: int = 300) -> dict: 91 | """ 92 | B站上报视频观看进度 93 | aid int 视频av号 94 | cid int 视频cid号 95 | progres int 观看秒数 96 | """ 97 | url = "http://api.bilibili.com/x/v2/history/report" 98 | post_data = {"aid": aid, "cid": cid, "progres": progres, "csrf": bili_jct} 99 | ret = session.post(url=url, data=post_data).json() 100 | return ret 101 | 102 | @staticmethod 103 | def share_task(session, bili_jct, aid) -> dict: 104 | """ 105 | 分享指定av号视频 106 | aid int 视频av号 107 | """ 108 | url = "https://api.bilibili.com/x/web-interface/share/add" 109 | post_data = {"aid": aid, "csrf": bili_jct} 110 | ret = session.post(url=url, data=post_data).json() 111 | return ret 112 | 113 | @staticmethod 114 | def get_followings( 115 | session, uid: int, pn: int = 1, ps: int = 50, order: str = "desc", order_type: str = "attention" 116 | ) -> dict: 117 | """ 118 | 获取指定用户关注的up主 119 | uid int 账户uid,默认为本账户,非登录账户只能获取20个*5页 120 | pn int 页码,默认第一页 121 | ps int 每页数量,默认50 122 | order str 排序方式,默认desc 123 | order_type 排序类型,默认attention 124 | """ 125 | params = { 126 | "vmid": uid, 127 | "pn": pn, 128 | "ps": ps, 129 | "order": order, 130 | "order_type": order_type, 131 | } 132 | url = f"https://api.bilibili.com/x/relation/followings" 133 | ret = session.get(url=url, params=params).json() 134 | return ret 135 | 136 | @staticmethod 137 | def space_arc_search( 138 | session, uid: int, pn: int = 1, ps: int = 100, tid: int = 0, order: str = "pubdate", keyword: str = "" 139 | ) -> dict: 140 | """ 141 | 获取指定up主空间视频投稿信息 142 | uid int 账户uid,默认为本账户 143 | pn int 页码,默认第一页 144 | ps int 每页数量,默认50 145 | tid int 分区 默认为0(所有分区) 146 | order str 排序方式,默认pubdate 147 | keyword str 关键字,默认为空 148 | """ 149 | params = { 150 | "mid": uid, 151 | "pn": pn, 152 | "ps": ps, 153 | "tid": tid, 154 | "order": order, 155 | "keyword": keyword, 156 | } 157 | url = f"https://api.bilibili.com/x/space/arc/search" 158 | ret = session.get(url=url, params=params).json() 159 | data_list = [ 160 | {"aid": one.get("aid"), "cid": 0, "title": one.get("title"), "owner": one.get("author")} 161 | for one in ret.get("data", {}).get("list", {}).get("vlist", []) 162 | ] 163 | return data_list 164 | 165 | @staticmethod 166 | def elec_pay(session, bili_jct, uid: int, num: int = 50) -> dict: 167 | """ 168 | 用B币给up主充电 169 | uid int up主uid 170 | num int 充电电池数量 171 | """ 172 | url = "https://api.bilibili.com/x/ugcpay/trade/elec/pay/quick" 173 | post_data = {"elec_num": num, "up_mid": uid, "otype": "up", "oid": uid, "csrf": bili_jct} 174 | ret = session.post(url=url, data=post_data).json() 175 | return ret 176 | 177 | @staticmethod 178 | def coin_add(session, bili_jct, aid: int, num: int = 1, select_like: int = 1) -> dict: 179 | """ 180 | 给指定 av 号视频投币 181 | aid int 视频av号 182 | num int 投币数量 183 | select_like int 是否点赞 184 | """ 185 | url = "https://api.bilibili.com/x/web-interface/coin/add" 186 | post_data = { 187 | "aid": aid, 188 | "multiply": num, 189 | "select_like": select_like, 190 | "cross_domain": "true", 191 | "csrf": bili_jct, 192 | } 193 | ret = session.post(url=url, data=post_data).json() 194 | 195 | return ret 196 | 197 | @staticmethod 198 | def live_status(session) -> dict: 199 | """B站直播获取金银瓜子状态""" 200 | url = "https://api.live.bilibili.com/pay/v1/Exchange/getStatus" 201 | ret = session.get(url=url).json() 202 | data = ret.get("data") 203 | silver = data.get("silver", 0) 204 | gold = data.get("gold", 0) 205 | coin = data.get("coin", 0) 206 | msg = f"银瓜子数量: {silver}\n金瓜子数量: {gold}\n硬币数量: {coin}" 207 | return msg 208 | 209 | @staticmethod 210 | def silver2coin(session, bili_jct) -> dict: 211 | """银瓜子兑换硬币""" 212 | url = "https://api.live.bilibili.com/pay/v1/Exchange/silver2coin" 213 | post_data = {"csrf_token": bili_jct} 214 | ret = session.post(url=url, data=post_data).json() 215 | return ret 216 | 217 | @staticmethod 218 | def get_region(session, rid=1, num=6) -> dict: 219 | """ 220 | 获取 B站分区视频信息 221 | rid int 分区号 222 | num int 获取视频数量 223 | """ 224 | url = "https://api.bilibili.com/x/web-interface/dynamic/region?ps=" + str(num) + "&rid=" + str(rid) 225 | ret = session.get(url=url).json() 226 | data_list = [ 227 | { 228 | "aid": one.get("aid"), 229 | "cid": one.get("cid"), 230 | "title": one.get("title"), 231 | "owner": one.get("owner", {}).get("name"), 232 | } 233 | for one in ret.get("data", {}).get("archives", []) 234 | ] 235 | return data_list 236 | 237 | def main(self): 238 | msg_list = [] 239 | bilibili_cookie = self.bilibili_cookie_list 240 | bili_jct = bilibili_cookie.get("bili_jct") 241 | 242 | if os.environ['BILI_NUM'] == "": 243 | coin_num = 0 # 投币数量 244 | else: 245 | coin_num = int(os.environ['BILI_NUM']) 246 | 247 | if os.environ['BILI_TYPE'] == "": 248 | coin_type = 1 # 投币方式 默认为 1 ;1: 为关注用户列表视频投币 0: 为随机投币。如果关注用户发布的视频不足配置的投币数,则剩余部分使用随机投币 249 | else: 250 | coin_type = int(os.environ['BILI_TYPE']) 251 | 252 | silver2coin = True #是否开启银瓜子换硬币,默认为 True 开启 253 | session = requests.session() 254 | requests.utils.add_dict_to_cookiejar(session.cookies, bilibili_cookie) 255 | session.headers.update( 256 | { 257 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/63.0.3239.108", 258 | "Referer": "https://www.bilibili.com/", 259 | "Connection": "keep-alive", 260 | } 261 | ) 262 | success_count = 0 263 | uname, uid, is_login, coin, vip_type, current_exp = self.get_nav(session=session) 264 | # print(uname, uid, is_login, coin, vip_type, current_exp) 265 | if is_login: 266 | manhua_msg = self.manga_sign(session=session) 267 | print(manhua_msg) 268 | live_msg = self.live_sign(session=session) 269 | print(live_msg) 270 | aid_list = self.get_region(session=session) 271 | reward_ret = self.reward(session=session) 272 | # print(reward_ret) # 取消本段输出 273 | coins_av_count = reward_ret.get("data", {}).get("coins_av") // 10 274 | coin_num = coin_num - coins_av_count 275 | coin_num = coin_num if coin_num < coin else coin 276 | print(coin_num) 277 | if coin_type == 1 and coin_num: 278 | following_list = self.get_followings(session=session, uid=uid) 279 | for following in following_list.get("data", {}).get("list"): 280 | mid = following.get("mid") 281 | if mid: 282 | aid_list += self.space_arc_search(session=session, uid=mid) 283 | if coin_num > 0: 284 | for aid in aid_list[::-1]: 285 | # print(f'成功给{aid.get("title")}投一个币') 286 | # coin_num -= 1 287 | # success_count += 1 288 | ret = self.coin_add(session=session, aid=aid.get("aid"), bili_jct=bili_jct) 289 | if ret["code"] == 0: 290 | coin_num -= 1 291 | print(f'成功给{aid.get("title")}投一个币') 292 | success_count += 1 293 | elif ret["code"] == 34005: 294 | print(f'投币{aid.get("title")}失败,原因为{ret["message"]}') 295 | continue 296 | # -104 硬币不够了 -111 csrf 失败 34005 投币达到上限 297 | else: 298 | print(f'投币{aid.get("title")}失败,原因为{ret["message"]},跳过投币') 299 | break 300 | if coin_num <= 0: 301 | break 302 | coin_msg = f"今日成功投币{success_count + coins_av_count}/{coin_num}个" 303 | print(coin_msg) 304 | else: 305 | coin_msg = f"今日成功投币{coins_av_count}/{coin_type}个" 306 | print(coin_msg) 307 | aid = aid_list[0].get("aid") 308 | cid = aid_list[0].get("cid") 309 | title = aid_list[0].get("title") 310 | report_ret = self.report_task(session=session, bili_jct=bili_jct, aid=aid, cid=cid) 311 | if report_ret.get("code") == 0: 312 | report_msg = f"观看《{title}》300秒" 313 | else: 314 | report_msg = f"任务失败" 315 | print(report_msg) 316 | share_ret = self.share_task(session=session, bili_jct=bili_jct, aid=aid) 317 | if share_ret.get("code") == 0: 318 | share_msg = f"分享《{title}》成功" 319 | else: 320 | share_msg = f"分享失败" 321 | print(share_msg) 322 | if silver2coin: 323 | silver2coin_ret = self.silver2coin(session=session, bili_jct=bili_jct) 324 | if silver2coin_ret["code"] == 0: 325 | silver2coin_msg = f"成功将银瓜子兑换为1个硬币" 326 | else: 327 | silver2coin_msg = silver2coin_ret["msg"] 328 | print(silver2coin_msg) 329 | else: 330 | silver2coin_msg = f"未开启银瓜子兑换硬币功能" 331 | live_stats = self.live_status(session=session) 332 | uname, uid, is_login, new_coin, vip_type, new_current_exp = self.get_nav(session=session) 333 | # print(uname, uid, is_login, new_coin, vip_type, new_current_exp) 334 | reward_ret = self.reward(session=session) 335 | login = reward_ret.get("data", {}).get("login") 336 | watch_av = reward_ret.get("data", {}).get("watch_av") 337 | coins_av = reward_ret.get("data", {}).get("coins_av", 0) 338 | share_av = reward_ret.get("data", {}).get("share_av") 339 | today_exp = len([one for one in [login, watch_av, share_av] if one]) * 5 340 | today_exp += coins_av 341 | update_data = (28800 - new_current_exp) // (today_exp if today_exp else 1) 342 | msg = ( 343 | f"【Bilibili签到】\n帐号信息: {uname}\n漫画签到: {manhua_msg}\n直播签到: {live_msg}\n" 344 | f"登陆任务: 今日已登陆\n观看视频: {report_msg}\n分享任务: {share_msg}\n投币任务: {coin_msg}\n" 345 | f"银瓜子兑换硬币: {silver2coin_msg}\n今日获得经验: {today_exp}\n当前经验: {new_current_exp}\n" 346 | f"按当前速度升级还需: {update_data}天\n{live_stats}" 347 | ) 348 | print(msg) 349 | if SEND_KEY == '': 350 | sendNotify.send(title = u"哔哩哔哩签到",msg = msg) 351 | msg_list.append(msg) 352 | return msg_list 353 | 354 | 355 | if __name__ == "__main__": 356 | # 未填写参数取消运行 357 | if os.environ['BILI_USER'] == "" or os.environ['BILI_PASS'] == "": 358 | if os.environ['BILI_COOKIE'] == "": 359 | print("未填写哔哩哔哩账号密码或COOKIE取消运行") 360 | exit(0) 361 | 362 | if BILI_COOKIE == "": 363 | b = Bilibili() 364 | login = b.login(username=os.environ['BILI_USER'], password=os.environ['BILI_PASS']) 365 | if login == False: 366 | sendNotify.send(title = u"哔哩哔哩签到", msg = "登录失败 账号或密码错误,详情前往Github查看") 367 | exit(0) 368 | _bilibili_cookie_list = b.get_cookies() 369 | else: 370 | _bilibili_cookie_list = {cookie.split('=')[0]:cookie.split('=')[-1] for cookie in BILI_COOKIE.split(';')} 371 | 372 | BiliBiliCheckIn(bilibili_cookie_list=_bilibili_cookie_list).main() -------------------------------------------------------------------------------- /function/bilibili/sendNotify.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import time 3 | import hmac 4 | import hashlib 5 | import base64 6 | import json 7 | import os 8 | import urllib.parse 9 | 10 | 11 | class sendNotify: 12 | # =======================================微信server酱通知设置区域=========================================== 13 | # 此处填你申请的SCKEY. 14 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入PUSH_KEY) 15 | SCKEY = '' 16 | 17 | # =======================================Bark App通知设置区域=========================================== 18 | # 此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) 19 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_PUSH) 20 | BARK_PUSH = '' 21 | # BARK app推送铃声,铃声列表去APP查看复制填写 22 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_SOUND , Value输入app提供的铃声名称,例如:birdsong) 23 | BARK_SOUND = '' 24 | 25 | # =======================================telegram机器人通知设置区域=========================================== 26 | # 此处填你telegram bot 的Token,例如:1077xxx4424:AAFjv0FlexboxEMGfi22B4yh15R5uw 27 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_BOT_TOKEN) 28 | TG_BOT_TOKEN = '' 29 | # 此处填你接收通知消息的telegram用户的id,例如:129xxx206 30 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_USER_ID) 31 | TG_USER_ID = '' 32 | 33 | # =======================================钉钉机器人通知设置区域=========================================== 34 | # 此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415assayed 35 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入DD_BOT_TOKEN) 36 | DD_BOT_TOKEN = '' 37 | # 密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 38 | DD_BOT_SECRET = '' 39 | 40 | # =======================================企业微信机器人通知设置区域=========================================== 此处填你企业微信机器人的 41 | # webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 42 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QYWX_KEY) 43 | # QYWX_KEY = '' 44 | 45 | # =======================================企业微信应用消息通知设置区域=========================================== 此处填你企业微信应用消息的 46 | # 第一个值是企业id,第二个值是secret,第三个值@all(或者成员id),第四个值是AgentID 中间以逗号隔开 47 | # 详情查看https://note.youdao.com/ynoteshare1/index.html?id=351e08a72378206f9dd64d2281e9b83b&type=note#/ 48 | # B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat 49 | QYWX_AM = '' 50 | 51 | # =======================================QQ酷推通知设置区域=========================================== 52 | # 此处填你申请的SKEY(具体详见文档 https://cp.xuthus.cc/) 53 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QQ_SKEY) 54 | # QQ_SKEY = '' 55 | # #此处填写私聊或群组推送,默认私聊(send或group或者wx) 56 | # QQ_MODE = 'send' 57 | 58 | # =======================================push+设置区域======================================= 59 | # 官方文档:https://www.pushplus.plus/ 60 | # PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 61 | PUSH_PLUS_TOKEN = '' 62 | # PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) 63 | PUSH_PLUS_USER = '' 64 | 65 | # Server酱 66 | if os.environ['PUSH_KEY'] != "": 67 | SCKEY = os.environ['PUSH_KEY'] 68 | 69 | # Bark App 70 | if os.environ['BARK_PUSH'] != "": 71 | if os.environ['BARK_PUSH'].find("https") != -1 or os.environ['BARK_PUSH'].find("http") != -1: 72 | BARK_PUSH = os.environ['PUSH_KEY'] 73 | else: 74 | BARK_PUSH = "https://api.day.app/" + os.environ['BARK_PUSH'] 75 | elif os.environ['BARK_SOUND'] != "": 76 | BARK_SOUND = os.environ['BARK_SOUND'] 77 | elif BARK_PUSH != "" or BARK_PUSH.find("https") != -1 or BARK_PUSH.find("http") != -1: 78 | BARK_PUSH = "https://api.day.app/" + BARK_PUSH 79 | 80 | # telegram 81 | if os.environ['TG_BOT_TOKEN'] != "": 82 | TG_BOT_TOKEN = os.environ['TG_BOT_TOKEN'] 83 | if os.environ['TG_USER_ID'] != "": 84 | TG_USER_ID = os.environ['TG_USER_ID'] 85 | 86 | # 钉钉机器人 87 | if os.environ['DD_BOT_TOKEN'] != "": 88 | DD_BOT_TOKEN = os.environ['DD_BOT_TOKEN'] 89 | if os.environ['DD_BOT_SECRET'] != "": 90 | DD_BOT_SECRET = os.environ['DD_BOT_SECRET'] 91 | 92 | # QQ酷推 93 | # if os.environ['QQ_SKEY'] != "": 94 | # QQ_SKEY = os.environ['QQ_SKEY'] 95 | # if os.environ['QQ_MODE'] != "": 96 | # QQ_MODE = os.environ['QQ_MODE'] 97 | 98 | # 企业微信 99 | # if os.environ['QYWX_KEY'] != "": 100 | # QQ_SKEY = os.environ['QYWX_KEY'] 101 | if os.environ['QYWX_AM'] != "": 102 | QYWX_AM = os.environ['QYWX_AM'] 103 | 104 | # push+ 105 | if os.environ['PUSH_PLUS_TOKEN'] != "": 106 | PUSH_PLUS_TOKEN = os.environ['PUSH_PLUS_TOKEN'] 107 | if os.environ['PUSH_PLUS_USER'] != "": 108 | PUSH_PLUS_USER = os.environ['PUSH_PLUS_USER'] 109 | 110 | def serverNotify(self, text, desp): 111 | if sendNotify.SCKEY != '': 112 | url = 'https://sctapi.ftqq.com/' + sendNotify.SCKEY + '.send' 113 | if "\n" in desp: 114 | desp = desp.replace("\n", "\n\n") 115 | data = { 116 | 'text': text, 117 | 'desp': desp 118 | } 119 | response = json.dumps(requests.post(url, data).json(), ensure_ascii=False) 120 | datas = json.loads(response) 121 | # print(datas) 122 | if datas['code'] == 0: 123 | print('\nserver酱发送通知消息成功\n') 124 | elif datas['code'] == 40001: 125 | print('\nPUSH_KEY 错误\n') 126 | else: 127 | print('\n发送通知调用API失败!!\n') 128 | else: 129 | print('\n您未提供server酱的SCKEY,取消微信推送消息通知\n') 130 | pass 131 | 132 | def BarkNotify(self, text, desp): 133 | if sendNotify.BARK_PUSH != '': 134 | url = sendNotify.BARK_PUSH + '/' + urllib.parse.quote(text) + '/' + urllib.parse.quote( 135 | desp) + '?sound=' + sendNotify.BARK_SOUND 136 | headers = {'Content-type': "application/x-www-form-urlencoded"} 137 | response = json.dumps(requests.get(url, headers=headers).json(), ensure_ascii=False) 138 | data = json.loads(response) 139 | # print(data) 140 | if data['code'] == 400: 141 | print('\n找不到 Key 对应的 DeviceToken\n') 142 | elif data['code'] == 200: 143 | print('\nBark APP发送通知消息成功\n') 144 | else: 145 | print('\nBark APP发送通知调用API失败!!\n') 146 | print(data) 147 | else: 148 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 149 | pass 150 | 151 | def tgBotNotify(self, text, desp): 152 | if sendNotify.TG_BOT_TOKEN != '' or sendNotify.TG_USER_ID != '': 153 | 154 | url = 'https://api.telegram.org/bot' + sendNotify.TG_BOT_TOKEN + '/sendMessage' 155 | headers = {'Content-type': "application/x-www-form-urlencoded"} 156 | body = 'chat_id=' + sendNotify.TG_USER_ID + '&text=' + urllib.parse.quote( 157 | text) + '\n\n' + urllib.parse.quote(desp) + '&disable_web_page_preview=true' 158 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 159 | 160 | data = json.loads(response) 161 | if data['ok']: 162 | print('\nTelegram发送通知消息完成\n') 163 | elif data['error_code'] == 400: 164 | print('\n请主动给bot发送一条消息并检查接收用户ID是否正确。\n') 165 | elif data['error_code'] == 401: 166 | print('\nTelegram bot token 填写错误。\n') 167 | else: 168 | print('\nTelegram bot发送通知调用API失败!!\n') 169 | print(data) 170 | else: 171 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 172 | pass 173 | 174 | def dingNotify(self, text, desp): 175 | if sendNotify.DD_BOT_TOKEN != '': 176 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN 177 | data = { 178 | "msgtype": "text", 179 | "text": { 180 | 'content': text + desp 181 | } 182 | } 183 | headers = { 184 | 'Content-Type': 'application/json;charset=utf-8' 185 | } 186 | if sendNotify.DD_BOT_SECRET != '': 187 | timestamp = str(round(time.time() * 1000)) 188 | secret = sendNotify.DD_BOT_SECRET 189 | secret_enc = secret.encode('utf-8') 190 | string_to_sign = '{}\n{}'.format(timestamp, secret) 191 | string_to_sign_enc = string_to_sign.encode('utf-8') 192 | hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() 193 | sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) 194 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN + '×tamp=' + timestamp + '&sign=' + sign 195 | 196 | response = requests.post(url=url, data=json.dumps(data), headers=headers).text 197 | if json.loads(response)['errcode'] == 0: 198 | print('\n钉钉发送通知消息成功\n') 199 | else: 200 | print('\n钉钉发送通知失败!!\n') 201 | else: 202 | print('\n您未提供钉钉的有关数据,取消钉钉推送消息通知\n') 203 | pass 204 | 205 | # def coolpush(self, text, desp): 206 | # if sendNotify.QQ_SKEY != '': 207 | # url = "https://push.xuthus.cc/" + sendNotify.QQ_MODE + "/" + sendNotify.QQ_SKEY 208 | # params = {"c": desp, "t": text} 209 | # headers = {'content-type': 'charset=utf8'} 210 | # response = json.dumps(requests.post(url=url, params=params, headers=headers).json(),ensure_ascii=False) 211 | # datas = json.loads(response) 212 | # 213 | # if datas['code'] == 200: 214 | # print('\nQQ推送发送通知消息成功\n') 215 | # elif datas['code'] == 500: 216 | # print('\nQQ推送QQ_SKEY错误\n') 217 | # else: 218 | # print('\n发送通知调用API失败!!\n') 219 | # 220 | # else: 221 | # print('\n您未提供酷推的SKEY,取消QQ推送消息通知\n') 222 | # pass 223 | def pushNotify(self, text, desp): 224 | if sendNotify.PUSH_PLUS_TOKEN != '': 225 | url = 'http://www.pushplus.plus/send' 226 | data = { 227 | "token": sendNotify.PUSH_PLUS_TOKEN, 228 | "title": text, 229 | "content": desp 230 | } 231 | if sendNotify.PUSH_PLUS_USER != '': 232 | data = { 233 | "token": sendNotify.PUSH_PLUS_TOKEN, 234 | "title": text, 235 | "content": desp, 236 | "topic": sendNotify.PUSH_PLUS_USER, 237 | "template": "html" 238 | } 239 | body = json.dumps(data).encode(encoding='utf-8') 240 | headers = {'Content-Type': 'application/json'} 241 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 242 | datas = json.loads(response) 243 | if datas['code'] == 200: 244 | print('\npush+发送通知消息成功\n') 245 | if datas['code'] == 600: 246 | print('\nPUSH_PLUS_TOKEN 错误\n') 247 | else: 248 | print('\npush+发送通知调用API失败!!\n') 249 | else: 250 | print('\n您未提供push+的PUSH_PLUS_TOKEN,取消push+推送消息通知\n') 251 | pass 252 | 253 | # 企业微信推送 254 | def sendWechat(self, desp): 255 | if sendNotify.QYWX_AM != '': 256 | # 获得access_token 257 | url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken' 258 | token_param = '?corpid=' + sendNotify.QYWX_AM.split(',')[0] + '&corpsecret=' + sendNotify.QYWX_AM.split(',')[1] 259 | token_data = requests.get(url + token_param) 260 | token_data.encoding = 'utf-8' 261 | token_data = token_data.json() 262 | access_token = token_data['access_token'] 263 | #发送内容 264 | content = desp 265 | #创建要发送的消息 266 | data = { 267 | "touser": sendNotify.QYWX_AM.split(',')[2], 268 | "msgtype": "text", 269 | "agentid": sendNotify.QYWX_AM.split(',')[3], 270 | "text": {"content": content} 271 | } 272 | send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + access_token 273 | message = requests.post(send_url, json=data) 274 | message.encoding = 'utf-8' 275 | res = message.json() 276 | print('企业微信推送 : ' + res['errmsg']) 277 | else: 278 | print('\n您未提供企业微信的QYWX_AM,取消企业微信推送消息通知\n') 279 | pass 280 | 281 | def send(self, **kwargs): 282 | send = sendNotify() 283 | title = kwargs.get("title", "") 284 | msg = kwargs.get("msg", "") 285 | send.serverNotify(title, msg) 286 | send.BarkNotify(title, msg) 287 | send.tgBotNotify(title, msg) 288 | send.dingNotify(title, msg) 289 | send.pushNotify(title, msg) 290 | send.sendWechat(msg) 291 | # send.coolpush(title,msg) 292 | 293 | # if __name__ == "__main__": 294 | # send(title = '这是标题',msg = '这是内容') 295 | -------------------------------------------------------------------------------- /function/iQIYI-DailyBonus/iQIYI-bak.js: -------------------------------------------------------------------------------- 1 | /* 2 | 爱奇艺会员签到脚本 3 | 4 | 更新时间: 2020.9.6 5 | 脚本兼容: QuantumultX, Surge4, Loon, JsBox, Node.js 6 | 电报频道: @NobyDa 7 | 问题反馈: @NobyDa_bot 8 | 9 | 获取Cookie说明: 10 | 打开爱奇艺App后(AppStore中国区),点击"我的", 如通知成功获取cookie, 则可以使用此签到脚本. 11 | 获取Cookie后, 请将Cookie脚本禁用并移除主机名,以免产生不必要的MITM. 12 | 脚本将在每天上午9:00执行, 您可以修改执行时间。 13 | 14 | 如果使用Node.js, 需自行安装'request'模块. 例: npm install request -g 15 | 16 | JsBox, Node.js用户抓取Cookie说明: 17 | 开启抓包, 打开爱奇艺App后(AppStore中国区),点击"我的" 返回抓包App 搜索请求头关键字 psp_cki= 或 P00001= 或 authcookie= 18 | 提取字母数字混合字段, 到&结束, 填入以下单引号内即可. 19 | */ 20 | 21 | var cookie = '' 22 | 23 | /********************* 24 | QuantumultX 远程脚本配置: 25 | ********************** 26 | [task_local] 27 | # 爱奇艺会员签到 28 | 0 9 * * * https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js 29 | 30 | [rewrite_local] 31 | # 获取Cookie 32 | ^https?:\/\/iface(\d)?\.iqiyi\.com\/ url script-request-header https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js 33 | 34 | [mitm] 35 | hostname= ifac*.iqiyi.com 36 | 37 | ********************** 38 | Surge 4.2.0+ 脚本配置: 39 | ********************** 40 | [Script] 41 | 爱奇艺签到 = type=cron,cronexp=0 9 * * *,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js 42 | 43 | 爱奇艺获取Cookie = type=http-request,pattern=^https?:\/\/iface(\d)?\.iqiyi\.com\/,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js 44 | 45 | [MITM] 46 | hostname= ifac*.iqiyi.com 47 | 48 | ************************ 49 | Loon 2.1.0+ 脚本配置: 50 | ************************ 51 | 52 | [Script] 53 | # 爱奇艺签到 54 | cron "0 9 * * *" script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js 55 | 56 | # 获取Cookie 57 | http-request ^https?:\/\/iface(\d)?\.iqiyi\.com\/ script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js 58 | 59 | [Mitm] 60 | hostname= ifac*.iqiyi.com 61 | 62 | */ 63 | 64 | var LogDetails = false; // 响应日志 65 | 66 | var out = 10000; // 超时 (毫秒) 如填写, 则不少于3000 67 | 68 | var $nobyda = nobyda(); 69 | 70 | (async () => { 71 | out = $nobyda.read("iQIYI_TimeOut") || out 72 | cookie = cookie || $nobyda.read("CookieQY") 73 | LogDetails = $nobyda.read("iQIYI_LogDetails") === "true" ? true : LogDetails 74 | if ($nobyda.isRequest) { 75 | GetCookie() 76 | } else if (cookie) { 77 | await login(); 78 | await Checkin(); 79 | await Lottery(500); 80 | await $nobyda.time(); 81 | } else { 82 | $nobyda.notify("爱奇艺会员", "", "签到终止, 未获取Cookie"); 83 | } 84 | })().finally(() => { 85 | $nobyda.done(); 86 | }) 87 | 88 | function login() { 89 | return new Promise(resolve => { 90 | var URL = { 91 | url: 'https://cards.iqiyi.com/views_category/3.0/vip_home?secure_p=iPhone&scrn_scale=0&dev_os=0&ouid=0&layout_v=6&psp_cki=' + cookie + '&page_st=suggest&app_k=8e48946f144759d86a50075555fd5862&dev_ua=iPhone8%2C2&net_sts=1&cupid_uid=0&xas=1&init_type=6&app_v=11.4.5&idfa=0&app_t=0&platform_id=0&layout_name=0&req_sn=0&api_v=0&psp_status=0&psp_uid=451953037415627&qyid=0&secure_v=0&req_times=0', 92 | headers: { 93 | sign: '7fd8aadd90f4cfc99a858a4b087bcc3a', 94 | t: '479112291' 95 | } 96 | } 97 | $nobyda.get(URL, function(error, response, data) { 98 | const Details = LogDetails ? data ? `response:\n${data}` : '' : '' 99 | if (!error && data.match(/\"text\":\"\d.+?\u5230\u671f\"/)) { 100 | $nobyda.expire = data.match(/\"text\":\"(\d.+?\u5230\u671f)\"/)[1] 101 | console.log(`爱奇艺-查询成功: ${$nobyda.expire} ${Details}`) 102 | } else { 103 | console.log(`爱奇艺-查询失败${error || ': 无到期数据 ⚠️'} ${Details}`) 104 | } 105 | resolve() 106 | }) 107 | if (out) setTimeout(resolve, out) 108 | }) 109 | } 110 | 111 | function Checkin() { 112 | return new Promise(resolve => { 113 | var URL = { 114 | url: 'https://tc.vip.iqiyi.com/taskCenter/task/queryUserTask?autoSign=yes&P00001=' + cookie 115 | } 116 | $nobyda.get(URL, function(error, response, data) { 117 | if (error) { 118 | $nobyda.data = "签到失败: 接口请求出错 ‼️" 119 | console.log(`爱奇艺-${$nobyda.data} ${error}`) 120 | } else { 121 | if(!isJSON_test(data)){ 122 | return false; 123 | } 124 | const obj = JSON.parse(data) 125 | const Details = LogDetails ? `response:\n${data}` : '' 126 | if (obj.msg === "成功") { 127 | if (obj.data.signInfo.code === "A00000") { 128 | var AwardName = obj.data.signInfo.data.rewards[0].name; 129 | var quantity = obj.data.signInfo.data.rewards[0].value; 130 | var continued = obj.data.signInfo.data.continueSignDaysSum; 131 | $nobyda.data = "签到成功: " + AwardName + quantity + ", 已连签" + continued + "天 🎉" 132 | console.log(`爱奇艺-${$nobyda.data} ${Details}`) 133 | } else { 134 | $nobyda.data = "签到失败: " + obj.data.signInfo.msg + " ⚠️" 135 | console.log(`爱奇艺-${$nobyda.data} ${Details}`) 136 | } 137 | } else { 138 | $nobyda.data = "签到失败: Cookie无效 ⚠️" 139 | console.log(`爱奇艺-${$nobyda.data} ${Details}`) 140 | } 141 | } 142 | resolve() 143 | }) 144 | if (out) setTimeout(resolve, out) 145 | }) 146 | } 147 | 148 | function Lottery(s) { 149 | return new Promise(resolve => { 150 | $nobyda.times++ 151 | const URL = { 152 | url: 'https://iface2.iqiyi.com/aggregate/3.0/lottery_activity?app_k=0&app_v=0&platform_id=0&dev_os=0&dev_ua=0&net_sts=0&qyid=0&psp_uid=0&psp_cki=' + cookie + '&psp_status=0&secure_p=0&secure_v=0&req_sn=0' 153 | } 154 | setTimeout(() => { 155 | $nobyda.get(URL, async function(error, response, data) { 156 | if (error) { 157 | $nobyda.data += "\n抽奖失败: 接口请求出错 ‼️" 158 | console.log(`爱奇艺-抽奖失败: 接口请求出错 ‼️ ${error} (${$nobyda.times})`) 159 | //$nobyda.notify("爱奇艺", "", $nobyda.data) 160 | } else { 161 | const obj = JSON.parse(data); 162 | const Details = LogDetails ? `response:\n${data}` : '' 163 | $nobyda.last = data.match(/(机会|已经)用完/) ? true : false 164 | if (obj.awardName && obj.code === 0) { 165 | $nobyda.data += !$nobyda.last ? `\n抽奖成功: ${obj.awardName.replace(/《.+》/, "未中奖")} 🎉` : `\n抽奖失败: 今日已抽奖 ⚠️` 166 | console.log(`爱奇艺-抽奖明细: ${obj.awardName.replace(/《.+》/, "未中奖")} 🎉 (${$nobyda.times}) ${Details}`) 167 | } else if (data.match(/\"errorReason\"/)) { 168 | msg = data.match(/msg=.+?\)/) ? data.match(/msg=(.+?)\)/)[1].replace(/用户(未登录|不存在)/, "Cookie无效") : "" 169 | $nobyda.data += `\n抽奖失败: ${msg || `未知错误`} ⚠️` 170 | console.log(`爱奇艺-抽奖失败: ${msg || `未知错误`} ⚠️ (${$nobyda.times}) ${msg ? Details : `response:\n${data}`}`) 171 | console.log(data) 172 | s = s + 500; 173 | if(s <= 4500){ 174 | await Lottery(s) 175 | } 176 | } else { 177 | $nobyda.data += "\n抽奖错误: 已输出日志 ⚠️" 178 | console.log(`爱奇艺-抽奖失败: \n${data} (${$nobyda.times})`) 179 | } 180 | } 181 | if (!$nobyda.last && $nobyda.times < 3) { 182 | await Lottery(s) 183 | } else { 184 | const expires = $nobyda.expire ? $nobyda.expire.replace(/\u5230\u671f/, "") : "获取失败 ⚠️" 185 | if (!$nobyda.isNode) $nobyda.notify("爱奇艺", "到期时间: " + expires, $nobyda.data) 186 | } 187 | resolve() 188 | }) 189 | }, s) 190 | if (out) setTimeout(resolve, out + s) 191 | }) 192 | } 193 | 194 | function GetCookie() { 195 | var CKA = $request.url.match(/(psp_cki=|P00001=|authcookie=)([A-Za-z0-9]+)/) 196 | var CKB = JSON.stringify($request.headers).match(/(psp_cki=|P00001=|authcookie=)([A-Za-z0-9]+)/) 197 | var iQIYI = CKA || CKB || null 198 | var RA = $nobyda.read("CookieQY") 199 | if (iQIYI) { 200 | if (RA !== iQIYI[2]) { 201 | var OldTime = $nobyda.read("CookieQYTime") 202 | if (!$nobyda.write(iQIYI[2], "CookieQY")) { 203 | $nobyda.notify(`${RA?`更新`:`首次写入`}爱奇艺签到Cookie失败‼️`, "", "") 204 | } else { 205 | if (!OldTime || OldTime && (Date.now() - OldTime) / 1000 >= 21600) { 206 | $nobyda.write(JSON.stringify(Date.now()), "CookieQYTime") 207 | $nobyda.notify(`${RA?`更新`:`首次写入`}爱奇艺签到Cookie成功 🎉`, "", "") 208 | } else { 209 | console.log(`\n更新爱奇艺Cookie成功! 🎉\n检测到频繁通知, 已转为输出日志`) 210 | } 211 | } 212 | } else { 213 | console.log("\n爱奇艺-与本机储存Cookie相同, 跳过写入 ⚠️") 214 | } 215 | } else { 216 | console.log("\n爱奇艺-请求不含Cookie, 跳过写入 ‼️") 217 | } 218 | } 219 | 220 | function nobyda() { 221 | const times = 0 222 | const start = Date.now() 223 | const isRequest = typeof $request != "undefined" 224 | const isSurge = typeof $httpClient != "undefined" 225 | const isQuanX = typeof $task != "undefined" 226 | const isLoon = typeof $loon != "undefined" 227 | const isJSBox = typeof $app != "undefined" && typeof $http != "undefined" 228 | const isNode = typeof require == "function" && !isJSBox; 229 | const node = (() => { 230 | if (isNode) { 231 | const request = require('request'); 232 | return ({ 233 | request 234 | }) 235 | } else { 236 | return (null) 237 | } 238 | })() 239 | const notify = (title, subtitle, message) => { 240 | if (isQuanX) $notify(title, subtitle, message) 241 | if (isSurge) $notification.post(title, subtitle, message) 242 | if (isNode) log('\n' + title + '\n' + subtitle + '\n' + message) 243 | if (isJSBox) $push.schedule({ 244 | title: title, 245 | body: subtitle ? subtitle + "\n" + message : message 246 | }) 247 | } 248 | const write = (value, key) => { 249 | if (isQuanX) return $prefs.setValueForKey(value, key) 250 | if (isSurge) return $persistentStore.write(value, key) 251 | } 252 | const read = (key) => { 253 | if (isQuanX) return $prefs.valueForKey(key) 254 | if (isSurge) return $persistentStore.read(key) 255 | } 256 | const adapterStatus = (response) => { 257 | if (response) { 258 | if (response.status) { 259 | response["statusCode"] = response.status 260 | } else if (response.statusCode) { 261 | response["status"] = response.statusCode 262 | } 263 | } 264 | return response 265 | } 266 | const get = (options, callback) => { 267 | if (isQuanX) { 268 | if (typeof options == "string") options = { 269 | url: options 270 | } 271 | options["method"] = "GET" 272 | $task.fetch(options).then(response => { 273 | callback(null, adapterStatus(response), response.body) 274 | }, reason => callback(reason.error, null, null)) 275 | } 276 | if (isSurge) $httpClient.get(options, (error, response, body) => { 277 | callback(error, adapterStatus(response), body) 278 | }) 279 | if (isNode) { 280 | node.request(options, (error, response, body) => { 281 | callback(error, adapterStatus(response), body) 282 | }) 283 | } 284 | if (isJSBox) { 285 | if (typeof options == "string") options = { 286 | url: options 287 | } 288 | options["header"] = options["headers"] 289 | options["handler"] = function(resp) { 290 | let error = resp.error; 291 | if (error) error = JSON.stringify(resp.error) 292 | let body = resp.data; 293 | if (typeof body == "object") body = JSON.stringify(resp.data); 294 | callback(error, adapterStatus(resp.response), body) 295 | }; 296 | $http.get(options); 297 | } 298 | } 299 | 300 | const log = (message) => console.log(message) 301 | const time = () => { 302 | const end = ((Date.now() - start) / 1000).toFixed(2) 303 | return console.log('\n签到用时: ' + end + ' 秒') 304 | } 305 | const done = (value = {}) => { 306 | if (isQuanX) return $done(value) 307 | if (isSurge) isRequest ? $done(value) : $done() 308 | } 309 | return { 310 | isRequest, 311 | isNode, 312 | notify, 313 | write, 314 | read, 315 | get, 316 | log, 317 | time, 318 | times, 319 | done 320 | } 321 | }; 322 | 323 | function isJSON_test(str) { 324 | if (typeof str == 'string') { 325 | try { 326 | var obj=JSON.parse(str); 327 | //console.log('转换成功:'+obj); 328 | return true; 329 | } catch(e) { 330 | console.log('no json'); 331 | console.log('error:'+str+'!!!'+e); 332 | return false; 333 | } 334 | } 335 | //console.log('It is not a string!') 336 | } -------------------------------------------------------------------------------- /function/iQIYI-DailyBonus/iqiyi.js: -------------------------------------------------------------------------------- 1 | // version v0.0.1 2 | // create by BlueSkyClouds 3 | // detail url: https://github.com/BlueskyClouds/My-Actions 4 | const exec = require('child_process').execSync 5 | const fs = require('fs') 6 | const download = require('download') 7 | 8 | const $ = new Env('爱奇艺会员签到'); 9 | const notify = $.isNode() ? require('../sendNotify') : ''; 10 | // 公共变量 11 | const KEY = process.env.iQIYI_COOKIE 12 | const SEND_KEY = process.env.SEND_KEY 13 | const UTC8 = new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000; 14 | 15 | async function downFile () { 16 | const url = 'https://raw.githubusercontent.com/BlueSkyClouds/My-Actions/master/function/iQIYI-DailyBonus/iQIYI-bak.js' 17 | await download(url, './') 18 | } 19 | 20 | async function changeFiele () { 21 | let content = await fs.readFileSync('./iQIYI-bak.js', 'utf8') 22 | content = content.replace(/var cookie = ''/, `var cookie = '${KEY}'`) 23 | await fs.writeFileSync( './iQIYI-bak.js', content, 'utf8') 24 | } 25 | 26 | async function deleteFile(path) { 27 | // 查看文件result.txt是 否存在,如果存在,先删除 28 | const fileExists = await fs.existsSync(path); 29 | // console.log('fileExists', fileExists); 30 | if (fileExists) { 31 | const unlinkRes = await fs.unlinkSync(path); 32 | // console.log('unlinkRes', unlinkRes) 33 | } 34 | } 35 | 36 | async function start() { 37 | if (!KEY) { 38 | console.log('请填写 key 后在继续') 39 | return 40 | } 41 | // 下载最新代码 42 | await downFile(); 43 | console.log('下载代码完毕') 44 | // 替换变量 45 | await changeFiele(); 46 | console.log('替换变量完毕') 47 | // 执行 48 | await exec("node iQIYI-bak.js >> result.txt"); 49 | console.log('执行完毕') 50 | const path = "./result.txt"; 51 | let content = ""; 52 | if (fs.existsSync(path)) { 53 | content = fs.readFileSync(path, "utf8"); 54 | } 55 | if (content.includes("今日已签到")) { 56 | //重复签到,不推送仅输出,因为每天会签到两次防止抽奖失败. 57 | console.log("爱奇艺签到-" + content + '\n重复签到,取消推送') 58 | }else if(SEND_KEY) { 59 | if (content.includes("Cookie")) { 60 | await notify.sendNotify("爱奇艺签到-" + timeFormat(UTC8), content); 61 | console.log("爱奇艺签到-" + content) 62 | }else{ 63 | console.log("爱奇艺签到-" + content) 64 | } 65 | }else{ 66 | await notify.sendNotify("爱奇艺签到-" + timeFormat(UTC8), content); 67 | console.log("爱奇艺签到-" + content) 68 | } 69 | 70 | //运行完成后,删除下载的文件 71 | console.log('运行完成后,删除下载的文件\n') 72 | await deleteFile(path); 73 | } 74 | 75 | start() 76 | 77 | function timeFormat(time) { 78 | let date; 79 | if (time) { 80 | date = new Date(time) 81 | } else { 82 | date = new Date(); 83 | } 84 | return date.getFullYear() + '年' + ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1)) + '月' + (date.getDate() >= 10 ? date.getDate() : '0' + date.getDate()) + '日'; 85 | } 86 | // prettier-ignore 87 | 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}isShadowrocket(){return"undefined"!=typeof $rocket}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();s&&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=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";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[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,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:i,...r}=t;this.got[s](i,r).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,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).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}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}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)} 88 | -------------------------------------------------------------------------------- /function/sendNotify.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import time 3 | import hmac 4 | import hashlib 5 | import base64 6 | import json 7 | import os 8 | import urllib.parse 9 | 10 | 11 | class sendNotify: 12 | # =======================================微信server酱通知设置区域=========================================== 13 | # 此处填你申请的SCKEY. 14 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入PUSH_KEY) 15 | SCKEY = '' 16 | 17 | # =======================================Bark App通知设置区域=========================================== 18 | # 此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) 19 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_PUSH) 20 | BARK_PUSH = '' 21 | # BARK app推送铃声,铃声列表去APP查看复制填写 22 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_SOUND , Value输入app提供的铃声名称,例如:birdsong) 23 | BARK_SOUND = '' 24 | 25 | # =======================================telegram机器人通知设置区域=========================================== 26 | # 此处填你telegram bot 的Token,例如:1077xxx4424:AAFjv0FlexboxEMGfi22B4yh15R5uw 27 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_BOT_TOKEN) 28 | TG_BOT_TOKEN = '' 29 | # 此处填你接收通知消息的telegram用户的id,例如:129xxx206 30 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_USER_ID) 31 | TG_USER_ID = '' 32 | 33 | # =======================================钉钉机器人通知设置区域=========================================== 34 | # 此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415assayed 35 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入DD_BOT_TOKEN) 36 | DD_BOT_TOKEN = '' 37 | # 密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 38 | DD_BOT_SECRET = '' 39 | 40 | # =======================================企业微信机器人通知设置区域=========================================== 此处填你企业微信机器人的 41 | # webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 42 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QYWX_KEY) 43 | # QYWX_KEY = '' 44 | 45 | # =======================================企业微信应用消息通知设置区域=========================================== 此处填你企业微信应用消息的 46 | # 第一个值是企业id,第二个值是secret,第三个值@all(或者成员id),第四个值是AgentID 中间以逗号隔开 47 | # 详情查看https://note.youdao.com/ynoteshare1/index.html?id=351e08a72378206f9dd64d2281e9b83b&type=note#/ 48 | # B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat 49 | QYWX_AM = '' 50 | 51 | # =======================================QQ酷推通知设置区域=========================================== 52 | # 此处填你申请的SKEY(具体详见文档 https://cp.xuthus.cc/) 53 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QQ_SKEY) 54 | # QQ_SKEY = '' 55 | # #此处填写私聊或群组推送,默认私聊(send或group或者wx) 56 | # QQ_MODE = 'send' 57 | 58 | # =======================================push+设置区域======================================= 59 | # 官方文档:https://www.pushplus.plus/ 60 | # PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 61 | PUSH_PLUS_TOKEN = '' 62 | # PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) 63 | PUSH_PLUS_USER = '' 64 | 65 | # Server酱 66 | if os.environ['PUSH_KEY'] != "": 67 | SCKEY = os.environ['PUSH_KEY'] 68 | 69 | # Bark App 70 | if os.environ['BARK_PUSH'] != "": 71 | if os.environ['BARK_PUSH'].find("https") != -1 or os.environ['BARK_PUSH'].find("http") != -1: 72 | BARK_PUSH = os.environ['PUSH_KEY'] 73 | else: 74 | BARK_PUSH = "https://api.day.app/" + os.environ['BARK_PUSH'] 75 | elif os.environ['BARK_SOUND'] != "": 76 | BARK_SOUND = os.environ['BARK_SOUND'] 77 | elif BARK_PUSH != "" or BARK_PUSH.find("https") != -1 or BARK_PUSH.find("http") != -1: 78 | BARK_PUSH = "https://api.day.app/" + BARK_PUSH 79 | 80 | # telegram 81 | if os.environ['TG_BOT_TOKEN'] != "": 82 | TG_BOT_TOKEN = os.environ['TG_BOT_TOKEN'] 83 | if os.environ['TG_USER_ID'] != "": 84 | TG_USER_ID = os.environ['TG_USER_ID'] 85 | 86 | # 钉钉机器人 87 | if os.environ['DD_BOT_TOKEN'] != "": 88 | DD_BOT_TOKEN = os.environ['DD_BOT_TOKEN'] 89 | if os.environ['DD_BOT_SECRET'] != "": 90 | DD_BOT_SECRET = os.environ['DD_BOT_SECRET'] 91 | 92 | # QQ酷推 93 | # if os.environ['QQ_SKEY'] != "": 94 | # QQ_SKEY = os.environ['QQ_SKEY'] 95 | # if os.environ['QQ_MODE'] != "": 96 | # QQ_MODE = os.environ['QQ_MODE'] 97 | 98 | # 企业微信 99 | # if os.environ['QYWX_KEY'] != "": 100 | # QQ_SKEY = os.environ['QYWX_KEY'] 101 | if os.environ['QYWX_AM'] != "": 102 | QYWX_AM = os.environ['QYWX_AM'] 103 | 104 | # push+ 105 | if os.environ['PUSH_PLUS_TOKEN'] != "": 106 | PUSH_PLUS_TOKEN = os.environ['PUSH_PLUS_TOKEN'] 107 | if os.environ['PUSH_PLUS_USER'] != "": 108 | PUSH_PLUS_USER = os.environ['PUSH_PLUS_USER'] 109 | 110 | def serverNotify(self, text, desp): 111 | if sendNotify.SCKEY != '': 112 | url = 'https://sctapi.ftqq.com/' + sendNotify.SCKEY + '.send' 113 | if "\n" in desp: 114 | desp = desp.replace("\n", "\n\n") 115 | data = { 116 | 'text': text, 117 | 'desp': desp 118 | } 119 | response = json.dumps(requests.post(url, data).json(), ensure_ascii=False) 120 | datas = json.loads(response) 121 | # print(datas) 122 | if datas['code'] == 0: 123 | print('\nserver酱发送通知消息成功\n') 124 | elif datas['code'] == 40001: 125 | print('\nPUSH_KEY 错误\n') 126 | else: 127 | print('\n发送通知调用API失败!!\n') 128 | else: 129 | print('\n您未提供server酱的SCKEY,取消微信推送消息通知\n') 130 | pass 131 | 132 | def BarkNotify(self, text, desp): 133 | if sendNotify.BARK_PUSH != '': 134 | url = sendNotify.BARK_PUSH + '/' + urllib.parse.quote(text) + '/' + urllib.parse.quote( 135 | desp) + '?sound=' + sendNotify.BARK_SOUND 136 | headers = {'Content-type': "application/x-www-form-urlencoded"} 137 | response = json.dumps(requests.get(url, headers=headers).json(), ensure_ascii=False) 138 | data = json.loads(response) 139 | # print(data) 140 | if data['code'] == 400: 141 | print('\n找不到 Key 对应的 DeviceToken\n') 142 | elif data['code'] == 200: 143 | print('\nBark APP发送通知消息成功\n') 144 | else: 145 | print('\nBark APP发送通知调用API失败!!\n') 146 | print(data) 147 | else: 148 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 149 | pass 150 | 151 | def tgBotNotify(self, text, desp): 152 | if sendNotify.TG_BOT_TOKEN != '' or sendNotify.TG_USER_ID != '': 153 | 154 | url = 'https://api.telegram.org/bot' + sendNotify.TG_BOT_TOKEN + '/sendMessage' 155 | headers = {'Content-type': "application/x-www-form-urlencoded"} 156 | body = 'chat_id=' + sendNotify.TG_USER_ID + '&text=' + urllib.parse.quote( 157 | text) + '\n\n' + urllib.parse.quote(desp) + '&disable_web_page_preview=true' 158 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 159 | 160 | data = json.loads(response) 161 | if data['ok']: 162 | print('\nTelegram发送通知消息完成\n') 163 | elif data['error_code'] == 400: 164 | print('\n请主动给bot发送一条消息并检查接收用户ID是否正确。\n') 165 | elif data['error_code'] == 401: 166 | print('\nTelegram bot token 填写错误。\n') 167 | else: 168 | print('\nTelegram bot发送通知调用API失败!!\n') 169 | print(data) 170 | else: 171 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 172 | pass 173 | 174 | def dingNotify(self, text, desp): 175 | if sendNotify.DD_BOT_TOKEN != '': 176 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN 177 | data = { 178 | "msgtype": "text", 179 | "text": { 180 | 'content': text + desp 181 | } 182 | } 183 | headers = { 184 | 'Content-Type': 'application/json;charset=utf-8' 185 | } 186 | if sendNotify.DD_BOT_SECRET != '': 187 | timestamp = str(round(time.time() * 1000)) 188 | secret = sendNotify.DD_BOT_SECRET 189 | secret_enc = secret.encode('utf-8') 190 | string_to_sign = '{}\n{}'.format(timestamp, secret) 191 | string_to_sign_enc = string_to_sign.encode('utf-8') 192 | hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() 193 | sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) 194 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN + '×tamp=' + timestamp + '&sign=' + sign 195 | 196 | response = requests.post(url=url, data=json.dumps(data), headers=headers).text 197 | if json.loads(response)['errcode'] == 0: 198 | print('\n钉钉发送通知消息成功\n') 199 | else: 200 | print('\n钉钉发送通知失败!!\n') 201 | else: 202 | print('\n您未提供钉钉的有关数据,取消钉钉推送消息通知\n') 203 | pass 204 | 205 | # def coolpush(self, text, desp): 206 | # if sendNotify.QQ_SKEY != '': 207 | # url = "https://push.xuthus.cc/" + sendNotify.QQ_MODE + "/" + sendNotify.QQ_SKEY 208 | # params = {"c": desp, "t": text} 209 | # headers = {'content-type': 'charset=utf8'} 210 | # response = json.dumps(requests.post(url=url, params=params, headers=headers).json(),ensure_ascii=False) 211 | # datas = json.loads(response) 212 | # 213 | # if datas['code'] == 200: 214 | # print('\nQQ推送发送通知消息成功\n') 215 | # elif datas['code'] == 500: 216 | # print('\nQQ推送QQ_SKEY错误\n') 217 | # else: 218 | # print('\n发送通知调用API失败!!\n') 219 | # 220 | # else: 221 | # print('\n您未提供酷推的SKEY,取消QQ推送消息通知\n') 222 | # pass 223 | def pushNotify(self, text, desp): 224 | if sendNotify.PUSH_PLUS_TOKEN != '': 225 | url = 'http://www.pushplus.plus/send' 226 | data = { 227 | "token": sendNotify.PUSH_PLUS_TOKEN, 228 | "title": text, 229 | "content": desp 230 | } 231 | if sendNotify.PUSH_PLUS_USER != '': 232 | data = { 233 | "token": sendNotify.PUSH_PLUS_TOKEN, 234 | "title": text, 235 | "content": desp, 236 | "topic": sendNotify.PUSH_PLUS_USER, 237 | "template": "html" 238 | } 239 | body = json.dumps(data).encode(encoding='utf-8') 240 | headers = {'Content-Type': 'application/json'} 241 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 242 | datas = json.loads(response) 243 | if datas['code'] == 200: 244 | print('\npush+发送通知消息成功\n') 245 | if datas['code'] == 600: 246 | print('\nPUSH_PLUS_TOKEN 错误\n') 247 | else: 248 | print('\npush+发送通知调用API失败!!\n') 249 | else: 250 | print('\n您未提供push+的PUSH_PLUS_TOKEN,取消push+推送消息通知\n') 251 | pass 252 | 253 | # 企业微信推送 254 | def sendWechat(self, desp): 255 | if sendNotify.QYWX_AM != '': 256 | # 获得access_token 257 | url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken' 258 | token_param = '?corpid=' + sendNotify.QYWX_AM.split(',')[0] + '&corpsecret=' + sendNotify.QYWX_AM.split(',')[1] 259 | token_data = requests.get(url + token_param) 260 | token_data.encoding = 'utf-8' 261 | token_data = token_data.json() 262 | access_token = token_data['access_token'] 263 | #发送内容 264 | content = desp 265 | #创建要发送的消息 266 | data = { 267 | "touser": sendNotify.QYWX_AM.split(',')[2], 268 | "msgtype": "text", 269 | "agentid": sendNotify.QYWX_AM.split(',')[3], 270 | "text": {"content": content} 271 | } 272 | send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + access_token 273 | message = requests.post(send_url, json=data) 274 | message.encoding = 'utf-8' 275 | res = message.json() 276 | print('企业微信推送 : ' + res['errmsg']) 277 | else: 278 | print('\n您未提供企业微信的QYWX_AM,取消企业微信推送消息通知\n') 279 | pass 280 | 281 | def send(self, **kwargs): 282 | send = sendNotify() 283 | title = kwargs.get("title", "") 284 | msg = kwargs.get("msg", "") 285 | send.serverNotify(title, msg) 286 | send.BarkNotify(title, msg) 287 | send.tgBotNotify(title, msg) 288 | send.dingNotify(title, msg) 289 | send.pushNotify(title, msg) 290 | send.sendWechat(msg) 291 | # send.coolpush(title,msg) 292 | 293 | # if __name__ == "__main__": 294 | # send(title = '这是标题',msg = '这是内容') 295 | -------------------------------------------------------------------------------- /function/v2ex/v2ex.js: -------------------------------------------------------------------------------- 1 | //V2ex-Auto-Sign 2 | const $ = new Env('V2ex自动签到'); 3 | const notify = $.isNode() ? require('../sendNotify') : ''; 4 | const cookie = process.env.V2EXCK 5 | const SEND_KEY = process.env.SEND_KEY 6 | const axios = require("axios") 7 | const UTC8 = new Date().getTime() + new Date().getTimezoneOffset()*60*1000 + 8*60*60*1000; 8 | 9 | once = null; 10 | ckstatus = 1; 11 | signstatus = 0; 12 | notice = timeFormat(UTC8) + "\n"; 13 | 14 | const header = { 15 | headers: { 16 | Referer: "https://www.v2ex.com/mission", 17 | Host: "www.v2ex.com", 18 | "user-agent": "Mozilla/5.0 (Linux; Android 10; Redmi K30) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.83 Mobile Safari/537.36", 19 | cookie: `'${cookie}'`, 20 | }, 21 | }; 22 | 23 | //获取once检查是否已签到 24 | function check() { 25 | return new Promise(async (resolve) => { 26 | try { 27 | let url = "https://www.v2ex.com/mission/daily"; 28 | let res = await axios.get(url, header); 29 | reg1 = /需要先登录/; 30 | if (reg1.test(res.data)) { 31 | console.log("cookie失效"); 32 | ckstatus = 0; 33 | notice += "cookie失效"; 34 | if(SEND_KEY){ 35 | notify.sendNotify("V2ex自动签到", notice); 36 | return; 37 | } 38 | } else { 39 | reg = /每日登录奖励已领取/; 40 | if (reg.test(res.data)) { 41 | notice += "今天已经签到过啦\n"; 42 | signstatus = 1; 43 | } else { 44 | reg = /redeem\?once=(.*?)'/; 45 | once = res.data.match(reg)[1]; 46 | console.log(`获取成功 once:${once}`); 47 | } 48 | } 49 | } catch (err) { 50 | console.log(err); 51 | } 52 | resolve(); 53 | }); 54 | } 55 | 56 | //每日签到 57 | function daily() { 58 | return new Promise(async (resolve) => { 59 | try { 60 | let url = `https://www.v2ex.com/mission/daily/redeem?once=${once}`; 61 | let res = await axios.get(url, header); 62 | reg = /已成功领取每日登录奖励/; 63 | if (reg.test(res.data)) { 64 | notice += "签到成功\n"; 65 | signstatus = 1; 66 | } else { 67 | notice += "签到失败Cookie疑似失效\n"; 68 | if(SEND_KEY){ 69 | notify.sendNotify("V2ex自动签到", notice); 70 | return; 71 | } 72 | } 73 | } catch (err) { 74 | console.log(err); 75 | } 76 | resolve(); 77 | }); 78 | } 79 | 80 | //查询余额 81 | function balance() { 82 | return new Promise(async (resolve) => { 83 | try { 84 | let url = "https://www.v2ex.com/balance"; 85 | let res = await axios.get(url, header); 86 | reg = /\d+?\s的每日登录奖励\s\d+\s铜币/; 87 | console.log(res.data.match(reg)[0]); 88 | notice += res.data.match(reg)[0]; 89 | } catch (err) { 90 | console.log(err); 91 | } 92 | resolve(); 93 | }); 94 | } 95 | 96 | function sign() { 97 | return new Promise(async (resolve) => { 98 | try { 99 | 100 | if (!cookie) { 101 | console.log("你的cookie呢!!!"); 102 | return; 103 | } 104 | await check(); 105 | if (once && signstatus === 0) { 106 | await daily(); 107 | await balance(); 108 | if (signstatus === 0) { 109 | console.log("签到失败Cookie疑似失效") 110 | } 111 | } 112 | console.log(notice); 113 | notify.sendNotify("V2ex自动签到", notice); 114 | } catch (err) { 115 | console.log(err); 116 | } 117 | resolve(); 118 | }); 119 | } 120 | 121 | sign(); 122 | 123 | function timeFormat(time) { 124 | let date; 125 | if (time) { 126 | date = new Date(time) 127 | } else { 128 | date = new Date(); 129 | } 130 | return date.getFullYear() + '年' + ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : '0' + (date.getMonth() + 1)) + '月' + (date.getDate() >= 10 ? date.getDate() : '0' + date.getDate()) + '日'; 131 | } 132 | // prettier-ignore 133 | 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}isShadowrocket(){return"undefined"!=typeof $rocket}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();s&&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=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";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[s](t,(t,s,i)=>{!t&&s&&(s.body=i,s.statusCode=s.status),e(t,s,i)});else if(this.isQuanX())t.method=s,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:i,...r}=t;this.got[s](i,r).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,e=null){const s=e?new Date(e):new Date;let i={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in i)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?i[e]:("00"+i[e]).substr((""+i[e]).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}}}};if(this.isMute||(this.isSurge()||this.isLoon()?$notification.post(e,s,i,o(r)):this.isQuanX()&&$notify(e,s,i,o(r))),!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),i&&t.push(i),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}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)} 134 | -------------------------------------------------------------------------------- /function/wps/sendNotify.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import time 3 | import hmac 4 | import hashlib 5 | import base64 6 | import json 7 | import os 8 | import urllib.parse 9 | 10 | 11 | class sendNotify: 12 | # =======================================微信server酱通知设置区域=========================================== 13 | # 此处填你申请的SCKEY. 14 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入PUSH_KEY) 15 | SCKEY = '' 16 | 17 | # =======================================Bark App通知设置区域=========================================== 18 | # 此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) 19 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_PUSH) 20 | BARK_PUSH = '' 21 | # BARK app推送铃声,铃声列表去APP查看复制填写 22 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_SOUND , Value输入app提供的铃声名称,例如:birdsong) 23 | BARK_SOUND = '' 24 | 25 | # =======================================telegram机器人通知设置区域=========================================== 26 | # 此处填你telegram bot 的Token,例如:1077xxx4424:AAFjv0FlexboxEMGfi22B4yh15R5uw 27 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_BOT_TOKEN) 28 | TG_BOT_TOKEN = '' 29 | # 此处填你接收通知消息的telegram用户的id,例如:129xxx206 30 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_USER_ID) 31 | TG_USER_ID = '' 32 | 33 | # =======================================钉钉机器人通知设置区域=========================================== 34 | # 此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415assayed 35 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入DD_BOT_TOKEN) 36 | DD_BOT_TOKEN = '' 37 | # 密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 38 | DD_BOT_SECRET = '' 39 | 40 | # =======================================企业微信机器人通知设置区域=========================================== 此处填你企业微信机器人的 41 | # webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 42 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QYWX_KEY) 43 | # QYWX_KEY = '' 44 | 45 | # =======================================企业微信应用消息通知设置区域=========================================== 此处填你企业微信应用消息的 46 | # 第一个值是企业id,第二个值是secret,第三个值@all(或者成员id),第四个值是AgentID 中间以逗号隔开 47 | # 详情查看https://note.youdao.com/ynoteshare1/index.html?id=351e08a72378206f9dd64d2281e9b83b&type=note#/ 48 | # B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat 49 | QYWX_AM = '' 50 | 51 | # =======================================QQ酷推通知设置区域=========================================== 52 | # 此处填你申请的SKEY(具体详见文档 https://cp.xuthus.cc/) 53 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QQ_SKEY) 54 | # QQ_SKEY = '' 55 | # #此处填写私聊或群组推送,默认私聊(send或group或者wx) 56 | # QQ_MODE = 'send' 57 | 58 | # =======================================push+设置区域======================================= 59 | # 官方文档:https://www.pushplus.plus/ 60 | # PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 61 | PUSH_PLUS_TOKEN = '' 62 | # PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) 63 | PUSH_PLUS_USER = '' 64 | 65 | # Server酱 66 | if os.environ['PUSH_KEY'] != "": 67 | SCKEY = os.environ['PUSH_KEY'] 68 | 69 | # Bark App 70 | if os.environ['BARK_PUSH'] != "": 71 | if os.environ['BARK_PUSH'].find("https") != -1 or os.environ['BARK_PUSH'].find("http") != -1: 72 | BARK_PUSH = os.environ['PUSH_KEY'] 73 | else: 74 | BARK_PUSH = "https://api.day.app/" + os.environ['BARK_PUSH'] 75 | elif os.environ['BARK_SOUND'] != "": 76 | BARK_SOUND = os.environ['BARK_SOUND'] 77 | elif BARK_PUSH != "" or BARK_PUSH.find("https") != -1 or BARK_PUSH.find("http") != -1: 78 | BARK_PUSH = "https://api.day.app/" + BARK_PUSH 79 | 80 | # telegram 81 | if os.environ['TG_BOT_TOKEN'] != "": 82 | TG_BOT_TOKEN = os.environ['TG_BOT_TOKEN'] 83 | if os.environ['TG_USER_ID'] != "": 84 | TG_USER_ID = os.environ['TG_USER_ID'] 85 | 86 | # 钉钉机器人 87 | if os.environ['DD_BOT_TOKEN'] != "": 88 | DD_BOT_TOKEN = os.environ['DD_BOT_TOKEN'] 89 | if os.environ['DD_BOT_SECRET'] != "": 90 | DD_BOT_SECRET = os.environ['DD_BOT_SECRET'] 91 | 92 | # QQ酷推 93 | # if os.environ['QQ_SKEY'] != "": 94 | # QQ_SKEY = os.environ['QQ_SKEY'] 95 | # if os.environ['QQ_MODE'] != "": 96 | # QQ_MODE = os.environ['QQ_MODE'] 97 | 98 | # 企业微信 99 | # if os.environ['QYWX_KEY'] != "": 100 | # QQ_SKEY = os.environ['QYWX_KEY'] 101 | if os.environ['QYWX_AM'] != "": 102 | QYWX_AM = os.environ['QYWX_AM'] 103 | 104 | # push+ 105 | if os.environ['PUSH_PLUS_TOKEN'] != "": 106 | PUSH_PLUS_TOKEN = os.environ['PUSH_PLUS_TOKEN'] 107 | if os.environ['PUSH_PLUS_USER'] != "": 108 | PUSH_PLUS_USER = os.environ['PUSH_PLUS_USER'] 109 | 110 | def serverNotify(self, text, desp): 111 | if sendNotify.SCKEY != '': 112 | url = 'https://sctapi.ftqq.com/' + sendNotify.SCKEY + '.send' 113 | if "\n" in desp: 114 | desp = desp.replace("\n", "\n\n") 115 | data = { 116 | 'text': text, 117 | 'desp': desp 118 | } 119 | response = json.dumps(requests.post(url, data).json(), ensure_ascii=False) 120 | datas = json.loads(response) 121 | # print(datas) 122 | if datas['code'] == 0: 123 | print('\nserver酱发送通知消息成功\n') 124 | elif datas['code'] == 40001: 125 | print('\nPUSH_KEY 错误\n') 126 | else: 127 | print('\n发送通知调用API失败!!\n') 128 | else: 129 | print('\n您未提供server酱的SCKEY,取消微信推送消息通知\n') 130 | pass 131 | 132 | def BarkNotify(self, text, desp): 133 | if sendNotify.BARK_PUSH != '': 134 | url = sendNotify.BARK_PUSH + '/' + urllib.parse.quote(text) + '/' + urllib.parse.quote( 135 | desp) + '?sound=' + sendNotify.BARK_SOUND 136 | headers = {'Content-type': "application/x-www-form-urlencoded"} 137 | response = json.dumps(requests.get(url, headers=headers).json(), ensure_ascii=False) 138 | data = json.loads(response) 139 | # print(data) 140 | if data['code'] == 400: 141 | print('\n找不到 Key 对应的 DeviceToken\n') 142 | elif data['code'] == 200: 143 | print('\nBark APP发送通知消息成功\n') 144 | else: 145 | print('\nBark APP发送通知调用API失败!!\n') 146 | print(data) 147 | else: 148 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 149 | pass 150 | 151 | def tgBotNotify(self, text, desp): 152 | if sendNotify.TG_BOT_TOKEN != '' or sendNotify.TG_USER_ID != '': 153 | 154 | url = 'https://api.telegram.org/bot' + sendNotify.TG_BOT_TOKEN + '/sendMessage' 155 | headers = {'Content-type': "application/x-www-form-urlencoded"} 156 | body = 'chat_id=' + sendNotify.TG_USER_ID + '&text=' + urllib.parse.quote( 157 | text) + '\n\n' + urllib.parse.quote(desp) + '&disable_web_page_preview=true' 158 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 159 | 160 | data = json.loads(response) 161 | if data['ok']: 162 | print('\nTelegram发送通知消息完成\n') 163 | elif data['error_code'] == 400: 164 | print('\n请主动给bot发送一条消息并检查接收用户ID是否正确。\n') 165 | elif data['error_code'] == 401: 166 | print('\nTelegram bot token 填写错误。\n') 167 | else: 168 | print('\nTelegram bot发送通知调用API失败!!\n') 169 | print(data) 170 | else: 171 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 172 | pass 173 | 174 | def dingNotify(self, text, desp): 175 | if sendNotify.DD_BOT_TOKEN != '': 176 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN 177 | data = { 178 | "msgtype": "text", 179 | "text": { 180 | 'content': text + desp 181 | } 182 | } 183 | headers = { 184 | 'Content-Type': 'application/json;charset=utf-8' 185 | } 186 | if sendNotify.DD_BOT_SECRET != '': 187 | timestamp = str(round(time.time() * 1000)) 188 | secret = sendNotify.DD_BOT_SECRET 189 | secret_enc = secret.encode('utf-8') 190 | string_to_sign = '{}\n{}'.format(timestamp, secret) 191 | string_to_sign_enc = string_to_sign.encode('utf-8') 192 | hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() 193 | sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) 194 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN + '×tamp=' + timestamp + '&sign=' + sign 195 | 196 | response = requests.post(url=url, data=json.dumps(data), headers=headers).text 197 | if json.loads(response)['errcode'] == 0: 198 | print('\n钉钉发送通知消息成功\n') 199 | else: 200 | print('\n钉钉发送通知失败!!\n') 201 | else: 202 | print('\n您未提供钉钉的有关数据,取消钉钉推送消息通知\n') 203 | pass 204 | 205 | # def coolpush(self, text, desp): 206 | # if sendNotify.QQ_SKEY != '': 207 | # url = "https://push.xuthus.cc/" + sendNotify.QQ_MODE + "/" + sendNotify.QQ_SKEY 208 | # params = {"c": desp, "t": text} 209 | # headers = {'content-type': 'charset=utf8'} 210 | # response = json.dumps(requests.post(url=url, params=params, headers=headers).json(),ensure_ascii=False) 211 | # datas = json.loads(response) 212 | # 213 | # if datas['code'] == 200: 214 | # print('\nQQ推送发送通知消息成功\n') 215 | # elif datas['code'] == 500: 216 | # print('\nQQ推送QQ_SKEY错误\n') 217 | # else: 218 | # print('\n发送通知调用API失败!!\n') 219 | # 220 | # else: 221 | # print('\n您未提供酷推的SKEY,取消QQ推送消息通知\n') 222 | # pass 223 | def pushNotify(self, text, desp): 224 | if sendNotify.PUSH_PLUS_TOKEN != '': 225 | url = 'http://www.pushplus.plus/send' 226 | data = { 227 | "token": sendNotify.PUSH_PLUS_TOKEN, 228 | "title": text, 229 | "content": desp 230 | } 231 | if sendNotify.PUSH_PLUS_USER != '': 232 | data = { 233 | "token": sendNotify.PUSH_PLUS_TOKEN, 234 | "title": text, 235 | "content": desp, 236 | "topic": sendNotify.PUSH_PLUS_USER, 237 | "template": "html" 238 | } 239 | body = json.dumps(data).encode(encoding='utf-8') 240 | headers = {'Content-Type': 'application/json'} 241 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 242 | datas = json.loads(response) 243 | if datas['code'] == 200: 244 | print('\npush+发送通知消息成功\n') 245 | if datas['code'] == 600: 246 | print('\nPUSH_PLUS_TOKEN 错误\n') 247 | else: 248 | print('\npush+发送通知调用API失败!!\n') 249 | else: 250 | print('\n您未提供push+的PUSH_PLUS_TOKEN,取消push+推送消息通知\n') 251 | pass 252 | 253 | # 企业微信推送 254 | def sendWechat(self, desp): 255 | if sendNotify.QYWX_AM != '': 256 | # 获得access_token 257 | url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken' 258 | token_param = '?corpid=' + sendNotify.QYWX_AM.split(',')[0] + '&corpsecret=' + sendNotify.QYWX_AM.split(',')[1] 259 | token_data = requests.get(url + token_param) 260 | token_data.encoding = 'utf-8' 261 | token_data = token_data.json() 262 | access_token = token_data['access_token'] 263 | #发送内容 264 | content = desp 265 | #创建要发送的消息 266 | data = { 267 | "touser": sendNotify.QYWX_AM.split(',')[2], 268 | "msgtype": "text", 269 | "agentid": sendNotify.QYWX_AM.split(',')[3], 270 | "text": {"content": content} 271 | } 272 | send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + access_token 273 | message = requests.post(send_url, json=data) 274 | message.encoding = 'utf-8' 275 | res = message.json() 276 | print('企业微信推送 : ' + res['errmsg']) 277 | else: 278 | print('\n您未提供企业微信的QYWX_AM,取消企业微信推送消息通知\n') 279 | pass 280 | 281 | def send(self, **kwargs): 282 | send = sendNotify() 283 | title = kwargs.get("title", "") 284 | msg = kwargs.get("msg", "") 285 | send.serverNotify(title, msg) 286 | send.BarkNotify(title, msg) 287 | send.tgBotNotify(title, msg) 288 | send.dingNotify(title, msg) 289 | send.pushNotify(title, msg) 290 | send.sendWechat(msg) 291 | # send.coolpush(title,msg) 292 | 293 | # if __name__ == "__main__": 294 | # send(title = '这是标题',msg = '这是内容') 295 | -------------------------------------------------------------------------------- /function/xiaomi_sports/sendNotify.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import time 3 | import hmac 4 | import hashlib 5 | import base64 6 | import json 7 | import os 8 | import urllib.parse 9 | 10 | 11 | class sendNotify: 12 | # =======================================微信server酱通知设置区域=========================================== 13 | # 此处填你申请的SCKEY. 14 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入PUSH_KEY) 15 | SCKEY = '' 16 | 17 | # =======================================Bark App通知设置区域=========================================== 18 | # 此处填你BarkAPP的信息(IP/设备码,例如:https://api.day.app/XXXXXXXX) 19 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_PUSH) 20 | BARK_PUSH = '' 21 | # BARK app推送铃声,铃声列表去APP查看复制填写 22 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入BARK_SOUND , Value输入app提供的铃声名称,例如:birdsong) 23 | BARK_SOUND = '' 24 | 25 | # =======================================telegram机器人通知设置区域=========================================== 26 | # 此处填你telegram bot 的Token,例如:1077xxx4424:AAFjv0FlexboxEMGfi22B4yh15R5uw 27 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_BOT_TOKEN) 28 | TG_BOT_TOKEN = '' 29 | # 此处填你接收通知消息的telegram用户的id,例如:129xxx206 30 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入TG_USER_ID) 31 | TG_USER_ID = '' 32 | 33 | # =======================================钉钉机器人通知设置区域=========================================== 34 | # 此处填你钉钉 bot 的webhook,例如:5a544165465465645d0f31dca676e7bd07415assayed 35 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入DD_BOT_TOKEN) 36 | DD_BOT_TOKEN = '' 37 | # 密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符串 38 | DD_BOT_SECRET = '' 39 | 40 | # =======================================企业微信机器人通知设置区域=========================================== 此处填你企业微信机器人的 41 | # webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770),例如:693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa 42 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QYWX_KEY) 43 | # QYWX_KEY = '' 44 | 45 | # =======================================企业微信应用消息通知设置区域=========================================== 此处填你企业微信应用消息的 46 | # 第一个值是企业id,第二个值是secret,第三个值@all(或者成员id),第四个值是AgentID 中间以逗号隔开 47 | # 详情查看https://note.youdao.com/ynoteshare1/index.html?id=351e08a72378206f9dd64d2281e9b83b&type=note#/ 48 | # B-791548lnzXBE6_BWfxdf3kSTMJr9vFEPKAbh6WERQ,mingcheng,1000001,2COXgjH2UIfERF2zxrtUOKgQ9XklUqMdGSWLBoW_lSDAdafat 49 | QYWX_AM = '' 50 | 51 | # =======================================QQ酷推通知设置区域=========================================== 52 | # 此处填你申请的SKEY(具体详见文档 https://cp.xuthus.cc/) 53 | # 注:此处设置github action用户填写到Settings-Secrets里面(Name输入QQ_SKEY) 54 | # QQ_SKEY = '' 55 | # #此处填写私聊或群组推送,默认私聊(send或group或者wx) 56 | # QQ_MODE = 'send' 57 | 58 | # =======================================push+设置区域======================================= 59 | # 官方文档:https://www.pushplus.plus/ 60 | # PUSH_PLUS_TOKEN:微信扫码登录后一对一推送或一对多推送下面的token(您的Token),不提供PUSH_PLUS_USER则默认为一对一推送 61 | PUSH_PLUS_TOKEN = '' 62 | # PUSH_PLUS_USER: 一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送) 63 | PUSH_PLUS_USER = '' 64 | 65 | # Server酱 66 | if os.environ['PUSH_KEY'] != "": 67 | SCKEY = os.environ['PUSH_KEY'] 68 | 69 | # Bark App 70 | if os.environ['BARK_PUSH'] != "": 71 | if os.environ['BARK_PUSH'].find("https") != -1 or os.environ['BARK_PUSH'].find("http") != -1: 72 | BARK_PUSH = os.environ['PUSH_KEY'] 73 | else: 74 | BARK_PUSH = "https://api.day.app/" + os.environ['BARK_PUSH'] 75 | elif os.environ['BARK_SOUND'] != "": 76 | BARK_SOUND = os.environ['BARK_SOUND'] 77 | elif BARK_PUSH != "" or BARK_PUSH.find("https") != -1 or BARK_PUSH.find("http") != -1: 78 | BARK_PUSH = "https://api.day.app/" + BARK_PUSH 79 | 80 | # telegram 81 | if os.environ['TG_BOT_TOKEN'] != "": 82 | TG_BOT_TOKEN = os.environ['TG_BOT_TOKEN'] 83 | if os.environ['TG_USER_ID'] != "": 84 | TG_USER_ID = os.environ['TG_USER_ID'] 85 | 86 | # 钉钉机器人 87 | if os.environ['DD_BOT_TOKEN'] != "": 88 | DD_BOT_TOKEN = os.environ['DD_BOT_TOKEN'] 89 | if os.environ['DD_BOT_SECRET'] != "": 90 | DD_BOT_SECRET = os.environ['DD_BOT_SECRET'] 91 | 92 | # QQ酷推 93 | # if os.environ['QQ_SKEY'] != "": 94 | # QQ_SKEY = os.environ['QQ_SKEY'] 95 | # if os.environ['QQ_MODE'] != "": 96 | # QQ_MODE = os.environ['QQ_MODE'] 97 | 98 | # 企业微信 99 | # if os.environ['QYWX_KEY'] != "": 100 | # QQ_SKEY = os.environ['QYWX_KEY'] 101 | if os.environ['QYWX_AM'] != "": 102 | QYWX_AM = os.environ['QYWX_AM'] 103 | 104 | # push+ 105 | if os.environ['PUSH_PLUS_TOKEN'] != "": 106 | PUSH_PLUS_TOKEN = os.environ['PUSH_PLUS_TOKEN'] 107 | if os.environ['PUSH_PLUS_USER'] != "": 108 | PUSH_PLUS_USER = os.environ['PUSH_PLUS_USER'] 109 | 110 | def serverNotify(self, text, desp): 111 | if sendNotify.SCKEY != '': 112 | url = 'https://sctapi.ftqq.com/' + sendNotify.SCKEY + '.send' 113 | if "\n" in desp: 114 | desp = desp.replace("\n", "\n\n") 115 | data = { 116 | 'text': text, 117 | 'desp': desp 118 | } 119 | response = json.dumps(requests.post(url, data).json(), ensure_ascii=False) 120 | datas = json.loads(response) 121 | # print(datas) 122 | if datas['code'] == 0: 123 | print('\nserver酱发送通知消息成功\n') 124 | elif datas['code'] == 40001: 125 | print('\nPUSH_KEY 错误\n') 126 | else: 127 | print('\n发送通知调用API失败!!\n') 128 | else: 129 | print('\n您未提供server酱的SCKEY,取消微信推送消息通知\n') 130 | pass 131 | 132 | def BarkNotify(self, text, desp): 133 | if sendNotify.BARK_PUSH != '': 134 | url = sendNotify.BARK_PUSH + '/' + urllib.parse.quote(text) + '/' + urllib.parse.quote( 135 | desp) + '?sound=' + sendNotify.BARK_SOUND 136 | headers = {'Content-type': "application/x-www-form-urlencoded"} 137 | response = json.dumps(requests.get(url, headers=headers).json(), ensure_ascii=False) 138 | data = json.loads(response) 139 | # print(data) 140 | if data['code'] == 400: 141 | print('\n找不到 Key 对应的 DeviceToken\n') 142 | elif data['code'] == 200: 143 | print('\nBark APP发送通知消息成功\n') 144 | else: 145 | print('\nBark APP发送通知调用API失败!!\n') 146 | print(data) 147 | else: 148 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 149 | pass 150 | 151 | def tgBotNotify(self, text, desp): 152 | if sendNotify.TG_BOT_TOKEN != '' or sendNotify.TG_USER_ID != '': 153 | 154 | url = 'https://api.telegram.org/bot' + sendNotify.TG_BOT_TOKEN + '/sendMessage' 155 | headers = {'Content-type': "application/x-www-form-urlencoded"} 156 | body = 'chat_id=' + sendNotify.TG_USER_ID + '&text=' + urllib.parse.quote( 157 | text) + '\n\n' + urllib.parse.quote(desp) + '&disable_web_page_preview=true' 158 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 159 | 160 | data = json.loads(response) 161 | if data['ok']: 162 | print('\nTelegram发送通知消息完成\n') 163 | elif data['error_code'] == 400: 164 | print('\n请主动给bot发送一条消息并检查接收用户ID是否正确。\n') 165 | elif data['error_code'] == 401: 166 | print('\nTelegram bot token 填写错误。\n') 167 | else: 168 | print('\nTelegram bot发送通知调用API失败!!\n') 169 | print(data) 170 | else: 171 | print('\n您未提供Bark的APP推送BARK_PUSH,取消Bark推送消息通知\n') 172 | pass 173 | 174 | def dingNotify(self, text, desp): 175 | if sendNotify.DD_BOT_TOKEN != '': 176 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN 177 | data = { 178 | "msgtype": "text", 179 | "text": { 180 | 'content': text + desp 181 | } 182 | } 183 | headers = { 184 | 'Content-Type': 'application/json;charset=utf-8' 185 | } 186 | if sendNotify.DD_BOT_SECRET != '': 187 | timestamp = str(round(time.time() * 1000)) 188 | secret = sendNotify.DD_BOT_SECRET 189 | secret_enc = secret.encode('utf-8') 190 | string_to_sign = '{}\n{}'.format(timestamp, secret) 191 | string_to_sign_enc = string_to_sign.encode('utf-8') 192 | hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest() 193 | sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) 194 | url = 'https://oapi.dingtalk.com/robot/send?access_token=' + sendNotify.DD_BOT_TOKEN + '×tamp=' + timestamp + '&sign=' + sign 195 | 196 | response = requests.post(url=url, data=json.dumps(data), headers=headers).text 197 | if json.loads(response)['errcode'] == 0: 198 | print('\n钉钉发送通知消息成功\n') 199 | else: 200 | print('\n钉钉发送通知失败!!\n') 201 | else: 202 | print('\n您未提供钉钉的有关数据,取消钉钉推送消息通知\n') 203 | pass 204 | 205 | # def coolpush(self, text, desp): 206 | # if sendNotify.QQ_SKEY != '': 207 | # url = "https://push.xuthus.cc/" + sendNotify.QQ_MODE + "/" + sendNotify.QQ_SKEY 208 | # params = {"c": desp, "t": text} 209 | # headers = {'content-type': 'charset=utf8'} 210 | # response = json.dumps(requests.post(url=url, params=params, headers=headers).json(),ensure_ascii=False) 211 | # datas = json.loads(response) 212 | # 213 | # if datas['code'] == 200: 214 | # print('\nQQ推送发送通知消息成功\n') 215 | # elif datas['code'] == 500: 216 | # print('\nQQ推送QQ_SKEY错误\n') 217 | # else: 218 | # print('\n发送通知调用API失败!!\n') 219 | # 220 | # else: 221 | # print('\n您未提供酷推的SKEY,取消QQ推送消息通知\n') 222 | # pass 223 | def pushNotify(self, text, desp): 224 | if sendNotify.PUSH_PLUS_TOKEN != '': 225 | url = 'http://www.pushplus.plus/send' 226 | data = { 227 | "token": sendNotify.PUSH_PLUS_TOKEN, 228 | "title": text, 229 | "content": desp 230 | } 231 | if sendNotify.PUSH_PLUS_USER != '': 232 | data = { 233 | "token": sendNotify.PUSH_PLUS_TOKEN, 234 | "title": text, 235 | "content": desp, 236 | "topic": sendNotify.PUSH_PLUS_USER, 237 | "template": "html" 238 | } 239 | body = json.dumps(data).encode(encoding='utf-8') 240 | headers = {'Content-Type': 'application/json'} 241 | response = json.dumps(requests.post(url, data=body, headers=headers).json(), ensure_ascii=False) 242 | datas = json.loads(response) 243 | if datas['code'] == 200: 244 | print('\npush+发送通知消息成功\n') 245 | if datas['code'] == 600: 246 | print('\nPUSH_PLUS_TOKEN 错误\n') 247 | else: 248 | print('\npush+发送通知调用API失败!!\n') 249 | else: 250 | print('\n您未提供push+的PUSH_PLUS_TOKEN,取消push+推送消息通知\n') 251 | pass 252 | 253 | # 企业微信推送 254 | def sendWechat(self, desp): 255 | if sendNotify.QYWX_AM != '': 256 | # 获得access_token 257 | url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken' 258 | token_param = '?corpid=' + sendNotify.QYWX_AM.split(',')[0] + '&corpsecret=' + sendNotify.QYWX_AM.split(',')[1] 259 | token_data = requests.get(url + token_param) 260 | token_data.encoding = 'utf-8' 261 | token_data = token_data.json() 262 | access_token = token_data['access_token'] 263 | #发送内容 264 | content = desp 265 | #创建要发送的消息 266 | data = { 267 | "touser": sendNotify.QYWX_AM.split(',')[2], 268 | "msgtype": "text", 269 | "agentid": sendNotify.QYWX_AM.split(',')[3], 270 | "text": {"content": content} 271 | } 272 | send_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=' + access_token 273 | message = requests.post(send_url, json=data) 274 | message.encoding = 'utf-8' 275 | res = message.json() 276 | print('企业微信推送 : ' + res['errmsg']) 277 | else: 278 | print('\n您未提供企业微信的QYWX_AM,取消企业微信推送消息通知\n') 279 | pass 280 | 281 | def send(self, **kwargs): 282 | send = sendNotify() 283 | title = kwargs.get("title", "") 284 | msg = kwargs.get("msg", "") 285 | send.serverNotify(title, msg) 286 | send.BarkNotify(title, msg) 287 | send.tgBotNotify(title, msg) 288 | send.dingNotify(title, msg) 289 | send.pushNotify(title, msg) 290 | send.sendWechat(msg) 291 | # send.coolpush(title,msg) 292 | 293 | # if __name__ == "__main__": 294 | # send(title = '这是标题',msg = '这是内容') 295 | -------------------------------------------------------------------------------- /function/xiaomi_sports/xiaomi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | # python >=3.8 3 | 4 | import random 5 | import re 6 | import sys 7 | 8 | sys.path.append("My-Actions/function/wps") 9 | from sendNotify import * 10 | 11 | sendNotify = sendNotify() 12 | now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 13 | headers = { 14 | 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9; MI 6 MIUI/20.6.18)' 15 | } 16 | 17 | 18 | # 获取登录code 19 | def get_code(location): 20 | code_pattern = re.compile("(?<=access=).*?(?=&)") 21 | code = code_pattern.findall(location)[0] 22 | return code 23 | 24 | 25 | # 登录 26 | def login(user, password): 27 | url1 = "https://api-user.huami.com/registrations/+86" + user + "/tokens" 28 | headers = { 29 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", 30 | "User-Agent": "MiFit/4.6.0 (iPhone; iOS 14.0.1; Scale/2.00)" 31 | } 32 | data1 = { 33 | "client_id": "HuaMi", 34 | "password": f"{password}", 35 | "redirect_uri": "https://s3-us-west-2.amazonaws.com/hm-registration/successsignin.html", 36 | "token": "access" 37 | } 38 | r1 = requests.post(url1, data=data1, headers=headers, allow_redirects=False) 39 | location = r1.headers["Location"] 40 | try: 41 | code = get_code(location) 42 | except: 43 | return 0, 0 44 | # print("access_code获取成功!") 45 | # print(code) 46 | 47 | url2 = "https://account.huami.com/v2/client/login" 48 | data2 = { 49 | "app_name": "com.xiaomi.hm.health", 50 | "app_version": "4.6.0", 51 | "code": f"{code}", 52 | "country_code": "CN", 53 | "device_id": "2C8B4939-0CCD-4E94-8CBA-CB8EA6E613A1", 54 | "device_model": "phone", 55 | "grant_type": "access_token", 56 | "third_name": "huami_phone", 57 | } 58 | r2 = requests.post(url2, data=data2, headers=headers).json() 59 | login_token = r2["token_info"]["login_token"] 60 | # print("login_token获取成功!") 61 | # print(login_token) 62 | userid = r2["token_info"]["user_id"] 63 | # print("userid获取成功!") 64 | # print(userid) 65 | 66 | return login_token, userid 67 | 68 | 69 | # 主函数 70 | def main(user, passwd, step): 71 | user = str(user) 72 | password = str(passwd) 73 | step = str(step) 74 | if user == '' or password == '': 75 | print("未填写小米运动用户名或密码,取消运行") 76 | exit(0) 77 | # return "用户名或密码填写有误!" 78 | if step == '': 79 | print("已设置为随机步数(10000-19999)") 80 | step = str(random.randint(10000, 19999)) 81 | login_token = 0 82 | login_token, userid = login(user, password) 83 | if login_token == 0: 84 | print("登陆失败!") 85 | if SEND_KEY != '': 86 | sendNotify.send(title="小米运动自动刷步数", msg="【小米运动自动刷步数】\n登陆失败!") 87 | return "login fail!" 88 | 89 | t = get_time() 90 | 91 | app_token = get_app_token(login_token) 92 | 93 | today = time.strftime("%F") 94 | 95 | data_json = '%5B%7B%22data_hr%22%3A%22%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9L%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FVv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0v%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9e%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0n%5C%2Fa%5C%2F%5C%2F%5C%2FS%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0b%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F1FK%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FR%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9PTFFpaf9L%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FR%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0j%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9K%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FOv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fzf%5C%2F%5C%2F%5C%2F86%5C%2Fzr%5C%2FOv88%5C%2Fzf%5C%2FPf%5C%2F%5C%2F%5C%2F0v%5C%2FS%5C%2F8%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FSf%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fz3%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0r%5C%2FOv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FS%5C%2F9L%5C%2Fzb%5C%2FSf9K%5C%2F0v%5C%2FRf9H%5C%2Fzj%5C%2FSf9K%5C%2F0%5C%2F%5C%2FN%5C%2F%5C%2F%5C%2F%5C%2F0D%5C%2FSf83%5C%2Fzr%5C%2FPf9M%5C%2F0v%5C%2FOv9e%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FS%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fzv%5C%2F%5C%2Fz7%5C%2FO%5C%2F83%5C%2Fzv%5C%2FN%5C%2F83%5C%2Fzr%5C%2FN%5C%2F86%5C%2Fz%5C%2F%5C%2FNv83%5C%2Fzn%5C%2FXv84%5C%2Fzr%5C%2FPP84%5C%2Fzj%5C%2FN%5C%2F9e%5C%2Fzr%5C%2FN%5C%2F89%5C%2F03%5C%2FP%5C%2F89%5C%2Fz3%5C%2FQ%5C%2F9N%5C%2F0v%5C%2FTv9C%5C%2F0H%5C%2FOf9D%5C%2Fzz%5C%2FOf88%5C%2Fz%5C%2F%5C%2FPP9A%5C%2Fzr%5C%2FN%5C%2F86%5C%2Fzz%5C%2FNv87%5C%2F0D%5C%2FOv84%5C%2F0v%5C%2FO%5C%2F84%5C%2Fzf%5C%2FMP83%5C%2FzH%5C%2FNv83%5C%2Fzf%5C%2FN%5C%2F84%5C%2Fzf%5C%2FOf82%5C%2Fzf%5C%2FOP83%5C%2Fzb%5C%2FMv81%5C%2FzX%5C%2FR%5C%2F9L%5C%2F0v%5C%2FO%5C%2F9I%5C%2F0T%5C%2FS%5C%2F9A%5C%2Fzn%5C%2FPf89%5C%2Fzn%5C%2FNf9K%5C%2F07%5C%2FN%5C%2F83%5C%2Fzn%5C%2FNv83%5C%2Fzv%5C%2FO%5C%2F9A%5C%2F0H%5C%2FOf8%5C%2F%5C%2Fzj%5C%2FPP83%5C%2Fzj%5C%2FS%5C%2F87%5C%2Fzj%5C%2FNv84%5C%2Fzf%5C%2FOf83%5C%2Fzf%5C%2FOf83%5C%2Fzb%5C%2FNv9L%5C%2Fzj%5C%2FNv82%5C%2Fzb%5C%2FN%5C%2F85%5C%2Fzf%5C%2FN%5C%2F9J%5C%2Fzf%5C%2FNv83%5C%2Fzj%5C%2FNv84%5C%2F0r%5C%2FSv83%5C%2Fzf%5C%2FMP%5C%2F%5C%2F%5C%2Fzb%5C%2FMv82%5C%2Fzb%5C%2FOf85%5C%2Fz7%5C%2FNv8%5C%2F%5C%2F0r%5C%2FS%5C%2F85%5C%2F0H%5C%2FQP9B%5C%2F0D%5C%2FNf89%5C%2Fzj%5C%2FOv83%5C%2Fzv%5C%2FNv8%5C%2F%5C%2F0f%5C%2FSv9O%5C%2F0ZeXv%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F1X%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9B%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2FTP%5C%2F%5C%2F%5C%2F1b%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F0%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F9N%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2F%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%5C%2Fv7%2B%22%2C%22date%22%3A%222020-08-14%22%2C%22data%22%3A%5B%7B%22start%22%3A0%2C%22stop%22%3A1439%2C%22value%22%3A%22UA8AUBQAUAwAUBoAUAEAYCcAUBkAUB4AUBgAUCAAUAEAUBkAUAwAYAsAYB8AYB0AYBgAYCoAYBgAYB4AUCcAUBsAUB8AUBwAUBIAYBkAYB8AUBoAUBMAUCEAUCIAYBYAUBwAUCAAUBgAUCAAUBcAYBsAYCUAATIPYD0KECQAYDMAYB0AYAsAYCAAYDwAYCIAYB0AYBcAYCQAYB0AYBAAYCMAYAoAYCIAYCEAYCYAYBsAYBUAYAYAYCIAYCMAUB0AUCAAUBYAUCoAUBEAUC8AUB0AUBYAUDMAUDoAUBkAUC0AUBQAUBwAUA0AUBsAUAoAUCEAUBYAUAwAUB4AUAwAUCcAUCYAUCwKYDUAAUUlEC8IYEMAYEgAYDoAYBAAUAMAUBkAWgAAWgAAWgAAWgAAWgAAUAgAWgAAUBAAUAQAUA4AUA8AUAkAUAIAUAYAUAcAUAIAWgAAUAQAUAkAUAEAUBkAUCUAWgAAUAYAUBEAWgAAUBYAWgAAUAYAWgAAWgAAWgAAWgAAUBcAUAcAWgAAUBUAUAoAUAIAWgAAUAQAUAYAUCgAWgAAUAgAWgAAWgAAUAwAWwAAXCMAUBQAWwAAUAIAWgAAWgAAWgAAWgAAWgAAWgAAWgAAWgAAWREAWQIAUAMAWSEAUDoAUDIAUB8AUCEAUC4AXB4AUA4AWgAAUBIAUA8AUBAAUCUAUCIAUAMAUAEAUAsAUAMAUCwAUBYAWgAAWgAAWgAAWgAAWgAAWgAAUAYAWgAAWgAAWgAAUAYAWwAAWgAAUAYAXAQAUAMAUBsAUBcAUCAAWwAAWgAAWgAAWgAAWgAAUBgAUB4AWgAAUAcAUAwAWQIAWQkAUAEAUAIAWgAAUAoAWgAAUAYAUB0AWgAAWgAAUAkAWgAAWSwAUBIAWgAAUC4AWSYAWgAAUAYAUAoAUAkAUAIAUAcAWgAAUAEAUBEAUBgAUBcAWRYAUA0AWSgAUB4AUDQAUBoAXA4AUA8AUBwAUA8AUA4AUA4AWgAAUAIAUCMAWgAAUCwAUBgAUAYAUAAAUAAAUAAAUAAAUAAAUAAAUAAAUAAAUAAAWwAAUAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAeSEAeQ8AcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBcAcAAAcAAAcCYOcBUAUAAAUAAAUAAAUAAAUAUAUAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCgAeQAAcAAAcAAAcAAAcAAAcAAAcAYAcAAAcBgAeQAAcAAAcAAAegAAegAAcAAAcAcAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCkAeQAAcAcAcAAAcAAAcAwAcAAAcAAAcAIAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcCIAeQAAcAAAcAAAcAAAcAAAcAAAeRwAeQAAWgAAUAAAUAAAUAAAUAAAUAAAcAAAcAAAcBoAeScAeQAAegAAcBkAeQAAUAAAUAAAUAAAUAAAUAAAUAAAcAAAcAAAcAAAcAAAcAAAcAAAegAAegAAcAAAcAAAcBgAeQAAcAAAcAAAcAAAcAAAcAAAcAkAegAAegAAcAcAcAAAcAcAcAAAcAAAcAAAcAAAcA8AeQAAcAAAcAAAeRQAcAwAUAAAUAAAUAAAUAAAUAAAUAAAcAAAcBEAcA0AcAAAWQsAUAAAUAAAUAAAUAAAUAAAcAAAcAoAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAYAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBYAegAAcAAAcAAAegAAcAcAcAAAcAAAcAAAcAAAcAAAeRkAegAAegAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAEAcAAAcAAAcAAAcAUAcAQAcAAAcBIAeQAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBsAcAAAcAAAcBcAeQAAUAAAUAAAUAAAUAAAUAAAUBQAcBYAUAAAUAAAUAoAWRYAWTQAWQAAUAAAUAAAUAAAcAAAcAAAcAAAcAAAcAAAcAMAcAAAcAQAcAAAcAAAcAAAcDMAeSIAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcAAAcBQAeQwAcAAAcAAAcAAAcAMAcAAAeSoAcA8AcDMAcAYAeQoAcAwAcFQAcEMAeVIAaTYAbBcNYAsAYBIAYAIAYAIAYBUAYCwAYBMAYDYAYCkAYDcAUCoAUCcAUAUAUBAAWgAAYBoAYBcAYCgAUAMAUAYAUBYAUA4AUBgAUAgAUAgAUAsAUAsAUA4AUAMAUAYAUAQAUBIAASsSUDAAUDAAUBAAYAYAUBAAUAUAUCAAUBoAUCAAUBAAUAoAYAIAUAQAUAgAUCcAUAsAUCIAUCUAUAoAUA4AUB8AUBkAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAAfgAA%22%2C%22tz%22%3A32%2C%22did%22%3A%22DA932FFFFE8816E7%22%2C%22src%22%3A24%7D%5D%2C%22summary%22%3A%22%7B%5C%22v%5C%22%3A6%2C%5C%22slp%5C%22%3A%7B%5C%22st%5C%22%3A1597349880%2C%5C%22ed%5C%22%3A1597369860%2C%5C%22dp%5C%22%3A39%2C%5C%22lt%5C%22%3A294%2C%5C%22wk%5C%22%3A0%2C%5C%22usrSt%5C%22%3A-1440%2C%5C%22usrEd%5C%22%3A-1440%2C%5C%22wc%5C%22%3A0%2C%5C%22is%5C%22%3A169%2C%5C%22lb%5C%22%3A10%2C%5C%22to%5C%22%3A23%2C%5C%22dt%5C%22%3A0%2C%5C%22rhr%5C%22%3A58%2C%5C%22ss%5C%22%3A69%2C%5C%22stage%5C%22%3A%5B%7B%5C%22start%5C%22%3A1698%2C%5C%22stop%5C%22%3A1711%2C%5C%22mode%5C%22%3A4%7D%2C%7B%5C%22start%5C%22%3A1712%2C%5C%22stop%5C%22%3A1728%2C%5C%22mode%5C%22%3A5%7D%2C%7B%5C%22start%5C%22%3A1729%2C%5C%22stop%5C%22%3A1818%2C%5C%22mode%5C%22%3A4%7D%2C%7B%5C%22start%5C%22%3A1819%2C%5C%22stop%5C%22%3A1832%2C%5C%22mode%5C%22%3A5%7D%2C%7B%5C%22start%5C%22%3A1833%2C%5C%22stop%5C%22%3A1920%2C%5C%22mode%5C%22%3A4%7D%2C%7B%5C%22start%5C%22%3A1921%2C%5C%22stop%5C%22%3A1928%2C%5C%22mode%5C%22%3A5%7D%2C%7B%5C%22start%5C%22%3A1929%2C%5C%22stop%5C%22%3A2030%2C%5C%22mode%5C%22%3A4%7D%5D%7D%2C%5C%22stp%5C%22%3A%7B%5C%22ttl%5C%22%3A125%2C%5C%22dis%5C%22%3A82%2C%5C%22cal%5C%22%3A5%2C%5C%22wk%5C%22%3A7%2C%5C%22rn%5C%22%3A0%2C%5C%22runDist%5C%22%3A23%2C%5C%22runCal%5C%22%3A3%7D%2C%5C%22goal%5C%22%3A8000%2C%5C%22tz%5C%22%3A%5C%2228800%5C%22%2C%5C%22sn%5C%22%3A%5C%22e716882f93da%5C%22%7D%22%2C%22source%22%3A24%2C%22type%22%3A0%7D%5D' 96 | 97 | finddate = re.compile(r'.*?date%22%3A%22(.*?)%22%2C%22data.*?') 98 | findstep = re.compile(r'.*?ttl%5C%22%3A(.*?)%2C%5C%22dis.*?') 99 | data_json = re.sub(finddate.findall(data_json)[0], today, str(data_json)) 100 | data_json = re.sub(findstep.findall(data_json)[0], step, str(data_json)) 101 | 102 | url = f'https://api-mifit-cn.huami.com/v1/data/band_data.json?&t={t}' 103 | head = { 104 | "apptoken": app_token, 105 | "Content-Type": "application/x-www-form-urlencoded" 106 | } 107 | 108 | data = f'userid={userid}&last_sync_data_time=1597306380&device_type=0&last_deviceid=DA932FFFFE8816E7&data_json={data_json}' 109 | 110 | response = requests.post(url, data=data, headers=head).json() 111 | # print(response) 112 | result = f"{user[:4]}****{user[-4:]}: [{now}] 修改步数({step})" + response['message'] 113 | print(result) 114 | return result 115 | 116 | 117 | # 获取时间戳 118 | def get_time(): 119 | url = 'http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp' 120 | response = requests.get(url, headers=headers).json() 121 | t = response['data']['t'] 122 | return t 123 | 124 | 125 | # 获取app_token 126 | def get_app_token(login_token): 127 | url = f"https://account-cn.huami.com/v1/client/app_tokens?app_name=com.xiaomi.hm.health&dn=api-user.huami.com%2Capi-mifit.huami.com%2Capp-analytics.huami.com&login_token={login_token}" 128 | response = requests.get(url, headers=headers).json() 129 | app_token = response['token_info']['app_token'] 130 | # print("app_token获取成功!") 131 | # print(app_token) 132 | return app_token 133 | 134 | 135 | if __name__ == "__main__": 136 | # Push Mode 137 | SEND_KEY = os.environ['SEND_KEY'] 138 | # 用户名(格式为 13800138000) 139 | user = os.environ['Xiaomi_User'] 140 | # 登录密码 141 | passwd = os.environ['Xiaomi_Pw'] 142 | # 要修改的步数,直接输入想要修改的步数值,留空为随机步数 143 | step = os.environ['Xiaomi_Bs'].replace('[', '').replace(']', '') 144 | 145 | user_list = user.split('#') 146 | passwd_list = passwd.split('#') 147 | setp_array = step.split('-') 148 | 149 | if len(user_list) == len(passwd_list): 150 | push = '' 151 | for line in range(0, len(user_list)): 152 | if len(setp_array) == 2: 153 | step = str(random.randint(int(setp_array[0]), int(setp_array[1]))) 154 | elif str(step) == '0': 155 | step = '' 156 | push += main(user_list[line], passwd_list[line], step) + '\n' 157 | if SEND_KEY == '': 158 | sendNotify.send(title="小米运动自动刷步数", msg="【小米运动自动刷步数】\n" + push) 159 | else: 160 | print('用户名和密码数量不对') 161 | -------------------------------------------------------------------------------- /icon/DD_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/DD_bot.png -------------------------------------------------------------------------------- /icon/TG_PUSH1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/TG_PUSH1.png -------------------------------------------------------------------------------- /icon/TG_PUSH2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/TG_PUSH2.png -------------------------------------------------------------------------------- /icon/TG_PUSH3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/TG_PUSH3.png -------------------------------------------------------------------------------- /icon/bark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/bark.jpg -------------------------------------------------------------------------------- /icon/create_new_sync_yaml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/create_new_sync_yaml.png -------------------------------------------------------------------------------- /icon/git1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git1.jpg -------------------------------------------------------------------------------- /icon/git10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git10.jpg -------------------------------------------------------------------------------- /icon/git11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git11.jpg -------------------------------------------------------------------------------- /icon/git12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git12.jpg -------------------------------------------------------------------------------- /icon/git13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git13.jpg -------------------------------------------------------------------------------- /icon/git14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git14.jpg -------------------------------------------------------------------------------- /icon/git2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git2.jpg -------------------------------------------------------------------------------- /icon/git3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git3.jpg -------------------------------------------------------------------------------- /icon/git4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git4.jpg -------------------------------------------------------------------------------- /icon/git5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git5.jpg -------------------------------------------------------------------------------- /icon/git6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git6.jpg -------------------------------------------------------------------------------- /icon/git7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git7.png -------------------------------------------------------------------------------- /icon/git8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git8.jpg -------------------------------------------------------------------------------- /icon/git9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/git9.jpg -------------------------------------------------------------------------------- /icon/new_access_token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/new_access_token.png -------------------------------------------------------------------------------- /icon/new_repository_secret.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/new_repository_secret.png -------------------------------------------------------------------------------- /icon/open_actions_permissions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/open_actions_permissions.png -------------------------------------------------------------------------------- /icon/reposync_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/reposync_result.png -------------------------------------------------------------------------------- /icon/run_reposync_actions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/run_reposync_actions.png -------------------------------------------------------------------------------- /icon/set_sectet_pat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/set_sectet_pat.png -------------------------------------------------------------------------------- /icon/set_up_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/set_up_workflow.png -------------------------------------------------------------------------------- /icon/your_new_token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qq332374857/BlueSkyClouds-My-Actions/f6b9de78c26b8667e556acccfd5fa295b682fefb/icon/your_new_token.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "My-Actions", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "Manga.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/BlueskyClouds/My-Actions.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/BlueskyClouds/My-Actions/issues" 18 | }, 19 | "homepage": "https://github.com/BlueskyClouds/My-Actions#readme", 20 | "dependencies": { 21 | "download": "^8.0.0", 22 | "request": "^2.88.2", 23 | "axios": "^0.21.1", 24 | "crypto-js": "^4.0.0", 25 | "request-promise": "^4.2.5", 26 | "got": "^11.7.0", 27 | "tunnel": "0.0.6", 28 | "tough-cookie": "^4.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | rsa 3 | pytz 4 | python-dateutil --------------------------------------------------------------------------------