Skip to content

Commit 06261ef

Browse files
committed
feat: update panel handling to support nullable channel and message IDs
1 parent 0a62226 commit 06261ef

8 files changed

Lines changed: 100 additions & 67 deletions

File tree

app/http/endpoints/api/panel/panelcreate.go

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import (
2626
const freePanelLimit = 3
2727

2828
type panelBody struct {
29-
ChannelId uint64 `json:"channel_id,string"`
30-
MessageId uint64 `json:"message_id,string"`
29+
ChannelId *uint64 `json:"channel_id,string"`
30+
MessageId *uint64 `json:"message_id,string"`
3131
Title string `json:"title"`
3232
Content string `json:"content"`
3333
Colour uint32 `json:"colour"`
@@ -52,9 +52,13 @@ type panelBody struct {
5252
UseThreads bool `json:"use_threads"`
5353
}
5454

55-
func (p *panelBody) IntoPanelMessageData(customId string, isPremium bool) panelMessageData {
56-
return panelMessageData{
57-
ChannelId: p.ChannelId,
55+
func (p *panelBody) IntoPanelMessageData(customId string, isPremium bool) *panelMessageData {
56+
if p.ChannelId == nil {
57+
// This should never happen due to earlier validation
58+
return nil
59+
}
60+
return &panelMessageData{
61+
ChannelId: *p.ChannelId,
5862
Title: p.Title,
5963
Content: p.Content,
6064
CustomId: customId,
@@ -87,7 +91,7 @@ func CreatePanel(c *gin.Context) {
8791
return
8892
}
8993

90-
data.MessageId = 0
94+
data.MessageId = nil
9195

9296
// Check panel quota
9397
premiumTier, err := rpc.PremiumClient.GetTierByGuildId(c, guildId, false, botContext.Token, botContext.RateLimiter)
@@ -168,20 +172,24 @@ func CreatePanel(c *gin.Context) {
168172
}
169173

170174
messageData := data.IntoPanelMessageData(customId, premiumTier > premium.None)
171-
msgId, err := messageData.send(botContext)
172-
if err != nil {
173-
var unwrapped request.RestError
174-
if errors.As(err, &unwrapped) {
175-
if unwrapped.StatusCode == http.StatusForbidden {
176-
c.JSON(400, utils.ErrorStr("Bot does not have permission to send messages in channel %d", data.ChannelId))
175+
var newMsgId *uint64
176+
if data.MessageId != nil {
177+
msgId, err := messageData.send(botContext)
178+
if err != nil {
179+
var unwrapped request.RestError
180+
if errors.As(err, &unwrapped) {
181+
if unwrapped.StatusCode == http.StatusForbidden {
182+
c.JSON(400, utils.ErrorStr("Bot does not have permission to send messages in channel %d", data.ChannelId))
183+
} else {
184+
c.JSON(400, utils.ErrorStr("Failed to send panel message to channel %d: %s", data.ChannelId, unwrapped.ApiError.Message))
185+
}
177186
} else {
178-
c.JSON(400, utils.ErrorStr("Failed to send panel message to channel %d: %s", data.ChannelId, unwrapped.ApiError.Message))
187+
_ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to send panel message to Discord"))
179188
}
180-
} else {
181-
_ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to send panel message to Discord"))
182-
}
183189

184-
return
190+
return
191+
}
192+
newMsgId = &msgId
185193
}
186194

187195
var emojiId *uint64
@@ -214,7 +222,7 @@ func CreatePanel(c *gin.Context) {
214222

215223
// Store in DB
216224
panel := database.Panel{
217-
MessageId: msgId,
225+
MessageId: newMsgId,
218226
ChannelId: data.ChannelId,
219227
GuildId: guildId,
220228
Title: data.Title,

app/http/endpoints/api/panel/paneldelete.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package api
22

33
import (
4-
"fmt"
54
"errors"
5+
"fmt"
66
"net/http"
77
"strconv"
88

@@ -70,11 +70,13 @@ func DeletePanel(c *gin.Context) {
7070
}
7171

7272
// TODO: Set timeout on context
73-
if err := rest.DeleteMessage(c, botContext.Token, botContext.RateLimiter, panel.ChannelId, panel.MessageId); err != nil {
74-
var unwrapped request.RestError
75-
if !errors.As(err, &unwrapped) || unwrapped.StatusCode != 404 {
76-
_ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to delete panel"))
77-
return
73+
if panel.ChannelId != nil && panel.MessageId != nil {
74+
if err := rest.DeleteMessage(c, botContext.Token, botContext.RateLimiter, *panel.ChannelId, *panel.MessageId); err != nil {
75+
var unwrapped request.RestError
76+
if !errors.As(err, &unwrapped) || unwrapped.StatusCode != 404 {
77+
_ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to delete panel"))
78+
return
79+
}
7880
}
7981
}
8082

app/http/endpoints/api/panel/panelmessagedata.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ type panelMessageData struct {
2727
IsPremium bool
2828
}
2929

30-
func panelIntoMessageData(panel database.Panel, isPremium bool) panelMessageData {
30+
func panelIntoMessageData(panel database.Panel, isPremium bool) *panelMessageData {
31+
if panel.ChannelId == nil {
32+
return nil
33+
}
34+
3135
var emote *emoji.Emoji
3236
if panel.EmojiName != nil { // No emoji = nil
3337
if panel.EmojiId == nil { // Unicode emoji
@@ -42,8 +46,8 @@ func panelIntoMessageData(panel database.Panel, isPremium bool) panelMessageData
4246
}
4347
}
4448

45-
return panelMessageData{
46-
ChannelId: panel.ChannelId,
49+
return &panelMessageData{
50+
ChannelId: *panel.ChannelId,
4751
Title: panel.Title,
4852
Content: panel.Content,
4953
CustomId: panel.CustomId,

app/http/endpoints/api/panel/panelresend.go

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package api
22

33
import (
4-
"fmt"
54
"context"
65
"errors"
6+
"fmt"
77
"strconv"
88

99
"github.com/TicketsBot-cloud/common/premium"
@@ -56,11 +56,13 @@ func ResendPanel(ctx *gin.Context) {
5656

5757
// delete old message
5858
// TODO: Use proper context
59-
if err := rest.DeleteMessage(context.Background(), botContext.Token, botContext.RateLimiter, panel.ChannelId, panel.GuildId); err != nil {
60-
var unwrapped request.RestError
61-
if errors.As(err, &unwrapped) && !unwrapped.IsClientError() {
62-
ctx.JSON(500, utils.ErrorStr("Failed to send message. Please try again."))
63-
return
59+
if panel.MessageId != nil {
60+
if err := rest.DeleteMessage(context.Background(), botContext.Token, botContext.RateLimiter, *panel.ChannelId, *panel.MessageId); err != nil {
61+
var unwrapped request.RestError
62+
if errors.As(err, &unwrapped) && !unwrapped.IsClientError() {
63+
ctx.JSON(500, utils.ErrorStr("Failed to send message. Please try again."))
64+
return
65+
}
6466
}
6567
}
6668

@@ -71,19 +73,23 @@ func ResendPanel(ctx *gin.Context) {
7173
}
7274

7375
messageData := panelIntoMessageData(panel, premiumTier > premium.None)
74-
msgId, err := messageData.send(botContext)
75-
if err != nil {
76-
var unwrapped request.RestError
77-
if errors.As(err, &unwrapped) && unwrapped.StatusCode == 403 {
78-
ctx.JSON(500, utils.ErrorStr("I do not have permission to send messages in the provided channel"))
79-
} else {
80-
ctx.JSON(500, utils.ErrorStr("Failed to send message. Please try again."))
81-
}
76+
var newMsgId *uint64
77+
if messageData != nil {
78+
msgId, err := messageData.send(botContext)
79+
if err != nil {
80+
var unwrapped request.RestError
81+
if errors.As(err, &unwrapped) && unwrapped.StatusCode == 403 {
82+
ctx.JSON(500, utils.ErrorStr("I do not have permission to send messages in the provided channel"))
83+
} else {
84+
ctx.JSON(500, utils.ErrorStr("Failed to send message. Please try again."))
85+
}
8286

83-
return
87+
return
88+
}
89+
newMsgId = &msgId
8490
}
8591

86-
if err = dbclient.Client.Panel.UpdateMessageId(ctx, panel.PanelId, msgId); err != nil {
92+
if err = dbclient.Client.Panel.UpdateMessageId(ctx, panel.PanelId, newMsgId); err != nil {
8793
ctx.JSON(500, utils.ErrorStr("Failed to send message. Please try again."))
8894
return
8995
}

app/http/endpoints/api/panel/panelupdate.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -146,32 +146,40 @@ func UpdatePanel(c *gin.Context) {
146146
existing.ButtonLabel != data.ButtonLabel ||
147147
existing.Disabled != data.Disabled
148148

149-
newMessageId := existing.MessageId
149+
var newMessageId *uint64
150+
if existing.ChannelId != nil && data.ChannelId != nil {
151+
// old message exists and provided channel exists
152+
newMessageId = existing.MessageId
153+
}
150154

151155
if shouldUpdateMessage {
152-
// delete old message, ignoring error
153156
// TODO: Use proper context
154-
_ = rest.DeleteMessage(c, botContext.Token, botContext.RateLimiter, existing.ChannelId, existing.MessageId)
157+
if existing.ChannelId != nil && existing.MessageId != nil {
158+
_ = rest.DeleteMessage(c, botContext.Token, botContext.RateLimiter, *existing.ChannelId, *existing.MessageId)
159+
}
155160

156-
messageData := data.IntoPanelMessageData(existing.CustomId, premiumTier > premium.None)
157-
newMessageId, err = messageData.send(botContext)
158-
if err != nil {
159-
var unwrapped request.RestError
160-
if errors.As(err, &unwrapped) {
161-
if unwrapped.StatusCode == 403 {
162-
c.JSON(403, utils.ErrorStr("I do not have permission to send messages in the specified channel"))
163-
return
164-
} else if unwrapped.StatusCode == 404 {
165-
// Swallow error
166-
// TODO: Make channel_id column nullable, and set to null
161+
if data.ChannelId == nil {
162+
messageData := data.IntoPanelMessageData(existing.CustomId, premiumTier > premium.None)
163+
messageId, err := messageData.send(botContext)
164+
if err != nil {
165+
var unwrapped request.RestError
166+
if errors.As(err, &unwrapped) {
167+
if unwrapped.StatusCode == 403 {
168+
c.JSON(403, utils.ErrorStr("I do not have permission to send messages in the specified channel"))
169+
return
170+
} else if unwrapped.StatusCode == 404 {
171+
// Swallow error
172+
dbclient.Client.Panel.UpdateChannelId(c, existing.PanelId, nil)
173+
} else {
174+
_ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to update panel"))
175+
return
176+
}
167177
} else {
168178
_ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to update panel"))
169179
return
170180
}
171-
} else {
172-
_ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to update panel"))
173-
return
174181
}
182+
newMessageId = &messageId
175183
}
176184
}
177185

app/http/endpoints/api/panel/validation.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,11 @@ func validateContent(ctx PanelValidationContext) validation.ValidationFunc {
9999

100100
func validateChannelId(ctx PanelValidationContext) validation.ValidationFunc {
101101
return func() error {
102+
if ctx.Data.ChannelId == nil {
103+
return nil
104+
}
102105
for _, ch := range ctx.Channels {
103-
if ch.Id == ctx.Data.ChannelId && (ch.Type == channel.ChannelTypeGuildText || ch.Type == channel.ChannelTypeGuildNews) {
106+
if ch.Id == *ctx.Data.ChannelId && (ch.Type == channel.ChannelTypeGuildText || ch.Type == channel.ChannelTypeGuildNews) {
104107
return nil
105108
}
106109
}

frontend/src/components/manage/PanelCreationForm.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@
409409
label="Panel Channel"
410410
allowAnnouncementChannel
411411
col4
412+
withNull
413+
nullLabel={"None"}
412414
{channels}
413415
bind:value={data.channel_id}
414416
/>

frontend/src/views/panels/Panels.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@
179179
<tbody>
180180
{#each panels as panel}
181181
<tr>
182-
<td
183-
>#{channels.find(
184-
(c) => c.id === panel.channel_id,
185-
)?.name ?? "Unknown Channel"}</td
186-
>
182+
{#if panel.channel_id == null || panel.channel_id == "null"}
183+
<td>None</td>
184+
{:else}
185+
<td>#{channels.find((c) => c.id === panel.channel_id)?.name ?? "Unknown Channel"}</td>
186+
{/if}
187187
<td>{panel.title}</td>
188188
<td>
189189
{#if panel.has_support_hours}
@@ -206,7 +206,7 @@
206206
<td class="actions-cell">
207207
<ActionDropdown bind:this={panel.dropdownRef}>
208208
<button
209-
disabled={panel.force_disabled}
209+
disabled={panel.force_disabled || panel.channel_id == null || panel.channel_id == "null"}
210210
on:click={() => {
211211
resendPanel(panel.panel_id);
212212
panel.dropdownRef?.close();

0 commit comments

Comments
 (0)