420 lines
19 KiB
Vue
420 lines
19 KiB
Vue
<template>
|
|
<form action="javascript:" class="uk-form-stacked" novalidate>
|
|
<div class="uk-margin">
|
|
<span uk-icon="info" uk-tooltip="Url of the webhook"></span>
|
|
<label class="uk-form-label" for="dwm-discord_webhook_url">
|
|
Discord webhook url: *
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.discord_webhook_url">
|
|
{{ errors.discord_webhook_url[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<input class="uk-input" name="discord_webhook_url" id="dwm-discord_webhook_url" type="url" placeholder="https://discordapp.com/api/webhooks/..." v-model="discord_webhook_url" />
|
|
</div>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-username">
|
|
<span uk-icon="info" uk-tooltip="Username shown when sending messages"></span>
|
|
Username:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.username">
|
|
{{ errors.username[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<input class="uk-input" name="username" id="dwm-username" type="text" placeholder="Username of the hook sender" v-model="username" />
|
|
</div>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-avatar">
|
|
<span uk-icon="info" uk-tooltip="Profile image of the user"></span>
|
|
Username avatar:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.avatar">
|
|
{{ errors.avatar[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<input name="avatar" id="dwm-avatar" type="file" class="uk-margin-small-right" @change="updateAvatar" />
|
|
<template v-if="avatarPreview">
|
|
<img :src="avatarPreview" alt="Bot avatar image" class="uk-margin-smalls-right" id="dwm-avatar-preview" />
|
|
<br>
|
|
<p v-if="avatarPreview.startsWith('data:image')"><strong>Note:</strong> before sending a test message you have to upload the new avatar image.</p>
|
|
<span v-if="!avatarPreview.startsWith('data:image')" class="uk-button uk-button-link" @click="deleteAvatar">Delete avatar</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-content">
|
|
<span uk-icon="info" uk-tooltip="Content of the text message"></span>
|
|
Content:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.content">
|
|
{{ errors.content[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<textarea class="uk-textarea" name="content" id="dwm-content" rows="3" placeholder="Text message, you can ping @everyone from here" v-model="content"></textarea>
|
|
</div>
|
|
</div>
|
|
<h4>
|
|
<label class="uk-flex uk-flex-between uk-flex-middle">
|
|
<span>
|
|
Embed options
|
|
</span>
|
|
<span class="switch">
|
|
<input type="checkbox" v-model="has_embed">
|
|
<span class="slider round"></span>
|
|
</span>
|
|
</label>
|
|
</h4>
|
|
<transition enter-active-class="animate__animated animate__slideInUp" leave-active-class="animate__animated animate__slideOutDown">
|
|
<div v-if="has_embed">
|
|
<p>
|
|
<strong>Note:</strong> test messages will not have any of these fields.
|
|
</p>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-embed_color">
|
|
<span uk-icon="info" uk-tooltip="Color shown at the left of the embed"></span>
|
|
Color:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.embed_color">
|
|
{{ errors.embed_color[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<input class="uk-input" name="embed_color" id="dwm-embed_color" type="color" v-model="embed_color" />
|
|
</div>
|
|
</div>
|
|
<div class="uk-margin uk-margin-small-right uk-display-inline-block">
|
|
<label class="uk-form-label" for="dwm-embed_author_name">
|
|
<span uk-icon="info" uk-tooltip="Show your Twitch username as the author name"></span>
|
|
Author name:
|
|
<span class="switch uk-display-inline-block">
|
|
<input class="uk-checkbox" name="embed_author_name" id="dwm-embed_author_name" type="checkbox" v-model="embed_author_name" />
|
|
<span class="slider round"></span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<div class="uk-margin uk-margin-small-right uk-display-inline-block">
|
|
<label class="uk-form-label" for="dwm-embed_author_url">
|
|
<span uk-icon="info" uk-tooltip="Link to the Twitch channel url"></span>
|
|
Author url:
|
|
<span class="switch">
|
|
<input class="uk-checkbox" name="embed_author_url" id="dwm-embed_author_url" type="checkbox" v-model="embed_author_url" />
|
|
<span class="slider round"></span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<div class="uk-margin uk-margin-small-right uk-display-inline-block">
|
|
<label class="uk-form-label" for="dwm-embed_author_icon">
|
|
<span uk-icon="info" uk-tooltip="Show Twitch profile picture as author icon"></span>
|
|
Author icon:
|
|
<span class="switch">
|
|
<input class="uk-checkbox" name="embed_author_icon" id="dwm-embed_author_icon" type="checkbox" v-model="embed_author_icon" />
|
|
<span class="slider round"></span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<div class="uk-margin uk-display-inline-block">
|
|
<label class="uk-form-label" for="dwm-embed_thumbnail">
|
|
<span uk-icon="info" uk-tooltip="Show Twitch profile picture on the top right"></span>
|
|
Thumbnail:
|
|
<span class="switch">
|
|
<input class="uk-checkbox" name="embed_thumbnail" id="dwm-embed_thumbnail" type="checkbox" v-model="embed_thumbnail" />
|
|
<span class="slider round"></span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-embed_title">
|
|
<span uk-icon="info" uk-tooltip="Keep empty to use stream title"></span>
|
|
Title:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.embed_title">
|
|
{{ errors.embed_title[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<input class="uk-input" name="embed_title" id="dwm-embed_title" type="text" placeholder="Title of the embed, keep empty to use stream title" v-model="embed_title" />
|
|
</div>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-embed_description">
|
|
<span uk-icon="info" uk-tooltip="Description of the embed"></span>
|
|
Description:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.embed_description">
|
|
{{ errors.embed_description[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<textarea class="uk-textarea" name="embed_description" id="dwm-embed_description" rows="3" placeholder="Description of the embed" v-model="embed_description"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-embed_url">
|
|
<span uk-icon="info" uk-tooltip="Keep empty to use stream url"></span>
|
|
Url:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.embed_url">
|
|
{{ errors.embed_url[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<input class="uk-input" name="embed_url" id="dwm-embed_url" type="url" placeholder="Url to redirec to when clicking the title, keep empty to use stream url" v-model="embed_url" />
|
|
</div>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label" for="dwm-embed_image">
|
|
<span uk-icon="info" uk-tooltip="Show stream preview image"></span>
|
|
Image:
|
|
</label>
|
|
<label class="uk-form-controls">
|
|
<span class="switch">
|
|
<input class="uk-checkbox" name="embed_image" id="dwm-embed_image" type="checkbox" v-model="embed_image" />
|
|
<span class="slider round"></span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<div class="uk-margin">
|
|
<label class="uk-form-label">
|
|
<span uk-icon="info" uk-tooltip="Custom fields"></span>
|
|
Fields:
|
|
</label>
|
|
<span class="uk-text-danger" v-if="errors.embed_fields">
|
|
{{ errors.embed_fields[0] }}
|
|
</span>
|
|
<div class="uk-form-controls">
|
|
<div>
|
|
Check the toggle to show the field in the same line as other fields, else each field will be shown on a different line.
|
|
<br/>
|
|
Available variables, set the value field to one of these to replace it with data taken from the stream.
|
|
<ul>
|
|
<li><code>%game%</code> name of the game</li>
|
|
<li><code>%viewer_count%</code> number of viewers</li>
|
|
</ul>
|
|
</div>
|
|
<div v-for="(field, i) in embed_fields" :key="i" :class="{'uk-margin-small-bottom': (i == (embed_fields.length - 1)) }" class="uk-child-width-auto uk-flex uk-flex-middle">
|
|
<input class="uk-input flex-grow" name="field[]" type="text" placeholder="Field name" v-model="field.name" />
|
|
<input class="uk-input flex-grow" name="fieldValue[]" type="text" placeholder="Field value" v-model="field.value" />
|
|
<label class="switch uk-margin-small-left uk-margin-small-right">
|
|
<input class="uk-checkbox" name="fieldInline[]" type="checkbox" v-model="field.inline" />
|
|
<span class="slider round"></span>
|
|
</label>
|
|
<span uk-icon="close" @click="removeField(i)"></span>
|
|
</div>
|
|
<button class="uk-button uk-button-small uk-button-default" @click="addField">
|
|
<span uk-icon="plus"></span> Add field
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</transition>
|
|
<div class="uk-margin">
|
|
<button class="uk-button uk-button-primary" @click="save">
|
|
<span uk-icon="check"></span>
|
|
Save
|
|
</button>
|
|
<button class="uk-button uk-button-default" @click="sendTestMessage" v-if="avatarPreview && !avatarPreview.startsWith('data:image')">
|
|
<span uk-icon="forward"></span>
|
|
Send test message
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
<style computed>
|
|
#dwm-avatar-preview {
|
|
width: 150px;
|
|
}
|
|
</style>
|
|
<script>
|
|
import UIkit from "uikit";
|
|
import { axios } from "../../../app";
|
|
|
|
export default {
|
|
props: {
|
|
data: {
|
|
type: Object
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
id: null,
|
|
discord_webhook_url: this.data.discord_webhook_url,
|
|
username: this.data.username,
|
|
avatar: null,
|
|
avatarPreview: this.data.avatar ? `${location.protocol}//${location.host}/storage/${this.data.avatar}` : "",
|
|
content: this.data.content,
|
|
has_embed: parseInt(this.data.has_embed),
|
|
embed_color: this.data.embed_color ? this.data.embed_color : "#9147ff",
|
|
embed_author_name: parseInt(this.data.embed_author_name),
|
|
embed_author_url: parseInt(this.data.embed_author_url),
|
|
embed_author_icon: parseInt(this.data.embed_author_icon),
|
|
embed_thumbnail: parseInt(this.data.embed_thumbnail),
|
|
embed_title: this.data.embed_title,
|
|
embed_description: this.data.embed_description,
|
|
embed_url: this.data.embed_url,
|
|
embed_image: parseInt(this.data.embed_image),
|
|
embed_fields: this.data.embed_fields ? JSON.parse(this.data.embed_fields) : [],
|
|
errors: {}
|
|
};
|
|
},
|
|
methods: {
|
|
updateAvatar(e) {
|
|
let file = e.target.files[0];
|
|
|
|
const fr = new FileReader();
|
|
fr.addEventListener("load", () => {
|
|
this.avatarPreview = fr.result;
|
|
});
|
|
|
|
if (file) {
|
|
fr.readAsDataURL(file);
|
|
this.avatar = file;
|
|
} else {
|
|
this.avatar = null;
|
|
this.avatarPreview = null;
|
|
}
|
|
},
|
|
addField() {
|
|
this.embed_fields.push({name: "", value: "", inline: false});
|
|
},
|
|
removeField(idx) {
|
|
this.embed_fields.splice(idx, 1);
|
|
},
|
|
async save() {
|
|
try {
|
|
const fd = new FormData();
|
|
fd.set("type", "stream");
|
|
fd.set("enabled", true ? 1 : 0);
|
|
fd.set("discord_webhook_url", this.discord_webhook_url);
|
|
fd.set("username", this.username ? this.username : '');
|
|
if (this.avatar) {
|
|
fd.set("avatar", this.avatar);
|
|
}
|
|
fd.set("content", this.content ? this.content : '');
|
|
fd.set("has_embed", this.has_embed ? 1 : 0);
|
|
fd.set("embed_color", this.embed_color);
|
|
fd.set("embed_author_name", this.embed_author_name ? 1 : 0);
|
|
fd.set("embed_author_url", this.embed_author_url ? 1 : 0);
|
|
fd.set("embed_author_icon", this.embed_author_icon ? 1 : 0);
|
|
fd.set("embed_thumbnail", this.embed_thumbnail ? 1 : 0);
|
|
fd.set("embed_title", this.embed_title ? this.embed_title : '');
|
|
fd.set("embed_description", this.embed_description ? this.embed_description : '');
|
|
fd.set("embed_url", this.embed_url ? this.embed_url : '');
|
|
fd.set("embed_image", this.embed_image ? 1 : 0);
|
|
fd.set("embed_fields", this.embed_fields ? JSON.stringify(this.embed_fields.filter(e => e.name && e.value)) : []);
|
|
|
|
let req = await axios.post(this.$parent.saveHookUrl, fd, {
|
|
headers: {
|
|
"Content-Type": "multipart/form-data"
|
|
}
|
|
});
|
|
|
|
if (req.data.action_id) {
|
|
this.id = req.data.action_id;
|
|
}
|
|
if (req.data.avatar) {
|
|
this.avatar = null;
|
|
this.avatarPreview = `${req.data.avatar}?${Date.now()}`;
|
|
}
|
|
|
|
UIkit.notification({
|
|
message: "Saved!",
|
|
status: "success"
|
|
});
|
|
|
|
this.errors = {};
|
|
|
|
} catch(e) {
|
|
let errorMsg = e.message;
|
|
switch(e.request.status) {
|
|
case 422:
|
|
errorMsg = e.response.data.message;
|
|
this.errors = e.response.data.errors;
|
|
break;
|
|
case 503:
|
|
errorMsg = "Site is in maintenance, retry in some minutes...";
|
|
break;
|
|
default:
|
|
console.error(e);
|
|
}
|
|
|
|
UIkit.notification({
|
|
message: errorMsg,
|
|
status: "danger"
|
|
});
|
|
}
|
|
},
|
|
async deleteAvatar() {
|
|
try {
|
|
let req = await axios.post(this.$parent.saveHookUrl, {
|
|
type: "stream",
|
|
enabled: true ? 1 : 0,
|
|
discord_webhook_url: this.discord_webhook_url,
|
|
delete_avatar: 1
|
|
});
|
|
|
|
this.avatarPreview = req.data.avatar;
|
|
|
|
UIkit.notification({
|
|
message: "Avatar reseted to default",
|
|
status: "success"
|
|
});
|
|
|
|
this.errors = {};
|
|
|
|
} catch (e) {
|
|
let errorMsg = e.message;
|
|
|
|
switch(e.request.status) {
|
|
case 422:
|
|
errorMsg = e.response.data.message;
|
|
this.errors = e.response.data.errors;
|
|
break;
|
|
case 503:
|
|
errorMsg = "Site is in maintenance, retry in some minutes...";
|
|
break;
|
|
default:
|
|
console.error(e);
|
|
}
|
|
|
|
UIkit.notification({
|
|
message: errorMsg,
|
|
status: "danger"
|
|
});
|
|
}
|
|
},
|
|
async sendTestMessage() {
|
|
try {
|
|
let req = await axios.post(this.$parent.sendTestMessageUrl, {
|
|
discord_webhook_url: this.discord_webhook_url,
|
|
username: this.username,
|
|
avatar: this.avatarPreview,
|
|
content: this.content
|
|
});
|
|
|
|
UIkit.notification({
|
|
message: "Test message sent!",
|
|
status: "success"
|
|
});
|
|
|
|
this.errors = {};
|
|
|
|
} catch (e) {
|
|
let errorMsg = e.message;
|
|
switch(e.request.status) {
|
|
case 422:
|
|
errorMsg = e.response.data.message;
|
|
this.errors = e.response.data.errors;
|
|
break;
|
|
case 503:
|
|
errorMsg = "Site is in maintenance, retry in some minutes...";
|
|
break;
|
|
default:
|
|
console.error(e);
|
|
}
|
|
|
|
UIkit.notification({
|
|
message: errorMsg,
|
|
status: "danger"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script> |