From 71230e3886a5f383644414ae31ba946e2ff2d51d Mon Sep 17 00:00:00 2001 From: Alessio Date: Sun, 5 May 2024 10:58:39 -0700 Subject: [PATCH] Fix 3 bugs in DMs - escape HTML entities in messages so "<" doesn't scrape as "<" - escape quotes in sent messages, so they no longer fail to send - fix the web UI receiving the last 50 messages after every sent message instead of just the new ones --- internal/webserver/handler_messages.go | 11 ++++++++++- .../webserver/tpl/tweet_page_includes/chat_view.tpl | 13 +++++++++++++ pkg/scraper/api_types_dms.go | 11 ++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/internal/webserver/handler_messages.go b/internal/webserver/handler_messages.go index 4211b76..5aa0995 100644 --- a/internal/webserver/handler_messages.go +++ b/internal/webserver/handler_messages.go @@ -39,16 +39,22 @@ func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) { panic_if(err) var message_data struct { Text string `json:"text"` + LatestPollingTimestamp int `json:"latest_polling_timestamp,string"` } panic_if(json.Unmarshal(body, &message_data)) trove := scraper.SendDMMessage(room_id, message_data.Text, 0) app.Profile.SaveDMTrove(trove, false) app.buffered_render_htmx(w, "dm-composer", global_data, chat_view_data) // Wipe the chat box go app.Profile.SaveDMTrove(trove, true) + chat_view_data.LatestPollingTimestamp = message_data.LatestPollingTimestamp // We're going to return some messages + } else { + chat_view_data.LatestPollingTimestamp = -1 // TODO: why not 0? If `0` then it won't generate a SQL `where` clause } + // TODO: Why are the input (parsed out of the HTTP request) and output (computed from the messsages + // fetched and printed into the HTTP response) using the same variable in `chat_view_data`? + chat_view_data.ActiveRoomID = room_id - chat_view_data.LatestPollingTimestamp = -1 // TODO: why not 0? If `0` then it won't generate a SQL `where` clause if latest_timestamp_str := r.URL.Query().Get("latest_timestamp"); latest_timestamp_str != "" { var err error chat_view_data.LatestPollingTimestamp, err = strconv.Atoi(latest_timestamp_str) @@ -78,6 +84,9 @@ func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) { // Polling for updates and sending a message should add messages at the bottom of the page (newest) if r.URL.Query().Has("poll") || is_sending { app.buffered_render_htmx(w, "messages-with-poller", global_data, chat_view_data) + + // OOB-swap the composer polling timestamp field since it may have updated + app.buffered_render_htmx(w, "composer-polling-timestamp-field", global_data, map[string]interface{}{"LatestPollingTimestamp": chat_view_data.LatestPollingTimestamp, "oob": true}) return } diff --git a/internal/webserver/tpl/tweet_page_includes/chat_view.tpl b/internal/webserver/tpl/tweet_page_includes/chat_view.tpl index 42af58a..74a0a1a 100644 --- a/internal/webserver/tpl/tweet_page_includes/chat_view.tpl +++ b/internal/webserver/tpl/tweet_page_includes/chat_view.tpl @@ -93,6 +93,18 @@ > {{end}} +{{define "composer-polling-timestamp-field"}} + +{{end}} + {{define "chat-view"}}
{{if .ActiveRoomID}} @@ -128,6 +140,7 @@ > {{template "dm-composer"}} + {{template "composer-polling-timestamp-field" (dict "LatestPollingTimestamp" .LatestPollingTimestamp "oob" false)}}
diff --git a/pkg/scraper/api_types_dms.go b/pkg/scraper/api_types_dms.go index a46c740..02745f4 100644 --- a/pkg/scraper/api_types_dms.go +++ b/pkg/scraper/api_types_dms.go @@ -4,6 +4,8 @@ import ( "fmt" "net/url" "strings" + "html" + "encoding/json" "github.com/google/uuid" ) @@ -71,6 +73,7 @@ func (m *APIDMMessage) NormalizeContent() { m.MessageData.Text = strings.Replace(m.MessageData.Text, m.MessageData.Attachment.Video.URL, "", 1) } + m.MessageData.Text = html.UnescapeString(m.MessageData.Text) m.MessageData.Text = strings.TrimSpace(m.MessageData.Text) } @@ -503,9 +506,15 @@ func (api *API) SendDMMessage(room_id DMChatRoomID, text string, in_reply_to_id replying_to_text = fmt.Sprintf(`"reply_to_dm_id":"%d",`, in_reply_to_id) } + // Format safely as JSON (escape quotes, etc) + sanitized_text, err := json.Marshal(text) + if err != nil { + panic(err) + } + post_data := `{"conversation_id":"` + string(room_id) + `","recipient_ids":false,"request_id":"` + request_id.String() + - `","text":"` + text + `",` + + `","text":` + string(sanitized_text) + `,` + replying_to_text + `"cards_platform":"Web-12","include_cards":1,"include_quote_count":true,"dm_users":false}` var result APIInbox