├── cache └── .gitignore ├── temp └── .gitignore ├── .gitignore ├── app.ts ├── src ├── config.ts ├── services │ ├── index.ts │ ├── Service.ts │ ├── ServiceInstance.ts │ ├── WeiboService.ts │ └── BilibiliService.ts ├── utils │ ├── Redis.ts │ ├── Downloader.ts │ └── Proxy.ts └── main.ts ├── tsconfig.json ├── package.json ├── LICENSE ├── README.md └── yarn.lock /cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /temp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /app.ts: -------------------------------------------------------------------------------- 1 | import { main } from './src/main'; 2 | 3 | main(); 4 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | export const Config = { 2 | weibo: { 3 | account: '', 4 | password: '', 5 | stopSend: false, 6 | }, 7 | bilibili: { 8 | checkCycle: 30, 9 | beforeTimestamp: 1545383129, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2017", 5 | "noImplicitAny": true, 6 | "outDir": "./dist", 7 | "sourceMap": true 8 | }, 9 | "include": [ 10 | "src/**/*" 11 | ] 12 | } -------------------------------------------------------------------------------- /src/services/index.ts: -------------------------------------------------------------------------------- 1 | import { ServiceInstance } from './ServiceInstance'; 2 | import { WebDriver } from 'selenium-webdriver'; 3 | 4 | export { Service } from './Service'; 5 | 6 | export function getServices(driver: WebDriver): ServiceInstance { 7 | return new ServiceInstance(driver); 8 | } 9 | -------------------------------------------------------------------------------- /src/utils/Redis.ts: -------------------------------------------------------------------------------- 1 | import { Tedis, TedisPool } from 'tedis'; 2 | 3 | export class RedisUtil { 4 | public static _pool: TedisPool = new TedisPool({ 5 | port: 6379, 6 | host: "127.0.0.1" 7 | }); 8 | 9 | public static getRedis(): Promise { 10 | return this._pool.getTedis(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/services/Service.ts: -------------------------------------------------------------------------------- 1 | import { WebDriver } from "selenium-webdriver"; 2 | import { ServiceInstance } from "./ServiceInstance"; 3 | export class Service { 4 | private _driver: WebDriver; 5 | constructor(driver: WebDriver) { 6 | this.setDriver(driver); 7 | } 8 | public getDriver(): WebDriver { 9 | return this._driver; 10 | } 11 | public setDriver(driver: WebDriver): void { 12 | this._driver = driver; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-porter", 3 | "version": "1.0.0", 4 | "main": "src/main.ts", 5 | "author": "smilec", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "ts-node app.ts" 9 | }, 10 | "dependencies": { 11 | "@types/download": "^6.2.3", 12 | "@types/node": "^10.12.17", 13 | "axios": "^0.18.0", 14 | "download": "^7.1.0", 15 | "selenium-webdriver": "^4.0.0-alpha.1", 16 | "tedis": "^0.1.4", 17 | "ts-node": "^7.0.1", 18 | "tslint": "^5.12.0", 19 | "typescript": "^3.2.2" 20 | }, 21 | "devDependencies": { 22 | "@types/selenium-webdriver": "^3.0.14", 23 | "uuid": "^3.3.2" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/Downloader.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | import * as download from 'download'; 4 | 5 | export class DownloaderUtil { 6 | /** 7 | * 下载文件到temp文件夹中 8 | * @param url 要下载文件的链接 9 | */ 10 | public static async download(url: string): Promise { 11 | const saveName = `${(new Date()).getTime()}_${path.basename(url)}`; 12 | const savePath = `${this.getTempPath()}/${saveName}`; 13 | const fileData = await download(url); 14 | fs.writeFileSync(savePath, fileData); 15 | return savePath; 16 | } 17 | 18 | public static getTempPath() { 19 | return `${path.dirname(require.main.filename)}/temp`; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/services/ServiceInstance.ts: -------------------------------------------------------------------------------- 1 | import { WebDriver } from "selenium-webdriver"; 2 | import { BilibiliService } from './BilibiliService'; 3 | import { WeiboService } from './WeiboService'; 4 | import * as fs from 'fs'; 5 | 6 | export class ServiceInstance { 7 | private _weiboService: WeiboService; 8 | private _bilibiliService: BilibiliService; 9 | constructor(driver: WebDriver) { 10 | this._weiboService = new WeiboService(driver); 11 | this._bilibiliService = new BilibiliService(driver); 12 | } 13 | public get weiboService(): WeiboService { 14 | return this._weiboService; 15 | } 16 | public get bilibiliService(): BilibiliService { 17 | return this._bilibiliService; 18 | } 19 | 20 | public init() { 21 | // fs.existsSync('./cache/init.json'); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Can 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 微博搬运姬 2 | 3 | 基于Firefox Headless,实现自动监听某位用户的B博(Bilibili动态),当有新动态发布时,自动将该条动态搬运至微博。 4 | 5 | - 7 * 24小时全自动无人值守 6 | - 自动转发图片与文字 7 | - 自动截屏转发内容上下文 8 | - 自动清除图片缓存 9 | - 使用原子锁防止重复搬运 10 | - 使用TypeScript编写 11 | 12 | ## 目录 13 | 14 | - [Demo](#demo) 15 | - [环境要求](#环境要求) 16 | - [快速开始](#快速开始) 17 | - [获取帮助](#获取帮助) 18 | - [已知问题](#已知问题) 19 | - [贡献代码](#贡献代码) 20 | - [鸣谢](#鸣谢) 21 | - [License](#License) 22 | 23 | ## Demo 24 | 25 | - [孙渣搬运bot](https://weibo.com/6697757382)(欢迎关注) 26 | 27 | ## 环境要求 28 | 29 | - Redis 30 | - Node.js 31 | - [Yarn](https://yarnpkg.com) 32 | - Firefox & [geckodriver](https://github.com/mozilla/geckodriver/releases) 33 | - Chrome & [chromedriver](http://chromedriver.chromium.org/) 34 | 35 | ## 快速开始 36 | 37 | 请确认Redis监听的端口为6379,否则请自行修改`src/utils/Redis.ts`中的连接地址。 38 | 39 | 准备好如上环境后,安装项目依赖。 40 | 41 | ```bash 42 | $ yarn install 43 | ``` 44 | 45 | 随后在`src/config.ts`中填写微博的账户与密码,首次运行建议开启`stopSend`,否则将会把被监听用户的最新一页动态全部搬运过来,耗时可能较长。 46 | 47 | 执行如下命令启动项目。 48 | 49 | ```bash 50 | $ yarn start 51 | ``` 52 | 53 | ## 获取帮助 54 | 55 | 如果您有疑问或者建议,或是反馈Bug,建议您在本项目的[Github issues](https://github.com/smilecc/weibo-porter/issues)中进行发布。 56 | 57 | ## 已知问题 58 | 59 | - 由于Firefox Headless的`element.taskScreenshot`无法单独截取该元素的图片,所以仍然使用了Chrome Headless作为元素截取工具。 60 | 61 | ## 贡献代码 62 | 63 | 欢迎提交PR。 64 | 65 | ## 鸣谢 66 | 67 | - [孙渣](https://space.bilibili.com/81976/dynamic)(本项目为孙老板而生) 68 | - [璨desu](https://weibo.com/smilexc8)(我 谢 我 自 己) 69 | 70 | ## License 71 | 72 | [MIT License](https://opensource.org/licenses/MIT) 73 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { Builder } from 'selenium-webdriver'; 2 | import * as firefox from 'selenium-webdriver/firefox'; 3 | import { getServices } from './services'; 4 | import { DownloaderUtil } from './utils/Downloader'; 5 | import * as fs from 'fs'; 6 | import { Config } from './config'; 7 | 8 | const CookiesCachePath = './cache/weibo.json'; 9 | 10 | export async function main() { 11 | // 构建浏览器驱动器 12 | let driver = await new Builder() 13 | .forBrowser('firefox') 14 | .setFirefoxOptions(new firefox.Options().headless()) 15 | .build(); 16 | // 构建本地服务 17 | const services = getServices(driver); 18 | 19 | // 接收程序退出的信号来关闭浏览器 20 | process.on('SIGINT', () => { 21 | driver.quit(); 22 | process.exit(); 23 | }); 24 | 25 | try { 26 | // 尝试加载 cookies 27 | await services.weiboService.loadCookies(CookiesCachePath); 28 | let isLogged = await services.weiboService.isLogged(); 29 | // 判断是否需要登录 30 | if (!isLogged) { 31 | console.log('Start login.') 32 | await services.weiboService.login(Config.weibo.account, Config.weibo.password, CookiesCachePath) 33 | } 34 | 35 | // 开始监听动态 36 | services.bilibiliService.startListenDynamic(81976, async (dynamic) => { 37 | if (Config.weibo.stopSend) { 38 | return; 39 | } 40 | // 处理动态的图片 41 | let localImgList: string[] = []; 42 | // 如果是转发 则把原博截图 43 | if (dynamic.hasOrigin && dynamic.imgs.length < 9) { 44 | localImgList.push(await services.bilibiliService.takeScreenshot(dynamic)); 45 | } 46 | // 处理图片列表 47 | for (const img of dynamic.imgs) { 48 | const localImg = await DownloaderUtil.download(img.src); 49 | localImgList.push(localImg); 50 | } 51 | // 发送微博 52 | await services.weiboService.sendPost(dynamic.content, localImgList); 53 | // 删除temp中的在本次使用到的图片 54 | for (const imgPath of localImgList) { 55 | fs.unlinkSync(imgPath); 56 | } 57 | // 防抖 58 | await driver.sleep(20 * 1000); 59 | }); 60 | } finally { 61 | // driver.quit(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/utils/Proxy.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import axios from 'axios'; 3 | import { WebDriver, By, until } from 'selenium-webdriver'; 4 | import { RedisUtil } from './Redis'; 5 | 6 | export class ProxyUtil { 7 | 8 | public static RedisBlockedSet: string = 'bilibili_blocked_proxy'; 9 | public static RedisProxySet: string = 'proxies'; 10 | public static RedisProxyCreatedTime: string = 'proxies_created_time'; 11 | 12 | public static async getHttpProxy(driver: WebDriver, forceReload: boolean = false): Promise { 13 | 14 | const redisClient = await RedisUtil.getRedis(); 15 | 16 | // 判断上次加载代理的时间 17 | const lastLoaded = await redisClient.get(this.RedisProxyCreatedTime) as number; 18 | if (forceReload || (lastLoaded && lastLoaded - (new Date()).getTime() > 43200 * 1000)) { 19 | await this.getNewProxy(driver); 20 | } 21 | 22 | // 开始获取代理 23 | let proxy: IProxy = null; 24 | 25 | while (await redisClient.scard(this.RedisProxySet) > 0) { 26 | // 检查IP是否可用 27 | const unchekedProxy: IProxy = JSON.parse(await redisClient.spop(this.RedisProxySet)); 28 | if (await redisClient.sismember(this.RedisBlockedSet, unchekedProxy.ip)) { 29 | continue; 30 | } 31 | // 确认IP可用 32 | proxy = unchekedProxy; 33 | break; 34 | } 35 | 36 | // 如果没有获取到 则重新加载一次代理列表 37 | if (proxy === null) { 38 | // 如果已经是强制刷新则抛出失败异常 39 | if (forceReload) { 40 | throw new Error('没有获取到可用的代理'); 41 | } 42 | proxy = await this.getHttpProxy(driver, true); 43 | } 44 | 45 | redisClient.close(); 46 | return proxy; 47 | } 48 | 49 | /** 50 | * 获取一批新的代理 51 | * @param driver WebDriver 52 | */ 53 | protected static async getNewProxy(driver: WebDriver): Promise { 54 | const proxyList = [ 55 | 'https://www.xicidaili.com/nn', 56 | 'https://www.xicidaili.com/nt/', 57 | 'https://www.xicidaili.com/wn/', 58 | 'https://www.xicidaili.com/wt/' 59 | ]; 60 | await driver.get(proxyList[Math.ceil(Math.random() * (proxyList.length - 1))]); 61 | const ipListTable = await driver.wait(until.elementLocated(By.id('ip_list'))); 62 | const trList = await ipListTable.findElements(By.tagName('tr')); 63 | const trListLength = trList.length; 64 | 65 | const redisClient = await RedisUtil.getRedis(); 66 | for (let i = 0; i < trListLength - 1; i++) { 67 | const tr = trList.pop(); 68 | const tdList = await tr.findElements(By.tagName('td')); 69 | let ip = await tdList[1].getText(); 70 | let port = await tdList[2].getText(); 71 | 72 | redisClient.sadd(this.RedisProxySet, JSON.stringify({ 73 | ip: ip.trim(), 74 | port: parseInt(port), 75 | })); 76 | } 77 | redisClient.set(this.RedisProxyCreatedTime, (new Date()).getTime().toString()); 78 | redisClient.close(); 79 | } 80 | } 81 | 82 | export interface IProxy { 83 | ip: string; 84 | port: number; 85 | } 86 | 87 | export interface IProxyCache { 88 | createdTime: number; 89 | proxyList: IProxy[]; 90 | } 91 | -------------------------------------------------------------------------------- /src/services/WeiboService.ts: -------------------------------------------------------------------------------- 1 | import { Service } from "./Service"; 2 | import { IWebDriverOptionsCookie, By, until, Key } from 'selenium-webdriver'; 3 | import { Config } from '../config'; 4 | import * as fs from 'fs'; 5 | 6 | export class WeiboService extends Service { 7 | 8 | /** 9 | * 登录账户 10 | * @param username 用户名 11 | * @param password 密码 12 | */ 13 | public async login(username: string, password: string, cookieSavePath: string) { 14 | const driver = this.getDriver(); 15 | await driver.get('https://m.weibo.cn/?jumpfrom=weibocom&sudaref=login.sina.com.cn'); 16 | await driver.wait(until.elementLocated(By.className('lite-iconf-releas')), 20 * 1000).click(); 17 | 18 | // 等待登录页面加载 19 | await driver.wait(until.titleContains('登录'), 20 * 1000); 20 | const waitLoginButton = await driver.wait(until.elementLocated(By.id('loginName')), 20 * 1000); 21 | await driver.wait(until.elementIsVisible(waitLoginButton), 20 * 1000); 22 | 23 | // 填写用户名密码 24 | await driver.findElement(By.id('loginName')).sendKeys(username); 25 | await driver.findElement(By.id('loginPassword')).sendKeys(password); 26 | await driver.findElement(By.id('loginAction')).click(); 27 | 28 | // 等待页面跳转 29 | await driver.wait(until.titleIs('微博'), 20 * 1000); 30 | const waitCreateButton = await driver.wait(until.elementLocated(By.className('lite-iconf-releas')), 20 * 1000); 31 | await driver.wait(until.elementIsVisible(waitCreateButton), 20 * 1000); 32 | 33 | // 保存 cookies 34 | let cookies = await driver.manage().getCookies() 35 | fs.writeFileSync(cookieSavePath, JSON.stringify(cookies)); 36 | } 37 | 38 | /** 39 | * 从本地加载 cookie 缓存 40 | * @param cachePath cookie 所缓存的路径 41 | */ 42 | public async loadCookies(cachePath: string): Promise { 43 | try { 44 | const cookies = JSON.parse(fs.readFileSync(cachePath).toString()) as IWebDriverOptionsCookie[]; 45 | await this.getDriver().get('https://m.weibo.cn/404'); 46 | for (const cookie of cookies) { 47 | await this.getDriver().manage().addCookie(cookie); 48 | } 49 | return true; 50 | } catch { 51 | return false; 52 | } 53 | } 54 | 55 | /** 56 | * 判断用户是否已经登录 57 | */ 58 | public async isLogged(): Promise { 59 | try { 60 | await this.getDriver().get('https://m.weibo.cn/?jumpfrom=weibocom&sudaref=login.sina.com.cn'); 61 | await this.getDriver().findElement(By.className('lite-iconf-msg')) 62 | return true; 63 | } catch (error) { 64 | return false; 65 | } 66 | } 67 | 68 | /** 69 | * 发布微博 70 | * @param content 要发布的内容 71 | * @param imgList 图片列表 72 | */ 73 | public async sendPost(content: string, imgList: string[] = []) { 74 | const driver = this.getDriver(); 75 | await driver.get('https://m.weibo.cn/?jumpfrom=weibocom&sudaref=login.sina.com.cn'); 76 | 77 | await driver.wait(until.elementLocated(By.className('lite-iconf-releas')), 20 * 1000).click(); 78 | 79 | // 等待界面加载完毕 80 | const textarea = await driver.wait(until.elementLocated(By.xpath('//*[@id="app"]/div[1]/div/main/div[1]/div/span/textarea[1]')), 20 * 1000); 81 | content = content.replace(/@/g, '&'); 82 | content = content.replace(/`/g, "'"); 83 | 84 | // 设置要发布的内容 85 | await driver.executeScript(` 86 | var textarea = document.querySelector('#app > div.m-wrapper.m-wbox > div > main > div.m-box-model.m-pos-r > div > span > textarea:nth-child(1)'); 87 | textarea.value = \`${content}\`; 88 | 89 | var fileInput = document.getElementById('selectphoto'); 90 | fileInput.style.display = 'block'; 91 | fileInput.style.opacity = 1; 92 | `); 93 | 94 | await textarea.sendKeys(' '); 95 | await textarea.sendKeys(Key.BACK_SPACE); 96 | await driver.sleep(1000); 97 | 98 | if (!Config.weibo.stopSend) { 99 | // 上传图片 100 | const uploadInput = await driver.findElement(By.id('selectphoto')); 101 | for (const imgPath of imgList) { 102 | await uploadInput.sendKeys(imgPath); 103 | await driver.wait(until.elementsLocated(By.className('m-rpic-close')), 100 * 1000); 104 | await driver.executeScript(` 105 | document.querySelector('.image-wrap').remove(); 106 | `); 107 | await driver.sleep(100); 108 | } 109 | 110 | await driver.sleep(2000); 111 | // await fs.writeFileSync('./temp/debug.png', await driver.takeScreenshot(), 'base64'); 112 | await driver.findElement(By.className('m-send-btn')).click(); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/services/BilibiliService.ts: -------------------------------------------------------------------------------- 1 | import { Service } from './Service'; 2 | import * as chrome from 'selenium-webdriver/chrome'; 3 | import axios, { AxiosResponse } from 'axios'; 4 | import { RedisUtil } from '../utils/Redis'; 5 | import { Builder, until, By } from 'selenium-webdriver'; 6 | import * as fs from 'fs'; 7 | import { DownloaderUtil } from '../utils/Downloader'; 8 | import { Config } from '../config'; 9 | import { ProxyUtil } from '../utils/Proxy'; 10 | 11 | 12 | export class BilibiliService extends Service { 13 | /** 14 | * 开始监听用户动态 15 | * @param uid 要监听的用户ID 16 | * @param newDynamicHandler 当监听到新动态时的处理器 17 | */ 18 | public async startListenDynamic(uid: number, newDynamicHandler: DynamicHandler) { 19 | await this.removeLock(); 20 | setInterval(async () => { 21 | if (await this.checkLock()) { 22 | return; 23 | } 24 | await this.createLock(); 25 | this.printLog('正在检查动态'); 26 | try { 27 | await this.getDynamics(uid, newDynamicHandler); 28 | this.printLog('检查动态完毕'); 29 | } catch (error) { 30 | this.printLog('出现异常:' + error.message); 31 | } 32 | await this.removeLock(); 33 | }, Config.bilibili.checkCycle * 1000) 34 | } 35 | 36 | public async getDynamics(uid: number, newDynamicHandler: DynamicHandler): Promise { 37 | // 获取代理 38 | const proxy = await ProxyUtil.getHttpProxy(this.getDriver()); 39 | this.printLog(`使用代理[${proxy.ip}:${proxy.port}]`); 40 | // 加载动态 41 | const axiosSource = axios.CancelToken.source(); 42 | const timeout = 20 * 1000; 43 | let response: AxiosResponse = null; 44 | // 超时处理 45 | setTimeout(() => { 46 | if (response === null) { 47 | axiosSource.cancel(); 48 | } 49 | }, timeout); 50 | // 请求 51 | response = await axios.get(`http://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history?visitor_uid=${Math.ceil(Math.random() * 987789)}&host_uid=${uid}`, { 52 | transformResponse: (data) => { 53 | return JSON.parse((data as string).replace(/"dynamic_id":(\d+?),/g, (content) => { 54 | return content.replace(/([\d]+)/g, (id) => `"${id}"`); 55 | })); 56 | }, 57 | responseType: 'json', 58 | proxy: { 59 | host: proxy.ip, 60 | port: proxy.port, 61 | }, 62 | timeout, 63 | cancelToken: axiosSource.token, 64 | }); 65 | let responseData: IBilibiliDynamicResponse = response.data; 66 | let dynamicList: ILocalDynamic[] = []; 67 | 68 | if (responseData.code === 0) { 69 | // 将动态push进列表 70 | for (const card of responseData.data.cards.reverse()) { 71 | // console.log(card) 72 | const dynamic: IBilibiliDynamic = JSON.parse(card.card); 73 | // 判断动态类型 并处理为本地动态类型 74 | if ('content' in dynamic.item) { 75 | dynamicList.push({ 76 | type: DynamicTypes.Text, 77 | id: `text_${card.desc.dynamic_id}`, 78 | dynamicId: card.desc.dynamic_id, 79 | title: '', 80 | content: dynamic.item.content, 81 | imgs: [], 82 | timestamp: card.desc.timestamp, 83 | hasOrigin: 'origin' in dynamic, 84 | }) 85 | } else if ('description' in dynamic.item) { 86 | dynamicList.push({ 87 | type: DynamicTypes.Article, 88 | id: `article_${card.desc.dynamic_id}`, 89 | dynamicId: card.desc.dynamic_id, 90 | title: dynamic.item.title, 91 | content: dynamic.item.description, 92 | imgs: dynamic.item.pictures ? dynamic.item.pictures.map((pic) => ({ src: pic.img_src })) : [], 93 | timestamp: card.desc.timestamp, 94 | hasOrigin: false, 95 | }) 96 | } 97 | } 98 | 99 | this.printLog(`请求[${uid}]动态成功,共获得${dynamicList.length}条动态 code:${responseData.code}`); 100 | 101 | const redisClient = await RedisUtil.getRedis(); 102 | 103 | // 分析是否有新动态 104 | for (const dynamic of dynamicList) { 105 | const redisSetKey: string = `bBo_${uid}`; 106 | const idCount = await redisClient.sismember(redisSetKey, dynamic.id); 107 | if (dynamic.timestamp > Config.bilibili.beforeTimestamp && idCount === 0) { 108 | this.printLog(`新动态:${dynamic.content}`); 109 | await newDynamicHandler(dynamic); 110 | await redisClient.sadd(redisSetKey, dynamic.id); 111 | await this.getDriver().sleep(1000); 112 | } 113 | } 114 | redisClient.close(); 115 | } else { 116 | throw new Error(`请求Bilibili API失败 code:${responseData.code}`); 117 | } 118 | } 119 | 120 | public async takeScreenshot(dynamic: ILocalDynamic): Promise { 121 | const driver = await new Builder() 122 | .forBrowser('chrome') 123 | .setChromeOptions(new chrome.Options().headless().addArguments('window-size=1980,1080')) 124 | .build(); 125 | await driver.get(`https://t.bilibili.com/${dynamic.dynamicId}`); 126 | await driver.wait(until.elementLocated(By.className('main-content'))); 127 | await driver.sleep(2 * 1000); 128 | 129 | await driver.executeScript(` 130 | var forwAreaList = document.getElementsByClassName('forw-area'); 131 | if (forwAreaList.length > 0) { 132 | forwAreaList[0].remove(); 133 | } 134 | `); 135 | await driver.sleep(500); 136 | const imgData = await driver.findElement(By.className('detail-card')).takeScreenshot(true); 137 | const savePath = `${DownloaderUtil.getTempPath()}/screenshot_${dynamic.id}.png`; 138 | await fs.writeFileSync(savePath, imgData, 'base64'); 139 | await driver.quit(); 140 | return savePath; 141 | } 142 | 143 | protected async checkLock(): Promise { 144 | const redisClient = await RedisUtil.getRedis(); 145 | const lockCount = await redisClient.exists('dynamic_lock'); 146 | redisClient.close(); 147 | return lockCount === 1; 148 | } 149 | 150 | protected async createLock() { 151 | const redisClient = await RedisUtil.getRedis(); 152 | redisClient.set('dynamic_lock', '1'); 153 | redisClient.close(); 154 | } 155 | 156 | protected async removeLock() { 157 | const redisClient = await RedisUtil.getRedis(); 158 | redisClient.del('dynamic_lock'); 159 | redisClient.close(); 160 | } 161 | 162 | protected printLog(log: string | number) { 163 | console.log(`[${(new Date()).toLocaleString('cn')}] ${log}`); 164 | } 165 | } 166 | 167 | export interface IBilibiliDynamicResponse { 168 | code: number; 169 | msg: string; 170 | message: string; 171 | data: { 172 | has_more: number; 173 | cards: { 174 | desc: { 175 | uid: number; 176 | dynamic_id: string; 177 | timestamp: number; 178 | }, 179 | card: string; 180 | }[] 181 | } 182 | } 183 | 184 | export interface IBilibiliDynamic { 185 | item: { 186 | id?: number; 187 | rp_id?: number; 188 | title?: string; 189 | description?: string; 190 | content?: string; 191 | pictures?: { 192 | img_src: string; 193 | }[], 194 | upload_time: number; 195 | timestamp: number; 196 | }, 197 | origin?: string; 198 | } 199 | 200 | export enum DynamicTypes { 201 | Article, 202 | Text, 203 | } 204 | 205 | export interface ILocalDynamic { 206 | type: DynamicTypes; 207 | id: string; 208 | dynamicId: string; 209 | title: string; 210 | content: string; 211 | imgs: { 212 | src: string; 213 | }[]; 214 | timestamp: number; 215 | hasOrigin: boolean; 216 | } 217 | 218 | type DynamicHandler = (dynamic: ILocalDynamic) => Promise; 219 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@sindresorhus/is@^0.7.0": 6 | version "0.7.0" 7 | resolved "http://registry.npm.taobao.org/@sindresorhus/is/download/@sindresorhus/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" 8 | integrity sha1-mgb08TfuhNffBGDB/bETX/psUP0= 9 | 10 | "@types/decompress@*": 11 | version "4.2.3" 12 | resolved "http://registry.npm.taobao.org/@types/decompress/download/@types/decompress-4.2.3.tgz#98eed48af80001038aa05690b2094915f296fe65" 13 | integrity sha1-mO7UivgAAQOKoFaQsglJFfKW/mU= 14 | dependencies: 15 | "@types/node" "*" 16 | 17 | "@types/download@^6.2.3": 18 | version "6.2.3" 19 | resolved "http://registry.npm.taobao.org/@types/download/download/@types/download-6.2.3.tgz#9bb00b4dbfd3530d562287b8d64f054c76704f7a" 20 | integrity sha1-m7ALTb/TUw1WIoe41k8FTHZwT3o= 21 | dependencies: 22 | "@types/decompress" "*" 23 | "@types/got" "^8" 24 | "@types/node" "*" 25 | 26 | "@types/got@^8": 27 | version "8.3.5" 28 | resolved "http://registry.npm.taobao.org/@types/got/download/@types/got-8.3.5.tgz#d8a0e8fa7598681b332a4d27779b022b2e55fb7f" 29 | integrity sha1-2KDo+nWYaBszKk0nd5sCKy5V+38= 30 | dependencies: 31 | "@types/node" "*" 32 | 33 | "@types/node@*": 34 | version "10.12.18" 35 | resolved "http://registry.npm.taobao.org/@types/node/download/@types/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" 36 | integrity sha1-HTynZHGJFVhPzZ9jRGIbdnJmXGc= 37 | 38 | "@types/node@^10.12.17": 39 | version "10.12.17" 40 | resolved "http://registry.npm.taobao.org/@types/node/download/@types/node-10.12.17.tgz#7040565b2c93d59325a68fa69073e754a7eda93a" 41 | 42 | "@types/selenium-webdriver@^3.0.14": 43 | version "3.0.14" 44 | resolved "http://registry.npm.taobao.org/@types/selenium-webdriver/download/@types/selenium-webdriver-3.0.14.tgz#0b20a2370e6b1b8322c9c3dfcaa409e6c7c0c0a9" 45 | 46 | ansi-regex@^2.0.0: 47 | version "2.1.1" 48 | resolved "http://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 49 | 50 | ansi-styles@^2.2.1: 51 | version "2.2.1" 52 | resolved "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 53 | 54 | ansi-styles@^3.2.1: 55 | version "3.2.1" 56 | resolved "http://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 57 | dependencies: 58 | color-convert "^1.9.0" 59 | 60 | archive-type@^4.0.0: 61 | version "4.0.0" 62 | resolved "http://registry.npm.taobao.org/archive-type/download/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" 63 | integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= 64 | dependencies: 65 | file-type "^4.2.0" 66 | 67 | argparse@^1.0.7: 68 | version "1.0.10" 69 | resolved "http://registry.npm.taobao.org/argparse/download/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 70 | dependencies: 71 | sprintf-js "~1.0.2" 72 | 73 | arrify@^1.0.0: 74 | version "1.0.1" 75 | resolved "http://registry.npm.taobao.org/arrify/download/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 76 | 77 | axios@^0.18.0: 78 | version "0.18.0" 79 | resolved "http://registry.npm.taobao.org/axios/download/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" 80 | dependencies: 81 | follow-redirects "^1.3.0" 82 | is-buffer "^1.1.5" 83 | 84 | babel-code-frame@^6.22.0: 85 | version "6.26.0" 86 | resolved "http://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" 87 | dependencies: 88 | chalk "^1.1.3" 89 | esutils "^2.0.2" 90 | js-tokens "^3.0.2" 91 | 92 | balanced-match@^1.0.0: 93 | version "1.0.0" 94 | resolved "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 95 | 96 | base64-js@0.0.8: 97 | version "0.0.8" 98 | resolved "http://registry.npm.taobao.org/base64-js/download/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" 99 | integrity sha1-EQHpVE9KdrG8OybUUsqW16NeeXg= 100 | 101 | bl@^1.0.0: 102 | version "1.2.2" 103 | resolved "http://registry.npm.taobao.org/bl/download/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" 104 | integrity sha1-oWCRFxcQPAdBDO9j71Gzl8Alr5w= 105 | dependencies: 106 | readable-stream "^2.3.5" 107 | safe-buffer "^5.1.1" 108 | 109 | brace-expansion@^1.1.7: 110 | version "1.1.11" 111 | resolved "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 112 | dependencies: 113 | balanced-match "^1.0.0" 114 | concat-map "0.0.1" 115 | 116 | buffer-alloc-unsafe@^1.1.0: 117 | version "1.1.0" 118 | resolved "http://registry.npm.taobao.org/buffer-alloc-unsafe/download/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" 119 | integrity sha1-vX3CauKXLQ7aJTvgYdupkjScGfA= 120 | 121 | buffer-alloc@^1.2.0: 122 | version "1.2.0" 123 | resolved "http://registry.npm.taobao.org/buffer-alloc/download/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" 124 | integrity sha1-iQ3ZDZI6hz4I4Q5f1RpX5bfM4Ow= 125 | dependencies: 126 | buffer-alloc-unsafe "^1.1.0" 127 | buffer-fill "^1.0.0" 128 | 129 | buffer-crc32@~0.2.3: 130 | version "0.2.13" 131 | resolved "http://registry.npm.taobao.org/buffer-crc32/download/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" 132 | integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= 133 | 134 | buffer-fill@^1.0.0: 135 | version "1.0.0" 136 | resolved "http://registry.npm.taobao.org/buffer-fill/download/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" 137 | integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= 138 | 139 | buffer-from@^1.0.0, buffer-from@^1.1.0: 140 | version "1.1.1" 141 | resolved "http://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 142 | 143 | buffer@^3.0.1: 144 | version "3.6.0" 145 | resolved "http://registry.npm.taobao.org/buffer/download/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" 146 | integrity sha1-pyyTb3e5a/UvX357RnGAYoVR3vs= 147 | dependencies: 148 | base64-js "0.0.8" 149 | ieee754 "^1.1.4" 150 | isarray "^1.0.0" 151 | 152 | builtin-modules@^1.1.1: 153 | version "1.1.1" 154 | resolved "http://registry.npm.taobao.org/builtin-modules/download/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 155 | 156 | cacheable-request@^2.1.1: 157 | version "2.1.4" 158 | resolved "http://registry.npm.taobao.org/cacheable-request/download/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" 159 | integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= 160 | dependencies: 161 | clone-response "1.0.2" 162 | get-stream "3.0.0" 163 | http-cache-semantics "3.8.1" 164 | keyv "3.0.0" 165 | lowercase-keys "1.0.0" 166 | normalize-url "2.0.1" 167 | responselike "1.0.2" 168 | 169 | caw@^2.0.1: 170 | version "2.0.1" 171 | resolved "http://registry.npm.taobao.org/caw/download/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" 172 | integrity sha1-bDygcfwZRyCIPC3F2psHS/x+npU= 173 | dependencies: 174 | get-proxy "^2.0.0" 175 | isurl "^1.0.0-alpha5" 176 | tunnel-agent "^0.6.0" 177 | url-to-options "^1.0.1" 178 | 179 | chalk@^1.1.3: 180 | version "1.1.3" 181 | resolved "http://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 182 | dependencies: 183 | ansi-styles "^2.2.1" 184 | escape-string-regexp "^1.0.2" 185 | has-ansi "^2.0.0" 186 | strip-ansi "^3.0.0" 187 | supports-color "^2.0.0" 188 | 189 | chalk@^2.3.0: 190 | version "2.4.1" 191 | resolved "http://registry.npm.taobao.org/chalk/download/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" 192 | dependencies: 193 | ansi-styles "^3.2.1" 194 | escape-string-regexp "^1.0.5" 195 | supports-color "^5.3.0" 196 | 197 | clone-response@1.0.2: 198 | version "1.0.2" 199 | resolved "http://registry.npm.taobao.org/clone-response/download/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" 200 | integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= 201 | dependencies: 202 | mimic-response "^1.0.0" 203 | 204 | color-convert@^1.9.0: 205 | version "1.9.3" 206 | resolved "http://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 207 | dependencies: 208 | color-name "1.1.3" 209 | 210 | color-name@1.1.3: 211 | version "1.1.3" 212 | resolved "http://registry.npm.taobao.org/color-name/download/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 213 | 214 | commander@^2.12.1: 215 | version "2.19.0" 216 | resolved "http://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" 217 | 218 | commander@~2.8.1: 219 | version "2.8.1" 220 | resolved "http://registry.npm.taobao.org/commander/download/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" 221 | integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= 222 | dependencies: 223 | graceful-readlink ">= 1.0.0" 224 | 225 | concat-map@0.0.1: 226 | version "0.0.1" 227 | resolved "http://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 228 | 229 | config-chain@^1.1.11: 230 | version "1.1.12" 231 | resolved "http://registry.npm.taobao.org/config-chain/download/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" 232 | integrity sha1-D96NCRIA616AjK8l/mGMAvSOTvo= 233 | dependencies: 234 | ini "^1.3.4" 235 | proto-list "~1.2.1" 236 | 237 | content-disposition@^0.5.2: 238 | version "0.5.3" 239 | resolved "http://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" 240 | integrity sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70= 241 | dependencies: 242 | safe-buffer "5.1.2" 243 | 244 | core-js@~2.3.0: 245 | version "2.3.0" 246 | resolved "http://registry.npm.taobao.org/core-js/download/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65" 247 | 248 | core-util-is@~1.0.0: 249 | version "1.0.2" 250 | resolved "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 251 | 252 | debug@=3.1.0: 253 | version "3.1.0" 254 | resolved "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 255 | dependencies: 256 | ms "2.0.0" 257 | 258 | decode-uri-component@^0.2.0: 259 | version "0.2.0" 260 | resolved "http://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" 261 | integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= 262 | 263 | decompress-response@^3.3.0: 264 | version "3.3.0" 265 | resolved "http://registry.npm.taobao.org/decompress-response/download/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" 266 | integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= 267 | dependencies: 268 | mimic-response "^1.0.0" 269 | 270 | decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: 271 | version "4.1.1" 272 | resolved "http://registry.npm.taobao.org/decompress-tar/download/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" 273 | integrity sha1-cYy9P8sWIJcW5womuE57pFkuWvE= 274 | dependencies: 275 | file-type "^5.2.0" 276 | is-stream "^1.1.0" 277 | tar-stream "^1.5.2" 278 | 279 | decompress-tarbz2@^4.0.0: 280 | version "4.1.1" 281 | resolved "http://registry.npm.taobao.org/decompress-tarbz2/download/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" 282 | integrity sha1-MIKluIDqQEOBY0nzeLVsUWvho5s= 283 | dependencies: 284 | decompress-tar "^4.1.0" 285 | file-type "^6.1.0" 286 | is-stream "^1.1.0" 287 | seek-bzip "^1.0.5" 288 | unbzip2-stream "^1.0.9" 289 | 290 | decompress-targz@^4.0.0: 291 | version "4.1.1" 292 | resolved "http://registry.npm.taobao.org/decompress-targz/download/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" 293 | integrity sha1-wJvDXE0R894J8tLaU+neI+fOHu4= 294 | dependencies: 295 | decompress-tar "^4.1.1" 296 | file-type "^5.2.0" 297 | is-stream "^1.1.0" 298 | 299 | decompress-unzip@^4.0.1: 300 | version "4.0.1" 301 | resolved "http://registry.npm.taobao.org/decompress-unzip/download/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" 302 | integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= 303 | dependencies: 304 | file-type "^3.8.0" 305 | get-stream "^2.2.0" 306 | pify "^2.3.0" 307 | yauzl "^2.4.2" 308 | 309 | decompress@^4.2.0: 310 | version "4.2.0" 311 | resolved "http://registry.npm.taobao.org/decompress/download/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" 312 | integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= 313 | dependencies: 314 | decompress-tar "^4.0.0" 315 | decompress-tarbz2 "^4.0.0" 316 | decompress-targz "^4.0.0" 317 | decompress-unzip "^4.0.1" 318 | graceful-fs "^4.1.10" 319 | make-dir "^1.0.0" 320 | pify "^2.3.0" 321 | strip-dirs "^2.0.0" 322 | 323 | diff@^3.1.0, diff@^3.2.0: 324 | version "3.5.0" 325 | resolved "http://registry.npm.taobao.org/diff/download/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 326 | 327 | download@^7.1.0: 328 | version "7.1.0" 329 | resolved "http://registry.npm.taobao.org/download/download/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233" 330 | integrity sha1-kFmqnXC1A+52oTKJe+beyOVYcjM= 331 | dependencies: 332 | archive-type "^4.0.0" 333 | caw "^2.0.1" 334 | content-disposition "^0.5.2" 335 | decompress "^4.2.0" 336 | ext-name "^5.0.0" 337 | file-type "^8.1.0" 338 | filenamify "^2.0.0" 339 | get-stream "^3.0.0" 340 | got "^8.3.1" 341 | make-dir "^1.2.0" 342 | p-event "^2.1.0" 343 | pify "^3.0.0" 344 | 345 | duplexer3@^0.1.4: 346 | version "0.1.4" 347 | resolved "http://registry.npm.taobao.org/duplexer3/download/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" 348 | integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= 349 | 350 | end-of-stream@^1.0.0: 351 | version "1.4.1" 352 | resolved "http://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" 353 | integrity sha1-7SljTRm6ukY7bOa4CjchPqtx7EM= 354 | dependencies: 355 | once "^1.4.0" 356 | 357 | es6-promise@~3.0.2: 358 | version "3.0.2" 359 | resolved "http://registry.npm.taobao.org/es6-promise/download/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6" 360 | 361 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 362 | version "1.0.5" 363 | resolved "http://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 364 | 365 | esprima@^4.0.0: 366 | version "4.0.1" 367 | resolved "http://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 368 | 369 | esutils@^2.0.2: 370 | version "2.0.2" 371 | resolved "http://registry.npm.taobao.org/esutils/download/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 372 | 373 | ext-list@^2.0.0: 374 | version "2.2.2" 375 | resolved "http://registry.npm.taobao.org/ext-list/download/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" 376 | integrity sha1-C5jmTtgvWs8PKTG6v2khLvUt3Tc= 377 | dependencies: 378 | mime-db "^1.28.0" 379 | 380 | ext-name@^5.0.0: 381 | version "5.0.0" 382 | resolved "http://registry.npm.taobao.org/ext-name/download/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" 383 | integrity sha1-cHgZgdGD7hXROZPIgiBFxQbI8KY= 384 | dependencies: 385 | ext-list "^2.0.0" 386 | sort-keys-length "^1.0.0" 387 | 388 | fd-slicer@~1.1.0: 389 | version "1.1.0" 390 | resolved "http://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" 391 | integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= 392 | dependencies: 393 | pend "~1.2.0" 394 | 395 | file-type@^3.8.0: 396 | version "3.9.0" 397 | resolved "http://registry.npm.taobao.org/file-type/download/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" 398 | integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= 399 | 400 | file-type@^4.2.0: 401 | version "4.4.0" 402 | resolved "http://registry.npm.taobao.org/file-type/download/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" 403 | integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= 404 | 405 | file-type@^5.2.0: 406 | version "5.2.0" 407 | resolved "http://registry.npm.taobao.org/file-type/download/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" 408 | integrity sha1-LdvqfHP/42No365J3DOMBYwritY= 409 | 410 | file-type@^6.1.0: 411 | version "6.2.0" 412 | resolved "http://registry.npm.taobao.org/file-type/download/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" 413 | integrity sha1-5QzXXTVv/tTjBtxPW89Sp5kDqRk= 414 | 415 | file-type@^8.1.0: 416 | version "8.1.0" 417 | resolved "http://registry.npm.taobao.org/file-type/download/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c" 418 | integrity sha1-JE87fvZBu+DMoZbHJ25LMyOZ9ow= 419 | 420 | filename-reserved-regex@^2.0.0: 421 | version "2.0.0" 422 | resolved "http://registry.npm.taobao.org/filename-reserved-regex/download/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" 423 | integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= 424 | 425 | filenamify@^2.0.0: 426 | version "2.1.0" 427 | resolved "http://registry.npm.taobao.org/filenamify/download/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" 428 | integrity sha1-iPr0lfsbR6v9YSMAACoWIoxnfuk= 429 | dependencies: 430 | filename-reserved-regex "^2.0.0" 431 | strip-outer "^1.0.0" 432 | trim-repeated "^1.0.0" 433 | 434 | follow-redirects@^1.3.0: 435 | version "1.5.10" 436 | resolved "http://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" 437 | dependencies: 438 | debug "=3.1.0" 439 | 440 | from2@^2.1.1: 441 | version "2.3.0" 442 | resolved "http://registry.npm.taobao.org/from2/download/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" 443 | integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= 444 | dependencies: 445 | inherits "^2.0.1" 446 | readable-stream "^2.0.0" 447 | 448 | fs-constants@^1.0.0: 449 | version "1.0.0" 450 | resolved "http://registry.npm.taobao.org/fs-constants/download/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" 451 | integrity sha1-a+Dem+mYzhavivwkSXue6bfM2a0= 452 | 453 | fs.realpath@^1.0.0: 454 | version "1.0.0" 455 | resolved "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 456 | 457 | get-proxy@^2.0.0: 458 | version "2.1.0" 459 | resolved "http://registry.npm.taobao.org/get-proxy/download/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" 460 | integrity sha1-NJ8rTZHUTE1NTpy6KtkBQ/rF75M= 461 | dependencies: 462 | npm-conf "^1.1.0" 463 | 464 | get-stream@3.0.0, get-stream@^3.0.0: 465 | version "3.0.0" 466 | resolved "http://registry.npm.taobao.org/get-stream/download/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 467 | integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= 468 | 469 | get-stream@^2.2.0: 470 | version "2.3.1" 471 | resolved "http://registry.npm.taobao.org/get-stream/download/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" 472 | integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= 473 | dependencies: 474 | object-assign "^4.0.1" 475 | pinkie-promise "^2.0.0" 476 | 477 | glob@^7.0.5, glob@^7.1.1: 478 | version "7.1.3" 479 | resolved "http://registry.npm.taobao.org/glob/download/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" 480 | dependencies: 481 | fs.realpath "^1.0.0" 482 | inflight "^1.0.4" 483 | inherits "2" 484 | minimatch "^3.0.4" 485 | once "^1.3.0" 486 | path-is-absolute "^1.0.0" 487 | 488 | got@^8.3.1: 489 | version "8.3.2" 490 | resolved "http://registry.npm.taobao.org/got/download/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" 491 | integrity sha1-HSP2Q5Dpf3dsrFLluTbl9RTS6Tc= 492 | dependencies: 493 | "@sindresorhus/is" "^0.7.0" 494 | cacheable-request "^2.1.1" 495 | decompress-response "^3.3.0" 496 | duplexer3 "^0.1.4" 497 | get-stream "^3.0.0" 498 | into-stream "^3.1.0" 499 | is-retry-allowed "^1.1.0" 500 | isurl "^1.0.0-alpha5" 501 | lowercase-keys "^1.0.0" 502 | mimic-response "^1.0.0" 503 | p-cancelable "^0.4.0" 504 | p-timeout "^2.0.1" 505 | pify "^3.0.0" 506 | safe-buffer "^5.1.1" 507 | timed-out "^4.0.1" 508 | url-parse-lax "^3.0.0" 509 | url-to-options "^1.0.1" 510 | 511 | graceful-fs@^4.1.10: 512 | version "4.1.15" 513 | resolved "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" 514 | integrity sha1-/7cD4QZuig7qpMi4C6klPu77+wA= 515 | 516 | "graceful-readlink@>= 1.0.0": 517 | version "1.0.1" 518 | resolved "http://registry.npm.taobao.org/graceful-readlink/download/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 519 | integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= 520 | 521 | has-ansi@^2.0.0: 522 | version "2.0.0" 523 | resolved "http://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 524 | dependencies: 525 | ansi-regex "^2.0.0" 526 | 527 | has-flag@^3.0.0: 528 | version "3.0.0" 529 | resolved "http://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 530 | 531 | has-symbol-support-x@^1.4.1: 532 | version "1.4.2" 533 | resolved "http://registry.npm.taobao.org/has-symbol-support-x/download/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" 534 | integrity sha1-FAn5i8ACR9pF2mfO4KNvKC/yZFU= 535 | 536 | has-to-string-tag-x@^1.2.0: 537 | version "1.4.1" 538 | resolved "http://registry.npm.taobao.org/has-to-string-tag-x/download/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" 539 | integrity sha1-oEWrOD17SyASoAFIqwql8pAETU0= 540 | dependencies: 541 | has-symbol-support-x "^1.4.1" 542 | 543 | http-cache-semantics@3.8.1: 544 | version "3.8.1" 545 | resolved "http://registry.npm.taobao.org/http-cache-semantics/download/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" 546 | integrity sha1-ObDhat2bYFvwqe89nar0hDtMrNI= 547 | 548 | ieee754@^1.1.4: 549 | version "1.1.12" 550 | resolved "http://registry.npm.taobao.org/ieee754/download/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" 551 | integrity sha1-UL8k5bnIu5ivSWTJQc2wkY2ntgs= 552 | 553 | immediate@~3.0.5: 554 | version "3.0.6" 555 | resolved "http://registry.npm.taobao.org/immediate/download/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" 556 | 557 | inflight@^1.0.4: 558 | version "1.0.6" 559 | resolved "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 560 | dependencies: 561 | once "^1.3.0" 562 | wrappy "1" 563 | 564 | inherits@2, inherits@^2.0.1, inherits@~2.0.1, inherits@~2.0.3: 565 | version "2.0.3" 566 | resolved "http://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 567 | 568 | ini@^1.3.4: 569 | version "1.3.5" 570 | resolved "http://registry.npm.taobao.org/ini/download/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" 571 | integrity sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc= 572 | 573 | into-stream@^3.1.0: 574 | version "3.1.0" 575 | resolved "http://registry.npm.taobao.org/into-stream/download/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" 576 | integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= 577 | dependencies: 578 | from2 "^2.1.1" 579 | p-is-promise "^1.1.0" 580 | 581 | is-buffer@^1.1.5: 582 | version "1.1.6" 583 | resolved "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 584 | 585 | is-natural-number@^4.0.1: 586 | version "4.0.1" 587 | resolved "http://registry.npm.taobao.org/is-natural-number/download/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" 588 | integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= 589 | 590 | is-object@^1.0.1: 591 | version "1.0.1" 592 | resolved "http://registry.npm.taobao.org/is-object/download/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" 593 | integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= 594 | 595 | is-plain-obj@^1.0.0: 596 | version "1.1.0" 597 | resolved "http://registry.npm.taobao.org/is-plain-obj/download/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" 598 | integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= 599 | 600 | is-retry-allowed@^1.1.0: 601 | version "1.1.0" 602 | resolved "http://registry.npm.taobao.org/is-retry-allowed/download/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" 603 | integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= 604 | 605 | is-stream@^1.1.0: 606 | version "1.1.0" 607 | resolved "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 608 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 609 | 610 | isarray@^1.0.0, isarray@~1.0.0: 611 | version "1.0.0" 612 | resolved "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 613 | 614 | isurl@^1.0.0-alpha5: 615 | version "1.0.0" 616 | resolved "http://registry.npm.taobao.org/isurl/download/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" 617 | integrity sha1-sn9PSfPNqj6kSgpbfzRi5u3DnWc= 618 | dependencies: 619 | has-to-string-tag-x "^1.2.0" 620 | is-object "^1.0.1" 621 | 622 | js-tokens@^3.0.2: 623 | version "3.0.2" 624 | resolved "http://registry.npm.taobao.org/js-tokens/download/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 625 | 626 | js-yaml@^3.7.0: 627 | version "3.12.0" 628 | resolved "http://registry.npm.taobao.org/js-yaml/download/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" 629 | dependencies: 630 | argparse "^1.0.7" 631 | esprima "^4.0.0" 632 | 633 | json-buffer@3.0.0: 634 | version "3.0.0" 635 | resolved "http://registry.npm.taobao.org/json-buffer/download/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" 636 | integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= 637 | 638 | jszip@^3.1.3: 639 | version "3.1.5" 640 | resolved "http://registry.npm.taobao.org/jszip/download/jszip-3.1.5.tgz#e3c2a6c6d706ac6e603314036d43cd40beefdf37" 641 | dependencies: 642 | core-js "~2.3.0" 643 | es6-promise "~3.0.2" 644 | lie "~3.1.0" 645 | pako "~1.0.2" 646 | readable-stream "~2.0.6" 647 | 648 | keyv@3.0.0: 649 | version "3.0.0" 650 | resolved "http://registry.npm.taobao.org/keyv/download/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" 651 | integrity sha1-RJI7o55osSp87H32wyaMAx8u83M= 652 | dependencies: 653 | json-buffer "3.0.0" 654 | 655 | lie@~3.1.0: 656 | version "3.1.1" 657 | resolved "http://registry.npm.taobao.org/lie/download/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" 658 | dependencies: 659 | immediate "~3.0.5" 660 | 661 | lowercase-keys@1.0.0: 662 | version "1.0.0" 663 | resolved "http://registry.npm.taobao.org/lowercase-keys/download/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" 664 | integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= 665 | 666 | lowercase-keys@^1.0.0: 667 | version "1.0.1" 668 | resolved "http://registry.npm.taobao.org/lowercase-keys/download/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" 669 | integrity sha1-b54wtHCE2XGnyCD/FabFFnt0wm8= 670 | 671 | make-dir@^1.0.0, make-dir@^1.2.0: 672 | version "1.3.0" 673 | resolved "http://registry.npm.taobao.org/make-dir/download/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" 674 | integrity sha1-ecEDO4BRW9bSTsmTPoYMp17ifww= 675 | dependencies: 676 | pify "^3.0.0" 677 | 678 | make-error@^1.1.1: 679 | version "1.3.5" 680 | resolved "http://registry.npm.taobao.org/make-error/download/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" 681 | 682 | mime-db@^1.28.0: 683 | version "1.37.0" 684 | resolved "http://registry.npm.taobao.org/mime-db/download/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" 685 | integrity sha1-C2oM5v2+lXbiXx8tL96IMNwK0Ng= 686 | 687 | mimic-response@^1.0.0: 688 | version "1.0.1" 689 | resolved "http://registry.npm.taobao.org/mimic-response/download/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 690 | integrity sha1-SSNTiHju9CBjy4o+OweYeBSHqxs= 691 | 692 | minimatch@^3.0.4: 693 | version "3.0.4" 694 | resolved "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 695 | dependencies: 696 | brace-expansion "^1.1.7" 697 | 698 | minimist@0.0.8: 699 | version "0.0.8" 700 | resolved "http://registry.npm.taobao.org/minimist/download/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 701 | 702 | minimist@^1.2.0: 703 | version "1.2.0" 704 | resolved "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 705 | 706 | mkdirp@^0.5.1: 707 | version "0.5.1" 708 | resolved "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 709 | dependencies: 710 | minimist "0.0.8" 711 | 712 | ms@2.0.0: 713 | version "2.0.0" 714 | resolved "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 715 | 716 | normalize-url@2.0.1: 717 | version "2.0.1" 718 | resolved "http://registry.npm.taobao.org/normalize-url/download/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" 719 | integrity sha1-g1qdoVUfom9w6SMpBpojqmV01+Y= 720 | dependencies: 721 | prepend-http "^2.0.0" 722 | query-string "^5.0.1" 723 | sort-keys "^2.0.0" 724 | 725 | npm-conf@^1.1.0: 726 | version "1.1.3" 727 | resolved "http://registry.npm.taobao.org/npm-conf/download/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" 728 | integrity sha1-JWzEe9DiGMJZxOlVC/QTvCGSr/k= 729 | dependencies: 730 | config-chain "^1.1.11" 731 | pify "^3.0.0" 732 | 733 | object-assign@^4.0.1, object-assign@^4.1.0: 734 | version "4.1.1" 735 | resolved "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 736 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 737 | 738 | once@^1.3.0, once@^1.4.0: 739 | version "1.4.0" 740 | resolved "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 741 | dependencies: 742 | wrappy "1" 743 | 744 | os-tmpdir@~1.0.1: 745 | version "1.0.2" 746 | resolved "http://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 747 | 748 | p-cancelable@^0.4.0: 749 | version "0.4.1" 750 | resolved "http://registry.npm.taobao.org/p-cancelable/download/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" 751 | integrity sha1-NfNj1n1SCByNlYXje8zrfgu8sqA= 752 | 753 | p-event@^2.1.0: 754 | version "2.1.0" 755 | resolved "http://registry.npm.taobao.org/p-event/download/p-event-2.1.0.tgz#74de477a4e6b3aa8267240c7099e78ac52cb4db4" 756 | integrity sha1-dN5Hek5rOqgmckDHCZ54rFLLTbQ= 757 | dependencies: 758 | p-timeout "^2.0.1" 759 | 760 | p-finally@^1.0.0: 761 | version "1.0.0" 762 | resolved "http://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 763 | integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= 764 | 765 | p-is-promise@^1.1.0: 766 | version "1.1.0" 767 | resolved "http://registry.npm.taobao.org/p-is-promise/download/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" 768 | integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= 769 | 770 | p-timeout@^2.0.1: 771 | version "2.0.1" 772 | resolved "http://registry.npm.taobao.org/p-timeout/download/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" 773 | integrity sha1-2N0ZeVldLcATnh/ka4tkbLPN8Dg= 774 | dependencies: 775 | p-finally "^1.0.0" 776 | 777 | pako@~1.0.2: 778 | version "1.0.7" 779 | resolved "http://registry.npm.taobao.org/pako/download/pako-1.0.7.tgz#2473439021b57f1516c82f58be7275ad8ef1bb27" 780 | 781 | path-is-absolute@^1.0.0: 782 | version "1.0.1" 783 | resolved "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 784 | 785 | path-parse@^1.0.6: 786 | version "1.0.6" 787 | resolved "http://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 788 | 789 | pend@~1.2.0: 790 | version "1.2.0" 791 | resolved "http://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" 792 | integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= 793 | 794 | pify@^2.3.0: 795 | version "2.3.0" 796 | resolved "http://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 797 | integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= 798 | 799 | pify@^3.0.0: 800 | version "3.0.0" 801 | resolved "http://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 802 | integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= 803 | 804 | pinkie-promise@^2.0.0: 805 | version "2.0.1" 806 | resolved "http://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 807 | integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= 808 | dependencies: 809 | pinkie "^2.0.0" 810 | 811 | pinkie@^2.0.0: 812 | version "2.0.4" 813 | resolved "http://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 814 | integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= 815 | 816 | prepend-http@^2.0.0: 817 | version "2.0.0" 818 | resolved "http://registry.npm.taobao.org/prepend-http/download/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" 819 | integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= 820 | 821 | process-nextick-args@~1.0.6: 822 | version "1.0.7" 823 | resolved "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" 824 | 825 | process-nextick-args@~2.0.0: 826 | version "2.0.0" 827 | resolved "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" 828 | integrity sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o= 829 | 830 | proto-list@~1.2.1: 831 | version "1.2.4" 832 | resolved "http://registry.npm.taobao.org/proto-list/download/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" 833 | integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= 834 | 835 | query-string@^5.0.1: 836 | version "5.1.1" 837 | resolved "http://registry.npm.taobao.org/query-string/download/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" 838 | integrity sha1-p4wBK3HBfgXy4/ojGd0zBoLvs8s= 839 | dependencies: 840 | decode-uri-component "^0.2.0" 841 | object-assign "^4.1.0" 842 | strict-uri-encode "^1.0.0" 843 | 844 | readable-stream@^2.0.0, readable-stream@^2.3.0, readable-stream@^2.3.5: 845 | version "2.3.6" 846 | resolved "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" 847 | integrity sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8= 848 | dependencies: 849 | core-util-is "~1.0.0" 850 | inherits "~2.0.3" 851 | isarray "~1.0.0" 852 | process-nextick-args "~2.0.0" 853 | safe-buffer "~5.1.1" 854 | string_decoder "~1.1.1" 855 | util-deprecate "~1.0.1" 856 | 857 | readable-stream@~2.0.6: 858 | version "2.0.6" 859 | resolved "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" 860 | dependencies: 861 | core-util-is "~1.0.0" 862 | inherits "~2.0.1" 863 | isarray "~1.0.0" 864 | process-nextick-args "~1.0.6" 865 | string_decoder "~0.10.x" 866 | util-deprecate "~1.0.1" 867 | 868 | resolve@^1.3.2: 869 | version "1.9.0" 870 | resolved "http://registry.npm.taobao.org/resolve/download/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" 871 | dependencies: 872 | path-parse "^1.0.6" 873 | 874 | responselike@1.0.2: 875 | version "1.0.2" 876 | resolved "http://registry.npm.taobao.org/responselike/download/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" 877 | integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= 878 | dependencies: 879 | lowercase-keys "^1.0.0" 880 | 881 | rimraf@^2.5.4: 882 | version "2.6.2" 883 | resolved "http://registry.npm.taobao.org/rimraf/download/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" 884 | dependencies: 885 | glob "^7.0.5" 886 | 887 | safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 888 | version "5.1.2" 889 | resolved "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 890 | integrity sha1-mR7GnSluAxN0fVm9/St0XDX4go0= 891 | 892 | sax@>=0.6.0: 893 | version "1.2.4" 894 | resolved "http://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" 895 | 896 | seek-bzip@^1.0.5: 897 | version "1.0.5" 898 | resolved "http://registry.npm.taobao.org/seek-bzip/download/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" 899 | integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= 900 | dependencies: 901 | commander "~2.8.1" 902 | 903 | selenium-webdriver@^4.0.0-alpha.1: 904 | version "4.0.0-alpha.1" 905 | resolved "http://registry.npm.taobao.org/selenium-webdriver/download/selenium-webdriver-4.0.0-alpha.1.tgz#cc93415e21d2dc1dfd85dfc5f6b55f3ac53933b1" 906 | dependencies: 907 | jszip "^3.1.3" 908 | rimraf "^2.5.4" 909 | tmp "0.0.30" 910 | xml2js "^0.4.17" 911 | 912 | semver@^5.3.0: 913 | version "5.6.0" 914 | resolved "http://registry.npm.taobao.org/semver/download/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" 915 | 916 | sort-keys-length@^1.0.0: 917 | version "1.0.1" 918 | resolved "http://registry.npm.taobao.org/sort-keys-length/download/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" 919 | integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= 920 | dependencies: 921 | sort-keys "^1.0.0" 922 | 923 | sort-keys@^1.0.0: 924 | version "1.1.2" 925 | resolved "http://registry.npm.taobao.org/sort-keys/download/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" 926 | integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= 927 | dependencies: 928 | is-plain-obj "^1.0.0" 929 | 930 | sort-keys@^2.0.0: 931 | version "2.0.0" 932 | resolved "http://registry.npm.taobao.org/sort-keys/download/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" 933 | integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= 934 | dependencies: 935 | is-plain-obj "^1.0.0" 936 | 937 | source-map-support@^0.5.6: 938 | version "0.5.9" 939 | resolved "http://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" 940 | dependencies: 941 | buffer-from "^1.0.0" 942 | source-map "^0.6.0" 943 | 944 | source-map@^0.6.0: 945 | version "0.6.1" 946 | resolved "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 947 | 948 | sprintf-js@~1.0.2: 949 | version "1.0.3" 950 | resolved "http://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 951 | 952 | strict-uri-encode@^1.0.0: 953 | version "1.1.0" 954 | resolved "http://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" 955 | integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= 956 | 957 | string_decoder@~0.10.x: 958 | version "0.10.31" 959 | resolved "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 960 | 961 | string_decoder@~1.1.1: 962 | version "1.1.1" 963 | resolved "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 964 | integrity sha1-nPFhG6YmhdcDCunkujQUnDrwP8g= 965 | dependencies: 966 | safe-buffer "~5.1.0" 967 | 968 | strip-ansi@^3.0.0: 969 | version "3.0.1" 970 | resolved "http://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 971 | dependencies: 972 | ansi-regex "^2.0.0" 973 | 974 | strip-dirs@^2.0.0: 975 | version "2.1.0" 976 | resolved "http://registry.npm.taobao.org/strip-dirs/download/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" 977 | integrity sha1-SYdzYmT8NEzyD2w0rKnRPR1O1sU= 978 | dependencies: 979 | is-natural-number "^4.0.1" 980 | 981 | strip-outer@^1.0.0: 982 | version "1.0.1" 983 | resolved "http://registry.npm.taobao.org/strip-outer/download/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" 984 | integrity sha1-sv0qv2YEudHmATBXGV34Nrip1jE= 985 | dependencies: 986 | escape-string-regexp "^1.0.2" 987 | 988 | supports-color@^2.0.0: 989 | version "2.0.0" 990 | resolved "http://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 991 | 992 | supports-color@^5.3.0: 993 | version "5.5.0" 994 | resolved "http://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 995 | dependencies: 996 | has-flag "^3.0.0" 997 | 998 | tar-stream@^1.5.2: 999 | version "1.6.2" 1000 | resolved "http://registry.npm.taobao.org/tar-stream/download/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" 1001 | integrity sha1-jqVdqzeXIlPZqa+Q/c1VmuQ1xVU= 1002 | dependencies: 1003 | bl "^1.0.0" 1004 | buffer-alloc "^1.2.0" 1005 | end-of-stream "^1.0.0" 1006 | fs-constants "^1.0.0" 1007 | readable-stream "^2.3.0" 1008 | to-buffer "^1.1.1" 1009 | xtend "^4.0.0" 1010 | 1011 | tedis@^0.1.4: 1012 | version "0.1.4" 1013 | resolved "http://registry.npm.taobao.org/tedis/download/tedis-0.1.4.tgz#0924e8c18c5a481fb68b91098f1371f0b123a5b7" 1014 | 1015 | through@^2.3.6: 1016 | version "2.3.8" 1017 | resolved "http://registry.npm.taobao.org/through/download/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1018 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 1019 | 1020 | timed-out@^4.0.1: 1021 | version "4.0.1" 1022 | resolved "http://registry.npm.taobao.org/timed-out/download/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" 1023 | integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= 1024 | 1025 | tmp@0.0.30: 1026 | version "0.0.30" 1027 | resolved "http://registry.npm.taobao.org/tmp/download/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" 1028 | dependencies: 1029 | os-tmpdir "~1.0.1" 1030 | 1031 | to-buffer@^1.1.1: 1032 | version "1.1.1" 1033 | resolved "http://registry.npm.taobao.org/to-buffer/download/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" 1034 | integrity sha1-STvUj2LXxD/N7TE6A9ytsuEhOoA= 1035 | 1036 | trim-repeated@^1.0.0: 1037 | version "1.0.0" 1038 | resolved "http://registry.npm.taobao.org/trim-repeated/download/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" 1039 | integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE= 1040 | dependencies: 1041 | escape-string-regexp "^1.0.2" 1042 | 1043 | ts-node@^7.0.1: 1044 | version "7.0.1" 1045 | resolved "http://registry.npm.taobao.org/ts-node/download/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" 1046 | dependencies: 1047 | arrify "^1.0.0" 1048 | buffer-from "^1.1.0" 1049 | diff "^3.1.0" 1050 | make-error "^1.1.1" 1051 | minimist "^1.2.0" 1052 | mkdirp "^0.5.1" 1053 | source-map-support "^0.5.6" 1054 | yn "^2.0.0" 1055 | 1056 | tslib@^1.8.0, tslib@^1.8.1: 1057 | version "1.9.3" 1058 | resolved "http://registry.npm.taobao.org/tslib/download/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" 1059 | 1060 | tslint@^5.12.0: 1061 | version "5.12.0" 1062 | resolved "http://registry.npm.taobao.org/tslint/download/tslint-5.12.0.tgz#47f2dba291ed3d580752d109866fb640768fca36" 1063 | dependencies: 1064 | babel-code-frame "^6.22.0" 1065 | builtin-modules "^1.1.1" 1066 | chalk "^2.3.0" 1067 | commander "^2.12.1" 1068 | diff "^3.2.0" 1069 | glob "^7.1.1" 1070 | js-yaml "^3.7.0" 1071 | minimatch "^3.0.4" 1072 | resolve "^1.3.2" 1073 | semver "^5.3.0" 1074 | tslib "^1.8.0" 1075 | tsutils "^2.27.2" 1076 | 1077 | tsutils@^2.27.2: 1078 | version "2.29.0" 1079 | resolved "http://registry.npm.taobao.org/tsutils/download/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" 1080 | dependencies: 1081 | tslib "^1.8.1" 1082 | 1083 | tunnel-agent@^0.6.0: 1084 | version "0.6.0" 1085 | resolved "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 1086 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 1087 | dependencies: 1088 | safe-buffer "^5.0.1" 1089 | 1090 | typescript@^3.2.2: 1091 | version "3.2.2" 1092 | resolved "http://registry.npm.taobao.org/typescript/download/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5" 1093 | 1094 | unbzip2-stream@^1.0.9: 1095 | version "1.3.1" 1096 | resolved "http://registry.npm.taobao.org/unbzip2-stream/download/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" 1097 | integrity sha1-eFTaUWIqfmNiQiEZY1eAO1UpZqE= 1098 | dependencies: 1099 | buffer "^3.0.1" 1100 | through "^2.3.6" 1101 | 1102 | url-parse-lax@^3.0.0: 1103 | version "3.0.0" 1104 | resolved "http://registry.npm.taobao.org/url-parse-lax/download/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" 1105 | integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= 1106 | dependencies: 1107 | prepend-http "^2.0.0" 1108 | 1109 | url-to-options@^1.0.1: 1110 | version "1.0.1" 1111 | resolved "http://registry.npm.taobao.org/url-to-options/download/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" 1112 | integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= 1113 | 1114 | util-deprecate@~1.0.1: 1115 | version "1.0.2" 1116 | resolved "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1117 | 1118 | uuid@^3.3.2: 1119 | version "3.3.2" 1120 | resolved "http://registry.npm.taobao.org/uuid/download/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" 1121 | 1122 | wrappy@1: 1123 | version "1.0.2" 1124 | resolved "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1125 | 1126 | xml2js@^0.4.17: 1127 | version "0.4.19" 1128 | resolved "http://registry.npm.taobao.org/xml2js/download/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" 1129 | dependencies: 1130 | sax ">=0.6.0" 1131 | xmlbuilder "~9.0.1" 1132 | 1133 | xmlbuilder@~9.0.1: 1134 | version "9.0.7" 1135 | resolved "http://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" 1136 | 1137 | xtend@^4.0.0: 1138 | version "4.0.1" 1139 | resolved "http://registry.npm.taobao.org/xtend/download/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 1140 | integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= 1141 | 1142 | yauzl@^2.4.2: 1143 | version "2.10.0" 1144 | resolved "http://registry.npm.taobao.org/yauzl/download/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" 1145 | integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= 1146 | dependencies: 1147 | buffer-crc32 "~0.2.3" 1148 | fd-slicer "~1.1.0" 1149 | 1150 | yn@^2.0.0: 1151 | version "2.0.0" 1152 | resolved "http://registry.npm.taobao.org/yn/download/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" 1153 | --------------------------------------------------------------------------------