Add guild selection setting and developer mode option
This commit is contained in:
parent
d3a5be365e
commit
086b6253bc
|
@ -47,10 +47,9 @@
|
||||||
{
|
{
|
||||||
"id": "developer-mode",
|
"id": "developer-mode",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"text": "Developer Mode",
|
"text": "Developer mode",
|
||||||
"hint": "BetterDiscord developer mode",
|
"hint": "Adds some of BetterDiscord's internal modules to `global._bd`.",
|
||||||
"value": false,
|
"value": false
|
||||||
"disabled": true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ignore-content-manager-errors",
|
"id": "ignore-content-manager-errors",
|
||||||
|
|
|
@ -19,33 +19,37 @@ const DEV = true;
|
||||||
class BetterDiscord {
|
class BetterDiscord {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
window.BDDEVMODE = function () {
|
this._bd = {
|
||||||
if (!DEV) return null;
|
DOM,
|
||||||
return window._bd = {
|
BdUI,
|
||||||
DOM,
|
Modals,
|
||||||
BdUI,
|
Reflection,
|
||||||
Modals,
|
Patcher,
|
||||||
Reflection,
|
Vendor,
|
||||||
Patcher,
|
Events,
|
||||||
Vendor,
|
CssEditor,
|
||||||
Events,
|
Globals,
|
||||||
CssEditor,
|
ExtModuleManager,
|
||||||
Globals,
|
PluginManager,
|
||||||
ExtModuleManager,
|
ThemeManager,
|
||||||
PluginManager,
|
ModuleManager,
|
||||||
ThemeManager,
|
WebpackModules,
|
||||||
ModuleManager,
|
Settings,
|
||||||
WebpackModules,
|
Database,
|
||||||
Settings,
|
ReactComponents,
|
||||||
Database,
|
DiscordApi,
|
||||||
ReactComponents,
|
Logger,
|
||||||
DiscordApi,
|
ClientIPC,
|
||||||
Logger,
|
Utils,
|
||||||
ClientIPC,
|
EmoteModule
|
||||||
Utils,
|
};
|
||||||
EmoteModule
|
|
||||||
}
|
const developermode = Settings.getSetting('core', 'advanced', 'developer-mode');
|
||||||
}
|
if (developermode.value) window._bd = this._bd;
|
||||||
|
developermode.on('setting-updated', event => {
|
||||||
|
if (event.value) window._bd = this._bd;
|
||||||
|
else if (window._bd) delete window._bd;
|
||||||
|
});
|
||||||
|
|
||||||
DOM.injectStyle(BdCss, 'bdmain');
|
DOM.injectStyle(BdCss, 'bdmain');
|
||||||
this.globalReady = this.globalReady.bind(this);
|
this.globalReady = this.globalReady.bind(this);
|
||||||
|
@ -79,16 +83,13 @@ class BetterDiscord {
|
||||||
this.vueInstance = BdUI.injectUi();
|
this.vueInstance = BdUI.injectUi();
|
||||||
this.init();
|
this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.BetterDiscord) {
|
if (window.BetterDiscord) {
|
||||||
Logger.log('main', 'Attempting to inject again?');
|
Logger.log('main', 'Attempting to inject again?');
|
||||||
} else {
|
} else {
|
||||||
let instance = null;
|
let instance = null;
|
||||||
// eslint-disable-next-line no-inner-declarations
|
Events.on('autopatcher', () => instance = new BetterDiscord());
|
||||||
function init() {
|
|
||||||
instance = new BetterDiscord();
|
|
||||||
}
|
|
||||||
Events.on('autopatcher', init);
|
|
||||||
ReactAutoPatcher.autoPatch().then(() => Events.emit('autopatcher'));
|
ReactAutoPatcher.autoPatch().then(() => Events.emit('autopatcher'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import SliderSetting from './types/slider';
|
||||||
import ColourSetting from './types/colour';
|
import ColourSetting from './types/colour';
|
||||||
import KeybindSetting from './types/keybind';
|
import KeybindSetting from './types/keybind';
|
||||||
import FileSetting from './types/file';
|
import FileSetting from './types/file';
|
||||||
|
import GuildSetting from './types/guild';
|
||||||
import ArraySetting from './types/array';
|
import ArraySetting from './types/array';
|
||||||
import CustomSetting from './types/custom';
|
import CustomSetting from './types/custom';
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ export default class Setting {
|
||||||
else if (args.type === 'colour') return new ColourSetting(args, ...merge);
|
else if (args.type === 'colour') return new ColourSetting(args, ...merge);
|
||||||
else if (args.type === 'keybind') return new KeybindSetting(args, ...merge);
|
else if (args.type === 'keybind') return new KeybindSetting(args, ...merge);
|
||||||
else if (args.type === 'file') return new FileSetting(args, ...merge);
|
else if (args.type === 'file') return new FileSetting(args, ...merge);
|
||||||
|
else if (args.type === 'guild') return new GuildSetting(args, ...merge);
|
||||||
else if (args.type === 'array') return new ArraySetting(args, ...merge);
|
else if (args.type === 'array') return new ArraySetting(args, ...merge);
|
||||||
else if (args.type === 'custom') return new CustomSetting(args, ...merge);
|
else if (args.type === 'custom') return new CustomSetting(args, ...merge);
|
||||||
else throw {message: `Setting type ${args.type} unknown`};
|
else throw {message: `Setting type ${args.type} unknown`};
|
||||||
|
|
|
@ -215,11 +215,6 @@ export default class ArraySetting extends Setting {
|
||||||
if (error) throw error;
|
if (error) throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit(...args) {
|
|
||||||
// console.log('Emitting event', args[0], 'with data', args[1]);
|
|
||||||
// return this.emitter.emit(...args);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the value of this array setting.
|
* Updates the value of this array setting.
|
||||||
* This only exists for use by array settings.
|
* This only exists for use by array settings.
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/**
|
||||||
|
* BetterDiscord Guild Setting Struct
|
||||||
|
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||||
|
* All rights reserved.
|
||||||
|
* https://betterdiscord.net
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { DiscordApi } from 'modules';
|
||||||
|
import { Utils, ClientLogger as Logger } from 'common';
|
||||||
|
import Setting from './basesetting';
|
||||||
|
|
||||||
|
export default class GuildSetting extends Setting {
|
||||||
|
|
||||||
|
constructor(args, ...merge) {
|
||||||
|
super(args, ...merge);
|
||||||
|
|
||||||
|
this.args.guilds = this.value ? this.value.map(guild_id => DiscordApi.guilds.get({ id: guild_id })) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value to use when the setting doesn't have a value.
|
||||||
|
*/
|
||||||
|
get defaultValue() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of currently selected guilds.
|
||||||
|
*/
|
||||||
|
get guilds() {
|
||||||
|
return this.args.guilds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum amount of guilds the user may select.
|
||||||
|
* This only restricts removing guilds when there is less or equal guilds than this, and does not ensure that this number of guilds actually exists.
|
||||||
|
*/
|
||||||
|
get min() {
|
||||||
|
return this.args.min || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of guilds the user may select.
|
||||||
|
*/
|
||||||
|
get max() {
|
||||||
|
return this.args.max || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a guild to the list of selected guilds.
|
||||||
|
* @param {Number} guild_id The ID of the guild to add
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
addGuild(guild_id) {
|
||||||
|
return this.setValue(this.value.concat([guild_id]));
|
||||||
|
|
||||||
|
// if (this.guilds.find(g => g && g.id === guild_id)) return;
|
||||||
|
// const guild = DiscordApi.guilds.get({ id: guild_id });
|
||||||
|
// this.guilds.push(guild);
|
||||||
|
// await this.emit('guild-added', guild);
|
||||||
|
// return await this.setValue(this.value.concat([guild_id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a guild from the list of selected guilds.
|
||||||
|
* @param {Number} guild_id The ID of the guild to remove
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
removeGuild(guild_id) {
|
||||||
|
return this.setValue(this.value.filter(g => g !== guild_id));
|
||||||
|
|
||||||
|
// const guild = this.guilds.find(g => g && g.id === guild_id);
|
||||||
|
// const value = Utils.removeFromArray(this.value.slice(0), guild_id);
|
||||||
|
// if (guild) {
|
||||||
|
// Utils.filterArray(this.guilds, g => !g || g.id !== guild_id);
|
||||||
|
// await this.emit('guild-removed', guild);
|
||||||
|
// }
|
||||||
|
// return await this.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be called after the value changes.
|
||||||
|
* This can be overridden by other settings types.
|
||||||
|
* This function is used when the value needs to be updated synchronously (basically just in the constructor - so there won't be any events to emit anyway).
|
||||||
|
* @param {SettingUpdatedEvent} updatedSetting
|
||||||
|
*/
|
||||||
|
setValueHookSync(updatedSetting) {
|
||||||
|
this.args.guilds = updatedSetting.value ? updatedSetting.value.map(guild_id => DiscordApi.guilds.get({ id: guild_id })) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be called after the value changes.
|
||||||
|
* This can be overridden by other settings types.
|
||||||
|
* @param {SettingUpdatedEvent} updatedSetting
|
||||||
|
*/
|
||||||
|
async setValueHook(updatedSetting) {
|
||||||
|
const newGuilds = [];
|
||||||
|
let error;
|
||||||
|
|
||||||
|
for (let newGuild of updatedSetting.value) {
|
||||||
|
try {
|
||||||
|
const guild = updatedSetting.old_value.find(g => g === newGuild);
|
||||||
|
|
||||||
|
if (guild) {
|
||||||
|
// Guild was already selected
|
||||||
|
newGuilds.push(guild);
|
||||||
|
} else {
|
||||||
|
// Add a new guild
|
||||||
|
Logger.log('GuildSetting', ['Adding guild', newGuild, 'to', this]);
|
||||||
|
newGuilds.push(newGuild);
|
||||||
|
await this.emit('guild-added', { id: newGuild });
|
||||||
|
}
|
||||||
|
} catch (e) { error = e; }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let guild_id of updatedSetting.old_value) {
|
||||||
|
if (newGuilds.find(g => g === guild_id)) continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Guild removed
|
||||||
|
Logger.log('GuildSetting', ['Removing guild', guild_id, 'from', this]);
|
||||||
|
await this.emit('guild-removed', { id: guild_id });
|
||||||
|
} catch (e) { error = e; }
|
||||||
|
}
|
||||||
|
|
||||||
|
this.args.guilds = newGuilds.map(id => DiscordApi.guilds.get({ id }));
|
||||||
|
|
||||||
|
// We can't throw anything before the guilds array is updated, otherwise the guild setting would be in an inconsistent state where the values in this.guilds wouldn't match the values in this.value
|
||||||
|
if (error) throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a representation of this setting's value in SCSS.
|
||||||
|
* @return {String|Promise}
|
||||||
|
*/
|
||||||
|
async toSCSS() {
|
||||||
|
if (!this.value || !this.value.length) return '()';
|
||||||
|
|
||||||
|
const guilds = [];
|
||||||
|
for (let guild_id of this.value) {
|
||||||
|
if (guild_id)
|
||||||
|
guilds.push(guild_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return guilds.length ? guilds.join(', ') : '()';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
.bd-form-guildinput {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-guilds {
|
||||||
|
// margin: 15px 0;
|
||||||
|
|
||||||
|
.bd-guild {
|
||||||
|
$size: 36px;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
width: $size;
|
||||||
|
height: $size;
|
||||||
|
background-color: rgb(47, 49, 54);
|
||||||
|
background-size: cover;
|
||||||
|
margin: 10px 10px 0 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-radius .4s cubic-bezier(0.5, 0, 0.27, 1.55), background-color .4s cubic-bezier(0.5, 0, 0.27, 1.55), box-shadow .4s cubic-bezier(0.5, 0, 0.27, 1.55);
|
||||||
|
|
||||||
|
.bd-guild-text {
|
||||||
|
float: left;
|
||||||
|
display: block;
|
||||||
|
width: $size;
|
||||||
|
height: $size;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: $size;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-radius: 30%;
|
||||||
|
background-color: $colbdblue;
|
||||||
|
|
||||||
|
&.bd-guild-has-icon {
|
||||||
|
background-color: rgb(47, 49, 54);
|
||||||
|
// box-shadow: 0 0 1px #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bd-active {
|
||||||
|
background-color: $colbdblue;
|
||||||
|
|
||||||
|
&.bd-guild-has-icon {
|
||||||
|
background-color: rgb(47, 49, 54);
|
||||||
|
box-shadow: 0 0 7px $colbdblue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
@import './main.scss';
|
@import './main.scss';
|
||||||
@import './switches.scss';
|
@import './switches.scss';
|
||||||
@import './text.scss';
|
@import './text.scss';
|
||||||
@import './files.scss';
|
|
||||||
@import './dropdowns.scss';
|
@import './dropdowns.scss';
|
||||||
@import './radios.scss';
|
@import './radios.scss';
|
||||||
@import './sliders.scss';
|
@import './sliders.scss';
|
||||||
@import './colourpickers.scss';
|
@import './colourpickers.scss';
|
||||||
@import './keybinds.scss';
|
@import './keybinds.scss';
|
||||||
|
@import './files.scss';
|
||||||
|
@import './guilds.scss';
|
||||||
@import './arrays.scss';
|
@import './arrays.scss';
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
.bd-form-colourpicker,
|
.bd-form-colourpicker,
|
||||||
.bd-form-keybind,
|
.bd-form-keybind,
|
||||||
.bd-form-fileinput,
|
.bd-form-fileinput,
|
||||||
|
.bd-form-guildinput,
|
||||||
.bd-form-settingsarray {
|
.bd-form-settingsarray {
|
||||||
.bd-title {
|
.bd-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**
|
||||||
|
* BetterDiscord Setting Guild Component
|
||||||
|
* Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks
|
||||||
|
* All rights reserved.
|
||||||
|
* https://betterdiscord.net
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="bd-form-guildinput">
|
||||||
|
<div class="bd-title">
|
||||||
|
<h3>{{ setting.text }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="bd-hint">{{ setting.hint }}</div>
|
||||||
|
<div class="bd-guilds">
|
||||||
|
<div class="bd-guild" :class="{'bd-active': isGuildSelected(guild), 'bd-guild-has-icon': guild.icon}" :style="{backgroundImage: `url('${getGuildIconURL(guild)}')`}" @click="() => isGuildSelected(guild) ? unselectGuild(guild) : selectGuild(guild)" v-for="guild in guilds" v-if="guild" v-tooltip="guild.name">
|
||||||
|
<div class="bd-guild-text" v-if="!guild.icon">{{ getGuildIconText(guild) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { DiscordApi } from 'modules';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['setting'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
user_guilds: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
guilds() {
|
||||||
|
const guilds = ([]).concat(this.user_guilds);
|
||||||
|
|
||||||
|
for (let guild of this.setting.guilds) {
|
||||||
|
if (!guilds.find(g => g && guild && g.id === guild.id))
|
||||||
|
guilds.push(guild);
|
||||||
|
}
|
||||||
|
|
||||||
|
return guilds.sort(function(a, b) {
|
||||||
|
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
|
||||||
|
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
|
||||||
|
if (nameA < nameB) return -1;
|
||||||
|
if (nameA > nameB) return 1;
|
||||||
|
// names must be equal
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isGuildSelected(guild) {
|
||||||
|
return this.setting.guilds.find(g => g && g.id === guild.id);
|
||||||
|
},
|
||||||
|
getGuildIconURL(guild) {
|
||||||
|
return `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.webp`;
|
||||||
|
},
|
||||||
|
getGuildIconText(guild) {
|
||||||
|
const words = guild.name.split(' ');
|
||||||
|
if (!words.length) return '';
|
||||||
|
const first = words[0].substr(0, 1);
|
||||||
|
if (words.length <= 1) return first;
|
||||||
|
const last = words[words.length - 1].substr(0, 1);
|
||||||
|
return `${first}${last}`;
|
||||||
|
},
|
||||||
|
async selectGuild(guild) {
|
||||||
|
if (this.setting.max && this.setting.guilds.length >= this.setting.max) return;
|
||||||
|
await this.setting.addGuild(guild.id);
|
||||||
|
},
|
||||||
|
async unselectGuild(guild) {
|
||||||
|
if (this.setting.min && this.setting.guilds.length <= this.setting.min) return;
|
||||||
|
await this.setting.removeGuild(guild.id);
|
||||||
|
},
|
||||||
|
refreshGuilds() {
|
||||||
|
this.user_guilds = DiscordApi.guilds;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.refreshGuilds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -20,6 +20,7 @@
|
||||||
<ColourSetting v-if="setting.type === 'colour'" :setting="setting" :change="change" />
|
<ColourSetting v-if="setting.type === 'colour'" :setting="setting" :change="change" />
|
||||||
<KeybindSetting v-if="setting.type === 'keybind'" :setting="setting" />
|
<KeybindSetting v-if="setting.type === 'keybind'" :setting="setting" />
|
||||||
<FileSetting v-if="setting.type === 'file'" :setting="setting" :change="change" />
|
<FileSetting v-if="setting.type === 'file'" :setting="setting" :change="change" />
|
||||||
|
<GuildSetting v-if="setting.type === 'guild'" :setting="setting" />
|
||||||
<ArraySetting v-if="setting.type === 'array'" :setting="setting" :change="change" />
|
<ArraySetting v-if="setting.type === 'array'" :setting="setting" :change="change" />
|
||||||
<CustomSetting v-if="setting.type === 'custom'" :setting="setting" :change="change" />
|
<CustomSetting v-if="setting.type === 'custom'" :setting="setting" :change="change" />
|
||||||
<div class="bd-form-divider"></div>
|
<div class="bd-form-divider"></div>
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
import ColourSetting from './Colour.vue';
|
import ColourSetting from './Colour.vue';
|
||||||
import KeybindSetting from './Keybind.vue';
|
import KeybindSetting from './Keybind.vue';
|
||||||
import FileSetting from './File.vue';
|
import FileSetting from './File.vue';
|
||||||
|
import GuildSetting from './Guild.vue';
|
||||||
import ArraySetting from './Array.vue';
|
import ArraySetting from './Array.vue';
|
||||||
import CustomSetting from './Custom.vue';
|
import CustomSetting from './Custom.vue';
|
||||||
|
|
||||||
|
@ -55,6 +57,7 @@
|
||||||
ColourSetting,
|
ColourSetting,
|
||||||
KeybindSetting,
|
KeybindSetting,
|
||||||
FileSetting,
|
FileSetting,
|
||||||
|
GuildSetting,
|
||||||
ArraySetting,
|
ArraySetting,
|
||||||
CustomSetting
|
CustomSetting
|
||||||
},
|
},
|
||||||
|
|
|
@ -162,6 +162,19 @@ export class Utils {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static filterArray(array, filter) {
|
||||||
|
const indexes = [];
|
||||||
|
for (let index in array) {
|
||||||
|
if (!filter(array[index], index))
|
||||||
|
indexes.push(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in indexes)
|
||||||
|
array.splice(indexes[i] - i, 1);
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
static removeFromArray(array, item) {
|
static removeFromArray(array, item) {
|
||||||
let index;
|
let index;
|
||||||
while ((index = array.indexOf(item)) > -1)
|
while ((index = array.indexOf(item)) > -1)
|
||||||
|
|
|
@ -84,6 +84,15 @@
|
||||||
"value": "mod+.",
|
"value": "mod+.",
|
||||||
"text": "Test Keybind Setting 1",
|
"text": "Test Keybind Setting 1",
|
||||||
"hint": "Test Keybind Setting Hint 1"
|
"hint": "Test Keybind Setting Hint 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "guild-1",
|
||||||
|
"type": "guild",
|
||||||
|
"value": [
|
||||||
|
"280806472928198656"
|
||||||
|
],
|
||||||
|
"text": "Test guild setting",
|
||||||
|
"hint": "Test guild setting hint"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue