Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions src/boost/boost.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,49 @@ func setChickenRunMessageID(contract *Contract, channelID, messageID string) {
saveData(contract.ContractHash)
}

// findLocation returns the LocationData for the given channelID, or nil if not found.
func (c *Contract) findLocation(channelID string) *LocationData {
if c == nil || channelID == "" {
return nil
}
for _, loc := range c.Location {
if loc.ChannelID == channelID {
return loc
}
}
return nil
}

// isOldBoostListMessage checks if messageID belongs to contract in channelID as a former boost list message
// that is no longer the active boost list.
func isOldBoostListMessage(contract *Contract, channelID string, messageID string) bool {
if contract == nil || channelID == "" || messageID == "" {
return false
}
for _, loc := range contract.Location {
if loc.ChannelID == channelID {
if messageID == loc.ListMsgID || messageID == loc.ReactionID {
return false
}
if contract.CRMessageIDs != nil && contract.CRMessageIDs[channelID] == messageID {
return false
}
return slices.Contains(loc.MessageIDs, messageID)
}
}
return false
}

// cleanupOldBoostListMessage deletes an old boost list message from Discord.
func cleanupOldBoostListMessage(client dc.Client, contract *Contract, channelID string, messageID string) {
if client == nil || contract == nil || channelID == "" || messageID == "" {
return
}
log.Printf("cleanupOldBoostListMessage: deleting stale boost list message %s in channel %s for contract %s",
messageID, channelID, contract.ContractHash)
_ = client.DeleteMessage(channelID, messageID)
}

func getTokenCountString(tokenStr string, tokensWanted int, tokensReceived int) (string, string) {
countStr := ""
signupCountStr := ""
Expand Down
56 changes: 48 additions & 8 deletions src/boost/boost_button_reactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,66 @@ func HandleContractReactions(client dc.Client, e *dc.ComponentEvent) {

redraw := false

// Check if this interaction came from an old/stale boost list message
isStale := isOldBoostListMessage(contract, e.ChannelID(), e.MessageID())
if !isStale {
if loc := contract.findLocation(e.ChannelID()); loc != nil {
if loc.ListMsgID != "" && e.MessageID() != loc.ListMsgID && e.MessageID() != loc.ReactionID {
isStale = true
}
}
}

if isStale {
cleanupOldBoostListMessage(client, contract, e.ChannelID(), e.MessageID())
redraw = true
}

switch cmd {
case "boost":
if e.MessageID() == contract.Location[0].ListMsgID {
redraw = buttonReactionBoost(client, e.GuildID(), e.ChannelID(), contract, userID)
if isStale {
redraw = true
} else {
loc := contract.findLocation(e.ChannelID())
if loc != nil && e.MessageID() == loc.ListMsgID {
redraw = buttonReactionBoost(client, e.GuildID(), e.ChannelID(), contract, userID)
}
}
case "bag":
_, redraw = buttonReactionBag(client, e.GuildID(), e.ChannelID(), contract, userID)
var r bool
_, r = buttonReactionBag(client, e.GuildID(), e.ChannelID(), contract, userID)
if r || isStale {
redraw = true
}
case "token":
_, redraw = buttonReactionToken(client, e.GuildID(), e.ChannelID(), contract, userID, 1, "")
var r bool
_, r = buttonReactionToken(client, e.GuildID(), e.ChannelID(), contract, userID, 1, "")
if r || isStale {
redraw = true
}
sendOrUpdateUserReactionSummary(e, contract, userID)
case "2token":
_, redraw = buttonReactionToken(client, e.GuildID(), e.ChannelID(), contract, userID, 2, "")
var r bool
_, r = buttonReactionToken(client, e.GuildID(), e.ChannelID(), contract, userID, 2, "")
if r || isStale {
redraw = true
}
sendOrUpdateUserReactionSummary(e, contract, userID)
case "swap":
redraw = buttonReactionSwap(client, e.GuildID(), e.ChannelID(), contract, userID)
if !isStale {
redraw = buttonReactionSwap(client, e.GuildID(), e.ChannelID(), contract, userID)
}
case "last":
_, redraw = buttonReactionLast(client, e.GuildID(), e.ChannelID(), contract, userID)
if !isStale {
_, redraw = buttonReactionLast(client, e.GuildID(), e.ChannelID(), contract, userID)
}
case "cr":
var str string
redraw, str = buttonReactionRunChickens(client, contract, userID)
var r bool
r, str = buttonReactionRunChickens(client, contract, userID)
if r || isStale {
redraw = true
}
// Ack the message for every other command
_ = e.Followup(dc.Message{
Content: str,
Expand Down
35 changes: 25 additions & 10 deletions src/boost/boost_reactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ func ReactionAdd(client dc.Client, e *dc.ReactionEvent) string {
return returnVal
}

isStale := isOldBoostListMessage(contract, e.ChannelID(), e.MessageID())
if isStale {
cleanupOldBoostListMessage(client, contract, e.ChannelID(), e.MessageID())
redraw = true
}

defer saveData(contract.ContractHash)

if emojiName == "⚙️" || emojiName == "⚙" {
Expand Down Expand Up @@ -107,25 +113,30 @@ func ReactionAdd(client dc.Client, e *dc.ReactionEvent) string {

switch e.EmojiName() {
case boostIconName:
if e.MessageID() == contract.Location[0].ListMsgID {
loc := contract.findLocation(e.ChannelID())
if loc != nil && e.MessageID() == loc.ListMsgID {
result := buttonReactionBoost(client, e.GuildID(), e.ChannelID(), contract, userID)
if result {
return returnVal
}
}
case "🔃":
result := buttonReactionSwap(client, e.GuildID(), e.ChannelID(), contract, userID)
if result {
return returnVal
if !isStale {
result := buttonReactionSwap(client, e.GuildID(), e.ChannelID(), contract, userID)
if result {
return returnVal
}
}
case "⤵️":
willReturn := false
willReturn, redraw = buttonReactionLast(client, e.GuildID(), e.ChannelID(), contract, userID)
if willReturn {
return returnVal
if !isStale {
willReturn := false
willReturn, redraw = buttonReactionLast(client, e.GuildID(), e.ChannelID(), contract, userID)
if willReturn {
return returnVal
}
}
case "🚽":
if contract.Boosters[userID].BoostState == BoostStateUnboosted {
if !isStale && contract.Boosters[userID].BoostState == BoostStateUnboosted {
// Bounds check: ensure currentBoosterIdx is valid before using it
if currentBoosterIdx < 0 {
_, _ = client.SendMessage(e.ChannelID(), dc.Message{Content: "Unable to move booster right now because the current booster position could not be determined."})
Expand Down Expand Up @@ -214,7 +225,11 @@ func ReactionAdd(client dc.Client, e *dc.ReactionEvent) string {
userID := e.UserID()

if strings.ToLower(e.EmojiName()) == tokenReactionStr {
_, redraw = buttonReactionToken(client, e.GuildID(), e.ChannelID(), contract, userID, 1, "")
var r bool
_, r = buttonReactionToken(client, e.GuildID(), e.ChannelID(), contract, userID, 1, "")
if r || isStale {
redraw = true
}
}
} else {
keepReaction = false
Expand Down
26 changes: 24 additions & 2 deletions src/boost/message_redraw.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,18 @@ func RedrawBoostList(client dc.Client, guildID string, channelID string) error {
buttonComponents := getContractReactionsComponents(contract)
for _, loc := range contract.Location {
if loc.GuildID == guildID && loc.ChannelID == channelID {
_ = client.DeleteMessage(loc.ChannelID, loc.ListMsgID)
oldMsgID := loc.ListMsgID
if oldMsgID != "" {
if err := client.DeleteMessage(loc.ChannelID, oldMsgID); err != nil {
log.Printf("RedrawBoostList: unable to delete old boost list message %s in channel %s for contract %s: %v",
oldMsgID, loc.ChannelID, contract.ContractHash, err)
time.AfterFunc(2*time.Second, func() {
if retryErr := client.DeleteMessage(loc.ChannelID, oldMsgID); retryErr != nil {
log.Printf("RedrawBoostList: retry delete old boost list message %s failed: %v", oldMsgID, retryErr)
}
})
}
}
var components []dc.LayoutComponent
listComp := DrawBoostList(contract)
components = append(components, listComp...)
Expand Down Expand Up @@ -232,7 +243,18 @@ func sendNextNotification(client dc.Client, contract *Contract, pingUsers bool)
if contract.State == ContractStateArchive {
_ = client.UnpinMessage(loc.ChannelID, loc.ReactionID)
}
_ = client.DeleteMessage(loc.ChannelID, loc.ListMsgID)
oldMsgID := loc.ListMsgID
if oldMsgID != "" {
if err := client.DeleteMessage(loc.ChannelID, oldMsgID); err != nil {
log.Printf("sendNextNotification: unable to delete old boost list message %s in channel %s for contract %s: %v",
oldMsgID, loc.ChannelID, contract.ContractHash, err)
time.AfterFunc(2*time.Second, func() {
if retryErr := client.DeleteMessage(loc.ChannelID, oldMsgID); retryErr != nil {
log.Printf("sendNextNotification: retry delete old boost list message %s failed: %v", oldMsgID, retryErr)
}
})
}
}

// Compose the message without a Ping
listComp := DrawBoostList(contract)
Expand Down
Loading
Loading