Compare commits

..

8 Commits

Author SHA1 Message Date
Stefan Zermatten
5ce1b6aff8 closes #210
closes #211
2019-04-03 10:16:24 +02:00
Stefan Zermatten
41731212ef Added application performance monitoring 2019-03-07 14:53:52 +02:00
Stefan Zermatten
ef9867d409 Merge branch 'feature-patreon-accounts' 2019-03-07 13:47:32 +02:00
Stefan Zermatten
721300700e Fixed capitalization error 2019-03-07 13:46:56 +02:00
Stefan Zermatten
bc6dfbe498 Fixed stray quotation mark 2019-03-07 13:45:38 +02:00
Stefan Zermatten
0a22073d67 Added library link for $5 patrons 2019-03-07 13:44:35 +02:00
Stefan Zermatten
857213f157 Improved Patreon linking 2019-03-07 13:35:31 +02:00
Stefan Zermatten
b3371fca53 Added fetching User data from patreon and writing it to the DiceCloud user database 2019-03-06 17:05:44 +02:00
14 changed files with 764 additions and 333 deletions

View File

@@ -37,7 +37,7 @@ changes on the fly. Let's look at a hypothetical example.
Getting started
---------------
Running DiceCloud locally, either to host it yourself away from an internet
Running DiceCloud locally, either to run it locally, away from an internet
connection, or to contribute to developing it further, is fairly
straightforward and it should work on Linux, Windows, and Mac.
@@ -45,18 +45,29 @@ You'll need to have installed:
- [git](https://www.atlassian.com/git/tutorials/install-git)
- [Meteor](https://www.meteor.com/install)
- [Bower](https://bower.io/)
Then, it's just a matter of cloning this repository into a folder, installing the bower dependencies and running
`meteor` in the app directory.
Then, it's just a matter of cloning this repository into a folder, installing the dependencies and running
`meteor` in the app directory:
`git clone https://github.com/ThaumRystra/DiceCloud dicecloud`
`cd dicecloud`
`cd app`
`bower install`
`meteor npm install`
`meteor`
You should see this:
If you edit the source code at this point, Meteor will rebuild the server with
your changes.
If you want to simulate a production environment, run `meteor --production`
This will minimize all the files served to your browser, and load a lot faster,
in exchange for not watching the source code for changes.
Note that this is not how you should deploy Meteor to your own web server, that
is documented here: https://guide.meteor.com/deployment.html
After running `meteor` or `meteor --production`, you should see this, possibly
mixed with other logged text:
```
=> Started proxy.
@@ -69,3 +80,14 @@ You should see this:
Now, visiting http://localhost:3000/ should show you an empty instance of
DiceCloud running.
To stop the process when you are done (or if it gets stuck) press `ctrl-c`
## Adding default documents
Navigate to `/dataSources/srd/srdimport.js`, and follow the steps under
'First Setup', running the code in your browser's console, while logged in to
your own instance of DiceCloud.
Do not run code in your browser console on the live version of DiceCloud hosted
at dicecloud.com, as doing so could result in a large number of denied requests
to the server, and may get your account permanently banned.

View File

@@ -27,7 +27,7 @@ meteor-base@1.4.0
mobile-experience@1.0.5
mongo@1.6.0
blaze-html-templates
session@1.1.8
session@1.2.0
jquery@1.11.10
tracker@1.2.0
logging@1.1.20
@@ -36,13 +36,11 @@ ejson@1.1.0
spacebars
check@1.3.1
useraccounts:iron-routing
wizonesolutions:canonical
standard-minifier-js@2.4.0
shell-server@0.4.0
seba:minifiers-autoprefixer
nikogosovd:multiple-uihooks
templates:array
ecmascript@0.12.0
ecmascript@0.12.4
es5-shim@4.8.0
differential:vulcanize
reactive-dict@1.2.1
@@ -54,3 +52,5 @@ ddp-rate-limiter@1.0.7
rate-limit@1.0.9
iron:router
littledata:synced-cron
montiapm:agent
zodern:standard-minifier-js

View File

@@ -1 +1 @@
METEOR@1.8
METEOR@1.8.0.2

View File

@@ -3,15 +3,15 @@ accounts-google@1.3.2
accounts-oauth@1.1.16
accounts-password@1.5.1
accounts-ui@1.3.1
accounts-ui-unstyled@1.4.1
accounts-ui-unstyled@1.4.2
aldeed:collection2@2.10.0
aldeed:collection2-core@1.2.0
aldeed:schema-deny@1.1.0
aldeed:schema-index@1.1.1
aldeed:simple-schema@1.5.4
allow-deny@1.1.0
autoupdate@1.5.0
babel-compiler@7.2.0
autoupdate@1.5.1
babel-compiler@7.2.4
babel-runtime@1.3.0
base64@1.0.11
binary-heap@1.0.11
@@ -19,7 +19,7 @@ blaze@2.3.3
blaze-html-templates@1.1.2
blaze-tools@1.0.10
boilerplate-generator@1.6.0
caching-compiler@1.2.0
caching-compiler@1.2.1
caching-html-compiler@1.1.3
callback-hook@1.1.0
check@1.3.1
@@ -33,10 +33,10 @@ ddp-common@1.4.0
ddp-rate-limiter@1.0.7
ddp-server@2.2.0
deps@1.0.12
diff-sequence@1.1.0
diff-sequence@1.1.1
differential:vulcanize@3.0.0
dynamic-import@0.5.0
ecmascript@0.12.0
dynamic-import@0.5.1
ecmascript@0.12.6
ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.8.0
ecmascript-runtime-server@0.7.1
@@ -44,14 +44,14 @@ ecwyne:mathjs@0.25.0
ejson@1.1.0
email@1.2.3
es5-shim@4.8.0
fetch@0.1.0
fetch@0.1.1
geojson-utils@1.0.10
google-config-ui@1.0.1
google-oauth@1.2.6
hot-code-push@1.0.4
html-tools@1.0.11
htmljs@1.0.11
http@1.4.1
http@1.4.2
id-map@1.1.0
inter-process-messaging@0.1.0
iron:controller@1.0.12
@@ -64,6 +64,7 @@ iron:router@1.1.2
iron:url@1.1.0
jquery@1.11.11
lai:collection-extensions@0.2.1_1
lamhieu:meteorx@2.0.1
launch-screen@1.1.1
less@2.8.0
littledata:synced-cron@1.5.1
@@ -72,32 +73,33 @@ localstorage@1.2.0
logging@1.1.20
matb33:collection-hooks@0.8.4
mdg:validation-error@0.5.1
meteor@1.9.2
meteor@1.9.3
meteor-base@1.4.0
meteorhacks:subs-manager@1.6.4
minifier-css@1.4.0
minifier-js@2.4.0
minifier-css@1.4.2
minimongo@1.4.5
mobile-experience@1.0.5
mobile-status-bar@1.0.14
modern-browsers@0.1.2
modern-browsers@0.1.4
modules@0.13.0
modules-runtime@0.10.2
momentjs:moment@2.22.2
mongo@1.6.0
mongo-decimal@0.1.0
modules-runtime@0.10.3
momentjs:moment@2.24.0
mongo@1.6.2
mongo-decimal@0.1.1
mongo-dev-server@1.1.0
mongo-id@1.0.7
mongo-livedata@1.0.12
montiapm:agent@2.35.0
nikogosovd:multiple-uihooks@0.1.8
npm-bcrypt@0.9.3
npm-mongo@3.1.1
oauth@1.2.3
npm-mongo@3.1.2
oauth@1.2.8
oauth2@1.2.1
observe-sequence@1.0.16
ongoworks:speakingurl@9.0.0
ordered-dict@1.1.0
percolate:migrations@0.9.8
promise@0.11.1
promise@0.11.2
raix:eventemitter@0.1.3
random@1.1.0
rate-limit@1.0.9
@@ -107,9 +109,9 @@ reload@1.2.0
retry@1.1.0
reywood:iron-router-ga@0.7.1
routepolicy@1.1.0
seba:minifiers-autoprefixer@1.1.1
seba:minifiers-autoprefixer@1.1.2
service-configuration@1.0.11
session@1.1.8
session@1.2.0
sha@1.0.9
shell-server@0.4.0
socket-stream-client@0.2.2
@@ -119,7 +121,6 @@ spacebars-compiler@1.1.3
splendido:accounts-emails-field@1.2.0
splendido:accounts-meld@1.3.1
srp@1.0.12
standard-minifier-js@2.4.0
templates:array@1.0.3
templating@1.3.2
templating-compiler@1.3.3
@@ -132,8 +133,9 @@ url@1.2.0
useraccounts:core@1.14.2
useraccounts:iron-routing@1.14.2
useraccounts:polymer@1.14.2
webapp@1.7.0
webapp@1.7.3
webapp-hashing@1.0.9
wizonesolutions:canonical@0.0.5
zimme:collection-behaviours@1.1.3
zimme:collection-softremovable@1.0.5
zodern:minifier-js@3.0.0
zodern:standard-minifier-js@3.0.0

View File

@@ -74,6 +74,41 @@ Schemas.User = new SimpleSchema({
type: String,
optional: true,
},
patreon: {
type: Object,
optional: true,
},
"patreon.accessToken": {
type: String,
optional: true,
},
"patreon.refreshToken": {
type: String,
optional: true,
},
"patreon.tokenExpiryDate": {
type: Date,
optional: true,
},
"patreon.userId": {
type: String,
optional: true,
index: 1,
},
"patreon.entitledCents": {
type: Number,
decimal: false,
optional: true,
},
"patreon.entitledCentsOverride": {
type: Number,
decimal: false,
optional: true,
},
"patreon.error": {
type: String,
optional: true,
},
});
Meteor.users.attachSchema(Schemas.User);

View File

@@ -21,6 +21,9 @@
<a href="/account" style="text-decoration: underline; cursor: pointer; font-size: 16px;">
{{profileLink}}
</a>
<a href="/account" style="text-decoration: underline; cursor: pointer; font-size: 16px; margin-left: 8px;">
{{patreonTier}} tier
</a>
{{else}}
<a href="/sign-in" style="text-decoration: underline; cursor: pointer; font-size: 16px;">
Sign in
@@ -41,6 +44,14 @@
Characters
</paper-icon-item>
</a>
{{#if isTier5}}
<a href="/library" tabindex="-1">
<paper-icon-item id="libary">
<iron-icon icon="book" item-icon></iron-icon>
Library (beta)
</paper-icon-item>
</a>
{{/if}}
<a href="/guide" tabindex="-1">
<paper-icon-item id="guide">
<iron-icon icon="social:school" item-icon></iron-icon>

View File

@@ -17,6 +17,27 @@ Template.appDrawer.helpers({
let post = PatreonPosts.findOne({}, {sort: {date: -1}});
return (post && post.link) || 'https://www.patreon.com/dicecloud';
},
isTier5: function(){
let user = Meteor.user();
if (!user) return false;
patreon = user.patreon;
if (!patreon) return false;
return patreon.entitledCents >= 500 || patreon.entitledCentsOverride >= 500;
},
patreonTier: function(){
let user = Meteor.user();
if (!user) return;
patreon = user.patreon;
if (!patreon) return "free";
let entitledCents = patreon.entitledCents || 0;
if (patreon.entitledCentsOverride > entitledCents){
return "$" + (patreon.entitledCentsOverride / 100).toFixed(0);
} else if (!patreon.entitledCents){
return "free";
} else {
return "$" + (patreon.entitledCents / 100).toFixed(0);
}
},
});
let drawerLayout;

View File

@@ -62,6 +62,28 @@
{{/if}}
</td>
</tr>
<tr>
<td>
Patreon
</td>
{{#if patreon.accessToken}}
<td>
{{tier}} tier
</td>
<td>
<paper-icon-button icon="refresh" class="refreshPatreon">
</paper-icon-button>
</td>
{{else}}
<td>
<a href="{{patreonLoginUrl}}">
<paper-button raised class="connectPatreon">
Connect Patreon account
</paper-button>
</a>
</td>
{{/if}}
</tr>
</table>
<div style="max-width: 250px">
{{> atForm state="signIn"}}

View File

@@ -1,5 +1,10 @@
import { format as formatUrl } from 'url';
const CLIENT_ID = Meteor.settings.public.patreon.clientId;
Template.profile.onCreated(function(){
this.showApiKey = new ReactiveVar(false);
this.loadingPatreon = new ReactiveVar(false);
});
Template.profile.helpers({
@@ -12,6 +17,40 @@ Template.profile.helpers({
showApiKey: function(){
return Template.instance().showApiKey.get();
},
patreonLoginUrl: function(){
return formatUrl({
protocol: 'https',
host: 'patreon.com',
pathname: '/oauth2/authorize',
query: {
response_type: 'code',
client_id: CLIENT_ID,
redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect',
state: Meteor.userId(),
scope: 'identity',
},
});
},
patreon: function(){
let user = Meteor.user();
return user && user.patreon || {};
},
tier: function(){
let user = Meteor.user();
if (!user) return;
patreon = user.patreon;
if (!patreon) return;
let entitledCents = patreon.entitledCents || 0;
if (Template.instance().loadingPatreon.get()){
return "loading..."
} else if (patreon.entitledCentsOverride > entitledCents){
return `$ ${(patreon.entitledCentsOverride / 100).toFixed(0)} (overridden)`;
} else if (patreon.entitledCents === undefined){
return "?";
} else {
return "$" + (patreon.entitledCents / 100).toFixed(0);
}
},
});
Template.profile.events({
@@ -39,4 +78,10 @@ Template.profile.events({
Meteor.call("generateMyApiKey");
instance.showApiKey.set(true);
},
"click .refreshPatreon": function(event, instance){
instance.loadingPatreon.set(true);
Meteor.call("updateMyPatreonDetails", (error) => {
instance.loadingPatreon.set(false);
});
},
});

583
app/package-lock.json generated
View File

@@ -26,21 +26,14 @@
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
"integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
"requires": {
"co": "^4.6.0",
"fast-deep-equal": "^1.0.0",
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.3.0"
},
"dependencies": {
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
}
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"ansi-regex": {
@@ -53,16 +46,34 @@
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"bcrypt": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz",
@@ -72,6 +83,14 @@
"node-pre-gyp": "0.6.36"
}
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"requires": {
"tweetnacl": "^0.14.3"
}
},
"block-stream": {
"version": "0.0.9",
"resolved": false,
@@ -81,9 +100,9 @@
}
},
"bower": {
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz",
"integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo="
"version": "1.8.8",
"resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz",
"integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A=="
},
"buffer-from": {
"version": "1.1.1",
@@ -108,6 +127,11 @@
"window-or-global": "^1.0.1"
}
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
@@ -135,6 +159,14 @@
"resolved": false,
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"core-js": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
@@ -155,6 +187,14 @@
"which": "^1.2.9"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -168,11 +208,33 @@
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"dijkstrajs": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz",
"integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs="
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"encoding": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
"requires": {
"iconv-lite": "~0.4.13"
}
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -195,15 +257,20 @@
"strip-eof": "^1.0.0"
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
},
"fast-json-stable-stringify": {
"version": "2.0.0",
@@ -228,36 +295,26 @@
"locate-path": "^2.0.0"
}
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "1.0.6",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
},
"dependencies": {
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"combined-stream": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
}
}
},
"form-urlencoded": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/form-urlencoded/-/form-urlencoded-2.0.9.tgz",
"integrity": "sha512-fWUzNiOnYa126vFAT6TFXd1mhJrvD8IqmQ9ilZPjkLYQfaRreBr5fIUoOpPlWtqaAG64nzoE7u5zSetifab9IA=="
},
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
@@ -268,6 +325,14 @@
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"graceful-fs": {
"version": "4.1.11",
"resolved": false,
@@ -279,11 +344,11 @@
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
"requires": {
"ajv": "^5.1.0",
"ajv": "^6.5.5",
"har-schema": "^2.0.0"
}
},
@@ -300,74 +365,14 @@
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
},
"dependencies": {
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"optional": true,
"requires": {
"tweetnacl": "^0.14.3"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true,
"requires": {
"jsbn": "~0.1.0"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"sshpk": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
"integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"tweetnacl": "~0.14.0"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
}
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"inherits": {
@@ -401,11 +406,24 @@
"number-is-nan": "^1.0.0"
}
},
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"requires": {
"isobject": "^3.0.1"
}
},
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isarray": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz",
@@ -416,10 +434,49 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
},
"isomorphic-fetch": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
"integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
"requires": {
"node-fetch": "^1.0.1",
"whatwg-fetch": ">=0.10.0"
}
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsonapi-datastore": {
"version": "0.4.0-beta",
"resolved": "https://registry.npmjs.org/jsonapi-datastore/-/jsonapi-datastore-0.4.0-beta.tgz",
"integrity": "sha1-tJn86STUXivDxheGgVIAY+I2HxA="
},
"jsprim": {
"version": "1.4.1",
@@ -430,13 +487,6 @@
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
},
"dependencies": {
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
}
}
},
"lcid": {
@@ -1076,37 +1126,6 @@
"requires": {
"inherits": "~2.0.1",
"readable-stream": "^2.0.2"
},
"dependencies": {
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"stream-http": {
@@ -1119,37 +1138,6 @@
"readable-stream": "^2.3.3",
"to-arraybuffer": "^1.0.0",
"xtend": "^4.0.0"
},
"dependencies": {
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"string_decoder": {
@@ -1228,16 +1216,16 @@
}
},
"mime-db": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
"version": "1.38.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
"integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
},
"mime-types": {
"version": "2.1.18",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
"version": "2.1.22",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
"integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
"requires": {
"mime-db": "~1.33.0"
"mime-db": "~1.38.0"
}
},
"mimic-fn": {
@@ -1255,6 +1243,15 @@
"resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
"integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U="
},
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
"requires": {
"encoding": "^0.1.11",
"is-stream": "^1.0.1"
}
},
"node-pre-gyp": {
"version": "0.6.36",
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz",
@@ -1511,6 +1508,11 @@
"resolved": false,
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@@ -1592,6 +1594,17 @@
"pify": "^2.0.0"
}
},
"patreon": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/patreon/-/patreon-0.4.1.tgz",
"integrity": "sha512-aLhjx4rg2BArTq0Kg61MrM4dkJnTQ9kPN8F6a2IlQoYVEtIH7kUK/dprClTx+QYQKlXMfKksN9NCux1YarQJsQ==",
"requires": {
"form-urlencoded": "^2.0.4",
"is-plain-object": "^2.0.4",
"isomorphic-fetch": "^2.2.1",
"jsonapi-datastore": "^0.4.0-beta"
}
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -1612,6 +1625,16 @@
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"psl": {
"version": "1.1.31",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"qrcode": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.3.0.tgz",
@@ -1687,103 +1710,30 @@
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
},
"request": {
"version": "2.87.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
"integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.6.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.5",
"extend": "~3.0.1",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.1",
"har-validator": "~5.0.3",
"form-data": "~2.3.2",
"har-validator": "~5.1.0",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.17",
"oauth-sign": "~0.8.2",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.1",
"safe-buffer": "^5.1.1",
"tough-cookie": "~2.3.3",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.4.3",
"tunnel-agent": "^0.6.0",
"uuid": "^3.1.0"
},
"dependencies": {
"aws4": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
"integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w=="
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"combined-stream": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"extend": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"oauth-sign": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"uuid": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
}
"uuid": "^3.3.2"
}
},
"require-directory": {
@@ -1883,6 +1833,16 @@
}
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
@@ -1953,6 +1913,22 @@
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
"integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w=="
},
"sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -2164,10 +2140,11 @@
}
},
"tough-cookie": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
"requires": {
"psl": "^1.1.24",
"punycode": "^1.4.1"
},
"dependencies": {
@@ -2178,11 +2155,37 @@
}
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"underscore": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
},
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"requires": {
"punycode": "^2.1.0"
}
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@@ -2200,13 +2203,6 @@
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
},
"dependencies": {
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
}
}
},
"webcomponents.js": {
@@ -2214,6 +2210,11 @@
"resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz",
"integrity": "sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ="
},
"whatwg-fetch": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
"integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",

View File

@@ -14,12 +14,14 @@
"@babel/runtime": "^7.1.2",
"@polymer/polymer": "^1.2.5-npm-test.2",
"bcrypt": "^1.0.3",
"bower": "^1.7.9",
"bower": "^1.8.8",
"core-js": "^2.5.7",
"fibers": "^2.0.2",
"file-saver": "^2.0.1",
"meteor-node-stubs": "^0.3.3",
"patreon": "^0.4.1",
"qrcode": "^1.3.0",
"request": "^2.88.0",
"source-map-support": "^0.5.9",
"underscore": "^1.9.1"
}

View File

@@ -0,0 +1,262 @@
import request from 'request';
if (
Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.patreon
) {
const CLIENT_ID = Meteor.settings.public.patreon.clientId;
const CLIENT_SECRET = Meteor.settings.patreon.clientSecret;
const CREATOR_ACCESS_TOKEN = Meteor.settings.patreon.creatorAccessToken;
const CAMPAIGN_ID = Meteor.settings.public.patreon.campaignId;
// Handle redirects from patreon
Router.map(function () {
this.route("patreon-redirect", {
path: "/patreon-redirect",
where: "server",
action: function () {
let route = this;
let userId = route.params.query.state;
let singleUseCode = route.params.query.code;
requestToken(singleUseCode, Meteor.bindEnvironment((error, response, body) => {
// Should return an access token, valid for 1 month, which needs to be
// stored and used to make requests on behalf of the user
if (error){
writePatreonError(userId, error);
return;
}
let token;
try {
token = JSON.parse(body);
writePatreonToken(userId, token);
} catch(error) {
writePatreonError(userId, error);
return;
}
updateIdentity(token.access_token, userId);
}));
route.response.writeHead(302, {
'Location': Meteor.absoluteUrl() + "account",
});
route.response.end();
},
});
});
const requestToken = function(singleUseCode, callback){
request({
method: "POST",
uri: "https://www.patreon.com/api/oauth2/token",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
qs: {
code: singleUseCode,
grant_type: "authorization_code",
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect',
},
}, callback);
}
const getIdentity = function(accessToken, callback){
request({
uri: "https://www.patreon.com/api/oauth2/v2/identity",
headers:{
Authorization: "Bearer " + accessToken,
},
qs: {
"include": "memberships",
"fields[member]": "currently_entitled_amount_cents",
}
}, callback);
};
// Should return a new access token for the user
// callback is called with (error, response, body)
const refreshAccessToken = Meteor.wrapAsync(function(refreshToken, userId, callback){
request({
method: "POST",
uri: "https://www.patreon.com/api/oauth2/token",
qs: {
grant_type: "refresh_token",
refresh_token: refreshToken,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
}
}, Meteor.bindEnvironment((error, response, body) => {
// Should return an access token, valid for 1 month, which needs to be
// stored and used to make requests on behalf of the user
if (error){
callback(error)
return;
}
let token;
try {
token = JSON.parse(body);
writePatreonToken(userId, token);
callback(undefined, token.access_token);
} catch(error) {
callback(error);
}
}));
});
const updateIdentity = Meteor.wrapAsync(function(accessToken, userId, callback){
getIdentity(accessToken, Meteor.bindEnvironment((error, response, body) => {
if (error){
writePatreonError(userId, error);
return;
}
try {
let identity = JSON.parse(body);
let membership = identity.included[0];
let entitledAmount = membership && membership.attributes
.currently_entitled_amount_cents || 0;
let patreonUserId = identity.data.id;
writeEntitledCentsAndId(userId, entitledAmount, patreonUserId);
if (callback) callback();
} catch(error) {
writePatreonError(userId, error);
if(callback) callback(error);
}
}));
});
Meteor.methods({
updateMyPatreonDetails(){
const userId = this.userId;
if (!userId) throw new Meteor.Error("not-logged-in", "You must be logged in to update Patreon details");
const user = Meteor.users.findOne(userId, {fields: {patreon: 1}});
Meteor.users.update(userId, {$unset: {"patreon.entitledCents": 1}});
if (!user.patreon || !user.patreon.accessToken){
throw new Meteor.Error("no-patreon-access", "Patreon access token not found for this user");
}
let accessToken = user.patreon.accessToken;
if (user.patreon.tokenExpiryDate < new Date()){
// Token expired, refresh it before continuing
accessToken = refreshAccessToken(user.patreon.refreshToken, userId);
}
updateIdentity(accessToken, userId);
},
});
const writePatreonToken = function(userId, {
access_token, refresh_token, expires_in
}){
// The expiry date is now plus `expires_in` seconds
let expiryDate = new Date();
expiryDate.setSeconds(expiryDate.getSeconds() + expires_in);
// Expire a day early so we don't accidentally miss it
expiryDate.setDate(expiryDate.getDate() - 1);
// Write
Meteor.users.update(userId, {
$set: {
"patreon.accessToken": access_token,
"patreon.refreshToken": refresh_token,
"patreon.tokenExpiryDate": expiryDate,
},
$unset: {
"patreon.error": 1,
},
});
};
const writeEntitledCentsAndId = function(userId, amount, patreonUserId){
Meteor.users.update(userId, {
$set: {
"patreon.entitledCents": amount,
"patreon.userId": patreonUserId,
},
$unset: {
"patreon.error": 1,
},
});
};
const writePatreonError = function(userId, error){
console.error({patreonError: error});
Meteor.users.update(userId, {
$set: {
"patreon.error": error.toString(),
},
});
}
const requestMembers = Meteor.wrapAsync(function(cursor, members, callback){
request({
uri: `https://www.patreon.com/api/oauth2/v2/campaigns/${CAMPAIGN_ID}/members`,
headers:{
Authorization: "Bearer " + CREATOR_ACCESS_TOKEN,
},
qs: {
"include": "user",
"fields[member]": "currently_entitled_amount_cents",
"page[cursor]": cursor,
}
}, (error, reponse, body) => {
if (error){
callback(error);
return;
}
let json = JSON.parse(body);
if (json.errors) {
callback(json.errors);
return;
}
let newMembers = json.data.map(member => ({
id: member.relationships.user.data.id,
entitledCents: member.attributes.currently_entitled_amount_cents,
}));
members.push(...newMembers);
let next = json.meta.pagination.cursors && json.meta.pagination.cursors.next;
if (next){
callback(undefined, next);
} else {
callback(undefined);
}
});
});
const updatePatreonMembersEntitledCents = function(){
let next = "";
let members = [];
do {
next = requestMembers(next, members);
} while (next)
members.forEach(({id, entitledCents}) => {
Meteor.users.update({
"patreon.userId": id
}, {$set: {
"patreon.entitledCents":entitledCents,
}});
});
return members;
}
// Method to run a manual update
Meteor.methods({
updatePatreonMembersEntitledCents(){
const user = Meteor.users.findOne(this.userId);
if (!user || !_.contains(user.roles, "admin")) throw new Meteor.Error(
"permission-error", "You need to be logged in as an admin to run this method"
);
return updatePatreonMembersEntitledCents();
},
});
// Cron job to run the update automatically
Meteor.startup(() => {
SyncedCron.add({
name: "updatePatreonMembersEntitledCents",
schedule: function(parser) {
return parser.text('every 4 hours');
},
job: updatePatreonMembersEntitledCents,
});
})
}

View File

@@ -7,6 +7,7 @@ Meteor.publish("user", function(){
apiKey: 1,
librarySubscriptions: 1,
lastPatreonPostClicked: 1,
patreon: 1,
}}),
PatreonPosts.find({},{sort: {dateAdded: -1}, limit: 1})
];

View File

@@ -1,6 +1,9 @@
// This all gets run in the console by an admin.
// Probably a good idea to reset the server after running big updates
// Only do if the library doesn't exist yet
// First Setup
// -----------
// Add the SRD library with the correct static ID:
id = Libraries.insert({
_id: "SRDLibraryGA3XWsd",
owner: Meteor.userId(),
@@ -8,19 +11,23 @@ id = Libraries.insert({
});
// First copy-paste the JSON into your console like `items = <pasted JSON>`
// First import, don't do this if the library is already populated
_.each(items, (item) => {
item.settings = {category: }; // "adventuringGear", "armor", "weapons", "tools"
// replace "adventuringGear" with appropriate category: "armor", "weapons", "tools"
// if needed
item.settings = {category: "adventuringGear"};
item.library = "SRDLibraryGA3XWsd"
LibraryItems.insert(item)
});
// First copy-paste the JSON into your console like `spells = <pasted JSON>`
_.each(spells, (spell) => {
spell.library = "SRDLibraryGA3XWsd"
LibrarySpells.insert(spell)
});
// Update the library using names as keys
// Updating the Libary
// -------------------
// Make sure you're subscribed to all item categories
handles = _.map(["weapons", "armor", "adventuringGear", "tools"],
category => Meteor.subscribe("standardLibraryItems", category)