From 6a659be1e4c41af5c7aa4879bc31fa7ff16f9761 Mon Sep 17 00:00:00 2001 From: Clayton Hadaway Date: Fri, 26 Jul 2019 13:29:49 -0500 Subject: [PATCH 1/2] update readme, add dotenv, more config vars --- .gitignore | 1 + README.md | 41 ++- croupier.ts | 32 +- index.ts | 9 +- keybase-bot.js | 3 +- package-lock.json | 873 +++++++++++++++++++++++++++++++++++++++++++--- package.json | 9 +- snipe.ts | 16 +- tslint.json | 6 +- 9 files changed, 897 insertions(+), 93 deletions(-) diff --git a/.gitignore b/.gitignore index 7d33be6b..8063ae8d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ index.js scratchpad.js deploy/docker-compose.yaml node_modules/ +.env \ No newline at end of file diff --git a/README.md b/README.md index 9e647417..2a11da8b 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,43 @@ ## Getting started -1. `npm install` -2. `npm install -g ts-node --save` -3. Create two paperkeys within Keybase for your bot (click the Devices tab within the Keybase GUI). +1. Create two bot accounts (one to use `/flip` and the other to read the result) + - Note: the bot with `DEV_CROUPIER_USERNAME1` is the Main bot +2. Create two paperkeys within Keybase for your bots (click the Devices tab within the Keybase GUI). +3. `npm install` 4. Set these envvars: - * `CROUPIER_PAPERKEY_1` - * `CROUPIER_PAPERKEY_2` - * `MONGODB_USERNAME` - * `MONGODB_PASSWORD` - * `MONGODB_HOST` + - `DEV_CROUPIER_USERNAME1` + - `DEV_CROUPIER_USERNAME2` + - `DEV_CROUPIER_PAPERKEY1` + - `DEV_CROUPIER_PAPERKEY2` + - `MONGODB_USERNAME` + - `MONGODB_PASSWORD` + - `MONGODB_HOST` + - `IS_CLUSTER` (true or false) -5. Run the bot with `ts-node index.ts` +5. Verify you have an instance of Mongo running somewhere +6. `npm run start` + +### Requirements + +- MongoDB (if you're running the bot locally) +- Unix/Linux Server - Croupier relies on non-Windows commands (namely `which`) +- `expect` command (`apt-get install expect`) +- Some Lumens to fund the bot accounts (Main bot needs at least 1XLM to function) ## Contributing -Contributions are welcome. Any new features should be accompanied by a test. To run the test suite, `yarn test --detectOpenHandles --verbose --forceExit` +Contributions are welcome. Any new features should be accompanied by a test. To run the test suite, `yarn test --detectOpenHandles --verbose --forceExit` Note: run `killall keybase` and `keybase ctl stop` before running test suite ## Releases -### All releases should more or less be stable. -* [Release v1](https://blog.codefor.cash/2019/07/01/finding-alice-and-bob-in-wonderland-a-writeup-of-croupier-the-keybase-bot/) +All releases should more or less be stable. + +- [Release v1](https://blog.codefor.cash/2019/07/01/finding-alice-and-bob-in-wonderland-a-writeup-of-croupier-the-keybase-bot/) + +The next release is a work in progress and is expected some time in July. -The next release is a work in progress and is expected some time in July. Join [@codeforcash](https://keybase.io/team/codeforcash) or [@mkbot#test3](https://keybase.io/team/mkbot#test3) on Keybase if you'd like to follow along. +Join [@codeforcash](https://keybase.io/team/codeforcash) or [@mkbot#test3](https://keybase.io/team/mkbot#test3) on Keybase if you'd like to follow along. diff --git a/croupier.ts b/croupier.ts index 82eea458..d19bbe83 100644 --- a/croupier.ts +++ b/croupier.ts @@ -4,9 +4,11 @@ import * as moment from "moment"; import * as mongodb from "mongodb"; import * as os from "os"; import * as throttledQueue from "throttled-queue"; +// @ts-ignore import * as Bot from "./keybase-bot"; import Snipe from "./snipe"; +// @ts-ignore import { ChatChannel, MessageSummary, Transaction } from "./keybase-bot"; import { IBetData, IBetList, IParticipant, IPopularityContest, IPositionSize, IPowerup, IPowerupAward, IReactionContent } from "./types"; @@ -14,7 +16,8 @@ class Croupier { public activeSnipes: object; public bot1: Bot; public bot2: Bot; - public botUsername: string; + public botUsername1: string; + public botUsername2: string; public paperKey1: string; public paperKey2: string; @@ -22,7 +25,8 @@ class Croupier { private mongoDbClient: mongodb.MongoClient; public constructor( - botUsername: string, + botUsername1: string, + botUsername2: string, paperKey1: string, paperKey2: string, mongoDbUsername: string, @@ -45,13 +49,21 @@ class Croupier { } else { uri = "mongodb://"; } - uri += `${mongoDbUsername}:${mongoDbPassword}@${mongoDbHost}`; + if (mongoDbUsername === "" && mongoDbPassword === "") { + uri += `${mongoDbHost}`; + } else { + uri += `${mongoDbUsername}:${mongoDbPassword}@${mongoDbHost}` + } uri += `/${mongoDbDatabase}?retryWrites=true&w=majority`; + this.mongoDbUri = uri; - this.botUsername = botUsername; + this.botUsername1 = botUsername1; + this.botUsername2 = botUsername2; + // @ts-ignore this.bot1 = new Bot(os.homedir()); + // @ts-ignore this.bot2 = new Bot(os.homedir()); this.paperKey1 = paperKey1; this.paperKey2 = paperKey2; @@ -59,8 +71,8 @@ class Croupier { public async init(): Promise { this.activeSnipes = {}; - await this.bot1.init(this.botUsername, this.paperKey1, null); - await this.bot2.init(this.botUsername, this.paperKey2, null); + await this.bot1.init(this.botUsername1, this.paperKey1, null); + await this.bot2.init(this.botUsername2, this.paperKey2, null); console.log("both paper keys initialized"); } @@ -237,7 +249,7 @@ class Croupier { self.bot1.chat.send( { - name: `zackburt,${self.botUsername}`, + name: `zackburt,${self.botUsername1}`, public: false, topicType: "chat", }, @@ -348,7 +360,7 @@ class Croupier { const snipe: Snipe = this.activeSnipes[JSON.stringify(channel)]; // If the transaction was not sent to us, then ignore - if (txn.toUsername !== this.botUsername) { + if (txn.toUsername !== this.botUsername1) { return; } @@ -444,7 +456,7 @@ class Croupier { this.bot1.chat.send(channel, { body: helpMsg, - }); + }, {}); } private routeIncomingMessage(msg: MessageSummary): void { @@ -467,7 +479,7 @@ class Croupier { if (typeof snipe === "undefined") { return; } - if (msg.content.type === "flip" && msg.sender.username === this.botUsername) { + if (msg.content.type === "flip" && msg.sender.username === this.botUsername1) { snipe.monitorFlipResults(msg); return; } diff --git a/index.ts b/index.ts index d0a3b42b..27fbb265 100644 --- a/index.ts +++ b/index.ts @@ -1,17 +1,20 @@ +import * as dotenv from "dotenv"; +dotenv.config(); + import Croupier from "./croupier"; -import * as Bot from "./keybase-bot"; let croupier: Croupier; async function main(): Promise { croupier = new Croupier( - "devcroupier", + process.env.DEV_CROUPIER_USERNAME1, + process.env.DEV_CROUPIER_USERNAME2, process.env.DEV_CROUPIER_PAPERKEY1, process.env.DEV_CROUPIER_PAPERKEY2, process.env.MONGODB_USERNAME, process.env.MONGODB_PASSWORD, process.env.MONGODB_HOST, - true, + JSON.parse(process.env.IS_CLUSTER), ); await croupier.run(true); } diff --git a/keybase-bot.js b/keybase-bot.js index f025c0fc..aee69b94 100644 --- a/keybase-bot.js +++ b/keybase-bot.js @@ -1,5 +1,4 @@ - function _interopDefault(ex) { return ex && typeof ex === 'object' && 'default' in ex ? ex.default : ex; } @@ -18,7 +17,7 @@ const fs = require('fs'); const fs__default = _interopDefault(fs); const path = _interopDefault(require('path')); -if (process.env.DEVELOPMENT == 'true') { +if (process.env.NODE_ENV === 'development') { var croupierDirectory = '.'; } else { var croupierDirectory = '/home/keybase/croupier'; diff --git a/package-lock.json b/package-lock.json index 3aa40d37..b63914c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1871,6 +1871,11 @@ "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==", "dev": true }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", @@ -1938,6 +1943,14 @@ "yargs": "^5.0.0" } }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "requires": { + "string-width": "^2.0.0" + } + }, "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", @@ -1947,14 +1960,12 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -1974,6 +1985,11 @@ "normalize-path": "^2.0.0" } }, + "arg": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz", + "integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2274,6 +2290,27 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2405,6 +2442,12 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -2488,6 +2531,11 @@ "rsvp": "^4.8.4" } }, + "capture-stack-trace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", + "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==" + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -2506,7 +2554,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -2538,8 +2585,7 @@ "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, "class-utils": { "version": "0.3.6", @@ -2567,6 +2613,11 @@ } } }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -2740,7 +2791,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -2748,8 +2798,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { "version": "0.6.2", @@ -2779,6 +2828,34 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, "confusing-browser-globals": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.7.tgz", @@ -2884,11 +2961,18 @@ "printj": "~1.1.0" } }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -2897,6 +2981,11 @@ "which": "^1.2.9" } }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, "cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", @@ -2985,6 +3074,11 @@ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -3076,6 +3170,11 @@ "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, + "diff": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==" + }, "diff-sequences": { "version": "24.3.0", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", @@ -3127,6 +3226,24 @@ "webidl-conversions": "^4.0.2" } }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "^1.0.0" + } + }, + "dotenv": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz", + "integrity": "sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg==" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3204,8 +3321,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "1.11.1", @@ -3771,6 +3887,293 @@ "locate-path": "^2.0.0" } }, + "find-yarn-workspace-root": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz", + "integrity": "sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q==", + "requires": { + "fs-extra": "^4.0.3", + "micromatch": "^3.1.4" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -3929,6 +4332,16 @@ "map-cache": "^0.2.2" } }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4496,6 +4909,14 @@ "is-glob": "^2.0.0" } }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "requires": { + "ini": "^1.3.4" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -4532,6 +4953,31 @@ } } }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "^3.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + } + } + }, "graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", @@ -4606,8 +5052,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.0", @@ -4837,6 +5282,11 @@ "resolve-from": "^4.0.0" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, "import-local": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", @@ -4904,8 +5354,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "3.2.0", @@ -5026,7 +5475,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, "requires": { "ci-info": "^2.0.0" } @@ -5094,8 +5542,7 @@ "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-generator-fn": { "version": "2.1.0", @@ -5111,6 +5558,30 @@ "is-extglob": "^1.0.0" } }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + }, + "dependencies": { + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "^1.0.1" + } + } + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", @@ -5122,8 +5593,7 @@ "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" }, "is-observable": { "version": "1.1.0", @@ -5189,6 +5659,11 @@ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, "is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", @@ -5204,11 +5679,15 @@ "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", "dev": true }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-symbol": { "version": "1.0.2", @@ -5248,8 +5727,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "2.1.0", @@ -7043,6 +7521,14 @@ } } }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", @@ -7074,12 +7560,28 @@ } } }, + "klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "requires": { + "graceful-fs": "^4.1.11" + } + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "requires": { + "package-json": "^4.0.0" + } + }, "lazy": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", @@ -7479,6 +7981,20 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -7500,8 +8016,7 @@ "make-error": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", - "dev": true + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" }, "makeerror": { "version": "1.0.11", @@ -7786,8 +8301,7 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "node-int64": { "version": "0.4.0", @@ -7846,7 +8360,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, "requires": { "path-key": "^2.0.0" } @@ -8056,8 +8569,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "p-defer": { "version": "1.0.0", @@ -8077,8 +8589,7 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-is-promise": { "version": "2.1.0", @@ -8122,6 +8633,17 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "requires": { + "got": "^6.7.1", + "registry-auth-token": "^3.0.1", + "registry-url": "^3.0.3", + "semver": "^5.1.0" + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -8161,6 +8683,33 @@ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, + "patch-package": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.1.2.tgz", + "integrity": "sha512-5GnzR8lEyeleeariG+hGabUnD2b1yL7AIGFjlLo95zMGRWhZCel58IpeKD46wwPb7i+uNhUI8unV56ogk8Bgqg==", + "requires": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^1.2.1", + "fs-extra": "^7.0.1", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.0", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "update-notifier": "^2.5.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -8175,14 +8724,12 @@ "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { "version": "1.0.6", @@ -8276,6 +8823,11 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -8394,6 +8946,11 @@ "event-stream": "~0.5" } }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, "psl": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", @@ -8441,6 +8998,24 @@ } } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, "react-is": { "version": "16.8.6", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", @@ -8844,6 +9419,23 @@ "unicode-match-property-value-ecmascript": "^1.1.0" } }, + "registry-auth-token": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "^1.0.1" + } + }, "regjsgen": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", @@ -9443,6 +10035,14 @@ "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "dev": true }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "requires": { + "semver": "^5.0.3" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -9473,7 +10073,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -9481,8 +10080,7 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "shellwords": { "version": "0.1.1", @@ -9509,8 +10107,7 @@ "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sisteransi": { "version": "1.0.2", @@ -9521,8 +10118,7 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" }, "slice-ansi": { "version": "2.1.0", @@ -9814,7 +10410,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -9843,7 +10438,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "^3.0.0" } @@ -9857,8 +10451,7 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-final-newline": { "version": "2.0.0", @@ -9869,14 +10462,12 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -9959,6 +10550,45 @@ } } }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "requires": { + "execa": "^0.7.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + } + } + }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -10102,11 +10732,15 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "requires": { "os-tmpdir": "~1.0.2" } @@ -10226,12 +10860,62 @@ } } }, + "ts-node": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.3.0.tgz", + "integrity": "sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ==", + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, + "tslint": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", + "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -10331,6 +11015,19 @@ "set-value": "^2.0.1" } }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -10372,6 +11069,43 @@ } } }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==" + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "requires": { + "ci-info": "^1.5.0" + } + } + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -10385,6 +11119,14 @@ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "^1.0.1" + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -10513,7 +11255,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -10523,6 +11264,14 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "requires": { + "string-width": "^2.1.1" + } + }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", @@ -10608,7 +11357,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", - "dev": true, "requires": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", @@ -10624,6 +11372,11 @@ "async-limiter": "~1.0.0" } }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, "xlsx": { "version": "0.13.5", "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.13.5.tgz", @@ -10649,6 +11402,11 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, "yargs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-5.0.0.tgz", @@ -10777,6 +11535,11 @@ "camelcase": "^3.0.0", "lodash.assign": "^4.1.0" } + }, + "yn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.0.tgz", + "integrity": "sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg==" } } } diff --git a/package.json b/package.json index e941e568..d323ec49 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,9 @@ "url": "https://github.com/codeforcash/croupier/issues" }, "scripts": { + "start": "ts-node index.ts", + "dev": "NODE_ENV=development ts-node index.ts", + "lint": "tslint --project tslint.json", "test": "jest --runInBand" }, "husky": { @@ -38,6 +41,7 @@ "@types/node": "^12.6.8", "alasql": "^0.4.11", "axios": "^0.19.0", + "dotenv": "^8.0.0", "forever": "^1.0.0", "lodash": "^4.17.15", "lodash.camelcase": "^4.3.0", @@ -46,9 +50,11 @@ "mkdirp": "0.5.1", "moment": "^2.24.0", "mongodb": "^3.2.7", + "patch-package": "^6.1.2", "prettier": "^1.18.2", "source-map-support": "^0.5.12", "throttled-queue": "^1.0.5", + "ts-node": "^8.3.0", "typescript": "^3.5.3" }, "devDependencies": { @@ -60,6 +66,7 @@ "husky": ">=1", "jest": "^24.8.0", "lint-staged": ">=8", - "ts-jest": "^24.0.2" + "ts-jest": "^24.0.2", + "tslint": "^5.18.0" } } diff --git a/snipe.ts b/snipe.ts index 42778085..707b3418 100644 --- a/snipe.ts +++ b/snipe.ts @@ -3,8 +3,10 @@ import * as _ from "lodash"; import * as moment from "moment"; import * as throttledQueue from "throttled-queue"; import Croupier from "./croupier"; +// @ts-ignore import * as Bot from "./keybase-bot"; +// @ts-ignore import { ChatChannel, MessageSummary, Transaction } from "./keybase-bot"; import { IBetData, IBetList, IParticipant, IPopularityContest, IPositionSize, IPowerup, IPowerupAward, IReactionContent } from "./types"; @@ -73,7 +75,7 @@ class Snipe { this.blinds = 0.01; } - const chatThrottle: any = throttledQueue(5, 5000); + const chatThrottle: any = throttledQueue(5, 5000, false); this.chatSend = (message) => { return new Promise((resolveChatThrottle) => { @@ -109,7 +111,7 @@ class Snipe { } catch (e) { self.bot1.chat.send( { - name: `zackburt,${self.croupier.botUsername}`, + name: `zackburt,${self.croupier.botUsername1}`, public: false, topicType: "chat", }, @@ -422,7 +424,7 @@ class Snipe { } catch (e) { self.bot1.chat.send( { - name: `zackburt,${self.croupier.botUsername}`, + name: `zackburt,${self.croupier.botUsername1}`, public: false, topicType: "chat", }, @@ -478,7 +480,7 @@ class Snipe { } else { const w9url: string = "https://www.irs.gov/pub/irs-pdf/fw9.pdf"; const w8benurl: string = "https://www.irs.gov/pub/irs-pdf/fw8ben.pdf"; - const channelName: string = `zackburt,${self.croupier.botUsername},${winnerUsername}`; + const channelName: string = `zackburt,${self.croupier.botUsername1},${winnerUsername}`; const channel: ChatChannel = { name: channelName, public: false, topicType: "chat" }; self.bot1.chat.send( @@ -761,7 +763,7 @@ class Snipe { const self: Snipe = this; let message: string = `The round has begun (**#${self.snipeId}**). `; message += `Bet in multiples of 0.01XLM. Betting format:`; - message += `\`\`\`+0.01XLM@${self.croupier.botUsername}\`\`\``; + message += `\`\`\`+0.01XLM@${self.croupier.botUsername1}\`\`\``; message += `Minimum bet: 0.01XLM\n`; message += `Make 3 uninterrupted bets of **${this.displayFixedNice(self.blinds)}XLM**`; message += ` and receive a powerup!`; @@ -1271,8 +1273,8 @@ class Snipe { sassyMessage += `First to 3 votes wins `; sassyMessage += `(4 votes including the initial reaction seeded by me the Croupier)!`; self.chatSend(sassyMessage).then((msgData) => { - const challengerReaction: Promise = self.bot1.chat.react(self.channel, msgData.id, `${consumer}`); - const leaderReaction: Promise = self.bot1.chat.react(self.channel, msgData.id, `${leader}`); + const challengerReaction: Promise = self.bot1.chat.react(self.channel, msgData.id, `${consumer}`, {}); + const leaderReaction: Promise = self.bot1.chat.react(self.channel, msgData.id, `${leader}`, {}); Promise.all([challengerReaction, leaderReaction]).then((values) => { self.popularityContests.push({ challenger: consumer, diff --git a/tslint.json b/tslint.json index aa819ffa..b3a371c4 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,5 @@ { "defaultSeverity": "error", - "extends": ["tslint:recommended"], "jsRules": {}, "rules": { "no-console": false, @@ -23,5 +22,8 @@ } ] }, - "rulesDirectory": [] + "rulesDirectory": [], + "linterOptions": { + "exclude": ["scratchpad.ts", "__tests__/*"] + } } From 20a33c4b5281bf22be792edd6d29b2b4ee440ded Mon Sep 17 00:00:00 2001 From: Clayton Hadaway Date: Fri, 26 Jul 2019 16:24:12 -0500 Subject: [PATCH 2/2] finish monkey patching keybase-bot --- __tests__/integration.test.ts | 4 +- croupier.ts | 6 +- keybase-bot.js | 1596 ------------------------------- package-lock.json | 66 +- package.json | 3 +- patches/keybase-bot+2.0.6.patch | 365 +++++++ scratchpad.ts | 2 +- snipe.ts | 18 +- tslint.json | 2 +- types.ts | 2 +- 10 files changed, 448 insertions(+), 1616 deletions(-) delete mode 100644 keybase-bot.js create mode 100644 patches/keybase-bot+2.0.6.patch diff --git a/__tests__/integration.test.ts b/__tests__/integration.test.ts index 57146773..9c8a7d2c 100644 --- a/__tests__/integration.test.ts +++ b/__tests__/integration.test.ts @@ -1,7 +1,7 @@ import * as os from "os"; import Croupier from "../croupier"; -import * as Bot from "../keybase-bot"; -import { ChatChannel, MessageSummary, Transaction } from "../keybase-bot"; +import * as Bot from "keybase-bot"; +import { ChatChannel, MessageSummary, Transaction } from "keybase-bot"; import { IBetData, diff --git a/croupier.ts b/croupier.ts index d19bbe83..44c5994a 100644 --- a/croupier.ts +++ b/croupier.ts @@ -5,11 +5,11 @@ import * as mongodb from "mongodb"; import * as os from "os"; import * as throttledQueue from "throttled-queue"; // @ts-ignore -import * as Bot from "./keybase-bot"; +import * as Bot from "keybase-bot"; import Snipe from "./snipe"; // @ts-ignore -import { ChatChannel, MessageSummary, Transaction } from "./keybase-bot"; +import { ChatChannel, MessageSummary, Transaction } from "keybase-bot"; import { IBetData, IBetList, IParticipant, IPopularityContest, IPositionSize, IPowerup, IPowerupAward, IReactionContent } from "./types"; class Croupier { @@ -77,7 +77,7 @@ class Croupier { } public async run(loadActiveSnipes: boolean): Promise { - if (!this.bot1._service.initialized) { + if (!this.bot1.myInfo()) { await this.init(); } diff --git a/keybase-bot.js b/keybase-bot.js deleted file mode 100644 index aee69b94..00000000 --- a/keybase-bot.js +++ /dev/null @@ -1,1596 +0,0 @@ - -function _interopDefault(ex) { - return ex && typeof ex === 'object' && 'default' in ex ? ex.default : ex; -} - -const snakeCase = _interopDefault(require('lodash.snakecase')); -const camelCase = _interopDefault(require('lodash.camelcase')); -const kebabCase = _interopDefault(require('lodash.kebabcase')); -const os = _interopDefault(require('os')); -const crypto = _interopDefault(require('crypto')); -const child_process = require('child_process'); -const readline = _interopDefault(require('readline')); -const mkdirp = _interopDefault(require('mkdirp')); -const util = require('util'); -const fs = require('fs'); - -const fs__default = _interopDefault(fs); -const path = _interopDefault(require('path')); - -if (process.env.NODE_ENV === 'development') { - var croupierDirectory = '.'; -} else { - var croupierDirectory = '/home/keybase/croupier'; -} -/** - Takes a Keybase API input JavaScript object and recursively formats it into snake_case or kebab-case instead of camelCase for the service. - * @ignore - * @param obj - The object to be formatted. - * @param apiType - The type of api the the input is being served to. Currently Keybase has chat, team, and wallet apis. - * @returns - The new, formatted object. - * @example - * const inputOptions = formatAPIObject({unreadOnly: true}) - * console.log(inputOptions) // {unread_only: true} - */ -function formatAPIObjectInput(obj, apiType) { - if (obj === null || obj === undefined || typeof obj !== 'object') { - return obj; - } if (Array.isArray(obj)) { - return obj.map(item => formatAPIObjectInput(item, apiType)); - } - return Object.keys(obj).reduce((newObj, key) => { - // TODO: hopefully we standardize how the Keybase API handles input keys - let formattedKey; - - if (apiType === 'wallet') { - formattedKey = kebabCase(key); - } else { - formattedKey = snakeCase(key); - } - - if (typeof obj[key] === 'object') { - return { ...newObj, [formattedKey]: formatAPIObjectInput(obj[key], apiType) }; - } - - return { ...newObj, [formattedKey]: obj[key] }; - }, {}); -} -/* - * An internal blacklist of parent levels at which formatAPIObjectOutput transformations - * shouldn't be performed. A `null` value matches everything. - */ - -const transformsBlacklist = { - chat: { - read: [['messages', null, 'msg', 'reactions', 'reactions', null]], - }, - /** - * Context of the object formatting process. - * @ignore - */ -}; - -/* - * Matches a context against the list of blacklisted parent levels. - * @ignore - * @param context - The context to match. - * @returns - Whether the context is blacklisted from being formatted. - */ -function matchBlacklist(context) { - if (!context || !transformsBlacklist[context.apiName] || !transformsBlacklist[context.apiName][context.method]) { - return false; - } - - const parentLength = context.parent ? context.parent.length : 0; - - for (const matcher of transformsBlacklist[context.apiName][context.method]) { - if (matcher.length !== parentLength) { - continue; - } // Iterate over the items of the matcher - - let mismatch = false; - - for (const [matcherIndex, desiredValue] of matcher.entries()) { - if (desiredValue === null) { - continue; - } - - if (typeof context.parent === 'object' && context.parent[matcherIndex] !== desiredValue) { - mismatch = true; - break; - } - } - - if (!mismatch) { - return true; - } - } - - return false; -} -/* - * Appends a new key to the parents array in the formatting context. - * @ignore - * @param context - The context to copy and modify. - * @param key - The key to apprent to the parent array. - * @returns - A new context. - */ - -function buildContext(context, key) { - if (!context) { - return context; - } - - const copiedContext = { ...context }; - - if (!copiedContext.parent) { - copiedContext.parent = [key]; - } else { - copiedContext.parent = copiedContext.parent.slice(); - copiedContext.parent.push(key); - } - - return copiedContext; -} -/** - Takes a Keybase output object and formats it in a more digestable JavaScript style by using camelCase instead of snake_case. - * @ignore - * @param obj - The object to be formatted. - * @param context - An optional context with information about the called method required to perform blacklist lookups. - * @returns - The new, formatted object. - * @example - * const outputRes = formatAPIObject({unread_only: true}) - * console.log(outputRes) // {unreadOnly: true} - */ - -function formatAPIObjectOutput(obj, context) { - if (obj == null || typeof obj !== 'object') { - return obj; - } if (Array.isArray(obj)) { - return obj.map((item, i) => formatAPIObjectOutput(item, buildContext(context, i))); - } - return Object.keys(obj).reduce((newObj, key) => { - const formattedKey = matchBlacklist(context) ? key : camelCase(key); - - if (typeof obj[key] === 'object') { - return { ...newObj, [formattedKey]: formatAPIObjectOutput(obj[key], buildContext(context, key)) }; - } - - return { ...newObj, [formattedKey]: obj[key] }; - }, {}); -} - -const keybaseExec = ( - workingDir, - homeDir, - args, - options = { - stdinBuffer: undefined, - onStdOut: undefined, - timeout: undefined, - }, -) => { - const runArgs = [...args]; - - if (homeDir) { - runArgs.unshift('--home', homeDir); - } - - const keybasePath = path.join(workingDir, 'keybase'); - const child = child_process.spawn(keybasePath, runArgs); - const stdOutBuffer = []; - const stdErrBuffer = []; - - if (options.stdinBuffer) { - child.stdin.write(options.stdinBuffer); - } - - child.stdin.end(); - const lineReaderStdout = readline.createInterface({ - input: child.stdout, - }); // Use readline interface to parse each line (\n separated) when provided - // with onStdOut callback - - if (options.onStdOut) { - lineReaderStdout.on('line', options.onStdOut); - } else { - child.stdout.on('data', (chunk) => { - stdOutBuffer.push(chunk); - }); - } // Capture STDERR and use as error message if needed - - child.stderr.on('data', (chunk) => { - stdErrBuffer.push(chunk); - }); - let done = false; - - if (options.timeout) { - setTimeout(() => { - if (!done) { - child.kill(); - } - }, options.timeout); - } - - return new Promise((resolve, reject) => { - child.on('close', (code) => { - done = true; - let finalStdOut = null; // Pass back - - if (code) { - const errorMessage = Buffer.concat(stdErrBuffer).toString('utf8'); - reject(new Error(errorMessage)); - } else { - const stdout = Buffer.concat(stdOutBuffer).toString('utf8'); - - try { - finalStdOut = options.json ? JSON.parse(stdout) : stdout; - } catch (e) { - reject(e); - } - } - - resolve(finalStdOut); - }); - }); -}; - -function randomTempDir() { - const name = crypto.randomBytes(16).toString('hex'); - return path.join(os.tmpdir(), `keybase_bot_${name}`); -} - -async function rmdirRecursive(dirName) { - const fsLstat = util.promisify(fs__default.lstat); - const fsUnlink = util.promisify(fs__default.unlink); - const fsRmdir = util.promisify(fs__default.rmdir); - const fsReaddir = util.promisify(fs__default.readdir); - const dirStat = await fsLstat(dirName); - - if (dirStat) { - for (const entry of await fsReaddir(dirName)) { - const entryPath = path.join(dirName, entry); - const stat = await fsLstat(entryPath); - - if (stat.isDirectory()) { - await rmdirRecursive(entryPath); - } else { - await fsUnlink(entryPath); - } - } - - await fsRmdir(dirName); - } -} - -/** - * Useful information like the username, device, home directory of your bot and - * configuration options. - */ - -/** - * Returns { username, devicename, homeDir } from `keybase status --json`. - * @ignore - * @param workingDir - the directory containing the binary, according to top level Bot - * @param homeDir - The home directory of the service you want to fetch the status from. - * @example - * keybaseStatus('/my/dir').then(status => console.log(status.username)) - */ -async function keybaseStatus(workingDir, homeDir) { - const status = await keybaseExec(workingDir, homeDir, ['status', '--json'], { - json: true, - }); - - if (status && status.Username && status.Device && status.Device.name) { - return { - username: status.Username, - devicename: status.Device.name, - homeDir, - }; - } - throw new Error('Failed to get current username and device name.'); -} - -/** - * Checks whether the keybase service is running by calling `keybase status --json`. - * @ignore - * @param workingDir - the directory containing the binary, according to top level Bot - * @param homeDir - The home directory of the service you want to fetch the status from. - * @example - * pingKeybaseService('/my/dir').then(status => console.log("service running", status)) - */ - -async function pingKeybaseService(workingDir, homeDir) { - // TODO: use a faster technique when core releases one - try { - await keybaseExec(workingDir, homeDir, ['--no-auto-fork', 'status', '--json'], { - json: true, - }); - return true; - } catch (err) { - return false; - } -} - -const aExec = util.promisify(child_process.exec); -/** - * Returns the full path to the keybase binary or throws an error - * @ignore - * @example - * whichKeybase().then((path) => console.log(path)) - */ - -async function whichKeybase() { - const { stdout } = await aExec('which keybase'); - - if (!stdout || !stdout.trim().length) { - throw new Error('Could not find keybase binary'); - } - - const res = stdout.trim(); - return res; -} - -function timeout(time) { - return new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, time); - }); -} - -class Service { - constructor(workingDir) { - this.workingDir = workingDir; - this.initialized = false; - this.verbose = false; - this.botLite = true; - this.disableTyping = true; - this.autoLogSendOnCrash = false; - } - - async init(username, paperkey, options) { - if (!username || typeof username !== 'string') { - throw new Error(`Please provide a username to initialize the bot. Got: ${JSON.stringify(username)}`); - } - - if (!paperkey || typeof paperkey !== 'string') { - // Don't want to accidentally print the paperkey to STDERR. - throw new Error('Please provide a paperkey to initialize the bot.'); - } - - if (this.initialized) { - throw new Error('Cannot initialize an already initialized bot.'); - } - - this.homeDir = this.workingDir; - this.serviceLogFile = path.join(this.homeDir, 'logs', 'keybase.service.log'); - this.botLite = options ? Boolean(typeof options.botLite !== 'boolean' || options.botLite) : true; - this.disableTyping = options ? Boolean(typeof options.disableTyping !== 'boolean' || options.disableTyping) : true; - this.autoLogSendOnCrash = options ? Boolean(typeof options.autoLogSendOnCrash === 'boolean' && options.autoLogSendOnCrash) : false; // Unlike with clients we don't need to store the service, since it shuts down with ctrl stop - - try { - await this.startupService(); - await keybaseExec(this.workingDir, this.homeDir, ['oneshot', '--username', username], { - stdinBuffer: paperkey, - }); // Set the typing notification settings for the bot - - await keybaseExec(this.workingDir, this.homeDir, ['chat', 'notification-settings', 'disable-typing', this.disableTyping.toString()]); - const currentInfo = await keybaseStatus(this.workingDir, this.homeDir); - - if (currentInfo && currentInfo.username && currentInfo.devicename) { - this.initialized = 'paperkey'; - this.username = currentInfo.username; - this._paperkey = paperkey; - this.devicename = currentInfo.devicename; - this.verbose = options ? Boolean(options.verbose) : false; - } - - if (this.username !== username) { - throw new Error('Failed to initialize service.'); - } - } catch (err) { - await this._killCustomService(); - throw err; - } - } - - async initFromRunningService(homeDir, options) { - if (this.initialized) { - throw new Error('Cannot initialize an already initialized bot.'); - } - - this.homeDir = homeDir; - const currentInfo = await keybaseStatus(this.workingDir, this.homeDir); - - if (currentInfo && currentInfo.username && currentInfo.devicename) { - this.initialized = 'runningService'; - this.username = currentInfo.username; - this.devicename = currentInfo.devicename; - this.verbose = options ? Boolean(options.verbose) : false; - } - } - - async _killCustomService() { - // these 2 commands might be unnecessary; since the service was `spawn`ed not detached - // they will also shutdown via SIGINT. We don't want to make service detached because it'd be nice for - // them to auto-shutdown if the user kills the process - try { - await keybaseExec(this.workingDir, this.homeDir, ['logout']); - } catch (e) {} - - try { - await keybaseExec(this.workingDir, this.homeDir, ['ctl', 'stop', '--shutdown']); - } catch (e) {} // wait until the process quits by watching the running property - - let i = 0; - - while (true) { - await timeout(100); - - if (!this.running) { - break; - } - - if (++i >= 100) { - throw new Error(`The service didn't finish shutting down in time (${this.workingDir})`); - } - } - } - - async deinit() { - if (!this.initialized) { - throw new Error('Cannot deinitialize an uninitialized bot.'); - } // If we init the bot using paperkey credentials, then we want to stop the service and remove our generated directory. - - if (this.initialized === 'paperkey') { - await this._killCustomService(); - } - - this.initialized = false; - } - - myInfo() { - if (this.username && this.devicename) { - return { - username: this.username, - devicename: this.devicename, - homeDir: this.homeDir ? this.homeDir : undefined, - botLite: this.botLite, - disableTyping: this.disableTyping, - }; - } - - return null; - } - /** - * - * @ignore - * This is a bit different from normal keybaseExecs and is unique to the service - * starting up - * @example - * service.startupService() - */ - - async startupService() { - const args = ['service']; - - if (this.homeDir) { - args.unshift('--home', this.homeDir); - } - - if (this.serviceLogFile) { - args.unshift('--log-file', this.serviceLogFile); - } - - if (this.botLite) { - args.unshift('--enable-bot-lite-mode'); - } - - const child = child_process.spawn(path.join(this.workingDir, 'keybase'), args, { - env: process.env, - }); // keep track of the subprocess' state - - this.running = true; - child.on('exit', async (code) => { - this.running = false; - - if (code !== 0 && this.autoLogSendOnCrash) { - await this.logSend(); - } - }); - return new Promise(async (resolve, reject) => { - child.on('close', (code) => { - // any code here including 0 is bad here, if it happens before resolve - // , since this service should stay running - reject(new Error(`keybase service exited with code ${code} (${this.workingDir})`)); - }); // Wait for the service to start up - give it 10s. - - let i = 0; - - while (!(await pingKeybaseService(this.workingDir, this.homeDir))) { - await timeout(100); - - if (++i >= 100) { - throw new Error("Couldn't start up service fast enough"); - } - } - - resolve(); - }); - } - - async logSend() { - const initiallyRunning = this.running; - - if (!initiallyRunning) { - try { - await this.startupService(); - - if (this.initialized === 'paperkey' && this.username) { - await keybaseExec(this.workingDir, this.homeDir, ['oneshot', '--username', this.username], { - stdinBuffer: this._paperkey, - }); - } - } catch (e) {} - } - - const feedback = `keybase-bot auto log send -username: ${this.username || 'none'} -initialized: ${this.initialized || 'false'}`; - const args = ['log', 'send', '--no-confirm', '--feedback', feedback]; - - if (this.serviceLogFile) { - args.unshift('--log-file', this.serviceLogFile); - } - - await keybaseExec(this.workingDir, this.homeDir, args); - - if (!initiallyRunning) { - await this._killCustomService(); - } - } -} - -const API_VERSIONS = { - chat: 1, - team: 1, - wallet: 1, -}; - -/** - * A Client base. - * @ignore - */ -class ClientBase { - constructor(workingDir) { - this._workingDir = workingDir; - this.initialized = false; - this.verbose = false; - this.spawnedProcesses = []; - } - - async _init(homeDir, options) { - const initBotInfo = await keybaseStatus(this._workingDir, homeDir); - this.homeDir = homeDir; - this.username = initBotInfo.username; - this.devicename = initBotInfo.devicename; - this.initialized = true; - } - - async _deinit() { - for (const child of this.spawnedProcesses) { - child.kill(); - } - } - - async _runApiCommand(arg) { - const options = arg.options ? formatAPIObjectInput(arg.options, arg.apiName) : undefined; - const input = { - method: arg.method, - params: { - version: API_VERSIONS[arg.apiName], - options, - }, - }; - const inputString = JSON.stringify(input); - - console.log(inputString); - - const size = inputString.length; - const output = await keybaseExec(this._workingDir, this.homeDir, [arg.apiName, 'api'], { - stdinBuffer: Buffer.alloc(size, inputString, 'utf8'), - json: true, - timeout: arg.timeout, - }); - - if (output.hasOwnProperty('error')) { - throw new Error(output.error.message); - } - - const res = formatAPIObjectOutput(output.result, { - apiName: arg.apiName, - method: arg.method, - }); - return res; - } - - async _guardInitialized() { - if (!this.initialized) { - throw new Error('The client is not yet initialized.'); - } - } - - _pathToKeybaseBinary() { - return path.join(this._workingDir, 'keybase'); - } -} - -/** The chat module of your Keybase bot. For more info about the API this module uses, you may want to check out `keybase chat api`. */ -class Chat extends ClientBase { - // Custom function that returns more information than the keybase-bot method, - // which doesn't provide error data nicely. - getFlipData(conversationId, flipConversationId, msgId, gameId) { - console.log('working dir and homedir:'); - console.log(this._workingDir); - console.log(this.homeDir); - - const stdout = []; - const stderr = []; - - const child = child_process.spawn(`${croupierDirectory}/scripts/getflipdata.sh`, [ - conversationId, - flipConversationId, - msgId, - gameId, - this._workingDir, - this.homeDir, - ]); - - return new Promise((resolve) => { - child.stdout.on('data', (data) => { - console.log(`stdout: ${data}`); - stdout.push(data.toString('utf8')); - }); - - child.stderr.on('data', (data) => { - console.log(`stderr: ${data}`); - stderr.push(data.toString('utf8')); - }); - - child.on('close', (code) => { - console.log(`child process exited with code ${code}`); - console.log('again, stdout:', stdout); - console.log('stdout length: ', stdout.length); - console.log('stdout 0', stdout[0]); - console.log('stdout 1', stdout[1]); - resolve([true, stdout[1], stderr]); - }); - - child.on('error', (err) => { - console.log(`child process errored with err ${err}`); - resolve([err, stdout, stderr]); - }); - }); - } - - sendMoneyInChat(topic, team, amount, recipient, extraParams) { - return new Promise((resolve) => { - console.log('sendMoneyInChat: 1'); - const child = child_process.spawn(`${croupierDirectory}/scripts/sendmoney.sh`, [ - team, - topic, - amount, - recipient, - extraParams, - this._workingDir, - this.homeDir, - ]); - - const errors = []; - - child.stdout.on('data', (data) => { - console.log(`stdout: ${data}`); - }); - - child.stderr.on('data', (data) => { - console.log(`stderr: ${data}`); - errors.push(data); - }); - - child.on('close', (code) => { - console.log(`child process exited with code ${code}`); - resolve(code); - }); - - child.on('error', (err) => { - console.log(`child process errored with err ${err}`); - errors.push(err); - throw JSON.stringify(errors); - }); - }); - } - - /** - * Lists your chats, with info on which ones have unread messages. - * @memberof Chat - * @param options - An object of options that can be passed to the method. - * @returns - An array of chat conversations. If there are no conversations, the array is empty. - * @example - * bot.chat.list({unreadOnly: true}).then(chatConversations => console.log(chatConversations)) - */ - async list(options) { - await this._guardInitialized(); - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'list', - options, - }); - - if (!res) { - throw new Error('Keybase chat list returned nothing.'); - } - - return res.conversations || []; - } - /** - * Lists conversation channels in a team - * @memberof Chat - * @param name - Name of the team - * @param options - An object of options that can be passed to the method. - * @returns - An array of chat conversations. If there are no conversations, the array is empty. - * @example - * bot.chat.listChannels('team_name').then(chatConversations => console.log(chatConversations)) - */ - - async listChannels(name, options) { - await this._guardInitialized(); - const optionsWithDefaults = { ...options, name, membersType: options && options.membersType ? options.membersType : 'team' }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'listconvsonname', - options: optionsWithDefaults, - }); - - if (!res) { - throw new Error('Keybase chat list convs on name returned nothing.'); - } - - return res.conversations || []; - } - /** - * Reads the messages in a channel. You can read with or without marking as read. - * @memberof Chat - * @param channel - The chat channel to read messages in. - * @param options - An object of options that can be passed to the method. - * @returns - A summary of data about a message, including who send it, when, the content of the message, etc. If there are no messages in your channel, then an error is thrown. - * @example - * alice.chat.read(channel).then(messages => console.log(messages)) - */ - - async read(channel, options) { - await this._guardInitialized(); - const optionsWithDefaults = { - ...options, - channel, - peek: options && options.peek ? options.peek : false, - unreadOnly: options && options.unreadOnly !== undefined ? options.unreadOnly : false, - }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'read', - options: optionsWithDefaults, - }); - - if (!res) { - throw new Error('Keybase chat read returned nothing.'); - } // Pagination gets passed as-is, while the messages get cleaned up - - return { - pagination: res.pagination, - messages: res.messages.map(message => message.msg), - }; - } - /** - * Joins a team conversation. - * @param channel - The team chat channel to join. - * @example - * bot.chat.listConvsOnName('team_name').then(async teamConversations => { - * for (const conversation of teamConversations) { - * if (conversation.memberStatus !== 'active') { - * await bot.chat.join(conversation.channel) - * console.log('Joined team channel', conversation.channel) - * } - * } - * }) - */ - - async joinChannel(channel) { - await this._guardInitialized(); - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'join', - options: { - channel, - }, - }); - - if (!res) { - throw new Error('Keybase chat join returned nothing'); - } - } - /** - * Leaves a team conversation. - * @param channel - The team chat channel to leave. - * @example - * bot.chat.listConvsOnName('team_name').then(async teamConversations => { - * for (const conversation of teamConversations) { - * if (conversation.memberStatus === 'active') { - * await bot.chat.leave(conversation.channel) - * console.log('Left team channel', conversation.channel) - * } - * } - * }) - */ - - async leaveChannel(channel) { - await this._guardInitialized(); - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'leave', - options: { - channel, - }, - }); - - if (!res) { - throw new Error('Keybase chat leave returned nothing'); - } - } - - // custom hack - async edit(channel, messageId, options) { - await this._guardInitialized(); - const args = { ...options, channel, messageId }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'edit', - options: args, - }); - - if (!res) { - throw new Error('Keybase chat edit returned nothing'); - } - - return { - id: res.id, - }; - } - - /** - * Send a message to a certain channel. - * @memberof Chat - * @param channel - The chat channel to send the message in. - * @param message - The chat message to send. - * @param options - An object of options that can be passed to the method. - * @example - * const channel = {name: 'kbot,' + bot.myInfo().username, public: false, topicType: 'chat'} - * const message = {body: 'Hello kbot!'} - * bot.chat.send(channel, message).then(() => console.log('message sent!')) - */ - - async send(channel, message, options) { - await this._guardInitialized(); - const args = { ...options, channel, message }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'send', - options: args, - }); - - if (!res) { - throw new Error('Keybase chat send returned nothing'); - } - - return { - id: res.id, - }; - } - /** - * Creates a new blank conversation. - * @memberof Chat - * @param channel - The chat channel to create. - * @example - * bot.chat.createChannel(channel).then(() => console.log('conversation created')) - */ - - async createChannel(channel) { - await this._guardInitialized(); - const args = { - channel, - }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'newconv', - options: args, - }); - - if (!res) { - throw new Error('Keybase chat newconv returned nothing'); - } - } - /** - * Send a file to a channel. - * @memberof Chat - * @param channel - The chat channel to send the message in. - * @param filename - The absolute path of the file to send. - * @param options - An object of options that can be passed to the method. - * @example - * bot.chat.attach(channel, '/Users/nathan/my_picture.png').then(() => console.log('Sent a picture!')) - */ - - async attach(channel, filename, options) { - await this._guardInitialized(); - const args = { ...options, channel, filename }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'attach', - options: args, - }); - - if (!res) { - throw new Error('Keybase chat attach returned nothing'); - } - - return { - id: res.id, - }; - } - /** - * Download a file send via Keybase chat. - * @memberof Chat - * @param channel - The chat channel that the desired attacment to download is in. - * @param messageId - The message id of the attached file. - * @param output - The absolute path of where the file should be downloaded to. - * @param options - An object of options that can be passed to the method - * @example - * bot.chat.download(channel, 325, '/Users/nathan/Downloads/file.png') - */ - - async download(channel, messageId, output, options) { - await this._guardInitialized(); - const args = { - ...options, channel, messageId, output, - }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'download', - options: args, - }); - - if (!res) { - throw new Error('Keybase chat download returned nothing'); - } - } - /** - * Reacts to a given message in a channel. Messages have messageId's associated with - * them, which you can learn in `bot.chat.read`. - * @memberof Chat - * @param channel - The chat channel to send the message in. - * @param messageId - The id of the message to react to. - * @param reaction - The reaction emoji, in colon form. - * @param options - An object of options that can be passed to the method. - * @example - * bot.chat.react(channel, 314, ':+1:').then(() => console.log('Thumbs up!')) - */ - - async react(channel, messageId, reaction, options) { - await this._guardInitialized(); - const args = { - ...options, - channel, - messageId, - message: { - body: reaction, - }, - }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'reaction', - options: args, - }); - - if (!res) { - throw new Error('Keybase chat react returned nothing.'); - } - - return { - id: res.id, - }; - } - /** - * Deletes a message in a channel. Messages have messageId's associated with - * them, which you can learn in `bot.chat.read`. Known bug: the GUI has a cache, - * and deleting from the CLI may not become apparent immediately. - * @memberof Chat - * @param channel - The chat channel to send the message in. - * @param messageId - The id of the message to delete. - * @param options - An object of options that can be passed to the method. - * @example - * bot.chat.delete(channel, 314).then(() => console.log('message deleted!')) - */ - - async delete(channel, messageId, options) { - await this._guardInitialized(); - const args = { ...options, channel, messageId }; - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'delete', - options: args, - }); - - if (!res) { - throw new Error('Keybase chat delete returned nothing.'); - } - } - /** - * Gets current unfurling settings - * @example - * bot.chat.getUnfurlSettings().then((mode) => console.log(mode)) - */ - - async getUnfurlSettings() { - await this._guardInitialized(); - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'getunfurlsettings', - options: {}, - }); - - if (!res) { - throw new Error('Keybase chat get unfurl mode returned nothing.'); - } - - return res; - } - /** - * Sets the unfurling mode - * @param mode - the new unfurl mode - * @example - * bot.chat.setUnfurlMode({ - * "mode": "always", - * }).then((mode) => console.log('mode updated!')) - */ - - async setUnfurlSettings(mode) { - await this._guardInitialized(); - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'setunfurlsettings', - options: mode, - }); - - if (!res) { - throw new Error('Keybase chat set unfurl mode returned nothing.'); - } - } - /** - * Loads a flip's details - * @param conversationID - conversation ID received in API listen. - * @param flipConversationID - flipConvID from the message summary. - * @param messageID - ID of the message in the conversation. - * @param gameID - gameID from the flip message contents. - */ - - async loadFlip(conversationID, flipConversationID, messageID, gameID) { - await this._guardInitialized(); - const res = await this._runApiCommand({ - apiName: 'chat', - method: 'loadflip', - options: { - conversation_id: conversationID, - flip_conversation_id: flipConversationID, - msg_id: messageID, - game_id: gameID, - }, - timeout: 2000, - }); - - if (!res) { - throw new Error('Keybase chat load flip returned nothing.'); - } - - return res.status; - } - /** - * Listens for new chat messages on a specified channel. The `onMessage` function is called for every message your bot receives. This is pretty similar to `watchAllChannelsForNewMessages`, except it specifically checks one channel. Note that it receives messages your own bot posts, but from other devices. You can filter out your own messages by looking at a message's sender object. - * Hides exploding messages by default. - * @memberof Chat - * @param channel - The chat channel to watch. - * @param onMessage - A callback that is triggered on every message your bot receives. - * @param onError - A callback that is triggered on any error that occurs while the method is executing. - * @param options - Options for the listen method. - * @example - * // Reply to all messages between you and `kbot` with 'thanks!' - * const channel = {name: 'kbot,' + bot.myInfo().username, public: false, topicType: 'chat'} - * const onMessage = message => { - * const channel = message.channel - * bot.chat.send(channel, {body: 'thanks!!!'}) - * } - * bot.chat.watchChannelForNewMessages(channel, onMessage) - */ - - async watchChannelForNewMessages(channel, onMessage, onError, options) { - await this._guardInitialized(); - - this._chatListen(onMessage, onError, channel, options); - } - /** - * This function will put your bot into full-read mode, where it reads - * everything it can and every new message it finds it will pass to you, so - * you can do what you want with it. For example, if you want to write a - * Keybase bot that talks shit at anyone who dares approach it, this is the - * function to use. Note that it receives messages your own bot posts, but from other devices. - * You can filter out your own messages by looking at a message's sender object. - * Hides exploding messages by default. - * @memberof Chat - * @param onMessage - A callback that is triggered on every message your bot receives. - * @param onError - A callback that is triggered on any error that occurs while the method is executing. - * @param options - Options for the listen method. - * @example - * // Reply to incoming traffic on all channels with 'thanks!' - * const onMessage = message => { - * const channel = message.channel - * bot.chat.send(channel, {body: 'thanks!!!'}) - * } - * bot.chat.watchAllChannelsForNewMessages(onMessage) - * - */ - - async watchAllChannelsForNewMessages(onMessage, onError, options) { - await this._guardInitialized(); - - this._chatListen(onMessage, onError, undefined, options); - } - /** - * Spawns the chat listen process and handles the calling of onMessage, onError, and filtering for a specific channel. - * @memberof Chat - * @ignore - * @param onMessage - A callback that is triggered on every message your bot receives. - * @param onError - A callback that is triggered on any error that occurs while the method is executing. - * @param channel - The chat channel to watch. - * @param options - Options for the listen method. - * @example - * this._chatListen(onMessage, onError) - */ - - _chatListen(onMessage, onError, channel, options) { - const args = ['chat', 'api-listen']; - - if (this.homeDir) { - args.unshift('--home', this.homeDir); - } - - if (!options || (options && options.hideExploding !== false)) { - args.push('--hide-exploding'); - } - - if (channel) { - args.push('--filter-channel', JSON.stringify(formatAPIObjectInput(channel, 'chat'))); - } - - const child = child_process.spawn(this._pathToKeybaseBinary(), args); - this.spawnedProcesses.push(child); - const lineReaderStdout = readline.createInterface({ - input: child.stdout, - }); - - const onLine = (line) => { - try { - const messageObject = formatAPIObjectOutput(JSON.parse(line)); - - if (messageObject.hasOwnProperty('error')) { - throw new Error(messageObject.error); - } else if ( - // fire onMessage if it was from a different sender or at least a different device - // from this sender. Bots can filter out their own messages from other devices. - this.username - && this.devicename - && (messageObject.msg.sender.username !== this.username.toLowerCase() || messageObject.msg.sender.deviceName !== this.devicename) - ) { - onMessage(messageObject.msg); - } - } catch (error) { - if (onError) { - onError(error); - } - } - }; - - lineReaderStdout.on('line', onLine); - } -} - -/** The wallet module of your Keybase bot. For more info about the API this module uses, you may want to check out `keybase wallet api`. */ -class Wallet extends ClientBase { - /** - * Provides a list of all accounts owned by the current Keybase user. - * @memberof Wallet - * @returns - An array of accounts. If there are no accounts, the array is empty. - * @example - * bot.wallet.balances().then(accounts => console.log(accounts)) - */ - async balances() { - await this._guardInitialized(); - const res = await this._runApiCommand({ - apiName: 'wallet', - method: 'balances', - }); - - if (!res) { - throw new Error('Keybase wallet balanaces returned nothing.'); - } - - return res || []; - } - /** - * Provides a list of all transactions in a single account. - * @memberof Wallet - * @param accountId - The id of an account owned by a Keybase user. - * @returns - An array of transactions related to the account. - * @example - * bot.wallet.history('GDUKZH6Q3U5WQD4PDGZXYLJE3P76BDRDWPSALN4OUFEESI2QL5UZHCK').then(transactions => console.log(transactions)) - */ - - async history(accountId) { - await this._guardInitialized(); - const options = { - accountId, - }; - const res = await this._runApiCommand({ - apiName: 'wallet', - method: 'history', - options, - }); - - if (!res) { - throw new Error('Keybase wallet history returned nothing.'); - } // Removes a single object with property `payment` - - const cleanedRes = res.map(payment => payment.payment); - return cleanedRes; - } - /** - * Get details about a particular transaction - * @memberof Wallet - * @param transactionId - The id of the transaction you would like details about. - * @returns - An object of details about the transaction specified. - * @example - * bot.wallet.details('e5334601b9dc2a24e031ffeec2fce37bb6a8b4b51fc711d16dec04d3e64976c4').then(details => console.log(details)) - */ - - async details(transactionId) { - await this._guardInitialized(); - const options = { - txid: transactionId, - }; - const res = await this._runApiCommand({ - apiName: 'wallet', - method: 'details', - options, - }); - - if (!res) { - throw new Error('Keybase wallet details returned nothing.'); - } - - return res; - } - /** - * Lookup the primary Stellar account ID of a Keybase user. - * @memberof Wallet - * @param name - The name of the user you want to lookup. This can be either a Keybase username or a username of another account that is supported by Keybase if it is followed by an '@'. - * @returns - An object containing the account ID and Keybase username of the found user. - * @example - * const lookup1 = bot.wallet.lookup('patrick') - * // 'patrick' on Keybase is 'patrickxb' on twitter - * const lookup2 = bot.wallet.lookup('patrcikxb@twitter') - * // Using Lodash's `isEqual` since objects with same values aren't equal in JavaScript - * _.isEqual(lookup1, lookup2) // => true - */ - - async lookup(name) { - await this._guardInitialized(); - const options = { - name, - }; - const res = await this._runApiCommand({ - apiName: 'wallet', - method: 'lookup', - options, - }); - - if (!res) { - throw new Error('Keybase wallet lookup returned nothing.'); - } - - return res; - } - /** - * Send lumens (XLM) via Keybase with your bot! - * @memberof Wallet - * @param recipient - Who you're sending your money to. This can be a Keybase user, stellar address, or a username of another account that is supported by Keybase if it is followed by an '@'. - * @param amount - The amount of XLM to send. - * @param [currency] - Adds a currency value to the amount specified. For example, adding 'USD' would send - * @param [message] - The message for your payment - * @returns - The trasaction object of the transaction. - * @example - * bot.wallet.send('nathunsmitty', '3.50') // Send 3.50 XLM to Keybase user `nathunsmitty` - * bot.wallet.send('nathunsmitty@github', '3.50') // Send 3.50 XLM to GitHub user `nathunsmitty` - * bot.wallet.send('nathunsmitty', '3.50', 'USD') // Send $3.50 worth of lumens to Keybase user `nathunsmitty` - * bot.wallet.send('nathunsmitty', '3.50', 'USD', 'Shut up and take my money!') // Send $3.50 worth of lumens to Keybase user `nathunsmitty` with a memo - */ - - async send(recipient, amount, currency, message) { - await this._guardInitialized(); - const options = { - recipient, - amount, - currency, - message, - }; - const res = await this._runApiCommand({ - apiName: 'wallet', - method: 'send', - options, - }); - - if (!res) { - throw new Error('Keybase wallet send returned nothing.'); - } - - return res; - } - /** - * Send lumens (XLM) via Keybase to more than one user at once. As opposed to the normal bot.wallet.send - * command, this can get multiple transactions into the same 5-second Stellar ledger. - * @memberof Wallet - * @param batchId - example, if sending a bunch of batches for an airdrop, you could pass them all `airdrop2025`. - * @param payments - an array of objects containing recipients and XLM of the form {"recipient": "someusername", "amount": "1.234", "message", "hi there"} - * @returns - an object - * @example - * bot.wallet.batch("airdrop2040",[{"recipient":"a1","amount": "1.414", "message": "hi a1, yes 1"},{"recipient": "a2", "amount": "3.14159", "message": "hi a2, yes 2"},}]) - */ - - async batch(batchId, payments) { - await this._guardInitialized(); - const options = { - batchId, - payments, - }; - const res = await this._runApiCommand({ - apiName: 'wallet', - method: 'batch', - options, - }); - - if (!res) { - throw new Error('Keybase wallet batch returned nothing.'); - } - - return res; - } - /** - * If you send XLM to a Keybase user who has not established a wallet, you can cancel the payment before the recipient claims it and the XLM will be returned to your account. - * @memberof Wallet - * @param transactionId - The id of the transaction to cancel. - * @example - * bot.wallet.cancel('e5334601b9dc2a24e031ffeec2fce37bb6a8b4b51fc711d16dec04d3e64976c4').then(() => console.log('Transaction successfully canceled!')) - */ - - async cancel(transactionId) { - await this._guardInitialized(); - const options = { - txid: transactionId, - }; - const res = await this._runApiCommand({ - apiName: 'wallet', - method: 'cancel', - options, - }); - - if (!res) { - throw new Error('Keybase wallet cancel returned nothing.'); - } - } -} - -/** The wallet module of your Keybase bot. For more info about the API this module uses, you may want to check out `keybase wallet api`. */ -class Team extends ClientBase { - createSubteam(name) { - return new Promise((resolve) => { - const child = child_process.spawn(`${croupierDirectory}/scripts/createteam.sh`, [name, this._workingDir, this.homeDir]); - - child.stdout.on('data', (data) => { - console.log(`stdout: ${data}`); - }); - - child.stderr.on('data', (data) => { - console.log(`stderr: ${data}`); - }); - - child.on('close', (code) => { - console.log(`child process exited with code ${code}`); - resolve(true); - }); - - child.on('error', (err) => { - console.log(`child process errored with err ${err}`); - resolve(false); - }); - }); - } - - /** - * Add a bunch of people with different privileges to a team - * @memberof Team - * @param additions - an array of the users to add, with privs - * @returns - - * @example - * bot.team.addMembers({"team": "phoenix", "emails": [{"email": "alice@keybase.io", "role": "writer"}, {"email": "cleo@keybase.io", "role": "admin"}], "usernames": [{"username": "frank", "role": "reader"}, {"username": "keybaseio@twitter", "role": "writer"}]}).then(res => console.log(res)) - */ - async addMembers(additions) { - await this._guardInitialized(); - const options = additions; - const res = await this._runApiCommand({ - apiName: 'team', - method: 'add-members', - options, - }); - - if (!res) { - throw new Error('addMembers'); - } - - return res; - } - /** - * Remove someone from a team - * @memberof Team - * @param removal - object with the `team` name and `username` - * @returns - - * @example - * bot.team.removeMember({"team": "phoenix", "username": "frank"}).then(res => console.log(res)) - */ - - async removeMember(removal) { - await this._guardInitialized(); - const options = removal; - const res = await this._runApiCommand({ - apiName: 'team', - method: 'remove-member', - options, - }); - return res; - } - /** - * List a team's members - * @memberof Team - * @param team - an object with the `team` name in it - * @returns - - * @example - * bot.team.listTeamMemberships({"team": "phoenix"}).then(res => console.log(res)) - */ - - async listTeamMemberships(team) { - await this._guardInitialized(); - const options = team; - const res = await this._runApiCommand({ - apiName: 'team', - method: 'list-team-memberships', - options, - }); - - if (!res) { - throw new Error('listTeamMemberships'); - } - - return res; - } -} - -/** A Keybase bot. */ -class Bot { - // where KB binary copied, and homeDir (if not existing svc) - - /** - * Create a bot. Note you can't do much too exciting with your bot after you instantiate it; you have to initialize it first. - * @memberof Bot - * @example - * const bot = new Bot() - */ - constructor() { - this._workingDir = randomTempDir(); - this._service = new Service(this._workingDir); - this.chat = new Chat(this._workingDir); - this.wallet = new Wallet(this._workingDir); - this.team = new Team(this._workingDir); - } - /** - * Initialize your bot by starting an instance of the Keybase service and logging in using oneshot mode. - * @memberof Bot - * @param username - The username of your bot's Keybase account. - * @param paperkey - The paperkey of your bot's Keybase account. - * @param options - The initialization options for your bot. - * @example - * bot.init('username', 'paperkey') - */ - - async init(username, paperkey, options) { - await this._prepWorkingDir(); - await this._service.init(username, paperkey, options); - await this._initSubBots(options); - } - /** - * Initialize your bot by using an existing running service with a logged in user. - * @memberof Bot - * @param homeDir - The home directory of this currently running service. Leave blank to use the default homeDir for your system. - * @param options - The initialization options for your bot. - * @example - * bot.initFromRunningService() - */ - - async initFromRunningService(homeDir, options) { - await this._prepWorkingDir(); - await this._service.initFromRunningService(homeDir, options); - await this._initSubBots(options); - } - /** - * Get info about your bot! - * @memberof Bot - * @returns – Useful information like the username, device, and home directory of your bot. If your bot isn't initialized, you'll get `null`. - * @example - * const info = bot.myInfo() - */ - - myInfo() { - return this._service.myInfo(); - } - /** - * Deinitializes the bot by logging out, stopping the keybase service, and removing any leftover login files made by the bot. This should be run before your bot ends. - * @memberof Bot - * @example - * bot.deinit() - */ - - async deinit() { - console.log('deinit', this._service.username); - // Stop the clients first, so that they aren't trying to - // talk to a deinit'ed service - await this.chat._deinit(); - await this._service.deinit(); - await rmdirRecursive(this._workingDir); - } - - async _prepWorkingDir() { - const keybaseBinaryLocation = await whichKeybase(); - const destination = path.join(this._workingDir, 'keybase'); - await util.promisify(mkdirp)(this._workingDir); - await util.promisify(fs.copyFile)(keybaseBinaryLocation, destination); - } - - async _initSubBots(options) { - const info = this.myInfo(); - - if (info) { - await this.chat._init(info.homeDir, options); - await this.wallet._init(info.homeDir, options); - await this.team._init(info.homeDir, options); - } else { - throw new Error('Issue initializing bot.'); - } - } -} - -module.exports = Bot; -// # sourceMappingURL=index.js.map diff --git a/package-lock.json b/package-lock.json index b63914c5..96764c31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1780,6 +1780,11 @@ "@babel/types": "^7.3.0" } }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==" + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", @@ -1871,6 +1876,42 @@ "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==", "dev": true }, + "@typescript-eslint/experimental-utils": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.10.2.tgz", + "integrity": "sha512-Hf5lYcrnTH5Oc67SRrQUA7KuHErMvCf5RlZsyxXPIT6AXa8fKTyfFO6vaEnUmlz48RpbxO4f0fY3QtWkuHZNjg==", + "requires": { + "@typescript-eslint/typescript-estree": "1.10.2", + "eslint-scope": "^4.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.10.2.tgz", + "integrity": "sha512-xWDWPfZfV0ENU17ermIUVEVSseBBJxKfqBcRCMZ8nAjJbfA5R7NWMZmFFHYnars5MjK4fPjhu4gwQv526oZIPQ==", + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "1.10.2", + "@typescript-eslint/typescript-estree": "1.10.2", + "eslint-visitor-keys": "^1.0.0" + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.10.2.tgz", + "integrity": "sha512-Kutjz0i69qraOsWeI8ETqYJ07tRLvD9URmdrMoF10bG8y8ucLmPtSxROvVejWvlJUGl2et/plnMiKRDW+rhEhw==", + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + } + } + }, "@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -3518,7 +3559,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" @@ -3533,8 +3573,7 @@ "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" }, "espree": { "version": "5.0.1", @@ -3566,7 +3605,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, "requires": { "estraverse": "^4.1.0" } @@ -3574,8 +3612,7 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" }, "esutils": { "version": "2.0.2", @@ -7545,6 +7582,18 @@ "verror": "1.10.0" } }, + "keybase-bot": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/keybase-bot/-/keybase-bot-2.0.6.tgz", + "integrity": "sha512-5WC4GsiYYXj4U8ubHIZthq1tXA9I99PTla1G4tEXf1JEX9FJfkHOdtuBL/ZRUF3JPc69mCEemXzU+QtmYcHjGQ==", + "requires": { + "@typescript-eslint/parser": "1.10.2", + "lodash.camelcase": "4.3.0", + "lodash.kebabcase": "4.1.1", + "lodash.snakecase": "4.1.1", + "mkdirp": "0.5.1" + } + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -7940,6 +7989,11 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=" + }, "log-symbols": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", diff --git a/package.json b/package.json index d323ec49..5e058f94 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,9 @@ "url": "https://github.com/codeforcash/croupier/issues" }, "scripts": { + "postinstall": "patch-package", "start": "ts-node index.ts", "dev": "NODE_ENV=development ts-node index.ts", - "lint": "tslint --project tslint.json", "test": "jest --runInBand" }, "husky": { @@ -43,6 +43,7 @@ "axios": "^0.19.0", "dotenv": "^8.0.0", "forever": "^1.0.0", + "keybase-bot": "^2.0.6", "lodash": "^4.17.15", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", diff --git a/patches/keybase-bot+2.0.6.patch b/patches/keybase-bot+2.0.6.patch new file mode 100644 index 00000000..812d6e01 --- /dev/null +++ b/patches/keybase-bot+2.0.6.patch @@ -0,0 +1,365 @@ +diff --git a/node_modules/keybase-bot/README.md b/node_modules/keybase-bot/README.md +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/chat-client/index.d.ts b/node_modules/keybase-bot/lib/chat-client/index.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/chat-client/index.js b/node_modules/keybase-bot/lib/chat-client/index.js +old mode 100644 +new mode 100755 +index a9ea5a9..55aa600 +--- a/node_modules/keybase-bot/lib/chat-client/index.js ++++ b/node_modules/keybase-bot/lib/chat-client/index.js +@@ -66,6 +66,15 @@ var child_process_1 = require("child_process"); + var readline_1 = __importDefault(require("readline")); + var client_base_1 = __importDefault(require("../client-base")); + var utils_1 = require("../utils"); ++ ++// Custom variable, holds working directory of croupier bot ++var croupierDirectory = ""; ++if (process.env.NODE_ENV === 'development') { ++ croupierDirectory = '.'; ++} else { ++ croupierDirectory = '/home/keybase/croupier'; ++} ++ + /** The chat module of your Keybase bot. For more info about the API this module uses, you may want to check out `keybase chat api`. */ + var Chat = /** @class */ (function (_super) { + __extends(Chat, _super); +@@ -638,6 +647,104 @@ var Chat = /** @class */ (function (_super) { + }; + lineReaderStdout.on('line', onLine); + }; ++ // Custom Function that gets the result of flip command ++ Chat.prototype.getFlipData = function (conversationId, flipConversationId, msgId, gameId) { ++ console.log('working dir and homedir:'); ++ console.log(this._workingDir); ++ console.log(this.homeDir); ++ ++ const stdout = []; ++ const stderr = []; ++ ++ const child = child_process_1.spawn(`${croupierDirectory}/scripts/getflipdata.sh`, [ ++ conversationId, ++ flipConversationId, ++ msgId, ++ gameId, ++ this._workingDir, ++ this.homeDir, ++ ]); ++ ++ return new Promise((resolve) => { ++ child.stdout.on('data', (data) => { ++ console.log(`stdout: ${data}`); ++ stdout.push(data.toString('utf8')); ++ }); ++ ++ child.stderr.on('data', (data) => { ++ console.log(`stderr: ${data}`); ++ stderr.push(data.toString('utf8')); ++ }); ++ ++ child.on('close', (code) => { ++ console.log(`child process exited with code ${code}`); ++ console.log('again, stdout:', stdout); ++ console.log('stdout length: ', stdout.length); ++ console.log('stdout 0', stdout[0]); ++ console.log('stdout 1', stdout[1]); ++ resolve([true, stdout[1], stderr]); ++ }); ++ ++ child.on('error', (err) => { ++ console.log(`child process errored with err ${err}`); ++ resolve([err, stdout, stderr]); ++ }); ++ }); ++ } ++ // Custom function that sends money to recipient ++ Chat.prototype.sendMoneyInChat = function (topic, team, amount, recipient, extraParams) { ++ return new Promise((resolve) => { ++ console.log('sendMoneyInChat: 1'); ++ const child = child_process_1.spawn(`${croupierDirectory}/scripts/sendmoney.sh`, [ ++ team, ++ topic, ++ amount, ++ recipient, ++ extraParams, ++ this._workingDir, ++ this.homeDir, ++ ]); ++ ++ const errors = []; ++ ++ child.stdout.on('data', (data) => { ++ console.log(`stdout: ${data}`); ++ }); ++ ++ child.stderr.on('data', (data) => { ++ console.log(`stderr: ${data}`); ++ errors.push(data); ++ }); ++ ++ child.on('close', (code) => { ++ console.log(`child process exited with code ${code}`); ++ resolve(code); ++ }); ++ ++ child.on('error', (err) => { ++ console.log(`child process errored with err ${err}`); ++ errors.push(err); ++ throw JSON.stringify(errors); ++ }); ++ }); ++ } ++ Chat.prototype.edit = async function(channel, messageId, options) { ++ await this._guardInitialized(); ++ const args = { ...options, channel, messageId }; ++ const res = await this._runApiCommand({ ++ apiName: 'chat', ++ method: 'edit', ++ options: args, ++ }); ++ ++ if (!res) { ++ throw new Error('Keybase chat edit returned nothing'); ++ } ++ ++ return { ++ id: res.id, ++ }; ++ } + return Chat; + }(client_base_1.default)); + exports.default = Chat; +diff --git a/node_modules/keybase-bot/lib/chat-client/index.js.map b/node_modules/keybase-bot/lib/chat-client/index.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/chat-client/types.d.ts b/node_modules/keybase-bot/lib/chat-client/types.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/chat-client/types.js b/node_modules/keybase-bot/lib/chat-client/types.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/chat-client/types.js.map b/node_modules/keybase-bot/lib/chat-client/types.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/client-base/index.d.ts b/node_modules/keybase-bot/lib/client-base/index.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/client-base/index.js b/node_modules/keybase-bot/lib/client-base/index.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/client-base/index.js.map b/node_modules/keybase-bot/lib/client-base/index.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/constants.d.ts b/node_modules/keybase-bot/lib/constants.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/constants.js b/node_modules/keybase-bot/lib/constants.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/constants.js.map b/node_modules/keybase-bot/lib/constants.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/index.d.ts b/node_modules/keybase-bot/lib/index.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/index.js b/node_modules/keybase-bot/lib/index.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/index.js.map b/node_modules/keybase-bot/lib/index.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/service/index.d.ts b/node_modules/keybase-bot/lib/service/index.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/service/index.js b/node_modules/keybase-bot/lib/service/index.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/service/index.js.map b/node_modules/keybase-bot/lib/service/index.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/team-client/index.d.ts b/node_modules/keybase-bot/lib/team-client/index.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/team-client/index.js b/node_modules/keybase-bot/lib/team-client/index.js +old mode 100644 +new mode 100755 +index 4169821..26d7652 +--- a/node_modules/keybase-bot/lib/team-client/index.js ++++ b/node_modules/keybase-bot/lib/team-client/index.js +@@ -52,6 +52,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) { + }; + Object.defineProperty(exports, "__esModule", { value: true }); + var client_base_1 = __importDefault(require("../client-base")); ++ ++// Custom variable, holds working directory of croupier bot ++var croupierDirectory = ""; ++if (process.env.NODE_ENV === 'development') { ++ croupierDirectory = '.'; ++} else { ++ croupierDirectory = '/home/keybase/croupier'; ++} ++ + /** The wallet module of your Keybase bot. For more info about the API this module uses, you may want to check out `keybase wallet api`. */ + var Team = /** @class */ (function (_super) { + __extends(Team, _super); +@@ -139,6 +148,29 @@ var Team = /** @class */ (function (_super) { + }); + }); + }; ++ Team.prototype.createSubteam = function (name) { ++ return new Promise((resolve) => { ++ const child = child_process.spawn(`${croupierDirectory}/scripts/createteam.sh`, [name, this._workingDir, this.homeDir]); ++ ++ child.stdout.on('data', (data) => { ++ console.log(`stdout: ${data}`); ++ }); ++ ++ child.stderr.on('data', (data) => { ++ console.log(`stderr: ${data}`); ++ }); ++ ++ child.on('close', (code) => { ++ console.log(`child process exited with code ${code}`); ++ resolve(true); ++ }); ++ ++ child.on('error', (err) => { ++ console.log(`child process errored with err ${err}`); ++ resolve(false); ++ }); ++ }); ++ } + return Team; + }(client_base_1.default)); + exports.default = Team; +diff --git a/node_modules/keybase-bot/lib/team-client/index.js.map b/node_modules/keybase-bot/lib/team-client/index.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/team-client/types.d.ts b/node_modules/keybase-bot/lib/team-client/types.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/team-client/types.js b/node_modules/keybase-bot/lib/team-client/types.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/team-client/types.js.map b/node_modules/keybase-bot/lib/team-client/types.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/formatAPIObject.d.ts b/node_modules/keybase-bot/lib/utils/formatAPIObject.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/formatAPIObject.js b/node_modules/keybase-bot/lib/utils/formatAPIObject.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/formatAPIObject.js.map b/node_modules/keybase-bot/lib/utils/formatAPIObject.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/index.d.ts b/node_modules/keybase-bot/lib/utils/index.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/index.js b/node_modules/keybase-bot/lib/utils/index.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/index.js.map b/node_modules/keybase-bot/lib/utils/index.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/keybaseExec.d.ts b/node_modules/keybase-bot/lib/utils/keybaseExec.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/keybaseExec.js b/node_modules/keybase-bot/lib/utils/keybaseExec.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/keybaseExec.js.map b/node_modules/keybase-bot/lib/utils/keybaseExec.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/keybaseStatus.d.ts b/node_modules/keybase-bot/lib/utils/keybaseStatus.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/keybaseStatus.js b/node_modules/keybase-bot/lib/utils/keybaseStatus.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/keybaseStatus.js.map b/node_modules/keybase-bot/lib/utils/keybaseStatus.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/options.d.ts b/node_modules/keybase-bot/lib/utils/options.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/options.js b/node_modules/keybase-bot/lib/utils/options.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/options.js.map b/node_modules/keybase-bot/lib/utils/options.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/pingKeybaseService.d.ts b/node_modules/keybase-bot/lib/utils/pingKeybaseService.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/pingKeybaseService.js b/node_modules/keybase-bot/lib/utils/pingKeybaseService.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/pingKeybaseService.js.map b/node_modules/keybase-bot/lib/utils/pingKeybaseService.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/randomTempDir.d.ts b/node_modules/keybase-bot/lib/utils/randomTempDir.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/randomTempDir.js b/node_modules/keybase-bot/lib/utils/randomTempDir.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/randomTempDir.js.map b/node_modules/keybase-bot/lib/utils/randomTempDir.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/rmdirRecursive.d.ts b/node_modules/keybase-bot/lib/utils/rmdirRecursive.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/rmdirRecursive.js b/node_modules/keybase-bot/lib/utils/rmdirRecursive.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/rmdirRecursive.js.map b/node_modules/keybase-bot/lib/utils/rmdirRecursive.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/safeJSONStringify.d.ts b/node_modules/keybase-bot/lib/utils/safeJSONStringify.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/safeJSONStringify.js b/node_modules/keybase-bot/lib/utils/safeJSONStringify.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/safeJSONStringify.js.map b/node_modules/keybase-bot/lib/utils/safeJSONStringify.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/timeout.d.ts b/node_modules/keybase-bot/lib/utils/timeout.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/timeout.js b/node_modules/keybase-bot/lib/utils/timeout.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/timeout.js.map b/node_modules/keybase-bot/lib/utils/timeout.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/whichKeybase.d.ts b/node_modules/keybase-bot/lib/utils/whichKeybase.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/whichKeybase.js b/node_modules/keybase-bot/lib/utils/whichKeybase.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/utils/whichKeybase.js.map b/node_modules/keybase-bot/lib/utils/whichKeybase.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/wallet-client/index.d.ts b/node_modules/keybase-bot/lib/wallet-client/index.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/wallet-client/index.js b/node_modules/keybase-bot/lib/wallet-client/index.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/wallet-client/index.js.map b/node_modules/keybase-bot/lib/wallet-client/index.js.map +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/wallet-client/types.d.ts b/node_modules/keybase-bot/lib/wallet-client/types.d.ts +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/wallet-client/types.js b/node_modules/keybase-bot/lib/wallet-client/types.js +old mode 100644 +new mode 100755 +diff --git a/node_modules/keybase-bot/lib/wallet-client/types.js.map b/node_modules/keybase-bot/lib/wallet-client/types.js.map +old mode 100644 +new mode 100755 diff --git a/scratchpad.ts b/scratchpad.ts index 250f19f3..89137852 100644 --- a/scratchpad.ts +++ b/scratchpad.ts @@ -6,7 +6,7 @@ // */ import * as os from "os"; -import * as Bot from "./keybase-bot"; +import * as Bot from "keybase-bot"; import * as _ from "lodash"; import "source-map-support/register"; diff --git a/snipe.ts b/snipe.ts index 707b3418..a6cdd1af 100644 --- a/snipe.ts +++ b/snipe.ts @@ -4,12 +4,13 @@ import * as moment from "moment"; import * as throttledQueue from "throttled-queue"; import Croupier from "./croupier"; // @ts-ignore -import * as Bot from "./keybase-bot"; +import * as Bot from "keybase-bot"; // @ts-ignore -import { ChatChannel, MessageSummary, Transaction } from "./keybase-bot"; +import { ChatChannel, MessageSummary, Transaction } from "keybase-bot"; import { IBetData, IBetList, IParticipant, IPopularityContest, IPositionSize, IPowerup, IPowerupAward, IReactionContent } from "./types"; +import { AddMemberUsernameItem } from "keybase-bot/lib/team-client/types"; type ThrottledChat = (message: string) => Promise; type ThrottledMoneyTransfer = (xlmAmount: number, recipient: string) => Promise; @@ -101,11 +102,12 @@ class Snipe { this.clockRemaining = options.clockRemaining; } - const moneyThrottle: any = throttledQueue(1, 1000); + const moneyThrottle: any = throttledQueue(1, 1000, false); this.moneySend = (amount, recipient, extraParams = "") => { return new Promise((resolveMoneyThrottle) => { moneyThrottle(() => { try { + // @ts-ignore self.bot1.chat.sendMoneyInChat(channel.topicName, channel.name, amount.toString(), recipient, extraParams); resolveMoneyThrottle(); } catch (e) { @@ -575,13 +577,14 @@ class Snipe { name: subteamName, }; + // @ts-ignore self.bot1.team.createSubteam(subteamName).then((res) => { console.log("Subteam creation complete!", res); console.log("Attempting to add people to the team", usernamesToAdd); self.bot1.team .addMembers({ team: subteamName, - usernames: usernamesToAdd, + usernames: usernamesToAdd as AddMemberUsernameItem[], }) .then((addMembersRes) => { console.log("Adding people to the team was successful!", addMembersRes); @@ -721,6 +724,7 @@ class Snipe { public redrawBettingTable(): void { const self: Snipe = this; if (this.bettingTable) { + // @ts-ignore this.bot1.chat.delete(this.channel, this.bettingTable, {}).then(() => { self.chatSend(self.buildBettingTable()).then((msg) => { self.bettingTable = msg.id; @@ -750,6 +754,7 @@ class Snipe { this.bettingStops = moment().add(timerEndsInSeconds, "seconds"); + // @ts-ignore this.bot1.chat.delete(this.channel, this.clock, {}); const self: Snipe = this; const finalizeBetsTimeout: NodeJS.Timeout = setTimeout(() => { @@ -918,6 +923,7 @@ class Snipe { // clear the interval // run the flip again self.bot1.chat + // @ts-ignore .getFlipData(msg.conversationId, msg.content.flip.flipConvId, msg.id, msg.content.flip.gameId) .then((getFlipDataRes) => { console.log("getflipdata res!"); @@ -1006,7 +1012,7 @@ class Snipe { if (seconds < 55) { stopsWhen = `in ${seconds} seconds`; } - console.log(`attempting to edit message ${self.clock} in channel ${self.channel}`); + console.log(`attempting to edit message ${self.clock} in channel ${self.channel.name}`); if (self.clock === null || typeof self.clock === "undefined") { self .chatSend(hourglass + ` betting stops ${stopsWhen}`) @@ -1018,6 +1024,7 @@ class Snipe { }); } else { self.bot1.chat + //@ts-ignore .edit(self.channel, self.clock, { message: { body: hourglass + ` betting stops ${stopsWhen}`, @@ -1043,6 +1050,7 @@ class Snipe { }, 1000); } else { setTimeout(() => { + // @ts-ignore self.bot1.chat.delete(self.channel, self.clock, {}); }, 1000); } diff --git a/tslint.json b/tslint.json index b3a371c4..c818eff6 100644 --- a/tslint.json +++ b/tslint.json @@ -24,6 +24,6 @@ }, "rulesDirectory": [], "linterOptions": { - "exclude": ["scratchpad.ts", "__tests__/*"] + "exclude": ["scratchpad.ts", "__tests__/*", "node_modules/*"] } } diff --git a/types.ts b/types.ts index 85e7771d..3eb17077 100644 --- a/types.ts +++ b/types.ts @@ -1,4 +1,4 @@ -import { ChatChannel, MessageSummary, Transaction } from "./keybase-bot"; +import { ChatChannel, MessageSummary, Transaction } from "keybase-bot"; export interface IReactionContent { type: "reaction";