From 85de6d175f957498ea4ef88f18d70eb8a929c333 Mon Sep 17 00:00:00 2001 From: Salastil Date: Sat, 28 Feb 2026 21:26:45 -0500 Subject: [PATCH] Restore functionality of edits, deletes and boundedmap uses UUID now --- discord/bridge.go | 58 +++++++++++++++++++++++---------------------- sneed/client.go | 58 +++++++++++++++++++-------------------------- sneed/types.go | 2 +- utils/boundedmap.go | 18 +++++++------- 4 files changed, 65 insertions(+), 71 deletions(-) diff --git a/discord/bridge.go b/discord/bridge.go index 55f96a6..711794d 100644 --- a/discord/bridge.go +++ b/discord/bridge.go @@ -186,8 +186,9 @@ func (b *Bridge) onDiscordMessageCreate(s *discordgo.Session, m *discordgo.Messa if m.ReferencedMessage != nil { refDiscordID := parseMessageID(m.ReferencedMessage.ID) - if sneedIDInt, ok := b.discordToSneed.Get(refDiscordID); ok { - if uname, ok2 := b.sneedUsernames.Get(sneedIDInt.(int)); ok2 { + if sneedUUIDVal, ok := b.discordToSneed.Get(strconv.Itoa(refDiscordID)); ok { + sneedUUID := sneedUUIDVal.(string) + if uname, ok2 := b.sneedUsernames.Get(sneedUUID); ok2 { contentText = fmt.Sprintf("@%s, %s", uname.(string), contentText) } } @@ -289,14 +290,14 @@ func (b *Bridge) onDiscordMessageEdit(s *discordgo.Session, m *discordgo.Message return } discordID := parseMessageID(m.ID) - sneedIDInt, ok := b.discordToSneed.Get(discordID) + sneedUUIDVal, ok := b.discordToSneed.Get(strconv.Itoa(discordID)) if !ok { return } - sneedID := sneedIDInt.(int) - payload := map[string]interface{}{"id": sneedID, "message": strings.TrimSpace(m.Content)} + sneedUUID := sneedUUIDVal.(string) + payload := map[string]interface{}{"uuid": sneedUUID, "message": strings.TrimSpace(m.Content)} data, _ := json.Marshal(payload) - log.Printf("↩️ Discord edit -> Sneedchat (sneed_id=%d)", sneedID) + log.Printf("↩️ Discord edit -> Sneedchat (sneed_uuid=%s)", sneedUUID) b.sneed.Send(fmt.Sprintf("/edit %s", string(data))) } @@ -305,12 +306,13 @@ func (b *Bridge) onDiscordMessageDelete(s *discordgo.Session, m *discordgo.Messa return } discordID := parseMessageID(m.ID) - sneedIDInt, ok := b.discordToSneed.Get(discordID) + sneedUUIDVal, ok := b.discordToSneed.Get(strconv.Itoa(discordID)) if !ok { return } - log.Printf("↩️ Discord delete -> Sneedchat (sneed_id=%d)", sneedIDInt.(int)) - b.sneed.Send(fmt.Sprintf("/delete %d", sneedIDInt.(int))) + sneedUUID := sneedUUIDVal.(string) + log.Printf("↩️ Discord delete -> Sneedchat (sneed_uuid=%s)", sneedUUID) + b.sneed.Send(fmt.Sprintf("/delete %s", sneedUUID)) } func (b *Bridge) onSneedMessage(msg map[string]interface{}) { @@ -348,17 +350,17 @@ func (b *Bridge) onSneedMessage(msg map[string]interface{}) { log.Printf("✅ Sent Sneedchat → Discord: %s", username) if sent != nil { - if mid, ok := msg["message_id"].(int); ok && mid > 0 { + if uuid, ok := msg["message_uuid"].(string); ok && uuid != "" { discordMsgID := parseMessageID(sent.ID) - b.sneedToDiscord.Set(mid, discordMsgID) - b.discordToSneed.Set(discordMsgID, mid) - b.sneedUsernames.Set(mid, username) + b.sneedToDiscord.Set(uuid, discordMsgID) + b.discordToSneed.Set(strconv.Itoa(discordMsgID), uuid) + b.sneedUsernames.Set(uuid, username) } } } -func (b *Bridge) handleSneedEdit(sneedID int, newContent string) { - discordIDInt, ok := b.sneedToDiscord.Get(sneedID) +func (b *Bridge) handleSneedEdit(sneedUUID string, newContent string) { + discordIDInt, ok := b.sneedToDiscord.Get(sneedUUID) if !ok { return } @@ -371,11 +373,11 @@ func (b *Bridge) handleSneedEdit(sneedID int, newContent string) { log.Printf("❌ Failed to edit Discord message id=%d: %v", discordID, err) return } - log.Printf("✏️ Edited Discord (webhook) message id=%d (sneed_id=%d)", discordID, sneedID) + log.Printf("✏️ Edited Discord (webhook) message id=%d (sneed_uuid=%s)", discordID, sneedUUID) } -func (b *Bridge) handleSneedDelete(sneedID int) { - discordIDInt, ok := b.sneedToDiscord.Get(sneedID) +func (b *Bridge) handleSneedDelete(sneedUUID string) { + discordIDInt, ok := b.sneedToDiscord.Get(sneedUUID) if !ok { return } @@ -386,10 +388,10 @@ func (b *Bridge) handleSneedDelete(sneedID int) { log.Printf("❌ Failed to delete Discord message id=%d: %v", discordID, err) return } - log.Printf("🗑️ Deleted Discord (webhook) message id=%d (sneed_id=%d)", discordID, sneedID) - b.sneedToDiscord.Delete(sneedID) - b.discordToSneed.Delete(discordID) - b.sneedUsernames.Delete(sneedID) + log.Printf("🗑️ Deleted Discord (webhook) message id=%d (sneed_uuid=%s)", discordID, sneedUUID) + b.sneedToDiscord.Delete(sneedUUID) + b.discordToSneed.Delete(strconv.Itoa(discordID)) + b.sneedUsernames.Delete(sneedUUID) } func (b *Bridge) onSneedConnect() { @@ -575,11 +577,11 @@ func (b *Bridge) recentOutboundIter() []map[string]interface{} { return res } -func (b *Bridge) mapDiscordSneed(discordID, sneedID int, username string) { - b.discordToSneed.Set(discordID, sneedID) - b.sneedToDiscord.Set(sneedID, discordID) - b.sneedUsernames.Set(sneedID, username) - log.Printf("Mapped sneed_id=%d <-> discord_id=%d (username='%s')", sneedID, discordID, username) +func (b *Bridge) mapDiscordSneed(sneedUUID string, discordID int, username string) { + b.discordToSneed.Set(strconv.Itoa(discordID), sneedUUID) + b.sneedToDiscord.Set(sneedUUID, discordID) + b.sneedUsernames.Set(sneedUUID, username) + log.Printf("Mapped sneed_uuid=%s <-> discord_id=%d (username='%s')", sneedUUID, discordID, username) } func (b *Bridge) sendUploadStatusMessage(channelID, mention string, attachmentCount int) (*discordgo.Message, error) { @@ -629,7 +631,7 @@ func (b *Bridge) awaitSneedConfirmation(discordID int, channelID, statusMessageI for { select { case <-ticker.C: - if _, ok := b.discordToSneed.Get(discordID); ok { + if _, ok := b.discordToSneed.Get(strconv.Itoa(discordID)); ok { desc := "Delivered to Sneedchat." b.editUploadStatusMessage(channelID, statusMessageID, b.uploadStatusTitle("complete"), desc, UploadStatusColorSuccess) b.scheduleUploadStatusDeletion(channelID, statusMessageID, UploadStatusCleanupDelay) diff --git a/sneed/client.go b/sneed/client.go index abf28a3..6d4710d 100644 --- a/sneed/client.go +++ b/sneed/client.go @@ -58,13 +58,13 @@ type Client struct { messageEditDates *utils.BoundedMap OnMessage func(map[string]interface{}) - OnEdit func(int, string) - OnDelete func(int) + OnEdit func(string, string) + OnDelete func(string) OnConnect func() OnDisconnect func() recentOutboundIter func() []map[string]interface{} - mapDiscordSneed func(int, int, string) + mapDiscordSneed func(string, int, string) bridgeUserID int bridgeUsername string @@ -367,23 +367,14 @@ func (c *Client) handleIncoming(raw string) { log.Printf("📦 payload: msgs=%d msg=%v del=%v", len(payload.Messages), payload.Message != nil, payload.Delete != nil) } - if payload.Delete != nil { - var ids []int - switch v := payload.Delete.(type) { - case float64: - ids = []int{int(v)} - case []interface{}: - for _, x := range v { - if fid, ok := x.(float64); ok { - ids = append(ids, int(fid)) - } - } + for _, uuid := range payload.Delete { + if uuid == "" { + continue } - for _, id := range ids { - c.messageEditDates.Delete(id) - if c.OnDelete != nil { - c.OnDelete(id) - } + c.messageEditDates.Delete(uuid) + c.removeFromProcessed(uuid) + if c.OnDelete != nil { + c.OnDelete(uuid) } } @@ -418,10 +409,10 @@ func (c *Client) processMessage(m SneedMessage) { editDate := m.MessageEditDate deleted := m.Deleted || m.IsDeleted if deleted { - c.messageEditDates.Delete(m.MessageID) + c.messageEditDates.Delete(uuid) c.removeFromProcessed(uuid) if c.OnDelete != nil { - c.OnDelete(m.MessageID) + c.OnDelete(uuid) } return } @@ -438,7 +429,7 @@ func (c *Client) processMessage(m SneedMessage) { if ts, ok := entry["ts"].(time.Time); ok { if content == messageText && now.Sub(ts) <= OutboundMatchWindow { if discordID, ok := entry["discord_id"].(int); ok { - c.mapDiscordSneed(discordID, m.MessageID, username) + c.mapDiscordSneed(uuid, discordID, username) entry["mapped"] = true break } @@ -447,16 +438,16 @@ func (c *Client) processMessage(m SneedMessage) { } } c.addToProcessed(uuid) - c.messageEditDates.Set(m.MessageID, editDate) + c.messageEditDates.Set(uuid, editDate) return } if c.isProcessed(uuid) { - if prev, exists := c.messageEditDates.Get(m.MessageID); exists { + if prev, exists := c.messageEditDates.Get(uuid); exists { if editDate > prev.(int) { - c.messageEditDates.Set(m.MessageID, editDate) + c.messageEditDates.Set(uuid, editDate) if c.OnEdit != nil { - c.OnEdit(m.MessageID, messageText) + c.OnEdit(uuid, messageText) } } } @@ -464,15 +455,16 @@ func (c *Client) processMessage(m SneedMessage) { } c.addToProcessed(uuid) - c.messageEditDates.Set(m.MessageID, editDate) + c.messageEditDates.Set(uuid, editDate) if c.OnMessage != nil { c.OnMessage(map[string]interface{}{ - "username": username, - "content": messageText, - "message_id": m.MessageID, - "author_id": userID, - "raw": m, + "username": username, + "content": messageText, + "message_uuid": uuid, + "message_id": m.MessageID, + "author_id": userID, + "raw": m, }) } } @@ -522,7 +514,7 @@ func (c *Client) SetOutboundIter(f func() []map[string]interface{}) { c.recentOutboundIter = f } -func (c *Client) SetMapDiscordSneed(f func(int, int, string)) { +func (c *Client) SetMapDiscordSneed(f func(string, int, string)) { c.mapDiscordSneed = f } diff --git a/sneed/types.go b/sneed/types.go index b19f287..1e6eb3c 100644 --- a/sneed/types.go +++ b/sneed/types.go @@ -14,5 +14,5 @@ type SneedMessage struct { type SneedPayload struct { Messages []SneedMessage `json:"messages"` Message *SneedMessage `json:"message"` - Delete interface{} `json:"delete"` + Delete []string `json:"delete"` } diff --git a/utils/boundedmap.go b/utils/boundedmap.go index e621232..b1bc3a6 100644 --- a/utils/boundedmap.go +++ b/utils/boundedmap.go @@ -7,24 +7,24 @@ import ( type BoundedMap struct { mu sync.RWMutex - data map[int]interface{} - timestamps map[int]time.Time + data map[string]interface{} + timestamps map[string]time.Time maxSize int maxAge time.Duration - keys []int + keys []string } func NewBoundedMap(maxSize int, maxAge time.Duration) *BoundedMap { return &BoundedMap{ - data: make(map[int]interface{}), - timestamps: make(map[int]time.Time), + data: make(map[string]interface{}), + timestamps: make(map[string]time.Time), maxSize: maxSize, maxAge: maxAge, - keys: make([]int, 0, maxSize), + keys: make([]string, 0, maxSize), } } -func (bm *BoundedMap) Set(key int, value interface{}) { +func (bm *BoundedMap) Set(key string, value interface{}) { bm.mu.Lock() defer bm.mu.Unlock() if _, ok := bm.data[key]; ok { @@ -50,14 +50,14 @@ func (bm *BoundedMap) Set(key int, value interface{}) { } } -func (bm *BoundedMap) Get(key int) (interface{}, bool) { +func (bm *BoundedMap) Get(key string) (interface{}, bool) { bm.mu.RLock() defer bm.mu.RUnlock() v, ok := bm.data[key] return v, ok } -func (bm *BoundedMap) Delete(key int) { +func (bm *BoundedMap) Delete(key string) { bm.mu.Lock() defer bm.mu.Unlock() delete(bm.data, key)