Improved custom rolls on log tab

This commit is contained in:
Stefan Zermatten
2020-10-06 09:53:08 +02:00
parent 844588cdbf
commit a87cb1286a
3 changed files with 115 additions and 14 deletions

View File

@@ -1,4 +1,11 @@
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
import Creatures from '/imports/api/creature/Creatures.js';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import {assertEditPermission} from '/imports/api/creature/creaturePermissions.js';
import { parse, CompilationContext } from '/imports/parser/parser.js';
const PER_CREATURE_LOG_LIMIT = 100;
if (Meteor.isServer){ if (Meteor.isServer){
var sendWebhookAsCreature = require('/imports/server/discord/sendWebhook.js').sendWebhookAsCreature; var sendWebhookAsCreature = require('/imports/server/discord/sendWebhook.js').sendWebhookAsCreature;
} }
@@ -36,11 +43,28 @@ CreatureLogs.attachSchema(CreatureLogSchema);
// This function should only be called by trusted code. No permission checks // This function should only be called by trusted code. No permission checks
const insertCreatureLog = function({log, creature}){ const insertCreatureLog = function({log, creature}){
const creatureId = creature._id;
// Build the new log
if (typeof log === 'string'){ if (typeof log === 'string'){
log = {text: log}; log = {text: log};
} }
log.creatureId = creature._id; log.creatureId = creatureId;
// Insert it
let id = CreatureLogs.insert(log); let id = CreatureLogs.insert(log);
// Find the first log that is over the limit
let firstExpiredLog = CreatureLogs.find({
creatureId
}, {
sort: {date: -1},
skip: PER_CREATURE_LOG_LIMIT,
});
// Remove all logs older than the one over the limit
CreatureLogs.remove({
creatureId,
date: {$lte: firstExpiredLog.date},
});
//TODO unblock before sending webhooks
// Send webhooks
if (Meteor.isServer){ if (Meteor.isServer){
sendWebhookAsCreature({ sendWebhookAsCreature({
creature, creature,
@@ -50,5 +74,55 @@ const insertCreatureLog = function({log, creature}){
return id; return id;
}; };
function equalIgnoringWhitespace(a, b){
if (typeof a !== 'string' || typeof b !== 'string') return a === b;
return a.replace(/\s/g,'') === b.replace(/\s/g, '');
}
const logRoll = new ValidatedMethod({
name: 'creatureLogs.methods.logForCreature',
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 5,
timeInterval: 5000,
},
validate: new SimpleSchema({
roll: {
type: String,
},
creatureId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
}).validator(),
run({roll, creatureId}){
const creature = Creatures.findOne(creatureId);
assertEditPermission(creature, this.userId);
let parsedResult = parse(roll);
let log;
if (parsedResult === null) {
log = 'Unexpected end of input';
}
else try {
let logText = [];
let rollContext = new CompilationContext();
let compiled = parsedResult.compile(creature.variables, rollContext);
let compiledString = compiled.toString();
if (!equalIgnoringWhitespace(compiledString, roll)) logText.push(roll);
logText.push(compiledString);
let rolled = compiled.roll(creature.variables, rollContext);
let rolledString = rolled.toString();
if (rolledString !== compiledString) logText.push(rolled.toString());
let result = rolled.reduce(creature.variables, rollContext);
let resultString = result.toString();
if (resultString !== rolledString) logText.push(resultString);
log = logText.join('\n\n');
} catch (e){
log = 'Calculation error';
}
return insertCreatureLog({log, creature});
},
});
export default CreatureLogs; export default CreatureLogs;
export { CreatureLogSchema, insertCreatureLog}; export { CreatureLogSchema, insertCreatureLog, logRoll};

View File

@@ -64,7 +64,7 @@
<v-snackbar <v-snackbar
v-for="(snackbar, index) in snackbars" v-for="(snackbar, index) in snackbars"
:key="index" :key="index"
v-model="snackbar.open" :value="true"
> >
{{ snackbar.text }} {{ snackbar.text }}
<v-btn <v-btn
@@ -142,7 +142,7 @@
added(doc){ added(doc){
console.log({added: doc}); console.log({added: doc});
that.snackbars.add(doc); that.snackbars.add(doc);
setTimeout(function(){that.snackbars.remove(doc)}, 8000); setTimeout(function(){that.snackbars.delete(doc)}, 8000);
}, },
}); });
console.log(observer); console.log(observer);

View File

@@ -1,15 +1,21 @@
<template lang="html"> <template lang="html">
<div <div
style="min-height: calc(100vh - 96px);" style="height: calc(100vh - 96px); overflow: hidden;"
class="layout column justify-end" class="log-tab layout column justify-end"
> >
<div class="log flex layout column reverse"> <div
<div class="log flex layout column reverse align-start pa-3"
style="overflow: auto;"
>
<v-card
v-for="log in logs" v-for="log in logs"
:key="log._id" :key="log._id"
class="ma-2"
> >
{{ log.text }} <v-card-text class="pa-2">
</div> <markdown-text :markdown="log.text" />
</v-card-text>
</v-card>
</div> </div>
<v-card> <v-card>
<v-text-field <v-text-field
@@ -17,22 +23,28 @@
solo solo
persistent-hint persistent-hint
style="flex-grow: 0" style="flex-grow: 0"
append-outer-icon="send"
:hint="inputHint" :hint="inputHint"
:error="inputError" :error-messages="inputError"
:disabled="!editPermission" :disabled="!editPermission"
@input="inputChanged" @click:append-outer="submit"
@keyup.enter="submit"
/> />
</v-card> </v-card>
</div> </div>
</template> </template>
<script> <script>
import CreatureLogs from '/imports/api/creature/log/CreatureLogs.js'; import CreatureLogs, { logRoll } from '/imports/api/creature/log/CreatureLogs.js';
import Creatures from '/imports/api/creature/Creatures.js'; import Creatures from '/imports/api/creature/Creatures.js';
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js'; import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
import { parse } from '/imports/parser/parser.js'; import { parse } from '/imports/parser/parser.js';
import MarkdownText from '/imports/ui/components/MarkdownText.vue';
export default { export default {
components: {
MarkdownText,
},
props: { props: {
creatureId: { creatureId: {
type: String, type: String,
@@ -71,6 +83,18 @@ export default {
} }
}, },
}, },
methods: {
submit(){
if (this.inputError) return;
logRoll.call({
roll: this.input,
creatureId: this.creatureId,
}, (error) => {
if (error) console.error(error);
});
this.input = '';
},
},
meteor: { meteor: {
logs(){ logs(){
return CreatureLogs.find({ return CreatureLogs.find({
@@ -95,5 +119,8 @@ export default {
} }
</script> </script>
<style lang="css" scoped> <style lang="css">
.log-tab p:last-child {
margin-bottom: 0;
}
</style> </style>