diff --git a/app/imports/api/creature/actions/applyAction.js b/app/imports/api/creature/actions/applyAction.js index f25a2213..0126ab51 100644 --- a/app/imports/api/creature/actions/applyAction.js +++ b/app/imports/api/creature/actions/applyAction.js @@ -3,8 +3,8 @@ import {insertCreatureLog} from '/imports/api/creature/log/CreatureLogs.js'; export default function applyAction({prop, creature}){ spendResources(prop); - insertCreatureLog({ + insertCreatureLog.call({ log: prop.name, - creature, + creatureId: creature._id, }); } diff --git a/app/imports/api/creature/actions/applyAttack.js b/app/imports/api/creature/actions/applyAttack.js index ba02dc15..7b03cc21 100644 --- a/app/imports/api/creature/actions/applyAttack.js +++ b/app/imports/api/creature/actions/applyAttack.js @@ -9,8 +9,8 @@ export default function applyAttack({ //actionContext }){ let result = math.roll(1, 20) + prop.rollBonusResult; - insertCreatureLog({ + insertCreatureLog.call({ log: `${prop.name} attack. ${result} to hit`, - creature, + creatureId: creature._id, }); } diff --git a/app/imports/api/creature/log/CreatureLogs.js b/app/imports/api/creature/log/CreatureLogs.js index 4474ee69..ba399f7c 100644 --- a/app/imports/api/creature/log/CreatureLogs.js +++ b/app/imports/api/creature/log/CreatureLogs.js @@ -41,16 +41,7 @@ let CreatureLogSchema = new SimpleSchema({ CreatureLogs.attachSchema(CreatureLogSchema); -// This function should only be called by trusted code. No permission checks -const insertCreatureLog = function({log, creature}){ - const creatureId = creature._id; - // Build the new log - if (typeof log === 'string'){ - log = {text: log}; - } - log.creatureId = creatureId; - // Insert it - let id = CreatureLogs.insert(log); +function removeOldLogs(creatureId){ // Find the first log that is over the limit let firstExpiredLog = CreatureLogs.find({ creatureId @@ -63,16 +54,61 @@ const insertCreatureLog = function({log, creature}){ creatureId, date: {$lte: firstExpiredLog.date}, }); - //TODO unblock before sending webhooks - // Send webhooks +} + +function logWebhook({log, creature}){ if (Meteor.isServer){ sendWebhookAsCreature({ creature, content: log.text, }); } - return id; -}; +} + +const insertCreatureLog = new ValidatedMethod({ + name: 'creatureLogs.methods.insertCreatureLog', + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + validate: new SimpleSchema({ + log: CreatureLogSchema.omit('type', 'date'), + creatureId: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + }).validator(), + run({log, creatureId}){ + const creature = Creatures.findOne(creatureId, {fields: { + readers: 1, + writers: 1, + owner: 1, + 'settings.discordWebhook': 1, + name: 1, + avatarPicture: 1, + }}); + assertEditPermission(creature, this.userId); + // Build the new log + if (typeof log === 'string'){ + log = {text: log}; + } + if (Meteor.isServer){ + Meteor._sleepForMs(5000); + } + log.creatureId = creatureId; + log.date = new Date(); + // Insert it + let id = CreatureLogs.insert(log); + if (Meteor.isServer){ + this.unblock(); + removeOldLogs(creatureId); + logWebhook({log, creature}); + } + return id; + }, +}); + function equalIgnoringWhitespace(a, b){ if (typeof a !== 'string' || typeof b !== 'string') return a === b; @@ -96,15 +132,23 @@ const logRoll = new ValidatedMethod({ }, }).validator(), run({roll, creatureId}){ - const creature = Creatures.findOne(creatureId); + const creature = Creatures.findOne(creatureId, {fields: { + variables: 1, + readers: 1, + writers: 1, + owner: 1, + 'settings.discordWebhook': 1, + name: 1, + avatarPicture: 1, + }}); assertEditPermission(creature, this.userId); let parsedResult = parse(roll); - let log; + let logText; if (parsedResult === null) { - log = 'Unexpected end of input'; + logText = 'Unexpected end of input'; } else try { - let logText = []; + logText = []; let rollContext = new CompilationContext(); let compiled = parsedResult.compile(creature.variables, rollContext); let compiledString = compiled.toString(); @@ -116,11 +160,22 @@ const logRoll = new ValidatedMethod({ let result = rolled.reduce(creature.variables, rollContext); let resultString = result.toString(); if (resultString !== rolledString) logText.push(resultString); - log = logText.join('\n\n'); + logText = logText.join('\n\n'); } catch (e){ - log = 'Calculation error'; + logText = 'Calculation error'; } - return insertCreatureLog({log, creature}); + const log = { + text: logText, + creatureId, + date: new Date(), + }; + let id = CreatureLogs.insert(log); + if (Meteor.isServer){ + this.unblock(); + removeOldLogs(creatureId); + logWebhook({log, creature}); + } + return id; }, }); diff --git a/app/imports/ui/creature/character/CharacterLog.vue b/app/imports/ui/creature/character/CharacterLog.vue index 40a94084..7e80b14b 100644 --- a/app/imports/ui/creature/character/CharacterLog.vue +++ b/app/imports/ui/creature/character/CharacterLog.vue @@ -101,8 +101,8 @@ export default { return CreatureLogs.find({ creatureId: this.creatureId, }, { - limit: 20, sort: {date: -1}, + limit: 20 }); }, creature(){ diff --git a/app/imports/ui/creature/character/CharacterSheet.vue b/app/imports/ui/creature/character/CharacterSheet.vue index 12f96432..7a3527f6 100644 --- a/app/imports/ui/creature/character/CharacterSheet.vue +++ b/app/imports/ui/creature/character/CharacterSheet.vue @@ -137,7 +137,7 @@ }).observe({ added(doc){ if (!that.$subReady.singleCharacter) return; - if (this.$store.state.rightDrawer) return; + if (that.$store.state.rightDrawer) return; if (that.snackbars.some(o => o._id === doc._id)) return; doc.open = true; that.snackbars.push(doc);