diff --git a/app/http/endpoints/api/panel/panelcreate.go b/app/http/endpoints/api/panel/panelcreate.go index f51cb7b..4f62540 100644 --- a/app/http/endpoints/api/panel/panelcreate.go +++ b/app/http/endpoints/api/panel/panelcreate.go @@ -19,6 +19,7 @@ import ( "github.com/rxdn/gdl/rest" "github.com/rxdn/gdl/rest/request" "golang.org/x/sync/errgroup" + "regexp" "strconv" "strings" ) @@ -37,6 +38,8 @@ type panelBody struct { Mentions []string `json:"mentions"` WithDefaultTeam bool `json:"default_team"` Teams []database.SupportTeam `json:"teams"` + ImageUrl *string `json:"image_url,omitempty"` + ThumbnailUrl *string `json:"thumbnail_url,omitempty"` } func CreatePanel(ctx *gin.Context) { @@ -91,7 +94,7 @@ func CreatePanel(ctx *gin.Context) { customId := utils.RandString(80) emoji, _ := data.getEmoji() // already validated - msgId, err := data.sendEmbed(&botContext, data.Title, customId, emoji, premiumTier > premium.None) + msgId, err := data.sendEmbed(&botContext, data.Title, customId, emoji, data.ImageUrl, data.ThumbnailUrl, premiumTier > premium.None) if err != nil { var unwrapped request.RestError if errors.As(err, &unwrapped) && unwrapped.StatusCode == 403 { @@ -123,6 +126,8 @@ func CreatePanel(ctx *gin.Context) { WelcomeMessage: data.WelcomeMessage, WithDefaultTeam: data.WithDefaultTeam, CustomId: customId, + ImageUrl: data.ImageUrl, + ThumbnailUrl: data.ThumbnailUrl, } panelId, err := dbclient.Client.Panel.Create(panel) @@ -202,6 +207,8 @@ func insertTeams(guildId uint64, panelId int, teams []database.SupportTeam) (int return 500, group.Wait() } +var urlRegex = regexp.MustCompile(`^https?://([-a-zA-Z0-9@:%._+~#=]{1,256})\.[a-zA-Z0-9()]{1,63}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$`) + func (p *panelBody) doValidations(ctx *gin.Context, guildId uint64) bool { if !p.verifyTitle() { ctx.AbortWithStatusJSON(400, gin.H{ @@ -254,6 +261,14 @@ func (p *panelBody) doValidations(ctx *gin.Context, guildId uint64) bool { return false } + if !p.verifyImageUrl() || !p.verifyThumbnailUrl() { + ctx.AbortWithStatusJSON(400, gin.H{ + "success": false, + "error": "Image URL must be between 1 - 255 characters and a valid URL", + }) + return false + } + return true } @@ -312,12 +327,36 @@ func (p *panelBody) verifyWelcomeMessage() bool { return p.WelcomeMessage == nil || (len(*p.WelcomeMessage) > 0 && len(*p.WelcomeMessage) < 1025) } -func (p *panelBody) sendEmbed(ctx *botcontext.BotContext, title, customId, emote string, isPremium bool) (uint64, error) { +func (p *panelBody) verifyImageUrl() bool { + if p.ImageUrl != nil && len(*p.ImageUrl) == 0 { + p.ImageUrl = nil + } + + return p.ImageUrl == nil || (len(*p.ImageUrl) <= 255 && urlRegex.MatchString(*p.ImageUrl)) +} + +func (p *panelBody) verifyThumbnailUrl() bool { + if p.ThumbnailUrl != nil && len(*p.ThumbnailUrl) == 0 { + p.ThumbnailUrl = nil + } + + return p.ThumbnailUrl == nil || (len(*p.ThumbnailUrl) <= 255 && urlRegex.MatchString(*p.ThumbnailUrl)) +} + +func (p *panelBody) sendEmbed(ctx *botcontext.BotContext, title, customId, emote string, imageUrl, thumbnailUrl *string, isPremium bool) (uint64, error) { e := embed.NewEmbed(). SetTitle(p.Title). SetDescription(p.Content). SetColor(int(p.Colour)) + if imageUrl != nil { + e.SetImage(*imageUrl) + } + + if thumbnailUrl != nil { + e.SetThumbnail(*thumbnailUrl) + } + if !isPremium { // TODO: Don't harcode e.SetFooter("Powered by ticketsbot.net", "https://cdn.discordapp.com/avatars/508391840525975553/ac2647ffd4025009e2aa852f719a8027.png?size=256") diff --git a/app/http/endpoints/api/panel/panellist.go b/app/http/endpoints/api/panel/panellist.go index 37fcee7..98acabe 100644 --- a/app/http/endpoints/api/panel/panellist.go +++ b/app/http/endpoints/api/panel/panellist.go @@ -11,17 +11,9 @@ import ( func ListPanels(ctx *gin.Context) { type panelResponse struct { - PanelId int `json:"panel_id"` - ChannelId uint64 `json:"channel_id,string"` - Title string `json:"title"` - Content string `json:"content"` - Colour uint32 `json:"colour"` - CategoryId uint64 `json:"category_id,string"` - Emote string `json:"emote"` - WelcomeMessage *string `json:"welcome_message"` - Mentions []string `json:"mentions"` - WithDefaultTeam bool `json:"default_team"` - Teams []database.SupportTeam `json:"teams"` + database.Panel + Mentions []string `json:"mentions"` + Teams []database.SupportTeam `json:"teams"` } guildId := ctx.Keys["guildid"].(uint64) @@ -74,17 +66,9 @@ func ListPanels(ctx *gin.Context) { } wrapped[i] = panelResponse{ - PanelId: p.PanelId, - ChannelId: p.ChannelId, - Title: p.Title, - Content: p.Content, - Colour: uint32(p.Colour), - CategoryId: p.TargetCategory, - Emote: p.ReactionEmote, - WelcomeMessage: p.WelcomeMessage, - Mentions: mentions, - WithDefaultTeam: p.WithDefaultTeam, - Teams: teams, + Panel: p, + Mentions: mentions, + Teams: teams, } return nil diff --git a/app/http/endpoints/api/panel/panelupdate.go b/app/http/endpoints/api/panel/panelupdate.go index bcb47a2..2cb42a5 100644 --- a/app/http/endpoints/api/panel/panelupdate.go +++ b/app/http/endpoints/api/panel/panelupdate.go @@ -104,7 +104,9 @@ func UpdatePanel(ctx *gin.Context) { existing.ChannelId != data.ChannelId || existing.Content != data.Content || existing.Title != data.Title || - existing.ReactionEmote != data.Emote + existing.ReactionEmote != data.Emote || + existing.ImageUrl != data.ImageUrl || + existing.ThumbnailUrl != data.ThumbnailUrl emoji, _ := data.getEmoji() // already validated newMessageId := existing.MessageId @@ -113,7 +115,7 @@ func UpdatePanel(ctx *gin.Context) { // delete old message, ignoring error _ = rest.DeleteMessage(botContext.Token, botContext.RateLimiter, existing.ChannelId, existing.MessageId) - newMessageId, err = data.sendEmbed(&botContext, existing.Title, existing.CustomId, existing.ReactionEmote, premiumTier > premium.None) + newMessageId, err = data.sendEmbed(&botContext, data.Title, existing.CustomId, data.Emote, data.ImageUrl, data.ThumbnailUrl, premiumTier > premium.None) if err != nil { var unwrapped request.RestError if errors.As(err, &unwrapped) && unwrapped.StatusCode == 403 { diff --git a/frontend/src/components/manage/PanelCreationForm.svelte b/frontend/src/components/manage/PanelCreationForm.svelte index eeb9cf7..1c4bc8a 100644 --- a/frontend/src/components/manage/PanelCreationForm.svelte +++ b/frontend/src/components/manage/PanelCreationForm.svelte @@ -43,6 +43,10 @@ +