From 76e16084c155c0b254fa8324de7de2d34f656a84 Mon Sep 17 00:00:00 2001 From: sogehige Date: Thu, 18 Jul 2019 17:37:34 +0200 Subject: [PATCH] feat(customvariables): get and post URLs for custom variables (#2456) URL must be generated through UI Requested by https://ideas.sogebot.xyz/posts/145/url-call-to-change-variable --- locales/cs/ui.registry.customvariables.json | 3 + locales/en/ui.registry.customvariables.json | 3 + src/bot/customvariables.js | 53 +++++++++-- src/bot/panel.js | 8 ++ .../custom-variables-edit.vue | 88 +++++++++++++++++++ 5 files changed, 149 insertions(+), 6 deletions(-) diff --git a/locales/cs/ui.registry.customvariables.json b/locales/cs/ui.registry.customvariables.json index cb4a9763d85..28aef8249f0 100644 --- a/locales/cs/ui.registry.customvariables.json +++ b/locales/cs/ui.registry.customvariables.json @@ -1,4 +1,7 @@ { + "urls": "Adresy URL", + "generateurl": "Vygenerovat novou URL", + "show-examples": "Ukázat CURL příklady", "response": { "name": "Odpověď po nastavení", "default": "Výchozí", diff --git a/locales/en/ui.registry.customvariables.json b/locales/en/ui.registry.customvariables.json index bcd52d0c4d9..994fb35a51f 100644 --- a/locales/en/ui.registry.customvariables.json +++ b/locales/en/ui.registry.customvariables.json @@ -1,4 +1,7 @@ { + "urls": "URLs", + "generateurl": "Generate new URL", + "show-examples": "show CURL examples", "response": { "name": "Response after variable set", "default": "Default", diff --git a/src/bot/customvariables.js b/src/bot/customvariables.js index e62e263b842..1c028ce405e 100644 --- a/src/bot/customvariables.js +++ b/src/bot/customvariables.js @@ -23,6 +23,53 @@ class CustomVariables { } } + async getURL(req: Request, res: Response) { + try { + const variable = (await global.db.engine.find('custom.variables')) + .find(variable => { + return _.get(variable, 'urls', []).find(url => url.id === req.params.id) + }); + if (variable) { + if (_.get(variable.urls.find(url => url.id === req.params.id), 'access.GET', false)) { + return res.status(200).send({ value: await this.getValueOf(variable.variableName) }); + } else { + return res.status(403).send({ error: 'This endpoint is not enabled for GET', code: 403 }); + } + } else { + return res.status(404).send({ error: 'Variable not found', code: 404 }); + } + } catch (e) { + res.status(500).send({ error: 'Internal Server Error', code: 500 }); + throw e; + } + } + + async postURL(req: Request, res: Response) { + try { + const variable = (await global.db.engine.find('custom.variables')) + .find(variable => { + return _.get(variable, 'urls', []).find(url => url.id === req.params.id) + }); + if (variable) { + if (_.get(variable.urls.find(url => url.id === req.params.id), 'access.POST', false)) { + const value = await this.setValueOf(variable.variableName, req.body.value, {}); + if (value.isOk) { + return res.status(200).send({ oldValue: variable.currentValue, value: value.updated.setValue }); + } else { + return res.status(400).send({ error: 'This value is not applicable for this endpoint', code: 400 }); + } + } else { + return res.status(403).send({ error: 'This endpoint is not enabled for POST', code: 403 }); + } + } else { + return res.status(404).send({ error: 'Variable not found', code: 404 }); + } + } catch (e) { + res.status(500).send({ error: 'Internal Server Error', code: 500 }); + throw e; + } + } + async addMenuAndListenersToPanel () { clearTimeout(this.timeouts[`${this.constructor.name}.addMenuAndListenersToPanel`]); @@ -291,12 +338,6 @@ class CustomVariables { } else { // set item permission to owner if missing item.permission = typeof item.permission === 'undefined' ? permission.CASTERS : item.permission; - let [isVIP, isMod, isOwner] = await Promise.all([ - commons.isVIP(opts.sender), - commons.isModerator(opts.sender), - commons.isOwner(opts.sender) - ]); - if (typeof opts.sender === 'string') { opts.sender = { username: opts.sender, diff --git a/src/bot/panel.js b/src/bot/panel.js index c00cd43dd19..bb66b063cf9 100644 --- a/src/bot/panel.js +++ b/src/bot/panel.js @@ -51,6 +51,14 @@ function Panel () { global.systems.highlights.url(req, res) }) + // customvariables system + app.get('/customvariables/:id', (req, res) => { + global.customvariables.getURL(req, res) + }) + app.post('/customvariables/:id', (req, res) => { + global.customvariables.postURL(req, res) + }) + // static routing app.use('/dist', express.static(path.join(__dirname, '..', 'public', 'dist'))) app.get('/popout/', this.authUser, function (req, res) { diff --git a/src/panel/views/registries/custom-variables/custom-variables-edit.vue b/src/panel/views/registries/custom-variables/custom-variables-edit.vue index af18f5ed990..7486eb64e9f 100644 --- a/src/panel/views/registries/custom-variables/custom-variables-edit.vue +++ b/src/panel/views/registries/custom-variables/custom-variables-edit.vue @@ -57,6 +57,73 @@ > + + {{translate('registry.customvariables.show-examples')}} + + + + $ curl -X GET {{origin}}/customvariables/<generated-id>
+ { "value": "{{currentValue}}" } +
+
+ + + $ curl -X POST {{origin}}/customvariables/<generated-id> -H "Content-Type: + application/json" -d '{ "value": "yourNewValue" }'
+ { "oldValue": "{{currentValue}}", "value": "yourNewValue" } +
+
+
+ + + + $ curl -X GET {{origin}}/customvariables/<generated-id>
+ { "error": "This endpoint is not enabled for GET", code: 403 } +
+
+ + + $ curl -X POST {{origin}}/customvariables/<generated-id> -H "Content-Type: + application/json" -d '{ "value": "yourNewValue" }'
+ { "error": "This endpoint is not enabled for POST", code: 400 } +
+
+
+ + + + + $ curl -X POST {{origin}}/customvariables/<generated-id> -H "Content-Type: + application/json" -d '{ "value": "yourNewValue" }'
+ { "error": "This value is not applicable for this endpoint", code: 400 } +
+
+
+ + + + + $ curl -X POST {{origin}}/customvariables/<generated-id> -H "Content-Type: + application/json" -d '{ "value": "yourNewValue" }'
+ { "error": "This value is not applicable for this endpoint", acceptableValues: ['value1', 'value2'], code: 400 } +
+
+
+ + + + GET + POST + +
{{origin}}/customvariables/{{url.id}}
+ + + +
+ {{ translate('registry.customvariables.generateurl') }} +
+
+ import { Vue, Component, Watch } from 'vue-property-decorator'; import { chunk, orderBy, get } from 'lodash'; +import uuid from 'uuid/v4'; import { codemirror } from 'vue-codemirror'; import 'codemirror/lib/codemirror.css'; @@ -275,12 +343,15 @@ export default class customVariablesEdit extends Vue { selectedRunEvery: string = 'isUsed'; runEveryX: number = 1; + showCurlExample: boolean = false; + variableName: string = ''; description: string = ''; currentValue: string = ''; usableOptions: string = ''; readOnly: boolean = false; permission: string | null = null; + urls: { id: string; access: { GET: boolean; POST: boolean }}[] = []; evalValue: string = evalDefault; evalError: string | null = null @@ -330,6 +401,7 @@ export default class customVariablesEdit extends Vue { this.selectedType = data.variable.type; this.responseType = data.variable.responseType; this.responseText = data.variable.responseText; + this.urls = data.variable.urls || []; this.permission = data.variable.permission || 0; this.readOnly = data.variable.readOnly || false; for (let h of data.history) { @@ -376,6 +448,21 @@ export default class customVariablesEdit extends Vue { } } + get origin() { + return window.location.origin; + } + + generateURL() { + this.urls.push({ + id: uuid(), + access: { GET: false, POST: false } + }); + } + + removeURL(id) { + this.urls = this.urls.filter(o => o.id !== id); + } + getPermissionName(id) { if (!id) return 'Disabled' const permission = this.permissions.find((o) => { @@ -445,6 +532,7 @@ export default class customVariablesEdit extends Vue { variableName: this.variableName, description: this.description, currentValue: this.currentValue, + urls: this.urls, usableOptions: this.usableOptions || '', evalValue: this.evalValue, runEvery: this.selectedType === 'eval'