472 lines
13 KiB
JavaScript
472 lines
13 KiB
JavaScript
/**
|
|
* @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,
|
|
},
|
|
});
|
|
};
|