Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce1b6aff8 | ||
|
|
41731212ef | ||
|
|
ef9867d409 | ||
|
|
721300700e | ||
|
|
bc6dfbe498 | ||
|
|
0a22073d67 | ||
|
|
857213f157 | ||
|
|
b3371fca53 | ||
|
|
3fbb006783 | ||
|
|
2253672f43 | ||
|
|
ed6d557f8a | ||
|
|
4d642b56bb | ||
|
|
cb71f6d380 | ||
|
|
2f04d9ec1c | ||
|
|
40c54524a7 | ||
|
|
b890a3b11e | ||
|
|
c9242a95f3 | ||
|
|
fedda62c7c | ||
|
|
612575d0e6 | ||
|
|
d1d22c0d89 | ||
|
|
b94f5ebb4b |
34
README.md
34
README.md
@@ -37,7 +37,7 @@ changes on the fly. Let's look at a hypothetical example.
|
|||||||
Getting started
|
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
|
connection, or to contribute to developing it further, is fairly
|
||||||
straightforward and it should work on Linux, Windows, and Mac.
|
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)
|
- [git](https://www.atlassian.com/git/tutorials/install-git)
|
||||||
- [Meteor](https://www.meteor.com/install)
|
- [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
|
Then, it's just a matter of cloning this repository into a folder, installing the dependencies and running
|
||||||
`meteor` in the app directory.
|
`meteor` in the app directory:
|
||||||
|
|
||||||
`git clone https://github.com/ThaumRystra/DiceCloud dicecloud`
|
`git clone https://github.com/ThaumRystra/DiceCloud dicecloud`
|
||||||
`cd dicecloud`
|
`cd dicecloud`
|
||||||
`cd app`
|
`cd app`
|
||||||
`bower install`
|
`meteor npm install`
|
||||||
`meteor`
|
`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.
|
=> Started proxy.
|
||||||
@@ -69,3 +80,14 @@ You should see this:
|
|||||||
Now, visiting http://localhost:3000/ should show you an empty instance of
|
Now, visiting http://localhost:3000/ should show you an empty instance of
|
||||||
DiceCloud running.
|
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.
|
||||||
|
|||||||
1
app/.gitignore
vendored
1
app/.gitignore
vendored
@@ -8,4 +8,5 @@ private/oldClient
|
|||||||
nohup.out
|
nohup.out
|
||||||
node_modules
|
node_modules
|
||||||
dump
|
dump
|
||||||
|
.idea/
|
||||||
.cache
|
.cache
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ meteor-base@1.4.0
|
|||||||
mobile-experience@1.0.5
|
mobile-experience@1.0.5
|
||||||
mongo@1.6.0
|
mongo@1.6.0
|
||||||
blaze-html-templates
|
blaze-html-templates
|
||||||
session@1.1.8
|
session@1.2.0
|
||||||
jquery@1.11.10
|
jquery@1.11.10
|
||||||
tracker@1.2.0
|
tracker@1.2.0
|
||||||
logging@1.1.20
|
logging@1.1.20
|
||||||
@@ -36,13 +36,11 @@ ejson@1.1.0
|
|||||||
spacebars
|
spacebars
|
||||||
check@1.3.1
|
check@1.3.1
|
||||||
useraccounts:iron-routing
|
useraccounts:iron-routing
|
||||||
wizonesolutions:canonical
|
|
||||||
standard-minifier-js@2.4.0
|
|
||||||
shell-server@0.4.0
|
shell-server@0.4.0
|
||||||
seba:minifiers-autoprefixer
|
seba:minifiers-autoprefixer
|
||||||
nikogosovd:multiple-uihooks
|
nikogosovd:multiple-uihooks
|
||||||
templates:array
|
templates:array
|
||||||
ecmascript@0.12.0
|
ecmascript@0.12.4
|
||||||
es5-shim@4.8.0
|
es5-shim@4.8.0
|
||||||
differential:vulcanize
|
differential:vulcanize
|
||||||
reactive-dict@1.2.1
|
reactive-dict@1.2.1
|
||||||
@@ -54,3 +52,5 @@ ddp-rate-limiter@1.0.7
|
|||||||
rate-limit@1.0.9
|
rate-limit@1.0.9
|
||||||
iron:router
|
iron:router
|
||||||
littledata:synced-cron
|
littledata:synced-cron
|
||||||
|
montiapm:agent
|
||||||
|
zodern:standard-minifier-js
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
METEOR@1.8
|
METEOR@1.8.0.2
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ accounts-google@1.3.2
|
|||||||
accounts-oauth@1.1.16
|
accounts-oauth@1.1.16
|
||||||
accounts-password@1.5.1
|
accounts-password@1.5.1
|
||||||
accounts-ui@1.3.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@2.10.0
|
||||||
aldeed:collection2-core@1.2.0
|
aldeed:collection2-core@1.2.0
|
||||||
aldeed:schema-deny@1.1.0
|
aldeed:schema-deny@1.1.0
|
||||||
aldeed:schema-index@1.1.1
|
aldeed:schema-index@1.1.1
|
||||||
aldeed:simple-schema@1.5.4
|
aldeed:simple-schema@1.5.4
|
||||||
allow-deny@1.1.0
|
allow-deny@1.1.0
|
||||||
autoupdate@1.5.0
|
autoupdate@1.5.1
|
||||||
babel-compiler@7.2.0
|
babel-compiler@7.2.4
|
||||||
babel-runtime@1.3.0
|
babel-runtime@1.3.0
|
||||||
base64@1.0.11
|
base64@1.0.11
|
||||||
binary-heap@1.0.11
|
binary-heap@1.0.11
|
||||||
@@ -19,7 +19,7 @@ blaze@2.3.3
|
|||||||
blaze-html-templates@1.1.2
|
blaze-html-templates@1.1.2
|
||||||
blaze-tools@1.0.10
|
blaze-tools@1.0.10
|
||||||
boilerplate-generator@1.6.0
|
boilerplate-generator@1.6.0
|
||||||
caching-compiler@1.2.0
|
caching-compiler@1.2.1
|
||||||
caching-html-compiler@1.1.3
|
caching-html-compiler@1.1.3
|
||||||
callback-hook@1.1.0
|
callback-hook@1.1.0
|
||||||
check@1.3.1
|
check@1.3.1
|
||||||
@@ -33,10 +33,10 @@ ddp-common@1.4.0
|
|||||||
ddp-rate-limiter@1.0.7
|
ddp-rate-limiter@1.0.7
|
||||||
ddp-server@2.2.0
|
ddp-server@2.2.0
|
||||||
deps@1.0.12
|
deps@1.0.12
|
||||||
diff-sequence@1.1.0
|
diff-sequence@1.1.1
|
||||||
differential:vulcanize@3.0.0
|
differential:vulcanize@3.0.0
|
||||||
dynamic-import@0.5.0
|
dynamic-import@0.5.1
|
||||||
ecmascript@0.12.0
|
ecmascript@0.12.6
|
||||||
ecmascript-runtime@0.7.0
|
ecmascript-runtime@0.7.0
|
||||||
ecmascript-runtime-client@0.8.0
|
ecmascript-runtime-client@0.8.0
|
||||||
ecmascript-runtime-server@0.7.1
|
ecmascript-runtime-server@0.7.1
|
||||||
@@ -44,14 +44,14 @@ ecwyne:mathjs@0.25.0
|
|||||||
ejson@1.1.0
|
ejson@1.1.0
|
||||||
email@1.2.3
|
email@1.2.3
|
||||||
es5-shim@4.8.0
|
es5-shim@4.8.0
|
||||||
fetch@0.1.0
|
fetch@0.1.1
|
||||||
geojson-utils@1.0.10
|
geojson-utils@1.0.10
|
||||||
google-config-ui@1.0.1
|
google-config-ui@1.0.1
|
||||||
google-oauth@1.2.6
|
google-oauth@1.2.6
|
||||||
hot-code-push@1.0.4
|
hot-code-push@1.0.4
|
||||||
html-tools@1.0.11
|
html-tools@1.0.11
|
||||||
htmljs@1.0.11
|
htmljs@1.0.11
|
||||||
http@1.4.1
|
http@1.4.2
|
||||||
id-map@1.1.0
|
id-map@1.1.0
|
||||||
inter-process-messaging@0.1.0
|
inter-process-messaging@0.1.0
|
||||||
iron:controller@1.0.12
|
iron:controller@1.0.12
|
||||||
@@ -64,6 +64,7 @@ iron:router@1.1.2
|
|||||||
iron:url@1.1.0
|
iron:url@1.1.0
|
||||||
jquery@1.11.11
|
jquery@1.11.11
|
||||||
lai:collection-extensions@0.2.1_1
|
lai:collection-extensions@0.2.1_1
|
||||||
|
lamhieu:meteorx@2.0.1
|
||||||
launch-screen@1.1.1
|
launch-screen@1.1.1
|
||||||
less@2.8.0
|
less@2.8.0
|
||||||
littledata:synced-cron@1.5.1
|
littledata:synced-cron@1.5.1
|
||||||
@@ -72,32 +73,33 @@ localstorage@1.2.0
|
|||||||
logging@1.1.20
|
logging@1.1.20
|
||||||
matb33:collection-hooks@0.8.4
|
matb33:collection-hooks@0.8.4
|
||||||
mdg:validation-error@0.5.1
|
mdg:validation-error@0.5.1
|
||||||
meteor@1.9.2
|
meteor@1.9.3
|
||||||
meteor-base@1.4.0
|
meteor-base@1.4.0
|
||||||
meteorhacks:subs-manager@1.6.4
|
meteorhacks:subs-manager@1.6.4
|
||||||
minifier-css@1.4.0
|
minifier-css@1.4.2
|
||||||
minifier-js@2.4.0
|
|
||||||
minimongo@1.4.5
|
minimongo@1.4.5
|
||||||
mobile-experience@1.0.5
|
mobile-experience@1.0.5
|
||||||
mobile-status-bar@1.0.14
|
mobile-status-bar@1.0.14
|
||||||
modern-browsers@0.1.2
|
modern-browsers@0.1.4
|
||||||
modules@0.13.0
|
modules@0.13.0
|
||||||
modules-runtime@0.10.2
|
modules-runtime@0.10.3
|
||||||
momentjs:moment@2.22.2
|
momentjs:moment@2.24.0
|
||||||
mongo@1.6.0
|
mongo@1.6.2
|
||||||
mongo-decimal@0.1.0
|
mongo-decimal@0.1.1
|
||||||
mongo-dev-server@1.1.0
|
mongo-dev-server@1.1.0
|
||||||
mongo-id@1.0.7
|
mongo-id@1.0.7
|
||||||
|
mongo-livedata@1.0.12
|
||||||
|
montiapm:agent@2.35.0
|
||||||
nikogosovd:multiple-uihooks@0.1.8
|
nikogosovd:multiple-uihooks@0.1.8
|
||||||
npm-bcrypt@0.9.3
|
npm-bcrypt@0.9.3
|
||||||
npm-mongo@3.1.1
|
npm-mongo@3.1.2
|
||||||
oauth@1.2.3
|
oauth@1.2.8
|
||||||
oauth2@1.2.1
|
oauth2@1.2.1
|
||||||
observe-sequence@1.0.16
|
observe-sequence@1.0.16
|
||||||
ongoworks:speakingurl@9.0.0
|
ongoworks:speakingurl@9.0.0
|
||||||
ordered-dict@1.1.0
|
ordered-dict@1.1.0
|
||||||
percolate:migrations@0.9.8
|
percolate:migrations@0.9.8
|
||||||
promise@0.11.1
|
promise@0.11.2
|
||||||
raix:eventemitter@0.1.3
|
raix:eventemitter@0.1.3
|
||||||
random@1.1.0
|
random@1.1.0
|
||||||
rate-limit@1.0.9
|
rate-limit@1.0.9
|
||||||
@@ -107,9 +109,9 @@ reload@1.2.0
|
|||||||
retry@1.1.0
|
retry@1.1.0
|
||||||
reywood:iron-router-ga@0.7.1
|
reywood:iron-router-ga@0.7.1
|
||||||
routepolicy@1.1.0
|
routepolicy@1.1.0
|
||||||
seba:minifiers-autoprefixer@1.1.1
|
seba:minifiers-autoprefixer@1.1.2
|
||||||
service-configuration@1.0.11
|
service-configuration@1.0.11
|
||||||
session@1.1.8
|
session@1.2.0
|
||||||
sha@1.0.9
|
sha@1.0.9
|
||||||
shell-server@0.4.0
|
shell-server@0.4.0
|
||||||
socket-stream-client@0.2.2
|
socket-stream-client@0.2.2
|
||||||
@@ -119,7 +121,6 @@ spacebars-compiler@1.1.3
|
|||||||
splendido:accounts-emails-field@1.2.0
|
splendido:accounts-emails-field@1.2.0
|
||||||
splendido:accounts-meld@1.3.1
|
splendido:accounts-meld@1.3.1
|
||||||
srp@1.0.12
|
srp@1.0.12
|
||||||
standard-minifier-js@2.4.0
|
|
||||||
templates:array@1.0.3
|
templates:array@1.0.3
|
||||||
templating@1.3.2
|
templating@1.3.2
|
||||||
templating-compiler@1.3.3
|
templating-compiler@1.3.3
|
||||||
@@ -132,8 +133,9 @@ url@1.2.0
|
|||||||
useraccounts:core@1.14.2
|
useraccounts:core@1.14.2
|
||||||
useraccounts:iron-routing@1.14.2
|
useraccounts:iron-routing@1.14.2
|
||||||
useraccounts:polymer@1.14.2
|
useraccounts:polymer@1.14.2
|
||||||
webapp@1.7.0
|
webapp@1.7.3
|
||||||
webapp-hashing@1.0.9
|
webapp-hashing@1.0.9
|
||||||
wizonesolutions:canonical@0.0.5
|
|
||||||
zimme:collection-behaviours@1.1.3
|
zimme:collection-behaviours@1.1.3
|
||||||
zimme:collection-softremovable@1.0.5
|
zimme:collection-softremovable@1.0.5
|
||||||
|
zodern:minifier-js@3.0.0
|
||||||
|
zodern:standard-minifier-js@3.0.0
|
||||||
|
|||||||
26
app/Model/Meta/PatreonPosts.js
Normal file
26
app/Model/Meta/PatreonPosts.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
PatreonPosts = new Mongo.Collection("patreonPosts");
|
||||||
|
|
||||||
|
Schemas.PatreonPosts = new SimpleSchema({
|
||||||
|
link: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
dateAdded: {
|
||||||
|
type: Date,
|
||||||
|
autoValue(){
|
||||||
|
return new Date();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
PatreonPosts.attachSchema(Schemas.PatreonPosts);
|
||||||
|
|
||||||
|
PatreonPosts.allow({
|
||||||
|
insert: function(userId, doc) {
|
||||||
|
var user = Meteor.users.findOne(userId);
|
||||||
|
if (user) return _.contains(user.roles, "admin");
|
||||||
|
},
|
||||||
|
remove: function(userId, doc) {
|
||||||
|
var user = Meteor.users.findOne(userId);
|
||||||
|
if (user) return _.contains(user.roles, "admin");
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -70,6 +70,45 @@ Schemas.User = new SimpleSchema({
|
|||||||
index: 1,
|
index: 1,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
lastPatreonPostClicked: {
|
||||||
|
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);
|
Meteor.users.attachSchema(Schemas.User);
|
||||||
@@ -107,3 +146,11 @@ if (Meteor.isServer) Meteor.methods({
|
|||||||
Meteor.users.update(this.userId, {$set: {apiKey}});
|
Meteor.users.update(this.userId, {$set: {apiKey}});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
clickPatreonPost(link) {
|
||||||
|
Meteor.users.update(this.userId, {$set: {
|
||||||
|
lastPatreonPostClicked: link
|
||||||
|
}});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,91 +1,268 @@
|
|||||||
Router.map(function() {
|
Router.map(function () {
|
||||||
this.route("vmixCharacter", {
|
this.route("vmixCharacter", {
|
||||||
path: "/vmix-character/:_id/",
|
path: "/vmix-character/:_id/",
|
||||||
where: "server",
|
where: "server",
|
||||||
action: function() {
|
action: function () {
|
||||||
this.response.setHeader("Content-Type", "application/json");
|
this.response.setHeader("Content-Type", "application/json");
|
||||||
var query = this.params.query;
|
var query = this.params.query;
|
||||||
var key = query && query.key;
|
var key = query && query.key;
|
||||||
ifKeyValid(key, this.response, "vmixCharacter", () =>
|
ifKeyValid(key, this.response, "vmixCharacter", () =>
|
||||||
this.response.end(vMixCharacter(this.params._id))
|
this.response.end(vMixCharacter(this.params._id))
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.route("vmixParty", {
|
this.route("vmixParty", {
|
||||||
path: "/vmix-party/:_id/",
|
path: "/vmix-party/:_id/",
|
||||||
where: "server",
|
where: "server",
|
||||||
action: function() {
|
action: function () {
|
||||||
this.response.setHeader("Content-Type", "application/json");
|
this.response.setHeader("Content-Type", "application/json");
|
||||||
var query = this.params.query;
|
var query = this.params.query;
|
||||||
var key = query && query.key;
|
var key = query && query.key;
|
||||||
ifKeyValid(key, this.response, "vmixParty", () =>
|
ifKeyValid(key, this.response, "vmixParty", () =>
|
||||||
this.response.end(vMixParty(this.params._id))
|
this.response.end(vMixParty(this.params._id))
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route("jsonCharacterSheet", {
|
this.route("jsonCharacterSheet", { // GET /character/:_id/json?key=:key
|
||||||
path: "/character/:_id/json",
|
path: "/character/:_id/json",
|
||||||
where: "server",
|
where: "server",
|
||||||
action: function() {
|
action: function () {
|
||||||
this.response.setHeader("Content-Type", "application/json");
|
this.response.setHeader("Content-Type", "application/json");
|
||||||
var query = this.params.query;
|
var query = this.params.query;
|
||||||
var key = query && query.key;
|
var key = query && query.key;
|
||||||
ifKeyValid(key, this.response, "jsonCharacterSheet", () => {
|
ifKeyValid(key, this.response, "jsonCharacterSheet", () => {
|
||||||
if (canViewCharacter(this.params._id, userIdFromKey(key))){
|
if (canViewCharacter(this.params._id, userIdFromKey(key))) {
|
||||||
this.response.end(JSONExport(this.params._id))
|
this.response.end(JSONExport(this.params._id))
|
||||||
} else {
|
} else {
|
||||||
this.response.writeHead(403, "You do not have permission to view this character");
|
this.response.writeHead(403, "You do not have permission to view this character");
|
||||||
this.response.end();
|
this.response.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route("getUserId", { // GET /api/user?username=:un&key=:key
|
||||||
|
path: "/api/user",
|
||||||
|
where: "server",
|
||||||
|
action: function () {
|
||||||
|
this.response.setHeader("Content-Type", "application/json");
|
||||||
|
var query = this.params.query;
|
||||||
|
var key = query && query.key;
|
||||||
|
var username = query && query.username;
|
||||||
|
ifKeyValid(key, this.response, "getUserId", () => {
|
||||||
|
Meteor.call("getUserId", username, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
this.response.writeHead(404, "User not found");
|
||||||
|
this.response.end();
|
||||||
|
} else {
|
||||||
|
console.log(result);
|
||||||
|
this.response.end(JSON.stringify({id: result}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("addSpellsToCharacter", { // POST /api/character/:_id/spellList/:listId
|
||||||
|
path: "/api/character/:_id/spellList/:listId",
|
||||||
|
where: "server"
|
||||||
|
}).post(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const spells = this.request.body;
|
||||||
|
const charId = this.params._id;
|
||||||
|
const listId = this.params.listId;
|
||||||
|
Meteor.call("insertSpells", key, charId, listId, spells, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("createCharacter", { // POST /api/character
|
||||||
|
path: "/api/character",
|
||||||
|
where: "server"
|
||||||
|
}).post(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const character = this.request.body;
|
||||||
|
Meteor.call("insertCharacter", key, character, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("deleteCharacter", { // DELETE /api/character/:_id
|
||||||
|
path: "/api/character/:_id",
|
||||||
|
where: "server"
|
||||||
|
}).delete(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const charId = this.params._id;
|
||||||
|
Meteor.call("deleteCharacter", key, charId, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("transferCharacterOwnership", { // PUT /api/character/:_id/owner
|
||||||
|
path: "/api/character/:_id/owner",
|
||||||
|
where: "server"
|
||||||
|
}).put(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const charId = this.params._id;
|
||||||
|
const ownerId = this.request.body['id'];
|
||||||
|
Meteor.call("transferCharacterOwnership", key, charId, ownerId, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("insertFeatures", { // POST /api/character/:_id/feature
|
||||||
|
path: "/api/character/:_id/feature",
|
||||||
|
where: "server",
|
||||||
|
}).post(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const charId = this.params._id;
|
||||||
|
const features = this.request.body;
|
||||||
|
Meteor.call("insertFeatures", key, charId, features, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("insertProfs", { // POST /api/character/:_id/prof
|
||||||
|
path: "/api/character/:_id/prof",
|
||||||
|
where: "server",
|
||||||
|
}).post(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const charId = this.params._id;
|
||||||
|
const profs = this.request.body;
|
||||||
|
Meteor.call("insertProfs", key, charId, profs, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("insertEffects", { // POST /api/character/:_id/effect
|
||||||
|
path: "/api/character/:_id/effect",
|
||||||
|
where: "server",
|
||||||
|
}).post(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const charId = this.params._id;
|
||||||
|
const effects = this.request.body;
|
||||||
|
Meteor.call("insertEffects", key, charId, effects, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.route("insertClasses", { // POST /api/character/:_id/class
|
||||||
|
path: "/api/character/:_id/class",
|
||||||
|
where: "server",
|
||||||
|
}).post(function () {
|
||||||
|
const key = startPOSTResponse(this);
|
||||||
|
const charId = this.params._id;
|
||||||
|
const classes = this.request.body;
|
||||||
|
Meteor.call("insertClasses", key, charId, classes, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
this.response.writeHead(err.error, err.reason);
|
||||||
|
this.response.end(err.details);
|
||||||
|
} else {
|
||||||
|
this.response.end(JSON.stringify(res));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var ifKeyValid = function(apiKey, response, method, callback){
|
const startPOSTResponse = function (request) {
|
||||||
if (!apiKey){
|
request.response.setHeader("Content-Type", "application/json");
|
||||||
response.writeHead(403, "You must use an api key to access this api");
|
const header = request.request.headers;
|
||||||
response.end();
|
return header && header['authorization'];
|
||||||
} else if (!isKeyValid(apiKey)){
|
|
||||||
response.writeHead(403, "API key is invalid");
|
|
||||||
response.end();
|
|
||||||
} else if (isRateLimited(apiKey, method)){
|
|
||||||
response.writeHead(429, "Too many requests");
|
|
||||||
response.end(JSON.stringify({
|
|
||||||
"timeToReset": rateLimiter.check({apiKey: apiKey, method: method}).timeToReset
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
rateLimiter.increment({apiKey: apiKey, method: method})
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var isKeyValid = function(apiKey){
|
var ifKeyValid = function (apiKey, response, method, callback) {
|
||||||
var user = Meteor.users.findOne({apiKey});
|
if (!apiKey) {
|
||||||
if (!user) return false;
|
response.writeHead(403, "You must use an api key to access this api");
|
||||||
var blackListed = Blacklist.findOne({userId: user._id});
|
response.end();
|
||||||
return !blackListed;
|
} else if (!isKeyValid(apiKey)) {
|
||||||
|
response.writeHead(403, "API key is invalid");
|
||||||
|
response.end();
|
||||||
|
} else if (isRateLimited(apiKey, method)) {
|
||||||
|
response.writeHead(429, "Too many requests");
|
||||||
|
response.end(JSON.stringify({
|
||||||
|
"timeToReset": rateLimiter.check({apiKey: apiKey, method: method}).timeToReset
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
rateLimiter.increment({apiKey: apiKey, method: method});
|
||||||
|
callback();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var userIdFromKey = function(apiKey){
|
isKeyValid = function (apiKey) {
|
||||||
var user = Meteor.users.findOne({apiKey}); // we know user exists from isKeyValid
|
var user = Meteor.users.findOne({apiKey});
|
||||||
return user._id;
|
if (!user) return false;
|
||||||
}
|
var blackListed = Blacklist.findOne({userId: user._id});
|
||||||
|
return !blackListed;
|
||||||
|
};
|
||||||
|
|
||||||
var rateLimiter = new RateLimiter();
|
userIdFromKey = function (apiKey) {
|
||||||
rateLimiter.addRule({apiKey: String}, 5, 5000);
|
var user = Meteor.users.findOne({apiKey}); // we know user exists from isKeyValid
|
||||||
|
return user._id;
|
||||||
|
};
|
||||||
|
|
||||||
|
rateLimiter = new RateLimiter();
|
||||||
|
// global limit
|
||||||
|
rateLimiter.addRule({apiKey: String}, 10, 1000);
|
||||||
|
|
||||||
|
// vmix stuff
|
||||||
rateLimiter.addRule({apiKey: String, method: "vmixCharacter"}, 2, 10000);
|
rateLimiter.addRule({apiKey: String, method: "vmixCharacter"}, 2, 10000);
|
||||||
rateLimiter.addRule({apiKey: String, method: "vmixParty"}, 2, 10000);
|
rateLimiter.addRule({apiKey: String, method: "vmixParty"}, 2, 10000);
|
||||||
rateLimiter.addRule({apiKey: String, method: "jsonCharacterSheet"}, 5, 5000);
|
|
||||||
|
|
||||||
var isRateLimited = function(apiKey, method){
|
// bot API endpoints
|
||||||
const limited = !rateLimiter.check({apiKey: apiKey, method: method}).allowed
|
rateLimiter.addRule({apiKey: String, method: "jsonCharacterSheet"}, 5, 5000);
|
||||||
if (limited) {
|
rateLimiter.addRule({apiKey: String, method: "getUserId"}, 5, 5000);
|
||||||
console.log(`Rate limit hit by API key ${apiKey}`);
|
rateLimiter.addRule({apiKey: String, method: "addSpellsToCharacter"}, 5, 5000);
|
||||||
return true;
|
rateLimiter.addRule({apiKey: String, method: "createCharacter"}, 5, 5000);
|
||||||
} else {
|
rateLimiter.addRule({apiKey: String, method: "transferCharacterOwnership"}, 5, 5000);
|
||||||
return false;
|
rateLimiter.addRule({apiKey: String, method: "insertFeatures"}, 5, 5000);
|
||||||
}
|
rateLimiter.addRule({apiKey: String, method: "insertProfs"}, 5, 5000);
|
||||||
|
rateLimiter.addRule({apiKey: String, method: "insertEffects"}, 5, 5000);
|
||||||
|
rateLimiter.addRule({apiKey: String, method: "insertClasses"}, 5, 5000);
|
||||||
|
|
||||||
|
isRateLimited = function (apiKey, method) {
|
||||||
|
const limited = !rateLimiter.check({apiKey: apiKey, method: method}).allowed;
|
||||||
|
if (limited) {
|
||||||
|
console.log(`Rate limit hit by API key ${apiKey}`);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,6 +21,9 @@
|
|||||||
<a href="/account" style="text-decoration: underline; cursor: pointer; font-size: 16px;">
|
<a href="/account" style="text-decoration: underline; cursor: pointer; font-size: 16px;">
|
||||||
{{profileLink}}
|
{{profileLink}}
|
||||||
</a>
|
</a>
|
||||||
|
<a href="/account" style="text-decoration: underline; cursor: pointer; font-size: 16px; margin-left: 8px;">
|
||||||
|
{{patreonTier}} tier
|
||||||
|
</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href="/sign-in" style="text-decoration: underline; cursor: pointer; font-size: 16px;">
|
<a href="/sign-in" style="text-decoration: underline; cursor: pointer; font-size: 16px;">
|
||||||
Sign in
|
Sign in
|
||||||
@@ -41,6 +44,14 @@
|
|||||||
Characters
|
Characters
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
</a>
|
</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">
|
<a href="/guide" tabindex="-1">
|
||||||
<paper-icon-item id="guide">
|
<paper-icon-item id="guide">
|
||||||
<iron-icon icon="social:school" item-icon></iron-icon>
|
<iron-icon icon="social:school" item-icon></iron-icon>
|
||||||
@@ -51,9 +62,16 @@
|
|||||||
<iron-icon icon="bug-report" item-icon></iron-icon>
|
<iron-icon icon="bug-report" item-icon></iron-icon>
|
||||||
Send Feedback
|
Send Feedback
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
<a class="patreon" href="https://www.patreon.com/dicecloud" target="_blank" tabindex="-1">
|
<a class="patreon" href="{{patreonLink}}" target="_blank" tabindex="-1">
|
||||||
<paper-icon-item>
|
<paper-icon-item>
|
||||||
<iron-icon icon="dicecloud:patreon" item-icon></iron-icon>
|
<iron-icon id="patreon-link-icon" icon="dicecloud:patreon" item-icon></iron-icon>
|
||||||
|
{{#if showPatreonBadge}}
|
||||||
|
<paper-badge
|
||||||
|
icon="av:new-releases"
|
||||||
|
for="patreon-link-icon"
|
||||||
|
label="New post">
|
||||||
|
</paper-badge>
|
||||||
|
{{/if}}
|
||||||
Patreon
|
Patreon
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -7,6 +7,37 @@ Template.appDrawer.helpers({
|
|||||||
var user = Meteor.user();
|
var user = Meteor.user();
|
||||||
return user.profile && user.profile.username || user.username || "My Account";
|
return user.profile && user.profile.username || user.username || "My Account";
|
||||||
},
|
},
|
||||||
|
showPatreonBadge: function(){
|
||||||
|
let post = PatreonPosts.findOne({}, {sort: {date: -1}});
|
||||||
|
let user = Meteor.user();
|
||||||
|
if (!post || !user) return false;
|
||||||
|
return post.link !== user.lastPatreonPostClicked;
|
||||||
|
},
|
||||||
|
patreonLink: function(){
|
||||||
|
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;
|
let drawerLayout;
|
||||||
@@ -37,6 +68,9 @@ Template.appDrawer.events({
|
|||||||
closeDrawer(instance);
|
closeDrawer(instance);
|
||||||
},
|
},
|
||||||
"click .patreon": function(event, instance){
|
"click .patreon": function(event, instance){
|
||||||
|
let post = PatreonPosts.findOne({}, {sort: {date: -1}});
|
||||||
|
let link = (post && post.link) || 'https://www.patreon.com/dicecloud';
|
||||||
|
Meteor.call('clickPatreonPost', link);
|
||||||
ga("send", "event", "externalLink", "patreon");
|
ga("send", "event", "externalLink", "patreon");
|
||||||
},
|
},
|
||||||
"click .github": function(event, instance){
|
"click .github": function(event, instance){
|
||||||
|
|||||||
@@ -62,6 +62,28 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</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>
|
</table>
|
||||||
<div style="max-width: 250px">
|
<div style="max-width: 250px">
|
||||||
{{> atForm state="signIn"}}
|
{{> atForm state="signIn"}}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
|
import { format as formatUrl } from 'url';
|
||||||
|
|
||||||
|
const CLIENT_ID = Meteor.settings.public.patreon.clientId;
|
||||||
|
|
||||||
Template.profile.onCreated(function(){
|
Template.profile.onCreated(function(){
|
||||||
this.showApiKey = new ReactiveVar(false);
|
this.showApiKey = new ReactiveVar(false);
|
||||||
|
this.loadingPatreon = new ReactiveVar(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.profile.helpers({
|
Template.profile.helpers({
|
||||||
@@ -12,6 +17,40 @@ Template.profile.helpers({
|
|||||||
showApiKey: function(){
|
showApiKey: function(){
|
||||||
return Template.instance().showApiKey.get();
|
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({
|
Template.profile.events({
|
||||||
@@ -39,4 +78,10 @@ Template.profile.events({
|
|||||||
Meteor.call("generateMyApiKey");
|
Meteor.call("generateMyApiKey");
|
||||||
instance.showApiKey.set(true);
|
instance.showApiKey.set(true);
|
||||||
},
|
},
|
||||||
|
"click .refreshPatreon": function(event, instance){
|
||||||
|
instance.loadingPatreon.set(true);
|
||||||
|
Meteor.call("updateMyPatreonDetails", (error) => {
|
||||||
|
instance.loadingPatreon.set(false);
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
"polyfill": "/components/webcomponentsjs/webcomponents.min.js",
|
"polyfill": "/components/webcomponentsjs/webcomponents.min.js",
|
||||||
"useShadowDom": true,
|
"useShadowDom": true,
|
||||||
"imports": [
|
"imports": [
|
||||||
"/components/app-layout/app-layout.html",
|
"/components/app-layout/app-layout.html",
|
||||||
"/components/app-layout/app-layout.html",
|
"/components/app-layout/app-layout.html",
|
||||||
"/components/app-layout/app-scroll-effects/effects/waterfall.html",
|
"/components/app-layout/app-scroll-effects/effects/waterfall.html",
|
||||||
"/components/app-layout/app-scroll-effects/effects/parallax-background.html",
|
"/components/app-layout/app-scroll-effects/effects/parallax-background.html",
|
||||||
"/components/app-layout/app-scroll-effects/effects/resize-title.html",
|
"/components/app-layout/app-scroll-effects/effects/resize-title.html",
|
||||||
|
|
||||||
"/components/iron-collapse/iron-collapse.html",
|
"/components/iron-collapse/iron-collapse.html",
|
||||||
"/components/iron-icon/iron-icon.html",
|
"/components/iron-icon/iron-icon.html",
|
||||||
"/components/iron-icons/av-icons.html",
|
"/components/iron-icons/av-icons.html",
|
||||||
"/components/iron-icons/editor-icons.html",
|
"/components/iron-icons/editor-icons.html",
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
"/components/neon-animation/neon-animation.html",
|
"/components/neon-animation/neon-animation.html",
|
||||||
|
|
||||||
"/components/paper-button/paper-button.html",
|
"/components/paper-button/paper-button.html",
|
||||||
|
"/components/paper-badge/paper-badge.html",
|
||||||
"/components/paper-swatch-picker/paper-swatch-picker.html",
|
"/components/paper-swatch-picker/paper-swatch-picker.html",
|
||||||
"/components/paper-dialog/paper-dialog.html",
|
"/components/paper-dialog/paper-dialog.html",
|
||||||
"/components/paper-dropdown-menu/paper-dropdown-menu.html",
|
"/components/paper-dropdown-menu/paper-dropdown-menu.html",
|
||||||
|
|||||||
471
app/lib/functions/api.js
Normal file
471
app/lib/functions/api.js
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
/**
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
JSONExport = function (charId) {
|
||||||
|
const character = {
|
||||||
|
"attacks": Attacks.find({charId: charId}).fetch(),
|
||||||
|
"characters": Characters.find({_id: charId}).fetch(),
|
||||||
|
"classes": Classes.find({charId: charId}).fetch(),
|
||||||
|
"containers": Containers.find({charId: charId}).fetch(),
|
||||||
|
"effects": Effects.find({charId: charId}).fetch(),
|
||||||
|
"experience": Experiences.find({charId: charId}).fetch(),
|
||||||
|
"features": Features.find({charId: charId}).fetch(),
|
||||||
|
"items": Items.find({charId: charId}).fetch(),
|
||||||
|
"notes": Notes.find({charId: charId}).fetch(),
|
||||||
|
"proficiencies": Proficiencies.find({charId: charId}).fetch(),
|
||||||
|
"spellLists": SpellLists.find({charId: charId}).fetch(),
|
||||||
|
"spells": Spells.find({charId: charId}).fetch()
|
||||||
|
};
|
||||||
|
return JSON.stringify(character);
|
||||||
|
};
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
"insertSpells": function (key, charId, listId, spells) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertCanEdit(key, charId, "addSpellsToCharacter");
|
||||||
|
let ids = [];
|
||||||
|
let error;
|
||||||
|
for (let spell of spells) {
|
||||||
|
spell.charId = charId;
|
||||||
|
try {
|
||||||
|
Schemas.Spell.clean(spell);
|
||||||
|
} catch (e) {
|
||||||
|
// console.log(e);
|
||||||
|
error = e.error;
|
||||||
|
}
|
||||||
|
if (!error) {
|
||||||
|
spell.parent = {id: listId, collection: "SpellLists"};
|
||||||
|
let id = Spells.direct.insert(spell, (err) => {
|
||||||
|
if (err) {
|
||||||
|
error = err.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// console.log(id);
|
||||||
|
ids.push(id);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
throw new Meteor.Error(400, "Failed to insert one or more spells", JSON.stringify({
|
||||||
|
err: error,
|
||||||
|
inserted: ids
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"insertCharacter": function (key, character) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertAuthorized(key, "createCharacter");
|
||||||
|
let error, id;
|
||||||
|
|
||||||
|
character.owner = userIdFromKey(key);
|
||||||
|
try {
|
||||||
|
Schemas.Character.clean(character);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
error = e.error;
|
||||||
|
}
|
||||||
|
if (!error) {
|
||||||
|
id = Characters.direct.insert(character, (err) => {
|
||||||
|
if (err)
|
||||||
|
error = err.message;
|
||||||
|
});
|
||||||
|
afterCharacterInsert(id);
|
||||||
|
return {id: id};
|
||||||
|
} else {
|
||||||
|
throw new Meteor.Error(400, "Failed to insert character", JSON.stringify({err: error}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"deleteCharacter": function (key, charId) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertAuthorized(key, "deleteCharacter");
|
||||||
|
if (isOwner(charId, userIdFromKey(key))) {
|
||||||
|
let error;
|
||||||
|
|
||||||
|
Characters.direct.remove({_id: charId}, (err) => {
|
||||||
|
if (err)
|
||||||
|
error = err.message;
|
||||||
|
});
|
||||||
|
if (error) {
|
||||||
|
throw new Meteor.Error(400, "Failed to delete character", JSON.stringify({err: error}));
|
||||||
|
} else {
|
||||||
|
return {success: true};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Meteor.Error(403, "You do not have permission to delete the requested character");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"transferCharacterOwnership": function (key, charId, newOwner) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertAuthorized(key, "transferCharacterOwnership");
|
||||||
|
if (isOwner(charId, userIdFromKey(key))) {
|
||||||
|
let error;
|
||||||
|
Characters.direct.update({_id: charId}, {"$set": {owner: newOwner}}, null,
|
||||||
|
(err) => {
|
||||||
|
if (err)
|
||||||
|
error = err.message;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw new Meteor.Error(400, "Failed to update character", JSON.stringify({err: error}));
|
||||||
|
} else {
|
||||||
|
return {success: true};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Meteor.Error(403, "You do not have permission to transfer the requested character");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"insertFeatures": function (key, charId, features) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertCanEdit(key, charId, "insertFeatures");
|
||||||
|
let ids = [];
|
||||||
|
let error;
|
||||||
|
for (let feature of features) {
|
||||||
|
feature.charId = charId;
|
||||||
|
try {
|
||||||
|
Schemas.Feature.clean(feature);
|
||||||
|
} catch (e) {
|
||||||
|
error = e.error;
|
||||||
|
}
|
||||||
|
if (!error) {
|
||||||
|
let id = Features.direct.insert(feature, (err) => {
|
||||||
|
if (err) {
|
||||||
|
error = err.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ids.push(id);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
throw new Meteor.Error(400, "Failed to insert one or more features", JSON.stringify({
|
||||||
|
err: error,
|
||||||
|
inserted: ids
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
"insertProfs": function (key, charId, profs) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertCanEdit(key, charId, "insertProfs");
|
||||||
|
let ids = [];
|
||||||
|
let error;
|
||||||
|
for (let prof of profs) {
|
||||||
|
prof.charId = charId;
|
||||||
|
try {
|
||||||
|
Schemas.Proficiency.clean(prof, {filter: false});
|
||||||
|
} catch (e) {
|
||||||
|
error = e.error;
|
||||||
|
}
|
||||||
|
if (!error) {
|
||||||
|
let id = Proficiencies.direct.insert(prof, (err) => {
|
||||||
|
if (err) {
|
||||||
|
error = err.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ids.push(id);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
throw new Meteor.Error(400, "Failed to insert one or more profs", JSON.stringify({
|
||||||
|
err: error,
|
||||||
|
inserted: ids
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"insertEffects": function (key, charId, effects) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertCanEdit(key, charId, "insertEffects");
|
||||||
|
let ids = [];
|
||||||
|
let error;
|
||||||
|
for (let effect of effects) {
|
||||||
|
effect.charId = charId;
|
||||||
|
try {
|
||||||
|
Schemas.Effect.clean(effect, {filter: false});
|
||||||
|
} catch (e) {
|
||||||
|
error = e.error;
|
||||||
|
}
|
||||||
|
if (!error) {
|
||||||
|
let id = Effects.direct.insert(effect, (err) => {
|
||||||
|
if (err) {
|
||||||
|
error = err.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ids.push(id);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
throw new Meteor.Error(400, "Failed to insert one or more effects", JSON.stringify({
|
||||||
|
err: error,
|
||||||
|
inserted: ids
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"insertClasses": function (key, charId, klasses) {
|
||||||
|
if (Meteor.isClient) return;
|
||||||
|
assertCanEdit(key, charId, "insertClasses");
|
||||||
|
let ids = [];
|
||||||
|
let error;
|
||||||
|
for (let klass of klasses) {
|
||||||
|
klass.charId = charId;
|
||||||
|
try {
|
||||||
|
Schemas.Class.clean(klass);
|
||||||
|
} catch (e) {
|
||||||
|
error = e.error;
|
||||||
|
}
|
||||||
|
if (!error) {
|
||||||
|
let id = Classes.direct.insert(klass, (err) => {
|
||||||
|
if (err) {
|
||||||
|
error = err.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ids.push(id);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error) {
|
||||||
|
throw new Meteor.Error(400, "Failed to insert one or more classes", JSON.stringify({
|
||||||
|
err: error,
|
||||||
|
inserted: ids
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var assertCanEdit = function (key, charId, method) {
|
||||||
|
if (canEditCharacter(charId, userIdFromKey(key))) {
|
||||||
|
assertAuthorized(key, method);
|
||||||
|
} else {
|
||||||
|
throw new Meteor.Error(403, "You do not have permission to edit the requested character");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var assertAuthorized = function (apiKey, method) {
|
||||||
|
if (!apiKey) {
|
||||||
|
throw new Meteor.Error(403, "You must use an api key to access this api");
|
||||||
|
} else if (!isKeyValid(apiKey)) {
|
||||||
|
throw new Meteor.Error(403, "API key is invalid");
|
||||||
|
} else if (isRateLimited(apiKey, method)) {
|
||||||
|
throw new Meteor.Error(429, "Too many requests", JSON.stringify({
|
||||||
|
"timeToReset": rateLimiter.check({apiKey: apiKey, method: method}).timeToReset
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
rateLimiter.increment({apiKey: apiKey, method: method});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var afterCharacterInsert = function (charId) {
|
||||||
|
// Effects
|
||||||
|
Effects.direct.insert({
|
||||||
|
charId: charId,
|
||||||
|
name: "Constitution modifier for each level",
|
||||||
|
stat: "hitPoints",
|
||||||
|
operation: "add",
|
||||||
|
calculation: "level * constitutionMod",
|
||||||
|
parent: {
|
||||||
|
id: charId,
|
||||||
|
collection: "Characters",
|
||||||
|
group: "Inate",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
charId: charId,
|
||||||
|
name: "Proficiency bonus by level",
|
||||||
|
stat: "proficiencyBonus",
|
||||||
|
operation: "add",
|
||||||
|
calculation: "floor(level / 4 + 1.75)",
|
||||||
|
parent: {
|
||||||
|
id: charId,
|
||||||
|
collection: "Characters",
|
||||||
|
group: "Inate",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
charId: charId,
|
||||||
|
name: "Dexterity Armor Bonus",
|
||||||
|
stat: "armor",
|
||||||
|
operation: "add",
|
||||||
|
calculation: "dexterityArmor",
|
||||||
|
parent: {
|
||||||
|
id: charId,
|
||||||
|
collection: "Characters",
|
||||||
|
group: "Inate",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
charId: charId,
|
||||||
|
name: "Natural Armor",
|
||||||
|
stat: "armor",
|
||||||
|
operation: "base",
|
||||||
|
value: 10,
|
||||||
|
parent: {
|
||||||
|
id: charId,
|
||||||
|
collection: "Characters",
|
||||||
|
group: "Inate",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
charId: charId,
|
||||||
|
name: "Natural Carrying Capacity",
|
||||||
|
stat: "carryMultiplier",
|
||||||
|
operation: "base",
|
||||||
|
value: "1",
|
||||||
|
parent: {
|
||||||
|
id: charId,
|
||||||
|
collection: "Characters",
|
||||||
|
group: "Inate",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Features
|
||||||
|
let featureId = Features.direct.insert({
|
||||||
|
name: "Base Ability Scores",
|
||||||
|
charId: charId,
|
||||||
|
enabled: true,
|
||||||
|
alwaysEnabled: true,
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
stat: "strength",
|
||||||
|
charId: charId,
|
||||||
|
parent: {
|
||||||
|
id: featureId,
|
||||||
|
collection: "Features",
|
||||||
|
},
|
||||||
|
operation: "base",
|
||||||
|
value: 10,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
stat: "dexterity",
|
||||||
|
charId: charId,
|
||||||
|
parent: {
|
||||||
|
id: featureId,
|
||||||
|
collection: "Features",
|
||||||
|
},
|
||||||
|
operation: "base",
|
||||||
|
value: 10,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
stat: "constitution",
|
||||||
|
charId: charId,
|
||||||
|
parent: {
|
||||||
|
id: featureId,
|
||||||
|
collection: "Features",
|
||||||
|
},
|
||||||
|
operation: "base",
|
||||||
|
value: 10,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
stat: "intelligence",
|
||||||
|
charId: charId,
|
||||||
|
parent: {
|
||||||
|
id: featureId,
|
||||||
|
collection: "Features",
|
||||||
|
},
|
||||||
|
operation: "base",
|
||||||
|
value: 10,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
stat: "wisdom",
|
||||||
|
charId: charId,
|
||||||
|
parent: {
|
||||||
|
id: featureId,
|
||||||
|
collection: "Features",
|
||||||
|
},
|
||||||
|
operation: "base",
|
||||||
|
value: 10,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
Effects.direct.insert({
|
||||||
|
stat: "charisma",
|
||||||
|
charId: charId,
|
||||||
|
parent: {
|
||||||
|
id: featureId,
|
||||||
|
collection: "Features",
|
||||||
|
},
|
||||||
|
operation: "base",
|
||||||
|
value: 10,
|
||||||
|
enabled: true,
|
||||||
|
});
|
||||||
|
// Items
|
||||||
|
let containerId = Containers.direct.insert({
|
||||||
|
name: "Coin Pouch",
|
||||||
|
charId: charId,
|
||||||
|
isCarried: true,
|
||||||
|
description: "A sturdy pouch for coins",
|
||||||
|
color: "d",
|
||||||
|
});
|
||||||
|
Items.direct.insert({
|
||||||
|
name: "Gold piece",
|
||||||
|
plural: "Gold pieces",
|
||||||
|
charId: charId,
|
||||||
|
quantity: 0,
|
||||||
|
weight: 0.02,
|
||||||
|
value: 1,
|
||||||
|
color: "n",
|
||||||
|
parent: {
|
||||||
|
id: containerId,
|
||||||
|
collection: "Containers",
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
showIncrement: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Items.direct.insert({
|
||||||
|
name: "Silver piece",
|
||||||
|
plural: "Silver pieces",
|
||||||
|
charId: charId,
|
||||||
|
quantity: 0,
|
||||||
|
weight: 0.02,
|
||||||
|
value: 0.1,
|
||||||
|
color: "q",
|
||||||
|
parent: {
|
||||||
|
id: containerId,
|
||||||
|
collection: "Containers",
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
showIncrement: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
Items.direct.insert({
|
||||||
|
name: "Copper piece",
|
||||||
|
plural: "Copper pieces",
|
||||||
|
charId: charId,
|
||||||
|
quantity: 0,
|
||||||
|
weight: 0.02,
|
||||||
|
value: 0.01,
|
||||||
|
color: "s",
|
||||||
|
parent: {
|
||||||
|
id: containerId,
|
||||||
|
collection: "Containers",
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
showIncrement: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
JSONExport = function(charId) {
|
|
||||||
var character = {
|
|
||||||
"attacks": Attacks.find({charId: charId}).fetch(),
|
|
||||||
"characters": Characters.find({_id: charId}).fetch(),
|
|
||||||
"classes": Classes.find({charId: charId}).fetch(),
|
|
||||||
"containers": Containers.find({charId: charId}).fetch(),
|
|
||||||
"effects": Effects.find({charId: charId}).fetch(),
|
|
||||||
"experience": Experiences.find({charId: charId}).fetch(),
|
|
||||||
"features": Features.find({charId: charId}).fetch(),
|
|
||||||
"items": Items.find({charId: charId}).fetch(),
|
|
||||||
"notes": Notes.find({charId: charId}).fetch(),
|
|
||||||
"proficiencies": Proficiencies.find({charId: charId}).fetch(),
|
|
||||||
"spellLists": SpellLists.find({charId: charId}).fetch(),
|
|
||||||
"spells": Spells.find({charId: charId}).fetch()
|
|
||||||
};
|
|
||||||
return JSON.stringify(character);
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
|
isOwner = function(charId, userId) {
|
||||||
|
userId = userId || Meteor.userId();
|
||||||
|
var char = Characters.findOne(charId, {fields: {owner: 1}});
|
||||||
|
if (!char) return true;
|
||||||
|
return (userId === char.owner);
|
||||||
|
};
|
||||||
|
|
||||||
canEditCharacter = function(charId, userId){
|
canEditCharacter = function(charId, userId){
|
||||||
userId = userId || Meteor.userId();
|
userId = userId || Meteor.userId();
|
||||||
var char = Characters.findOne(charId, {fields: {owner: 1, writers: 1}});
|
var char = Characters.findOne(charId, {fields: {owner: 1, writers: 1}});
|
||||||
|
|||||||
589
app/package-lock.json
generated
589
app/package-lock.json
generated
@@ -26,21 +26,14 @@
|
|||||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||||
},
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "5.5.2",
|
"version": "6.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
|
||||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
"integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"co": "^4.6.0",
|
"fast-deep-equal": "^2.0.1",
|
||||||
"fast-deep-equal": "^1.0.0",
|
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
"json-schema-traverse": "^0.3.0"
|
"json-schema-traverse": "^0.4.1",
|
||||||
},
|
"uri-js": "^4.2.2"
|
||||||
"dependencies": {
|
|
||||||
"co": {
|
|
||||||
"version": "4.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
|
||||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
@@ -53,16 +46,34 @@
|
|||||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
|
"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": {
|
"assert-plus": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||||
},
|
},
|
||||||
|
"asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||||
|
},
|
||||||
"aws-sign2": {
|
"aws-sign2": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
"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": {
|
"bcrypt": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz",
|
||||||
@@ -72,6 +83,14 @@
|
|||||||
"node-pre-gyp": "0.6.36"
|
"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": {
|
"block-stream": {
|
||||||
"version": "0.0.9",
|
"version": "0.0.9",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
@@ -81,9 +100,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bower": {
|
"bower": {
|
||||||
"version": "1.8.4",
|
"version": "1.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz",
|
||||||
"integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo="
|
"integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A=="
|
||||||
},
|
},
|
||||||
"buffer-from": {
|
"buffer-from": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
@@ -108,6 +127,11 @@
|
|||||||
"window-or-global": "^1.0.1"
|
"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": {
|
"cliui": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
||||||
@@ -135,6 +159,14 @@
|
|||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
"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": {
|
"core-js": {
|
||||||
"version": "2.5.7",
|
"version": "2.5.7",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
|
||||||
@@ -155,6 +187,14 @@
|
|||||||
"which": "^1.2.9"
|
"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": {
|
"debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
"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": {
|
"dijkstrajs": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz",
|
||||||
"integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs="
|
"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": {
|
"error-ex": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||||
@@ -195,15 +257,20 @@
|
|||||||
"strip-eof": "^1.0.0"
|
"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": {
|
"extsprintf": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||||
},
|
},
|
||||||
"fast-deep-equal": {
|
"fast-deep-equal": {
|
||||||
"version": "1.1.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||||
},
|
},
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@@ -216,9 +283,9 @@
|
|||||||
"integrity": "sha512-HfVRxhYG7C8Jl9FqtrlElMR2z/8YiLQVDKf67MLY25Ic+ILx3ecmklfT1v3u+7P5/4vEFjuxaAFXhr2/Afwk5g=="
|
"integrity": "sha512-HfVRxhYG7C8Jl9FqtrlElMR2z/8YiLQVDKf67MLY25Ic+ILx3ecmklfT1v3u+7P5/4vEFjuxaAFXhr2/Afwk5g=="
|
||||||
},
|
},
|
||||||
"file-saver": {
|
"file-saver": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.1.tgz",
|
||||||
"integrity": "sha512-cYM1ic5DAkg25pHKgi5f10ziAM7RJU37gaH1XQlyNDrtUnzhC/dfoV9zf2OmF0RMKi42jG5B0JWBnPQqyj/G6g=="
|
"integrity": "sha512-dCB3K7/BvAcUmtmh1DzFdv0eXSVJ9IAFt1mw3XZfAexodNRoE29l3xB2EX4wH2q8m/UTzwzEPq/ArYk98kUkBQ=="
|
||||||
},
|
},
|
||||||
"find-up": {
|
"find-up": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
@@ -228,36 +295,26 @@
|
|||||||
"locate-path": "^2.0.0"
|
"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": {
|
"form-data": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "1.0.6",
|
"combined-stream": "^1.0.6",
|
||||||
"mime-types": "^2.1.12"
|
"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": {
|
"get-caller-file": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
"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",
|
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
|
"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": {
|
"graceful-fs": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": false,
|
"resolved": false,
|
||||||
@@ -279,11 +344,11 @@
|
|||||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||||
},
|
},
|
||||||
"har-validator": {
|
"har-validator": {
|
||||||
"version": "5.0.3",
|
"version": "5.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^5.1.0",
|
"ajv": "^6.5.5",
|
||||||
"har-schema": "^2.0.0"
|
"har-schema": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -300,74 +365,14 @@
|
|||||||
"assert-plus": "^1.0.0",
|
"assert-plus": "^1.0.0",
|
||||||
"jsprim": "^1.2.2",
|
"jsprim": "^1.2.2",
|
||||||
"sshpk": "^1.7.0"
|
"sshpk": "^1.7.0"
|
||||||
},
|
}
|
||||||
"dependencies": {
|
},
|
||||||
"asn1": {
|
"iconv-lite": {
|
||||||
"version": "0.2.3",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
},
|
"requires": {
|
||||||
"bcrypt-pbkdf": {
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
"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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
@@ -401,11 +406,24 @@
|
|||||||
"number-is-nan": "^1.0.0"
|
"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": {
|
"is-stream": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
"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": {
|
"isarray": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
"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": {
|
"json-schema-traverse": {
|
||||||
"version": "0.3.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
"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": {
|
"jsprim": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
@@ -430,13 +487,6 @@
|
|||||||
"extsprintf": "1.3.0",
|
"extsprintf": "1.3.0",
|
||||||
"json-schema": "0.2.3",
|
"json-schema": "0.2.3",
|
||||||
"verror": "1.10.0"
|
"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": {
|
"lcid": {
|
||||||
@@ -1076,37 +1126,6 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "~2.0.1",
|
"inherits": "~2.0.1",
|
||||||
"readable-stream": "^2.0.2"
|
"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": {
|
"stream-http": {
|
||||||
@@ -1119,37 +1138,6 @@
|
|||||||
"readable-stream": "^2.3.3",
|
"readable-stream": "^2.3.3",
|
||||||
"to-arraybuffer": "^1.0.0",
|
"to-arraybuffer": "^1.0.0",
|
||||||
"xtend": "^4.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": {
|
"string_decoder": {
|
||||||
@@ -1228,16 +1216,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.33.0",
|
"version": "1.38.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz",
|
||||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
|
"integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg=="
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.18",
|
"version": "2.1.22",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz",
|
||||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
"integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "~1.33.0"
|
"mime-db": "~1.38.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mimic-fn": {
|
"mimic-fn": {
|
||||||
@@ -1255,6 +1243,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
|
||||||
"integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U="
|
"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": {
|
"node-pre-gyp": {
|
||||||
"version": "0.6.36",
|
"version": "0.6.36",
|
||||||
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz",
|
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz",
|
||||||
@@ -1511,6 +1508,11 @@
|
|||||||
"resolved": false,
|
"resolved": false,
|
||||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
"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": {
|
"os-homedir": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||||
@@ -1592,6 +1594,17 @@
|
|||||||
"pify": "^2.0.0"
|
"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": {
|
"performance-now": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
"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": {
|
"qrcode": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.3.0.tgz",
|
||||||
@@ -1687,103 +1710,30 @@
|
|||||||
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
|
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
|
||||||
},
|
},
|
||||||
"request": {
|
"request": {
|
||||||
"version": "2.87.0",
|
"version": "2.88.0",
|
||||||
"resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
|
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||||
"integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
|
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"aws-sign2": "~0.7.0",
|
"aws-sign2": "~0.7.0",
|
||||||
"aws4": "^1.6.0",
|
"aws4": "^1.8.0",
|
||||||
"caseless": "~0.12.0",
|
"caseless": "~0.12.0",
|
||||||
"combined-stream": "~1.0.5",
|
"combined-stream": "~1.0.6",
|
||||||
"extend": "~3.0.1",
|
"extend": "~3.0.2",
|
||||||
"forever-agent": "~0.6.1",
|
"forever-agent": "~0.6.1",
|
||||||
"form-data": "~2.3.1",
|
"form-data": "~2.3.2",
|
||||||
"har-validator": "~5.0.3",
|
"har-validator": "~5.1.0",
|
||||||
"http-signature": "~1.2.0",
|
"http-signature": "~1.2.0",
|
||||||
"is-typedarray": "~1.0.0",
|
"is-typedarray": "~1.0.0",
|
||||||
"isstream": "~0.1.2",
|
"isstream": "~0.1.2",
|
||||||
"json-stringify-safe": "~5.0.1",
|
"json-stringify-safe": "~5.0.1",
|
||||||
"mime-types": "~2.1.17",
|
"mime-types": "~2.1.19",
|
||||||
"oauth-sign": "~0.8.2",
|
"oauth-sign": "~0.9.0",
|
||||||
"performance-now": "^2.1.0",
|
"performance-now": "^2.1.0",
|
||||||
"qs": "~6.5.1",
|
"qs": "~6.5.2",
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.2",
|
||||||
"tough-cookie": "~2.3.3",
|
"tough-cookie": "~2.4.3",
|
||||||
"tunnel-agent": "^0.6.0",
|
"tunnel-agent": "^0.6.0",
|
||||||
"uuid": "^3.1.0"
|
"uuid": "^3.3.2"
|
||||||
},
|
|
||||||
"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=="
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require-directory": {
|
"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": {
|
"semver": {
|
||||||
"version": "5.4.1",
|
"version": "5.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
|
||||||
"integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w=="
|
"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": {
|
"string-width": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||||
@@ -2164,10 +2140,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tough-cookie": {
|
"tough-cookie": {
|
||||||
"version": "2.3.4",
|
"version": "2.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
|
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"psl": "^1.1.24",
|
||||||
"punycode": "^1.4.1"
|
"punycode": "^1.4.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"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": {
|
"underscore": {
|
||||||
"version": "1.9.1",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
|
||||||
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
|
"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": {
|
"validate-npm-package-license": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
"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",
|
"assert-plus": "^1.0.0",
|
||||||
"core-util-is": "1.0.2",
|
"core-util-is": "1.0.2",
|
||||||
"extsprintf": "^1.2.0"
|
"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": {
|
"webcomponents.js": {
|
||||||
@@ -2214,6 +2210,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz",
|
"resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz",
|
||||||
"integrity": "sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ="
|
"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": {
|
"which": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
|
|||||||
@@ -14,12 +14,14 @@
|
|||||||
"@babel/runtime": "^7.1.2",
|
"@babel/runtime": "^7.1.2",
|
||||||
"@polymer/polymer": "^1.2.5-npm-test.2",
|
"@polymer/polymer": "^1.2.5-npm-test.2",
|
||||||
"bcrypt": "^1.0.3",
|
"bcrypt": "^1.0.3",
|
||||||
"bower": "^1.7.9",
|
"bower": "^1.8.8",
|
||||||
"core-js": "^2.5.7",
|
"core-js": "^2.5.7",
|
||||||
"fibers": "^2.0.2",
|
"fibers": "^2.0.2",
|
||||||
"file-saver": "^2.0.0",
|
"file-saver": "^2.0.1",
|
||||||
"meteor-node-stubs": "^0.3.3",
|
"meteor-node-stubs": "^0.3.3",
|
||||||
|
"patreon": "^0.4.1",
|
||||||
"qrcode": "^1.3.0",
|
"qrcode": "^1.3.0",
|
||||||
|
"request": "^2.88.0",
|
||||||
"source-map-support": "^0.5.9",
|
"source-map-support": "^0.5.9",
|
||||||
"underscore": "^1.9.1"
|
"underscore": "^1.9.1"
|
||||||
}
|
}
|
||||||
|
|||||||
262
app/server/patreon/patreon.js
Normal file
262
app/server/patreon/patreon.js
Normal 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,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
Meteor.publish("user", function(){
|
Meteor.publish("user", function(){
|
||||||
return Meteor.users.find(this.userId, {fields: {
|
return [
|
||||||
roles: 1,
|
Meteor.users.find(this.userId, {fields: {
|
||||||
username: 1,
|
roles: 1,
|
||||||
profile: 1,
|
username: 1,
|
||||||
apiKey: 1,
|
profile: 1,
|
||||||
librarySubscriptions: 1,
|
apiKey: 1,
|
||||||
}});
|
librarySubscriptions: 1,
|
||||||
|
lastPatreonPostClicked: 1,
|
||||||
|
patreon: 1,
|
||||||
|
}}),
|
||||||
|
PatreonPosts.find({},{sort: {dateAdded: -1}, limit: 1})
|
||||||
|
];
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
// This all gets run in the console by an admin.
|
// 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 = Libraries.insert({
|
||||||
_id: "SRDLibraryGA3XWsd",
|
_id: "SRDLibraryGA3XWsd",
|
||||||
owner: Meteor.userId(),
|
owner: Meteor.userId(),
|
||||||
@@ -8,19 +11,23 @@ id = Libraries.insert({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// First copy-paste the JSON into your console like `items = <pasted JSON>`
|
// 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) => {
|
_.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"
|
item.library = "SRDLibraryGA3XWsd"
|
||||||
LibraryItems.insert(item)
|
LibraryItems.insert(item)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// First copy-paste the JSON into your console like `spells = <pasted JSON>`
|
||||||
_.each(spells, (spell) => {
|
_.each(spells, (spell) => {
|
||||||
spell.library = "SRDLibraryGA3XWsd"
|
spell.library = "SRDLibraryGA3XWsd"
|
||||||
LibrarySpells.insert(spell)
|
LibrarySpells.insert(spell)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update the library using names as keys
|
// Updating the Libary
|
||||||
|
// -------------------
|
||||||
|
|
||||||
// Make sure you're subscribed to all item categories
|
// Make sure you're subscribed to all item categories
|
||||||
handles = _.map(["weapons", "armor", "adventuringGear", "tools"],
|
handles = _.map(["weapons", "armor", "adventuringGear", "tools"],
|
||||||
category => Meteor.subscribe("standardLibraryItems", category)
|
category => Meteor.subscribe("standardLibraryItems", category)
|
||||||
|
|||||||
Reference in New Issue
Block a user