├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── images ├── 1.jpg ├── 2.jpg └── 3.jpg ├── package.json ├── prettier.config.js ├── public ├── favicon.ico └── index.html ├── server ├── app.js ├── package.json └── yarn.lock ├── src ├── App.vue ├── assets │ └── logo.png ├── main.js ├── plugins │ ├── at.js │ ├── decrypt.js │ └── http.js ├── router │ └── index.js ├── views │ ├── Home.vue │ └── Login.vue └── work │ └── gb.work.js ├── vue.config.js └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: ['plugin:vue/essential', '@vue/prettier'], 7 | rules: { 8 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 9 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 10 | }, 11 | parserOptions: { 12 | parser: 'babel-eslint' 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | server/static 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hbooker-extractor 2 | 3 | 使用 vue 和 at-ui 编写的 刺猬猫 小说提取工具。 4 | 5 | ## 更新日志 6 | 7 | 2020.8.30 8 | 9 | - 使用列表视图展示书架,避免额外请求 10 | - 修正只能获取书架前一百本书籍的问题 11 | - 支持切换书架 12 | - 其它 UI 更新 13 | 14 | ## 程序部署 15 | 16 | ``` 17 | //开发环境为 node v12.18.3 18 | //拉取依赖 19 | yarn install 20 | //开发调试 21 | yarn serve 22 | //编译 23 | yarn build&&cd server&&yarn 24 | //运行编译结果 25 | cd server&&node app.js 26 | ``` 27 | 28 | ## 其他说明 29 | 30 | 在开发环境下,程序使用 webpack 的 devServer 来反代刺猬猫的后端接口以解决跨域问题,而如果要打包,则已经在 server 目录中内置了一个由 koa 驱动的代理服务。webpack 会自动把打包结果输出到 server/static 目录下供之调用。 31 | 32 | 由于是一个较为简单的实现,所以目前只是以单线程进行下载,慢慢等待即可 :) 33 | 34 | 你的登录状态以及账户信息完全保存在你的本地,本程序不会保存和分发任何你的私有信息。 35 | 36 | 程序下载的内容仅包括免费书籍以及您登陆的账户所订阅的章节,无任何破解相关的功能,望周知。 37 | 38 | 作者写书不易,请自觉保护版权!请勿将本程序用于非法行为,作者不承担任何责任! 39 | 40 | ## 截图 41 | 42 | ![](images/1.jpg) 43 | 44 | ![](images/2.jpg) 45 | 46 | ![](images/3.jpg) 47 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/cli-plugin-babel/preset'], 3 | plugins: [ 4 | [ 5 | 'import', 6 | { 7 | libraryName: 'at', 8 | libraryDirectory: 'src/components' 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /images/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/hbooker-extractor/3743bd783bf6bb6ef9d008cc4a1ad71a0d415098/images/1.jpg -------------------------------------------------------------------------------- /images/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/hbooker-extractor/3743bd783bf6bb6ef9d008cc4a1ad71a0d415098/images/2.jpg -------------------------------------------------------------------------------- /images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/hbooker-extractor/3743bd783bf6bb6ef9d008cc4a1ad71a0d415098/images/3.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hbooker-extractor", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "server": "node server/app.js", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint" 10 | }, 11 | "dependencies": { 12 | "at-ui": "^1.3.3", 13 | "at-ui-style": "^1.5.1", 14 | "axios": "^0.19.0", 15 | "babel-plugin-import": "^1.13.0", 16 | "core-js": "^3.4.3", 17 | "http-proxy-middleware": "^0.20.0", 18 | "koa": "^2.11.0", 19 | "koa-bodyparser": "^4.2.1", 20 | "koa2-connect": "^1.0.2", 21 | "koa2-cors": "^2.0.6", 22 | "stylus": "^0.54.7", 23 | "stylus-loader": "^3.0.2", 24 | "vue": "^2.6.10", 25 | "vue-router": "^3.1.3", 26 | "vuex": "^3.1.2", 27 | "worker-loader": "^2.0.0" 28 | }, 29 | "devDependencies": { 30 | "@vue/cli-plugin-babel": "^4.1.0", 31 | "@vue/cli-plugin-eslint": "^4.1.0", 32 | "@vue/cli-plugin-router": "^4.1.0", 33 | "@vue/cli-plugin-vuex": "^4.1.0", 34 | "@vue/cli-service": "^4.1.0", 35 | "@vue/eslint-config-prettier": "^5.0.0", 36 | "babel-eslint": "^10.0.3", 37 | "eslint": "^5.16.0", 38 | "eslint-plugin-prettier": "^3.1.1", 39 | "eslint-plugin-vue": "^5.0.0", 40 | "prettier": "^1.19.1", 41 | "vue-template-compiler": "^2.6.10" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // tab缩进大小,默认为2 3 | tabWidth: 2, 4 | // 使用tab缩进,默认false 5 | useTabs: false, 6 | // 使用分号, 默认true 7 | semi: false, 8 | // 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号) 9 | singleQuote: true, 10 | // 行尾逗号,默认none,可选 none|es5|all 11 | // es5 包括es5中的数组、对象 12 | // all 包括函数对象等所有可选 13 | TrailingCooma: 'none', 14 | // 对象中的空格 默认true 15 | // true: { foo: bar } 16 | // false: {foo: bar} 17 | bracketSpacing: true, 18 | // JSX标签闭合位置 默认false 19 | // false:
23 | // true:
26 | jsxBracketSameLine: false, 27 | // 箭头函数参数括号 默认avoid 可选 avoid| always 28 | // avoid 能省略括号的时候就省略 例如x => x 29 | // always 总是有括号 30 | arrowParens: 'avoid', 31 | //html 模板设置 32 | htmlWhitespaceSensitivity: 'ignore', 33 | proseWrap: 'preserve', 34 | printWidth: 120 //默认为80 35 | } 36 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/hbooker-extractor/3743bd783bf6bb6ef9d008cc4a1ad71a0d415098/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | hbooker-extractor 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | const Koa = require("koa"); 2 | const path = require("path"); 3 | const cors = require("koa2-cors"); 4 | const httpProxy = require("http-proxy-middleware"); 5 | const k2c = require("koa2-connect"); 6 | const bodyparser = require("koa-bodyparser"); 7 | const statickoa = require("koa-static"); 8 | console.log("正在启动服务……"); 9 | const app = new Koa(); 10 | const staticPath = "./static"; 11 | app.use(cors()); 12 | app.use(statickoa(path.join(__dirname, staticPath))); 13 | app.use(async (ctx, next) => { 14 | if (ctx.url.startsWith("/api")) { 15 | ctx.respond = false; 16 | await k2c( 17 | httpProxy({ 18 | target: "https://app.hbooker.com", 19 | changeOrigin: true, 20 | secure: false, 21 | pathRewrite: { "^/api": "" } 22 | }) 23 | )(ctx, next); 24 | } 25 | await next(); 26 | }); 27 | app.use(bodyparser({ enableTypes: ["json", "form", "text"] })); 28 | app.listen(9612); 29 | console.log("启动成功,监听端口:9612"); 30 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hbooker-extractor-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "zsakvo", 10 | "license": "ISC", 11 | "dependencies": { 12 | "http-proxy-middleware": "^0.20.0", 13 | "koa": "^2.11.0", 14 | "koa-bodyparser": "^4.2.1", 15 | "koa-static": "^5.0.0", 16 | "koa2-connect": "^1.0.2", 17 | "koa2-cors": "^2.0.6" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /server/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | accepts@^1.3.5: 6 | version "1.3.7" 7 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" 8 | integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== 9 | dependencies: 10 | mime-types "~2.1.24" 11 | negotiator "0.6.2" 12 | 13 | any-promise@^1.0.0, any-promise@^1.1.0: 14 | version "1.3.0" 15 | resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" 16 | integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= 17 | 18 | braces@^3.0.1: 19 | version "3.0.2" 20 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" 21 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== 22 | dependencies: 23 | fill-range "^7.0.1" 24 | 25 | bytes@3.1.0: 26 | version "3.1.0" 27 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" 28 | integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== 29 | 30 | cache-content-type@^1.0.0: 31 | version "1.0.1" 32 | resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c" 33 | integrity sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA== 34 | dependencies: 35 | mime-types "^2.1.18" 36 | ylru "^1.2.0" 37 | 38 | co-body@^6.0.0: 39 | version "6.0.0" 40 | resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.0.0.tgz#965b9337d7f5655480787471f4237664820827e3" 41 | integrity sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw== 42 | dependencies: 43 | inflation "^2.0.0" 44 | qs "^6.5.2" 45 | raw-body "^2.3.3" 46 | type-is "^1.6.16" 47 | 48 | co@^4.6.0: 49 | version "4.6.0" 50 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" 51 | integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= 52 | 53 | content-disposition@~0.5.2: 54 | version "0.5.3" 55 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" 56 | integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== 57 | dependencies: 58 | safe-buffer "5.1.2" 59 | 60 | content-type@^1.0.4: 61 | version "1.0.4" 62 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 63 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 64 | 65 | cookies@~0.8.0: 66 | version "0.8.0" 67 | resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" 68 | integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== 69 | dependencies: 70 | depd "~2.0.0" 71 | keygrip "~1.1.0" 72 | 73 | copy-to@^2.0.1: 74 | version "2.0.1" 75 | resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5" 76 | integrity sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU= 77 | 78 | debug@^3.0.0, debug@^3.1.0: 79 | version "3.2.6" 80 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" 81 | integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== 82 | dependencies: 83 | ms "^2.1.1" 84 | 85 | debug@~3.1.0: 86 | version "3.1.0" 87 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 88 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== 89 | dependencies: 90 | ms "2.0.0" 91 | 92 | deep-equal@~1.0.1: 93 | version "1.0.1" 94 | resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" 95 | integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= 96 | 97 | delegates@^1.0.0: 98 | version "1.0.0" 99 | resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" 100 | integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= 101 | 102 | depd@^1.1.2, depd@~1.1.2: 103 | version "1.1.2" 104 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 105 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= 106 | 107 | depd@~2.0.0: 108 | version "2.0.0" 109 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 110 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 111 | 112 | destroy@^1.0.4: 113 | version "1.0.4" 114 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 115 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= 116 | 117 | ee-first@1.1.1: 118 | version "1.1.1" 119 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 120 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 121 | 122 | encodeurl@^1.0.2: 123 | version "1.0.2" 124 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 125 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 126 | 127 | error-inject@^1.0.0: 128 | version "1.0.0" 129 | resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37" 130 | integrity sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc= 131 | 132 | escape-html@^1.0.3: 133 | version "1.0.3" 134 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 135 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 136 | 137 | eventemitter3@^4.0.0: 138 | version "4.0.0" 139 | resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" 140 | integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== 141 | 142 | fill-range@^7.0.1: 143 | version "7.0.1" 144 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" 145 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== 146 | dependencies: 147 | to-regex-range "^5.0.1" 148 | 149 | follow-redirects@^1.0.0: 150 | version "1.9.0" 151 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f" 152 | integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A== 153 | dependencies: 154 | debug "^3.0.0" 155 | 156 | fresh@~0.5.2: 157 | version "0.5.2" 158 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 159 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= 160 | 161 | http-assert@^1.3.0: 162 | version "1.4.1" 163 | resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.1.tgz#c5f725d677aa7e873ef736199b89686cceb37878" 164 | integrity sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw== 165 | dependencies: 166 | deep-equal "~1.0.1" 167 | http-errors "~1.7.2" 168 | 169 | http-errors@1.7.3, http-errors@^1.6.3, http-errors@~1.7.2: 170 | version "1.7.3" 171 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" 172 | integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== 173 | dependencies: 174 | depd "~1.1.2" 175 | inherits "2.0.4" 176 | setprototypeof "1.1.1" 177 | statuses ">= 1.5.0 < 2" 178 | toidentifier "1.0.0" 179 | 180 | http-errors@~1.6.2: 181 | version "1.6.3" 182 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" 183 | integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= 184 | dependencies: 185 | depd "~1.1.2" 186 | inherits "2.0.3" 187 | setprototypeof "1.1.0" 188 | statuses ">= 1.4.0 < 2" 189 | 190 | http-proxy-middleware@^0.20.0: 191 | version "0.20.0" 192 | resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.20.0.tgz#5b128f7207985c4ea91b53fab8ad897a48c690d6" 193 | integrity sha512-dNJAk71nEJhPiAczQH9hGvE/MT9kEs+zn2Dh+Hi94PGZe1GluQirC7mw5rdREUtWx6qGS1Gu0bZd4qEAg+REgw== 194 | dependencies: 195 | http-proxy "^1.17.0" 196 | is-glob "^4.0.1" 197 | lodash "^4.17.14" 198 | micromatch "^4.0.2" 199 | 200 | http-proxy@^1.17.0: 201 | version "1.18.0" 202 | resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a" 203 | integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ== 204 | dependencies: 205 | eventemitter3 "^4.0.0" 206 | follow-redirects "^1.0.0" 207 | requires-port "^1.0.0" 208 | 209 | iconv-lite@0.4.24: 210 | version "0.4.24" 211 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 212 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 213 | dependencies: 214 | safer-buffer ">= 2.1.2 < 3" 215 | 216 | inflation@^2.0.0: 217 | version "2.0.0" 218 | resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f" 219 | integrity sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8= 220 | 221 | inherits@2.0.3: 222 | version "2.0.3" 223 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 224 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= 225 | 226 | inherits@2.0.4: 227 | version "2.0.4" 228 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 229 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 230 | 231 | is-extglob@^2.1.1: 232 | version "2.1.1" 233 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 234 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 235 | 236 | is-generator-function@^1.0.7: 237 | version "1.0.7" 238 | resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" 239 | integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== 240 | 241 | is-glob@^4.0.1: 242 | version "4.0.1" 243 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 244 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 245 | dependencies: 246 | is-extglob "^2.1.1" 247 | 248 | is-number@^7.0.0: 249 | version "7.0.0" 250 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 251 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 252 | 253 | keygrip@~1.1.0: 254 | version "1.1.0" 255 | resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" 256 | integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ== 257 | dependencies: 258 | tsscmp "1.0.6" 259 | 260 | koa-bodyparser@^4.2.1: 261 | version "4.2.1" 262 | resolved "https://registry.yarnpkg.com/koa-bodyparser/-/koa-bodyparser-4.2.1.tgz#4d7dacb5e6db1106649b595d9e5ccb158b6f3b29" 263 | integrity sha512-UIjPAlMZfNYDDe+4zBaOAUKYqkwAGcIU6r2ARf1UOXPAlfennQys5IiShaVeNf7KkVBlf88f2LeLvBFvKylttw== 264 | dependencies: 265 | co-body "^6.0.0" 266 | copy-to "^2.0.1" 267 | 268 | koa-compose@^3.0.0: 269 | version "3.2.1" 270 | resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-3.2.1.tgz#a85ccb40b7d986d8e5a345b3a1ace8eabcf54de7" 271 | integrity sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec= 272 | dependencies: 273 | any-promise "^1.1.0" 274 | 275 | koa-compose@^4.1.0: 276 | version "4.1.0" 277 | resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877" 278 | integrity sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw== 279 | 280 | koa-convert@^1.2.0: 281 | version "1.2.0" 282 | resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-1.2.0.tgz#da40875df49de0539098d1700b50820cebcd21d0" 283 | integrity sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA= 284 | dependencies: 285 | co "^4.6.0" 286 | koa-compose "^3.0.0" 287 | 288 | koa-send@^5.0.0: 289 | version "5.0.0" 290 | resolved "https://registry.yarnpkg.com/koa-send/-/koa-send-5.0.0.tgz#5e8441e07ef55737734d7ced25b842e50646e7eb" 291 | integrity sha512-90ZotV7t0p3uN9sRwW2D484rAaKIsD8tAVtypw/aBU+ryfV+fR2xrcAwhI8Wl6WRkojLUs/cB9SBSCuIb+IanQ== 292 | dependencies: 293 | debug "^3.1.0" 294 | http-errors "^1.6.3" 295 | mz "^2.7.0" 296 | resolve-path "^1.4.0" 297 | 298 | koa-static@^5.0.0: 299 | version "5.0.0" 300 | resolved "https://registry.yarnpkg.com/koa-static/-/koa-static-5.0.0.tgz#5e92fc96b537ad5219f425319c95b64772776943" 301 | integrity sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ== 302 | dependencies: 303 | debug "^3.1.0" 304 | koa-send "^5.0.0" 305 | 306 | koa2-connect@^1.0.2: 307 | version "1.0.2" 308 | resolved "https://registry.yarnpkg.com/koa2-connect/-/koa2-connect-1.0.2.tgz#cf196d70a4e6a055f717522768d26cdfc5396f7b" 309 | integrity sha1-zxltcKTmoFX3F1InaNJs38U5b3s= 310 | 311 | koa2-cors@^2.0.6: 312 | version "2.0.6" 313 | resolved "https://registry.yarnpkg.com/koa2-cors/-/koa2-cors-2.0.6.tgz#9ad23df3a0b9bb84530b46f5944f3fb576086554" 314 | integrity sha512-JRCcSM4lamM+8kvKGDKlesYk2ASrmSTczDtGUnIadqMgnHU4Ct5Gw7Bxt3w3m6d6dy3WN0PU4oMP43HbddDEWg== 315 | 316 | koa@^2.11.0: 317 | version "2.11.0" 318 | resolved "https://registry.yarnpkg.com/koa/-/koa-2.11.0.tgz#fe5a51c46f566d27632dd5dc8fd5d7dd44f935a4" 319 | integrity sha512-EpR9dElBTDlaDgyhDMiLkXrPwp6ZqgAIBvhhmxQ9XN4TFgW+gEz6tkcsNI6BnUbUftrKDjVFj4lW2/J2aNBMMA== 320 | dependencies: 321 | accepts "^1.3.5" 322 | cache-content-type "^1.0.0" 323 | content-disposition "~0.5.2" 324 | content-type "^1.0.4" 325 | cookies "~0.8.0" 326 | debug "~3.1.0" 327 | delegates "^1.0.0" 328 | depd "^1.1.2" 329 | destroy "^1.0.4" 330 | encodeurl "^1.0.2" 331 | error-inject "^1.0.0" 332 | escape-html "^1.0.3" 333 | fresh "~0.5.2" 334 | http-assert "^1.3.0" 335 | http-errors "^1.6.3" 336 | is-generator-function "^1.0.7" 337 | koa-compose "^4.1.0" 338 | koa-convert "^1.2.0" 339 | on-finished "^2.3.0" 340 | only "~0.0.2" 341 | parseurl "^1.3.2" 342 | statuses "^1.5.0" 343 | type-is "^1.6.16" 344 | vary "^1.1.2" 345 | 346 | lodash@^4.17.14: 347 | version "4.17.19" 348 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" 349 | integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== 350 | 351 | media-typer@0.3.0: 352 | version "0.3.0" 353 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 354 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= 355 | 356 | micromatch@^4.0.2: 357 | version "4.0.2" 358 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" 359 | integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== 360 | dependencies: 361 | braces "^3.0.1" 362 | picomatch "^2.0.5" 363 | 364 | mime-db@1.42.0: 365 | version "1.42.0" 366 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" 367 | integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== 368 | 369 | mime-types@^2.1.18, mime-types@~2.1.24: 370 | version "2.1.25" 371 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" 372 | integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== 373 | dependencies: 374 | mime-db "1.42.0" 375 | 376 | ms@2.0.0: 377 | version "2.0.0" 378 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 379 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 380 | 381 | ms@^2.1.1: 382 | version "2.1.2" 383 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 384 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 385 | 386 | mz@^2.7.0: 387 | version "2.7.0" 388 | resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" 389 | integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== 390 | dependencies: 391 | any-promise "^1.0.0" 392 | object-assign "^4.0.1" 393 | thenify-all "^1.0.0" 394 | 395 | negotiator@0.6.2: 396 | version "0.6.2" 397 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" 398 | integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== 399 | 400 | object-assign@^4.0.1: 401 | version "4.1.1" 402 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 403 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 404 | 405 | on-finished@^2.3.0: 406 | version "2.3.0" 407 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 408 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 409 | dependencies: 410 | ee-first "1.1.1" 411 | 412 | only@~0.0.2: 413 | version "0.0.2" 414 | resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" 415 | integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= 416 | 417 | parseurl@^1.3.2: 418 | version "1.3.3" 419 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 420 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 421 | 422 | path-is-absolute@1.0.1: 423 | version "1.0.1" 424 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 425 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 426 | 427 | picomatch@^2.0.5: 428 | version "2.1.1" 429 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" 430 | integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== 431 | 432 | qs@^6.5.2: 433 | version "6.9.1" 434 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9" 435 | integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA== 436 | 437 | raw-body@^2.3.3: 438 | version "2.4.1" 439 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" 440 | integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== 441 | dependencies: 442 | bytes "3.1.0" 443 | http-errors "1.7.3" 444 | iconv-lite "0.4.24" 445 | unpipe "1.0.0" 446 | 447 | requires-port@^1.0.0: 448 | version "1.0.0" 449 | resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 450 | integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= 451 | 452 | resolve-path@^1.4.0: 453 | version "1.4.0" 454 | resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7" 455 | integrity sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc= 456 | dependencies: 457 | http-errors "~1.6.2" 458 | path-is-absolute "1.0.1" 459 | 460 | safe-buffer@5.1.2: 461 | version "5.1.2" 462 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 463 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 464 | 465 | "safer-buffer@>= 2.1.2 < 3": 466 | version "2.1.2" 467 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 468 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 469 | 470 | setprototypeof@1.1.0: 471 | version "1.1.0" 472 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" 473 | integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== 474 | 475 | setprototypeof@1.1.1: 476 | version "1.1.1" 477 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" 478 | integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== 479 | 480 | "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@^1.5.0: 481 | version "1.5.0" 482 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 483 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= 484 | 485 | thenify-all@^1.0.0: 486 | version "1.6.0" 487 | resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" 488 | integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= 489 | dependencies: 490 | thenify ">= 3.1.0 < 4" 491 | 492 | "thenify@>= 3.1.0 < 4": 493 | version "3.3.0" 494 | resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" 495 | integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= 496 | dependencies: 497 | any-promise "^1.0.0" 498 | 499 | to-regex-range@^5.0.1: 500 | version "5.0.1" 501 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 502 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 503 | dependencies: 504 | is-number "^7.0.0" 505 | 506 | toidentifier@1.0.0: 507 | version "1.0.0" 508 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" 509 | integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== 510 | 511 | tsscmp@1.0.6: 512 | version "1.0.6" 513 | resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" 514 | integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== 515 | 516 | type-is@^1.6.16: 517 | version "1.6.18" 518 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 519 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 520 | dependencies: 521 | media-typer "0.3.0" 522 | mime-types "~2.1.24" 523 | 524 | unpipe@1.0.0: 525 | version "1.0.0" 526 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 527 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 528 | 529 | vary@^1.1.2: 530 | version "1.1.2" 531 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 532 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 533 | 534 | ylru@^1.2.0: 535 | version "1.2.1" 536 | resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" 537 | integrity sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ== 538 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zsakvo/hbooker-extractor/3743bd783bf6bb6ef9d008cc4a1ad71a0d415098/src/assets/logo.png -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import './plugins/at' 5 | import installHttp from './plugins/http' 6 | import decrypt from './plugins/decrypt' 7 | 8 | Vue.config.productionTip = false 9 | Vue.prototype.$get = installHttp.get 10 | Vue.prototype.$post = installHttp.post 11 | Vue.prototype.$dcy = decrypt 12 | 13 | new Vue({ 14 | router, 15 | render: h => h(App) 16 | }).$mount('#app') 17 | -------------------------------------------------------------------------------- /src/plugins/at.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import 'at-ui-style' 3 | import { Button, Input, Notification, Modal, Table, Dropdown, DropdownMenu, DropdownItem } from 'at-ui' 4 | Vue.use(Button) 5 | Vue.use(Input) 6 | Vue.use(Modal) 7 | Vue.use(Table) 8 | Vue.use(Dropdown) 9 | Vue.use(DropdownMenu) 10 | Vue.use(DropdownItem) 11 | Vue.prototype.$Notify = Notification 12 | -------------------------------------------------------------------------------- /src/plugins/decrypt.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto') 2 | // let key = crypto 3 | // .createHash("sha256") 4 | // .update("zG2nSeEfSHfvTCHy5LCcqtBbQehKNLXn") 5 | // .digest(); 6 | 7 | var decrypt = function decrypt(data, key) { 8 | if (key == null) { 9 | key = crypto 10 | .createHash('sha256') 11 | .update('zG2nSeEfSHfvTCHy5LCcqtBbQehKNLXn') 12 | .digest() 13 | } else { 14 | key = crypto 15 | .createHash('sha256') 16 | .update(key) 17 | .digest() 18 | } 19 | let decipher = crypto.createDecipheriv('aes-256-cbc', key, new Uint8Array(16)) 20 | decipher.setAutoPadding(false) 21 | let decrypted = decipher.update(data, 'base64', 'utf8') 22 | decrypted += decipher.final('utf8') 23 | return decrypted 24 | } 25 | 26 | module.exports = decrypt 27 | -------------------------------------------------------------------------------- /src/plugins/http.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | const mixin = { 4 | baseUrl: '/api', //url前缀 5 | standardFlag: true, 6 | timeout: 15000, 7 | withCredentials: false //跨域请求是否使用凭证 8 | } 9 | 10 | const para = { 11 | app_version: '2.3.020', 12 | device_token: 'ciweimao_powered_by_zsakvo_with_vue' 13 | } 14 | 15 | axios.interceptors.response.use( 16 | response => { 17 | return response 18 | }, 19 | error => { 20 | if (error && error.response) { 21 | switch (error.response.status) { 22 | case 400: 23 | error.message = '请求错误' 24 | break 25 | case 401: 26 | error.message = '未授权,请登录' 27 | break 28 | case 403: 29 | error.message = '拒绝访问' 30 | break 31 | case 404: 32 | error.message = '请求地址出错' 33 | break 34 | case 408: 35 | error.message = '请求超时' 36 | break 37 | case 500: 38 | error.message = '服务器内部错误' 39 | break 40 | case 501: 41 | error.message = '服务未实现' 42 | break 43 | case 502: 44 | error.message = '网关错误' 45 | break 46 | case 503: 47 | error.message = '服务不可用' 48 | break 49 | case 504: 50 | error.message = '网关超时' 51 | break 52 | case 505: 53 | error.message = 'HTTP版本不受支持' 54 | break 55 | default: 56 | } 57 | } 58 | return Promise.reject(error) 59 | } 60 | ) 61 | 62 | function get(options, final) { 63 | let params = Object.assign({}, para, options.para) 64 | return new Promise((resolve, reject) => { 65 | axios 66 | .get(mixin.baseUrl + options.url, { 67 | params: params 68 | }) 69 | .then(response => { 70 | let data = this.$dcy(response.data.trim()) 71 | var lastIndex = data.lastIndexOf('}') 72 | data = data.substr(0, lastIndex + 1) 73 | let json = JSON.parse(data) 74 | switch (json.code) { 75 | case 100000: 76 | // console.log("成功"); 77 | resolve(json.data) 78 | break 79 | case 200100: 80 | this.$router.push('/login') 81 | break 82 | default: 83 | this.$Notify.error({ 84 | title: '错误', 85 | message: json.tip 86 | }) 87 | } 88 | }) 89 | .catch(err => { 90 | this.$Notify.error({ 91 | title: '错误', 92 | message: err.message 93 | }) 94 | reject(err) 95 | }) 96 | .finally(() => { 97 | if (final != null) final() 98 | }) 99 | }) 100 | } 101 | 102 | function post(obj, final) { 103 | let options = mixin 104 | options = Object.assign({}, options, obj) 105 | return new Promise((resolve, reject) => { 106 | axios 107 | .post(options.baseUrl + options.url, options.para, { 108 | headers: options.header, 109 | timeout: options.timeout, 110 | withCredentials: options.withCredentials 111 | }) 112 | .then( 113 | response => { 114 | let data = this.$dcy(response.data.trim()) 115 | var lastIndex = data.lastIndexOf('}') 116 | data = data.substr(0, lastIndex + 1) 117 | let json = JSON.parse(data) 118 | switch (json.code) { 119 | case 100000: 120 | resolve(json.data) 121 | break 122 | default: 123 | this.$Notify.error({ 124 | title: '错误', 125 | message: json.tip 126 | }) 127 | } 128 | }, 129 | err => { 130 | this.$Notify.error({ 131 | title: '错误', 132 | message: err.message 133 | }) 134 | reject(err) 135 | } 136 | ) 137 | .finally(() => { 138 | if (final != null) final() 139 | }) 140 | }) 141 | } 142 | 143 | const installHttp = { 144 | get, 145 | post 146 | } 147 | export default installHttp 148 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import Home from '../views/Home.vue' 4 | 5 | Vue.use(VueRouter) 6 | 7 | const routes = [ 8 | { 9 | path: '/', 10 | name: 'home', 11 | component: Home 12 | }, 13 | { 14 | path: '/login', 15 | name: 'login', 16 | component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue') 17 | } 18 | ] 19 | 20 | const router = new VueRouter({ 21 | mode: 'history', 22 | base: process.env.BASE_URL, 23 | routes 24 | }) 25 | 26 | export default router 27 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 327 | 328 | 370 | -------------------------------------------------------------------------------- /src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 61 | 62 | 95 | -------------------------------------------------------------------------------- /src/work/gb.work.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import decrypt from '../plugins/decrypt' 3 | const mixin = { 4 | baseUrl: '/api', //url前缀 5 | standardFlag: true, 6 | timeout: 15000, 7 | withCredentials: false //跨域请求是否使用凭证 8 | } 9 | const para = { 10 | app_version: '2.3.020', 11 | device_token: 'ciweimao_powered_by_zsakvo_with_vue' 12 | } 13 | var loginToken 14 | var account 15 | var book = '' 16 | var bookOutOfOrder = [] 17 | var chapterNum = 0 18 | // 响应父线程的消息 19 | self.addEventListener('message', async event => { 20 | let cmd = event.data.cmd 21 | let para = event.data.para 22 | loginToken = event.data.loginToken 23 | account = event.data.account 24 | switch (cmd) { 25 | case 'begin': 26 | for (let i = 0; i < para.length; i++) { 27 | const chapter = para[i] 28 | getChapter(chapter, i, para.length) 29 | } 30 | break 31 | } 32 | }) 33 | 34 | var getChapter = async function(chapter, i, length) { 35 | try { 36 | let key = await getChapterKey(chapter.chapter_id) 37 | let content = await getChapterContent(chapter.chapter_id, key) 38 | let chapterInfo = content.chapter_info 39 | if (Object.keys(chapterInfo).length != 0) { 40 | let contentTitle = chapterInfo.chapter_title 41 | let contentText = chapterInfo.txt_content 42 | let decryptContent = decrypt(contentText, key) 43 | bookOutOfOrder[i] = contentTitle + '\n' + decryptContent + '\n\n\n' 44 | } else { 45 | throw new Error('Failed to get chapter info') 46 | } 47 | } catch (e) { 48 | bookOutOfOrder[i] = 'download failed\n' 49 | console.error(e) 50 | } 51 | chapterNum++ 52 | self.postMessage({ msg: 'chapter_complete', content: chapterNum }) 53 | if (chapterNum === length) { 54 | for (let ii = 0; ii < length; ii++) { 55 | book += bookOutOfOrder[ii] 56 | } 57 | self.postMessage({ msg: 'all_complete', content: book }) 58 | } 59 | } 60 | 61 | var getChapterKey = async function(cid) { 62 | return await get({ 63 | url: '/chapter/get_chapter_cmd', 64 | para: { 65 | login_token: loginToken, 66 | account: account, 67 | chapter_id: cid 68 | } 69 | }).then(res => { 70 | return res.command 71 | }) 72 | } 73 | 74 | var getChapterContent = async function(cid, key) { 75 | return await get({ 76 | url: '/chapter/get_cpt_ifm', 77 | para: { 78 | login_token: loginToken, 79 | account: account, 80 | chapter_id: cid, 81 | chapter_command: key 82 | } 83 | }).then(res => { 84 | return res 85 | }) 86 | } 87 | 88 | var get = function(options) { 89 | let params = Object.assign({}, para, options.para) 90 | return new Promise((resolve, reject) => { 91 | axios 92 | .get(mixin.baseUrl + options.url, { 93 | params: params 94 | }) 95 | .then(response => { 96 | let data = decrypt(response.data.trim()) 97 | var lastIndex = data.lastIndexOf('}') 98 | data = data.substr(0, lastIndex + 1) 99 | let json = JSON.parse(data) 100 | switch (json.code) { 101 | case 100000: 102 | resolve(json.data) 103 | break 104 | default: 105 | } 106 | }) 107 | .catch(err => { 108 | reject(err) 109 | }) 110 | }) 111 | } 112 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | // vue.config.js 2 | module.exports = { 3 | outputDir: 'server/static', 4 | publicPath: './', 5 | productionSourceMap: false, 6 | devServer: { 7 | port: 8089, 8 | proxy: { 9 | '/api': { 10 | target: 'https://app.hbooker.com', //目标主机 11 | changeOrigin: true, //是否跨域 默认true 12 | ws: true, //代理的WebSockets 默认true 13 | secure: true, //是否开启ssl加密 https 14 | pathRewrite: { 15 | '^/api': '' //路径替换 16 | } 17 | } 18 | } 19 | } 20 | } 21 | --------------------------------------------------------------------------------