Custom embeds

This commit is contained in:
rxdn 2022-06-27 21:33:24 +01:00
parent 0b743b52d2
commit 9818bad95e
18 changed files with 821 additions and 140 deletions

View File

@ -2,6 +2,7 @@ package api
import ( import (
"errors" "errors"
"fmt"
"github.com/TicketsBot/GoPanel/botcontext" "github.com/TicketsBot/GoPanel/botcontext"
dbclient "github.com/TicketsBot/GoPanel/database" dbclient "github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/rpc" "github.com/TicketsBot/GoPanel/rpc"
@ -12,6 +13,7 @@ import (
"github.com/TicketsBot/common/premium" "github.com/TicketsBot/common/premium"
"github.com/TicketsBot/database" "github.com/TicketsBot/database"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/rxdn/gdl/objects/channel" "github.com/rxdn/gdl/objects/channel"
"github.com/rxdn/gdl/objects/guild/emoji" "github.com/rxdn/gdl/objects/guild/emoji"
"github.com/rxdn/gdl/objects/interaction/component" "github.com/rxdn/gdl/objects/interaction/component"
@ -33,7 +35,7 @@ type panelBody struct {
Colour uint32 `json:"colour"` Colour uint32 `json:"colour"`
CategoryId uint64 `json:"category_id,string"` CategoryId uint64 `json:"category_id,string"`
Emoji types.Emoji `json:"emote"` Emoji types.Emoji `json:"emote"`
WelcomeMessage *string `json:"welcome_message"` WelcomeMessage *types.CustomEmbed `json:"welcome_message" validate:"omitempty,dive"`
Mentions []string `json:"mentions"` Mentions []string `json:"mentions"`
WithDefaultTeam bool `json:"default_team"` WithDefaultTeam bool `json:"default_team"`
Teams []int `json:"teams"` Teams []int `json:"teams"`
@ -66,10 +68,7 @@ func CreatePanel(ctx *gin.Context) {
botContext, err := botcontext.ContextForGuild(guildId) botContext, err := botcontext.ContextForGuild(guildId)
if err != nil { if err != nil {
ctx.AbortWithStatusJSON(500, gin.H{ ctx.JSON(500, utils.ErrorJson(err))
"success": false,
"error": err.Error(),
})
return return
} }
@ -137,26 +136,41 @@ func CreatePanel(ctx *gin.Context) {
} }
} }
// Store welcome message embed first
var welcomeMessageEmbed *int
if data.WelcomeMessage != nil {
embed, fields := data.WelcomeMessage.IntoDatabaseStruct()
embed.GuildId = guildId
id, err := dbclient.Client.Embeds.CreateWithFields(embed, fields)
if err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
welcomeMessageEmbed = &id
}
// Store in DB // Store in DB
panel := database.Panel{ panel := database.Panel{
MessageId: msgId, MessageId: msgId,
ChannelId: data.ChannelId, ChannelId: data.ChannelId,
GuildId: guildId, GuildId: guildId,
Title: data.Title, Title: data.Title,
Content: data.Content, Content: data.Content,
Colour: int32(data.Colour), Colour: int32(data.Colour),
TargetCategory: data.CategoryId, TargetCategory: data.CategoryId,
EmojiId: emojiId, EmojiId: emojiId,
EmojiName: emojiName, EmojiName: emojiName,
WelcomeMessage: data.WelcomeMessage, WelcomeMessageEmbed: welcomeMessageEmbed,
WithDefaultTeam: data.WithDefaultTeam, WithDefaultTeam: data.WithDefaultTeam,
CustomId: customId, CustomId: customId,
ImageUrl: data.ImageUrl, ImageUrl: data.ImageUrl,
ThumbnailUrl: data.ThumbnailUrl, ThumbnailUrl: data.ThumbnailUrl,
ButtonStyle: int(data.ButtonStyle), ButtonStyle: int(data.ButtonStyle),
ButtonLabel: data.ButtonLabel, ButtonLabel: data.ButtonLabel,
FormId: data.FormId, FormId: data.FormId,
NamingScheme: data.NamingScheme, NamingScheme: data.NamingScheme,
} }
panelId, err := dbclient.Client.Panel.Create(panel) panelId, err := dbclient.Client.Panel.Create(panel)
@ -214,8 +228,27 @@ func CreatePanel(ctx *gin.Context) {
} }
var urlRegex = regexp.MustCompile(`^https?://([-a-zA-Z0-9@:%._+~#=]{1,256})\.[a-zA-Z0-9()]{1,63}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$`) var urlRegex = regexp.MustCompile(`^https?://([-a-zA-Z0-9@:%._+~#=]{1,256})\.[a-zA-Z0-9()]{1,63}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$`)
var validate = validator.New()
func (p *panelBody) doValidations(ctx *gin.Context, guildId uint64) bool { func (p *panelBody) doValidations(ctx *gin.Context, guildId uint64) bool {
err := validate.Struct(p)
if err != nil {
validationErrors, ok := err.(validator.ValidationErrors)
if !ok {
ctx.JSON(500, utils.ErrorStr("An error occurred while validating the panel"))
return false
}
formatted := "Your input contained the following errors:"
for _, validationError := range validationErrors {
formatted += fmt.Sprintf("\n%s", validationError.Error())
}
formatted = strings.TrimSuffix(formatted, "\n")
ctx.JSON(400, utils.ErrorStr(formatted))
return false
}
botContext, err := botcontext.ContextForGuild(guildId) botContext, err := botcontext.ContextForGuild(guildId)
if err != nil { if err != nil {
return false // TODO: Log error return false // TODO: Log error
@ -254,14 +287,6 @@ func (p *panelBody) doValidations(ctx *gin.Context, guildId uint64) bool {
return false return false
} }
if !p.verifyWelcomeMessage() {
ctx.JSON(400, gin.H{
"success": false,
"error": "Welcome message must be blank or between 1 - 4096 characters",
})
return false
}
if !p.verifyImageUrl() || !p.verifyThumbnailUrl() { if !p.verifyImageUrl() || !p.verifyThumbnailUrl() {
ctx.JSON(400, gin.H{ ctx.JSON(400, gin.H{
"success": false, "success": false,
@ -405,10 +430,6 @@ func (p *panelBody) verifyEmoji(ctx botcontext.BotContext, guildId uint64) bool
} }
} }
func (p *panelBody) verifyWelcomeMessage() bool {
return p.WelcomeMessage == nil || (len(*p.WelcomeMessage) > 0 && len(*p.WelcomeMessage) <= 4096)
}
func (p *panelBody) verifyImageUrl() bool { func (p *panelBody) verifyImageUrl() bool {
if p.ImageUrl != nil && len(*p.ImageUrl) == 0 { if p.ImageUrl != nil && len(*p.ImageUrl) == 0 {
p.ImageUrl = nil p.ImageUrl = nil

View File

@ -45,6 +45,14 @@ func DeletePanel(ctx *gin.Context) {
return return
} }
// Delete welcome message embed
if panel.WelcomeMessageEmbed != nil {
if err := database.Client.Embeds.Delete(*panel.WelcomeMessageEmbed); err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
}
if err := database.Client.Panel.Delete(panelId); err != nil { if err := database.Client.Panel.Delete(panelId); err != nil {
ctx.JSON(500, utils.ErrorJson(err)) ctx.JSON(500, utils.ErrorJson(err))
return return

View File

@ -14,21 +14,25 @@ import (
func ListPanels(ctx *gin.Context) { func ListPanels(ctx *gin.Context) {
type panelResponse struct { type panelResponse struct {
database.Panel database.Panel
UseCustomEmoji bool `json:"use_custom_emoji"` WelcomeMessage *types.CustomEmbed `json:"welcome_message"`
Emoji types.Emoji `json:"emote"` UseCustomEmoji bool `json:"use_custom_emoji"`
Mentions []string `json:"mentions"` Emoji types.Emoji `json:"emote"`
Teams []int `json:"teams"` Mentions []string `json:"mentions"`
UseServerDefaultNamingScheme bool `json:"use_server_default_naming_scheme"` Teams []int `json:"teams"`
UseServerDefaultNamingScheme bool `json:"use_server_default_naming_scheme"`
} }
guildId := ctx.Keys["guildid"].(uint64) guildId := ctx.Keys["guildid"].(uint64)
panels, err := dbclient.Client.Panel.GetByGuild(guildId) panels, err := dbclient.Client.Panel.GetByGuildWithWelcomeMessage(guildId)
if err != nil { if err != nil {
ctx.AbortWithStatusJSON(500, gin.H{ ctx.JSON(500, utils.ErrorJson(err))
"success": false, return
"error": err.Error(), }
})
allFields, err := dbclient.Client.EmbedFields.GetAllFieldsForPanels(guildId)
if err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return return
} }
@ -75,8 +79,15 @@ func ListPanels(ctx *gin.Context) {
teamIds = make([]int, 0) teamIds = make([]int, 0)
} }
var welcomeMessage *types.CustomEmbed
if p.WelcomeMessage != nil {
fields := allFields[p.WelcomeMessage.Id]
welcomeMessage = types.NewCustomEmbed(p.WelcomeMessage, fields)
}
wrapped[i] = panelResponse{ wrapped[i] = panelResponse{
Panel: p, Panel: p.Panel,
WelcomeMessage: welcomeMessage,
UseCustomEmoji: p.EmojiId != nil, UseCustomEmoji: p.EmojiId != nil,
Emoji: types.NewEmoji(p.EmojiName, p.EmojiId), Emoji: types.NewEmoji(p.EmojiName, p.EmojiId),
Mentions: mentions, Mentions: mentions,

View File

@ -2,6 +2,7 @@ package api
import ( import (
"errors" "errors"
"fmt"
"github.com/TicketsBot/GoPanel/botcontext" "github.com/TicketsBot/GoPanel/botcontext"
dbclient "github.com/TicketsBot/GoPanel/database" dbclient "github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/rpc" "github.com/TicketsBot/GoPanel/rpc"
@ -105,31 +106,67 @@ func UpdatePanel(ctx *gin.Context) {
} }
} }
// Update welcome message
var welcomeMessageEmbed *int
if data.WelcomeMessage == nil {
if existing.WelcomeMessageEmbed != nil { // If welcome message wasn't null, but now is, delete the embed
if err := dbclient.Client.Embeds.Delete(*existing.WelcomeMessageEmbed); err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
} // else, welcomeMessageEmbed will be nil
} else {
// TODO: Upsert? Don't think we can, as no unique key in the table, panel_id is in panels table
if existing.WelcomeMessageEmbed == nil { // Create
embed, fields := data.WelcomeMessage.IntoDatabaseStruct()
embed.GuildId = guildId
id, err := dbclient.Client.Embeds.CreateWithFields(embed, fields)
if err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
welcomeMessageEmbed = &id
} else { // Update
welcomeMessageEmbed = existing.WelcomeMessageEmbed
embed, fields := data.WelcomeMessage.IntoDatabaseStruct()
embed.Id = *existing.WelcomeMessageEmbed
embed.GuildId = guildId
if err := dbclient.Client.Embeds.UpdateWithFields(embed, fields); err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
}
}
// Store in DB // Store in DB
panel := database.Panel{ panel := database.Panel{
PanelId: panelId, PanelId: panelId,
MessageId: newMessageId, MessageId: newMessageId,
ChannelId: data.ChannelId, ChannelId: data.ChannelId,
GuildId: guildId, GuildId: guildId,
Title: data.Title, Title: data.Title,
Content: data.Content, Content: data.Content,
Colour: int32(data.Colour), Colour: int32(data.Colour),
TargetCategory: data.CategoryId, TargetCategory: data.CategoryId,
EmojiName: emojiName, EmojiName: emojiName,
EmojiId: emojiId, EmojiId: emojiId,
WelcomeMessage: data.WelcomeMessage, WelcomeMessageEmbed: welcomeMessageEmbed,
WithDefaultTeam: data.WithDefaultTeam, WithDefaultTeam: data.WithDefaultTeam,
CustomId: existing.CustomId, CustomId: existing.CustomId,
ImageUrl: data.ImageUrl, ImageUrl: data.ImageUrl,
ThumbnailUrl: data.ThumbnailUrl, ThumbnailUrl: data.ThumbnailUrl,
ButtonStyle: int(data.ButtonStyle), ButtonStyle: int(data.ButtonStyle),
ButtonLabel: data.ButtonLabel, ButtonLabel: data.ButtonLabel,
FormId: data.FormId, FormId: data.FormId,
NamingScheme: data.NamingScheme, NamingScheme: data.NamingScheme,
} }
if err = dbclient.Client.Panel.Update(panel); err != nil { if err = dbclient.Client.Panel.Update(panel); err != nil {
ctx.AbortWithStatusJSON(500, utils.ErrorJson(err)) ctx.JSON(500, utils.ErrorJson(err))
return return
} }
@ -149,7 +186,7 @@ func UpdatePanel(ctx *gin.Context) {
} else { } else {
roleId, err := strconv.ParseUint(mention, 10, 64) roleId, err := strconv.ParseUint(mention, 10, 64)
if err != nil { if err != nil {
ctx.AbortWithStatusJSON(500, utils.ErrorJson(err)) ctx.JSON(500, utils.ErrorJson(err))
return return
} }
@ -159,6 +196,7 @@ func UpdatePanel(ctx *gin.Context) {
} }
} }
fmt.Println(panel.PanelId)
if err := dbclient.Client.PanelUserMention.Set(panel.PanelId, shouldMentionUser); err != nil { if err := dbclient.Client.PanelUserMention.Set(panel.PanelId, shouldMentionUser); err != nil {
ctx.AbortWithStatusJSON(500, utils.ErrorJson(err)) ctx.AbortWithStatusJSON(500, utils.ErrorJson(err))
return return

View File

@ -12,5 +12,6 @@
font-size: 14px; font-size: 14px;
padding: 0 4px; padding: 0 4px;
margin-left: 4px; margin-left: 4px;
margin-bottom: 5px;
} }
</style> </style>

View File

@ -0,0 +1,80 @@
<div style="margin-bottom: 8px">
<div style="cursor: pointer;" class="inline" on:click={toggle}>
{#if expanded}
<i class="{retractIcon}"></i>
{:else}
<i class="{expandIcon}"></i>
{/if}
<slot name="header"></slot>
<hr/>
</div>
<div bind:this={content} class="content">
<slot name="content"></slot>
</div>
</div>
<script>
import {onMount} from "svelte";
export let retractIcon = "fas fa-minus";
export let expandIcon = "fas fa-plus";
let expanded = false;
let showOverflow = true;
let content;
export function toggle() {
if (expanded) {
content.style.maxHeight = 0;
} else {
updateSize();
}
expanded = !expanded;
}
export function updateSize() {
content.style.maxHeight = `${content.scrollHeight}px`;
}
onMount(() => {
const fn = (e) => {
if (expanded) {
updateSize();
}
}
content.addEventListener('DOMNodeInserted', fn);
content.addEventListener('DOMNodeRemoved', fn);
});
</script>
<style>
.content {
display: flex;
transition: max-height .3s ease-in-out, margin-top .3s ease-in-out, margin-bottom .3s ease-in-out;
position: relative;
overflow: hidden;
max-height: 0;
}
.inline {
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
gap: 10px;
}
hr {
border-top: 1px solid #777;
border-bottom: 0;
border-left: 0;
border-right: 0;
width: 100%;
}
</style>

View File

@ -0,0 +1,208 @@
<div class="modal" transition:fade>
<div class="modal-wrapper">
<Card footer="{true}" footerRight="{true}" fill="{false}">
<span slot="title">Embed Builder</span>
<div slot="body" class="body-wrapper">
<form class="form-wrapper" on:submit|preventDefault>
<div class="row">
<Colour col3 label="Embed Colour" bind:value={data.colour}/>
<Input col3 label="Title" placeholder="Embed Title" bind:value={data.title}/>
<Input col3 label="Title URL (Optional)" placeholder="https://example.com" bind:value={data.url}/>
</div>
<div class="row">
<Textarea col1 label="Description" placeholder="Large text area, up to 4096 characters"
bind:value={data.description}/>
</div>
<Collapsible>
<span slot="header">Author</span>
<div slot="content" class="row">
<Input col3 label="Author Name" placeholder="Author Name" bind:value={data.author.name}/>
<Input col3 label="Author Icon URL (Optional)" placeholder="https://example.com/image.png"
tooltipText="Small icon displayed in the top left" bind:value={data.author.icon_url}/>
<Input col3 label="Author URL (Optional)" placeholder="https://example.com"
tooltipText="Hyperlink on the author's name" bind:value={data.author.url}/>
</div>
</Collapsible>
<Collapsible>
<span slot="header">Images</span>
<div slot="content" class="row">
<Input col2 label="Large Image URL" placeholder="https://example.com/image.png"
bind:value={data.image_url}/>
<Input col2 label="Small Image URL" placeholder="https://example.com/image.png"
bind:value={data.thumbnail_url}/>
</div>
</Collapsible>
<Collapsible>
<span slot="header">Footer</span>
<div slot="content" class="row">
<Input col3 label="Footer Text" placeholder="Footer Text" badge="Premium" bind:value={data.footer.text}/>
<Input col3 label="Footer Icon URL (Optional)" badge="Premium" placeholder="https://example.com/image.png"
bind:value={data.footer.icon_url}/>
<DateTimePicker col3 label="Footer Timestamp (Optional)" bind:value={data.timestamp}/>
</div>
</Collapsible>
<Collapsible>
<span slot="header">Fields</span>
<div slot="content" class="col-1">
{#each data.fields as field, i}
<div class="row" style="justify-content: flex-start; gap: 10px">
<Input col2 label="Field Name" placeholder="Field Name" bind:value={field.name}/>
<Checkbox label="Inline" bind:value={field.inline}/>
<div style="margin-top: 18px; display: flex; align-self: center">
<Button danger icon="fas fa-trash-can" on:click={() => deleteField(i)}>Delete</Button>
</div>
</div>
<div class="row">
<Textarea col1 label="Field Value" placeholder="Large text area, up to 1024 characters"
bind:value={field.value}/>
</div>
{/each}
<Button type="button" icon="fas fa-plus" fullWidth on:click={addField}>Add Field</Button>
</div>
</Collapsible>
</form>
</div>
<div slot="footer">
<Button danger={true} on:click={dispatchClose}>Cancel</Button>
<div style="margin-left: 12px">
<Button icon="fas fa-paper-plane" on:click={dispatchConfirm}>Submit</Button>
</div>
</div>
</Card>
</div>
</div>
<div class="modal-backdrop" transition:fade>
</div>
<svelte:window on:keydown={handleKeydown}/>
<script>
import {createEventDispatcher} from 'svelte';
import {fade} from 'svelte/transition'
import Card from "./Card.svelte";
import Button from "./Button.svelte";
import Input from "./form/Input.svelte";
import Colour from "./form/Colour.svelte";
import Textarea from "./form/Textarea.svelte";
import DateTimePicker from "./form/DateTimePicker.svelte";
import Collapsible from "./Collapsible.svelte";
import Checkbox from "./form/Checkbox.svelte";
export let guildId;
export let data;
if (data === undefined || data === null) {
if (!data) {
data = {};
}
data.fields = [];
data.colour = '#2ECC71';
data.author = {};
data.footer = {};
}
function addField() {
data.fields.push({name: '', value: '', inline: false});
data = data;
}
function deleteField(i) {
data.fields.splice(i, 1);
data = data;
}
const dispatch = createEventDispatcher();
function dispatchClose() {
dispatch('close', {});
}
// Dispatch with data
function dispatchConfirm() {
// Map blank strings to null
const mapper = (obj) => {
Object.keys(obj).forEach(key => {
if (typeof obj[key] === 'string' && obj[key] === '') {
obj[key] = null;
} else if (typeof obj[key] === 'object') {
mapper(obj[key]);
}
});
}
mapper(data);
dispatch('confirm', data);
}
function handleKeydown(e) {
if (e.key === "Escape") {
dispatchClose();
}
}
</script>
<style>
.modal {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999;
display: flex;
justify-content: center;
align-items: center;
}
.modal-wrapper {
display: flex;
width: 60%;
margin: 10% auto auto auto;
}
@media only screen and (max-width: 1280px) {
.modal-wrapper {
width: 96%;
}
}
.modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 500;
background-color: #000;
opacity: .5;
}
.form-wrapper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.row {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,42 @@
<div class:col-1={col1} class:col-2={col2} class:col-3={col3} class:col-4={col4}>
{#if label !== undefined}
<div class="label-wrapper">
<label for="picker" class="form-label">
{label}
</label>
</div>
{/if}
<input type="datetime-local" id="picker" class="form-input" disabled="{disabled}"
bind:this={picker} on:input on:change bind:value={value} on:click={() => picker.showPicker()}>
</div>
<script>
let picker;
export let value;
export let label;
export let placeholder;
export let disabled = false;
export let col1 = false;
export let col2 = false;
export let col3 = false;
export let col4 = false;
</script>
<style>
input {
width: 100%;
}
.label-wrapper {
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
}
.tooltip-icon {
cursor: pointer;
}
</style>

View File

@ -1,22 +1,23 @@
<div class:col-1={col1} class:col-2={col2} class:col-3={col3} class:col-4={col4}> <div class:col-1={col1} class:col-2={col2} class:col-3={col3} class:col-4={col4}>
{#if label !== undefined} {#if label !== undefined}
<div class="label-wrapper"> <div class="label-wrapper">
<label for="input" class="form-label"> <label for="input" class="form-label">{label}</label>
{label} {#if badge !== undefined}
</label> <Badge>{badge}</Badge>
{#if tooltipText !== undefined} {/if}
<div style="margin-bottom: 5px"> {#if tooltipText !== undefined}
<Tooltip tip={tooltipText} top color="#121212"> <div style="margin-bottom: 5px">
{#if tooltipLink !== undefined} <Tooltip tip={tooltipText} top color="#121212">
<a href={tooltipLink} target="_blank"> {#if tooltipLink !== undefined}
<i class="fas fa-circle-info form-label tooltip-icon"></i> <a href={tooltipLink} target="_blank">
</a> <i class="fas fa-circle-info form-label tooltip-icon"></i>
{:else} </a>
<i class="fas fa-circle-info form-label tooltip-icon"></i> {:else}
{/if} <i class="fas fa-circle-info form-label tooltip-icon"></i>
</Tooltip> {/if}
</div> </Tooltip>
{/if} </div>
{/if}
</div> </div>
{/if} {/if}
<input id="input" class="form-input" placeholder="{placeholder}" disabled="{disabled}" on:input on:change <input id="input" class="form-input" placeholder="{placeholder}" disabled="{disabled}" on:input on:change
@ -25,10 +26,12 @@
<script> <script>
import Tooltip from 'svelte-tooltip'; import Tooltip from 'svelte-tooltip';
import Badge from "../Badge.svelte";
export let value; export let value;
export let label; export let label;
export let placeholder; export let placeholder;
export let badge;
export let disabled = false; export let disabled = false;
export let tooltipText = undefined; export let tooltipText = undefined;

View File

@ -69,6 +69,7 @@
.modal-wrapper { .modal-wrapper {
display: flex; display: flex;
width: 75%; width: 75%;
margin: 10% auto auto auto;
} }
@media only screen and (max-width: 1280px) { @media only screen and (max-width: 1280px) {

View File

@ -1,3 +1,9 @@
{#if welcomeMessageBuilder}
<EmbedBuilder data={data.welcome_message}
on:close={closeWelcomeMessageBuilder}
on:confirm={handleWelcomeMessageUpdate}/>
{/if}
<form class="settings-form" on:submit|preventDefault> <form class="settings-form" on:submit|preventDefault>
<div class="row"> <div class="row">
<div class="col-1-3"> <div class="col-1-3">
@ -68,9 +74,35 @@
class:advanced-settings-hide={!advancedSettings} class:show-overflow={overflowShow}> class:advanced-settings-hide={!advancedSettings} class:show-overflow={overflowShow}>
<div class="inner" class:inner-show={advancedSettings} class:absolute={advancedSettings && !overflowShow} > <div class="inner" class:inner-show={advancedSettings} class:absolute={advancedSettings && !overflowShow} >
<div class="row"> <div class="row">
<Textarea col1=true bind:value={data.welcome_message} label="Welcome Message" <div class="col-2">
placeholder="If blank, your server's default welcome message will be used" <label class="form-label">Welcome Message</label>
on:input={handleWelcomeMessageUpdate}/> <div class="row" style="justify-content: flex-start; gap: 10px">
<Button icon="fas fa-brush" on:click={openWelcomeMessageBuilder}>Open Editor</Button>
<Button icon="fas fa-trash-can" danger
on:click={() => data.welcome_message = null}>Clear</Button>
</div>
</div>
<div class="col-2">
<label for="naming-scheme-wrapper" class="form-label">Naming Scheme</label>
<div class="row" id="naming-scheme-wrapper">
<div>
<label class="form-label">Use Server Default</label>
<Toggle hideLabel
toggledColor="#66bb6a"
untoggledColor="#ccc"
bind:toggled={data.use_server_default_naming_scheme} />
</div>
<div class="col-fill">
{#if !data.use_server_default_naming_scheme}
<Input label="Naming Scheme"
bind:value={data.naming_scheme}
placeholder="ticket-%id%"
tooltipText="Click here for the full placeholder list"
tooltipLink="https://docs.ticketsbot.net" />
{/if}
</div>
</div>
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-2"> <div class="col-2">
@ -104,29 +136,6 @@
<Input col2={true} label="Large Image URL" bind:value={data.image_url} placeholder="https://example.com/image.png" /> <Input col2={true} label="Large Image URL" bind:value={data.image_url} placeholder="https://example.com/image.png" />
<Input col2={true} label="Small Image URL" bind:value={data.thumbnail_url} placeholder="https://example.com/image.png" /> <Input col2={true} label="Small Image URL" bind:value={data.thumbnail_url} placeholder="https://example.com/image.png" />
</div> </div>
<div class="row">
<div class="col-2">
<label for="naming-scheme-wrapper" class="form-label">Naming Scheme</label>
<div class="row" id="naming-scheme-wrapper">
<div>
<label class="form-label">Use Server Default</label>
<Toggle hideLabel
toggledColor="#66bb6a"
untoggledColor="#ccc"
bind:toggled={data.use_server_default_naming_scheme} />
</div>
<div class="col-fill">
{#if !data.use_server_default_naming_scheme}
<Input label="Naming Scheme"
bind:value={data.naming_scheme}
placeholder="ticket-%id%"
tooltipText="Click here for the full placeholder list"
tooltipLink="https://docs.ticketsbot.net" />
{/if}
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</form> </form>
@ -137,6 +146,7 @@
import Colour from "../form/Colour.svelte"; import Colour from "../form/Colour.svelte";
import Button from "../Button.svelte"; import Button from "../Button.svelte";
import ChannelDropdown from "../ChannelDropdown.svelte"; import ChannelDropdown from "../ChannelDropdown.svelte";
import EmbedBuilder from "../EmbedBuilder.svelte";
import {createEventDispatcher, onMount} from 'svelte'; import {createEventDispatcher, onMount} from 'svelte';
import {colourToInt, intToColour} from "../../js/util"; import {colourToInt, intToColour} from "../../js/util";
@ -145,9 +155,7 @@
import EmojiItem from "../EmojiItem.svelte"; import EmojiItem from "../EmojiItem.svelte";
import Select from 'svelte-select'; import Select from 'svelte-select';
import Dropdown from "../form/Dropdown.svelte"; import Dropdown from "../form/Dropdown.svelte";
import Checkbox from "../form/Checkbox.svelte";
import Toggle from "svelte-toggle"; import Toggle from "svelte-toggle";
import Slider from "../form/Slider.svelte";
export let guildId; export let guildId;
export let seedDefault = true; export let seedDefault = true;
@ -173,6 +181,17 @@
let selectedTeams = seedDefault ? [{id: 'default', name: 'Default'}] : []; let selectedTeams = seedDefault ? [{id: 'default', name: 'Default'}] : [];
let selectedMentions = []; let selectedMentions = [];
let welcomeMessageBuilder = false;
function openWelcomeMessageBuilder() {
welcomeMessageBuilder = true;
window.scrollTo({ top: 0, behavior: 'smooth' });
}
function closeWelcomeMessageBuilder() {
welcomeMessageBuilder = false;
}
// Replace spaces with dashes in naming scheme as the user types // Replace spaces with dashes in naming scheme as the user types
$: if (data.naming_scheme !== undefined && data.naming_scheme !== null && data.naming_scheme.includes(' ')) { $: if (data.naming_scheme !== undefined && data.naming_scheme !== null && data.naming_scheme.includes(' ')) {
data.naming_scheme = data.naming_scheme.replaceAll(' ', '-'); data.naming_scheme = data.naming_scheme.replaceAll(' ', '-');
@ -222,10 +241,9 @@
} }
} }
function handleWelcomeMessageUpdate() { function handleWelcomeMessageUpdate(e) {
if (data.welcome_message === "") { data.welcome_message = e.detail;
data.welcome_message = null; closeWelcomeMessageBuilder();
}
} }
function handleEmojiTypeChange(e) { function handleEmojiTypeChange(e) {

View File

@ -74,6 +74,7 @@
.modal-wrapper { .modal-wrapper {
display: flex; display: flex;
width: 75%; width: 75%;
margin: 10% auto auto auto;
} }
@media only screen and (max-width: 1280px) { @media only screen and (max-width: 1280px) {

14
go.mod
View File

@ -6,14 +6,15 @@ require (
github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml v0.3.1
github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc
github.com/TicketsBot/common v0.0.0-20220615205931-a6a31e73b52a github.com/TicketsBot/common v0.0.0-20220615205931-a6a31e73b52a
github.com/TicketsBot/database v0.0.0-20220623211222-6d64f44d5cfb github.com/TicketsBot/database v0.0.0-20220627203133-dd19fe34f094
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c
github.com/TicketsBot/worker v0.0.0-20220621165800-203b0004b733 github.com/TicketsBot/worker v0.0.0-20220627203254-f37bdb40b39a
github.com/apex/log v1.1.2 github.com/apex/log v1.1.2
github.com/getsentry/sentry-go v0.13.0 github.com/getsentry/sentry-go v0.13.0
github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2 github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2
github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607 github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607
github.com/gin-gonic/gin v1.7.7 github.com/gin-gonic/gin v1.7.7
github.com/go-playground/validator/v10 v10.11.0
github.com/go-redis/redis v6.15.9+incompatible github.com/go-redis/redis v6.15.9+incompatible
github.com/go-redis/redis/v8 v8.11.3 github.com/go-redis/redis/v8 v8.11.3
github.com/go-redis/redis_rate/v9 v9.1.1 github.com/go-redis/redis_rate/v9 v9.1.1
@ -39,9 +40,8 @@ require (
github.com/getsentry/raven-go v0.2.0 // indirect github.com/getsentry/raven-go v0.2.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-errors/errors v1.1.0 // indirect github.com/go-errors/errors v1.1.0 // indirect
github.com/go-playground/locales v0.13.0 // indirect github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.6.1 // indirect
github.com/gofrs/uuid v3.3.0+incompatible // indirect github.com/gofrs/uuid v3.3.0+incompatible // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/gomodule/redigo v2.0.0+incompatible // indirect github.com/gomodule/redigo v2.0.0+incompatible // indirect
@ -60,7 +60,7 @@ require (
github.com/juju/ratelimit v1.0.1 // indirect github.com/juju/ratelimit v1.0.1 // indirect
github.com/klauspost/compress v1.10.10 // indirect github.com/klauspost/compress v1.10.10 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/leodido/go-urn v1.2.0 // indirect github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
@ -71,7 +71,7 @@ require (
github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9 // indirect github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9 // indirect
github.com/ugorji/go/codec v1.2.6 // indirect github.com/ugorji/go/codec v1.2.6 // indirect
go.uber.org/atomic v1.6.0 // indirect go.uber.org/atomic v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect

49
go.sum
View File

@ -5,18 +5,15 @@ github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc h1:n15W8
github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc/go.mod h1:2KcfHS0JnSsgcxZBs3NyWMXNQzEo67mBSGOyzHPWOCc= github.com/TicketsBot/archiverclient v0.0.0-20220326163414-558fd52746dc/go.mod h1:2KcfHS0JnSsgcxZBs3NyWMXNQzEo67mBSGOyzHPWOCc=
github.com/TicketsBot/common v0.0.0-20220615205931-a6a31e73b52a h1:SwA18cDURmnXSrKBdetNVanSsyJBMtyosDzvgYMpKP4= github.com/TicketsBot/common v0.0.0-20220615205931-a6a31e73b52a h1:SwA18cDURmnXSrKBdetNVanSsyJBMtyosDzvgYMpKP4=
github.com/TicketsBot/common v0.0.0-20220615205931-a6a31e73b52a/go.mod h1:ZAoYcDD7SQLTsZT7dbo/X0J256+pogVRAReunCGng+U= github.com/TicketsBot/common v0.0.0-20220615205931-a6a31e73b52a/go.mod h1:ZAoYcDD7SQLTsZT7dbo/X0J256+pogVRAReunCGng+U=
github.com/TicketsBot/database v0.0.0-20220623160906-a56dc9dfda90 h1:K0t6IaZdeZzEr2BaYj/NBuWIm/hA31jkqFh2c3nyDrw= github.com/TicketsBot/database v0.0.0-20220627203133-dd19fe34f094 h1:a272Wj4At5XjIjLoRAdn4PwfZ288+A4QzwTvFAR6fho=
github.com/TicketsBot/database v0.0.0-20220623160906-a56dc9dfda90/go.mod h1:F57cywrZsnper1cy56Bx0c/HEsxQBLHz3Pl98WXblWw= github.com/TicketsBot/database v0.0.0-20220627203133-dd19fe34f094/go.mod h1:F57cywrZsnper1cy56Bx0c/HEsxQBLHz3Pl98WXblWw=
github.com/TicketsBot/database v0.0.0-20220623203124-d335941a5a86 h1:oCynNT5m2nP5y+rf52/tGGhRGI85C3YSaoI4Ox3RuLs=
github.com/TicketsBot/database v0.0.0-20220623203124-d335941a5a86/go.mod h1:F57cywrZsnper1cy56Bx0c/HEsxQBLHz3Pl98WXblWw=
github.com/TicketsBot/database v0.0.0-20220623211222-6d64f44d5cfb h1:nLL2HT+RZVnGIi474Al+xdLiBH9Wsr287m7tBAePJQY=
github.com/TicketsBot/database v0.0.0-20220623211222-6d64f44d5cfb/go.mod h1:F57cywrZsnper1cy56Bx0c/HEsxQBLHz3Pl98WXblWw=
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c h1:OqGjFH6mbE6gd+NqI2ARJdtH3UUvhiAkD0r0fhGJK2s= github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c h1:OqGjFH6mbE6gd+NqI2ARJdtH3UUvhiAkD0r0fhGJK2s=
github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c/go.mod h1:jgi2OXQKsd5nUnTIRkwvPmeuD/i7OhN68LKMssuQY1c= github.com/TicketsBot/logarchiver v0.0.0-20220326162808-cdf0310f5e1c/go.mod h1:jgi2OXQKsd5nUnTIRkwvPmeuD/i7OhN68LKMssuQY1c=
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 h1:NHD5GB6cjlkpZFjC76Yli2S63/J2nhr8MuE6KlYJpQM= github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 h1:NHD5GB6cjlkpZFjC76Yli2S63/J2nhr8MuE6KlYJpQM=
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261/go.mod h1:2zPxDAN2TAPpxUPjxszjs3QFKreKrQh5al/R3cMXmYk= github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261/go.mod h1:2zPxDAN2TAPpxUPjxszjs3QFKreKrQh5al/R3cMXmYk=
github.com/TicketsBot/worker v0.0.0-20220621165800-203b0004b733 h1:G4iUjk4lgGRvbRCSJshpwuQetl+z3v7PmHzIW+HII9k=
github.com/TicketsBot/worker v0.0.0-20220621165800-203b0004b733/go.mod h1:fhEqdxVhgXds/xB3ql05XSDqPLF4XWjkfyHr+JQFe0g= github.com/TicketsBot/worker v0.0.0-20220621165800-203b0004b733/go.mod h1:fhEqdxVhgXds/xB3ql05XSDqPLF4XWjkfyHr+JQFe0g=
github.com/TicketsBot/worker v0.0.0-20220627203254-f37bdb40b39a h1:cx2YtngcJ7KpOBm/QotWKHb2XZbvUDJwD9azBl31e/k=
github.com/TicketsBot/worker v0.0.0-20220627203254-f37bdb40b39a/go.mod h1:R70+F86Z+UlretKMxOX1jRqCwvVlvuem9UAyAL4EiG8=
github.com/apex/log v1.1.2 h1:bnDuVoi+o98wOdVqfEzNDlY0tcmBia7r4YkjS9EqGYk= github.com/apex/log v1.1.2 h1:bnDuVoi+o98wOdVqfEzNDlY0tcmBia7r4YkjS9EqGYk=
github.com/apex/log v1.1.2/go.mod h1:SyfRweFO+TlkIJ3DVizTSeI1xk7jOIIqOnUPZQTTsww= github.com/apex/log v1.1.2/go.mod h1:SyfRweFO+TlkIJ3DVizTSeI1xk7jOIIqOnUPZQTTsww=
github.com/apex/logs v0.0.3/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= github.com/apex/logs v0.0.3/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
@ -37,6 +34,7 @@ github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMe
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -68,14 +66,16 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.6.1 h1:W6TRDXt4WcWp4c4nf/G+6BkGdhiIo0k417gfr+V6u4I= github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
github.com/go-playground/validator/v10 v10.6.1/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk= github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.3.4/go.mod h1:jszGxBCez8QA1HWSmQxJO9Y82kNibbUmeYhKWrBejTU= github.com/go-redis/redis/v8 v8.3.4/go.mod h1:jszGxBCez8QA1HWSmQxJO9Y82kNibbUmeYhKWrBejTU=
@ -200,13 +200,18 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@ -234,7 +239,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@ -252,6 +256,7 @@ github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+t
github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c h1:Gcce/r5tSQeprxswXXOwQ/RBU1bjQWVd9dB7QKoPXBE= github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c h1:Gcce/r5tSQeprxswXXOwQ/RBU1bjQWVd9dB7QKoPXBE=
github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c/go.mod h1:1iCZ0433JJMecYqCa+TdWA9Pax8MGl4ByuNDZ7eSnQY= github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c/go.mod h1:1iCZ0433JJMecYqCa+TdWA9Pax8MGl4ByuNDZ7eSnQY=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -261,6 +266,9 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
@ -289,6 +297,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9 h1:i2aD44Moa5N5pt/WNwHLvIklzPymtr8vkkBlVdNElUE= github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9 h1:i2aD44Moa5N5pt/WNwHLvIklzPymtr8vkkBlVdNElUE=
github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9/go.mod h1:6HrfShlf4bKeQEFdWn4JP/yet/mHW2RhxOQf0e3HWA0= github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9/go.mod h1:6HrfShlf4bKeQEFdWn4JP/yet/mHW2RhxOQf0e3HWA0=
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
@ -324,8 +333,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@ -340,7 +349,8 @@ golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f h1:1scJEYZBaF48BaG6tYbtxmLcXqwYGSfGcMoStTqkkIw= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
@ -368,6 +378,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -411,7 +422,8 @@ gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVC
gopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7SLonnE4drU= gopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7SLonnE4drU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
@ -428,6 +440,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
nhooyr.io/websocket v1.8.4 h1:P43INlkmY2eCxLvHeiMFK/ROUiOm0NdzRGGDtURbe58= nhooyr.io/websocket v1.8.4 h1:P43INlkmY2eCxLvHeiMFK/ROUiOm0NdzRGGDtURbe58=
nhooyr.io/websocket v1.8.4/go.mod h1:LiqdCg1Cu7TPWxEvPjPa0TGYxCsy4pHNTN9gGluwBpQ= nhooyr.io/websocket v1.8.4/go.mod h1:LiqdCg1Cu7TPWxEvPjPa0TGYxCsy4pHNTN9gGluwBpQ=

38
utils/types/colour.go Normal file
View File

@ -0,0 +1,38 @@
package types
import (
"fmt"
"strconv"
"strings"
)
type Colour uint32
func (c Colour) Uint32() uint32 {
return uint32(c)
}
func (c Colour) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"#%06x"`, c)), nil
}
func (c *Colour) UnmarshalJSON(b []byte) error {
if len(b) < 2 {
return fmt.Errorf("invalid colour")
}
s := string(b)[1 : len(b)-1] // Trim quotes
s = strings.TrimPrefix(s, `#`) // Trim # if present
tmp, err := strconv.ParseUint(s, 16, 32)
if err != nil {
return err
}
if tmp > 0xFFFFFF {
return fmt.Errorf("colour value %v is out of range", tmp)
}
*c = Colour(tmp)
return nil
}

141
utils/types/customembed.go Normal file
View File

@ -0,0 +1,141 @@
package types
import (
"github.com/TicketsBot/GoPanel/utils"
"github.com/TicketsBot/database"
"github.com/rxdn/gdl/objects/channel/embed"
)
type CustomEmbed struct {
Title *string `json:"title" validate:"omitempty,min=1,max=255"`
Description *string `json:"description" validate:"omitempty,min=1,max=4096"`
Url *string `json:"url" validate:"omitempty,url"`
Colour Colour `json:"colour" validate:"required,gte=0,lte=16777215"`
Author Author `json:"author" validate:"dive"`
ImageUrl *string `json:"image_url" validate:"omitempty,url"`
ThumbnailUrl *string `json:"thumbnail_url" validate:"omitempty,url"`
Footer Footer `json:"footer" validate:"dive"`
Timestamp *DateTimeLocal `json:"timestamp" validate:"omitempty"`
Fields []Field `json:"fields" validate:"dive,max=25"`
}
type Author struct {
Name *string `json:"name" validate:"omitempty,min=1,max=255"`
IconUrl *string `json:"icon_url" validate:"omitempty,url"`
Url *string `json:"url" validate:"omitempty,url"`
}
type Footer struct {
Text *string `json:"text" validate:"omitempty,min=1,max=2048"`
IconUrl *string `json:"icon_url" validate:"omitempty,url"`
}
type Field struct {
Name string `json:"name" validate:"min=1,max=255"`
Value string `json:"value" validate:"min=1,max=1024"`
Inline bool `json:"inline"`
}
func NewCustomEmbed(c *database.CustomEmbed, fields []database.EmbedField) *CustomEmbed {
wrappedFields := make([]Field, len(fields))
for i, field := range fields {
wrappedFields[i] = Field{
Name: field.Name,
Value: field.Value,
Inline: field.Inline,
}
}
return &CustomEmbed{
Title: c.Title,
Description: c.Description,
Url: c.Url,
Colour: Colour(c.Colour),
Author: Author{
Name: c.AuthorName,
IconUrl: c.AuthorIconUrl,
Url: c.AuthorUrl,
},
ImageUrl: c.ImageUrl,
ThumbnailUrl: c.ThumbnailUrl,
Footer: Footer{
Text: c.FooterText,
IconUrl: c.FooterIconUrl,
},
Timestamp: NewDateTimeLocalFromPtr(c.Timestamp),
Fields: wrappedFields,
}
}
func (c *CustomEmbed) IntoDatabaseStruct() (*database.CustomEmbed, []database.EmbedField) {
fields := make([]database.EmbedField, len(c.Fields))
for i, field := range c.Fields {
fields[i] = database.EmbedField{
Name: field.Name,
Value: field.Value,
Inline: field.Inline,
}
}
return &database.CustomEmbed{
Title: c.Title,
Description: c.Description,
Url: c.Url,
Colour: uint32(c.Colour),
AuthorName: c.Author.Name,
AuthorIconUrl: c.Author.IconUrl,
AuthorUrl: c.Author.Url,
ImageUrl: c.ImageUrl,
ThumbnailUrl: c.ThumbnailUrl,
FooterText: c.Footer.Text,
FooterIconUrl: c.Footer.IconUrl,
Timestamp: TimeOrNil(c.Timestamp),
}, fields
}
func (c *CustomEmbed) IntoDiscordEmbed() *embed.Embed {
e := &embed.Embed{
Title: utils.ValueOrZero(c.Title),
Description: utils.ValueOrZero(c.Description),
Url: utils.ValueOrZero(c.Url),
Timestamp: TimeOrNil(c.Timestamp),
Color: int(c.Colour),
}
if c.Footer.Text != nil {
e.Footer = &embed.EmbedFooter{
Text: *c.Footer.Text,
IconUrl: utils.ValueOrZero(c.Footer.IconUrl),
}
}
if c.ImageUrl != nil {
e.SetImage(*c.ImageUrl)
}
if c.ThumbnailUrl != nil {
e.SetThumbnail(*c.ThumbnailUrl)
}
if c.Author.Name != nil {
e.Author = &embed.EmbedAuthor{
Name: *c.Author.Name,
IconUrl: utils.ValueOrZero(c.Author.IconUrl),
Url: utils.ValueOrZero(c.Author.Url),
}
}
if len(c.Fields) > 0 {
e.Fields = make([]*embed.EmbedField, len(c.Fields))
for i, field := range c.Fields {
e.Fields[i] = &embed.EmbedField{
Name: field.Name,
Value: field.Value,
Inline: field.Inline,
}
}
}
return e
}

View File

@ -0,0 +1,49 @@
package types
import (
"fmt"
"github.com/TicketsBot/GoPanel/utils"
"time"
)
type DateTimeLocal time.Time
var format = "2006-01-02T15:04"
func NewDateTimeLocalFromPtr(t *time.Time) *DateTimeLocal {
if t == nil {
return nil
}
return utils.Ptr(DateTimeLocal(*t))
}
func TimeOrNil(d *DateTimeLocal) *time.Time {
if d == nil {
return nil
}
return utils.Ptr(d.Time())
}
func (d DateTimeLocal) Time() time.Time {
return time.Time(d)
}
func (d DateTimeLocal) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, time.Time(d).Format(format))), nil
}
func (d *DateTimeLocal) UnmarshalJSON(b []byte) error {
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
return fmt.Errorf("invalid DateTimeLocal")
}
tmp, err := time.Parse(format, string(b[1:len(b)-1]))
if err != nil {
return err
}
*d = DateTimeLocal(tmp)
return nil
}

View File

@ -3,3 +3,11 @@ package utils
func Ptr[T any](v T) *T { func Ptr[T any](v T) *T {
return &v return &v
} }
func ValueOrZero[T any](v *T) T {
if v == nil {
return *new(T)
} else {
return *v
}
}