diff --git a/internal/webserver/handler_messages.go b/internal/webserver/handler_messages.go
index 9103055..aff75e4 100644
--- a/internal/webserver/handler_messages.go
+++ b/internal/webserver/handler_messages.go
@@ -25,6 +25,30 @@ func (app *Application) messages_index(w http.ResponseWriter, r *http.Request) {
app.buffered_render_page(w, "tpl/messages.tpl", global_data, chat_view_data)
}
+func (app *Application) message_mark_as_read(w http.ResponseWriter, r *http.Request) {
+ room_id := get_room_id_from_context(r.Context())
+
+ c := persistence.NewConversationCursor(room_id)
+ c.PageSize = 1
+ chat_contents := app.Profile.GetChatRoomMessagesByCursor(c)
+ last_message_id := chat_contents.MessageIDs[len(chat_contents.MessageIDs)-1]
+ scraper.MarkDMChatRead(room_id, last_message_id)
+ room := chat_contents.Rooms[room_id]
+ participant, is_ok := room.Participants[app.ActiveUser.ID]
+ if !is_ok {
+ panic(room)
+ }
+ participant.LastReadEventID = last_message_id
+ room.Participants[app.ActiveUser.ID] = participant
+ panic_if(app.Profile.SaveChatRoom(room))
+ app.toast(w, r, Toast{
+ Title: "Success",
+ Message: `Conversation marked as "read"`,
+ Type: "success",
+ AutoCloseDelay: 2000,
+ })
+}
+
func (app *Application) message_send(w http.ResponseWriter, r *http.Request) {
room_id := get_room_id_from_context(r.Context())
@@ -48,6 +72,11 @@ func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) {
chat_view_data, global_data := app.get_message_global_data()
+ if len(parts) == 1 && parts[0] == "mark-as-read" {
+ app.message_mark_as_read(w, r)
+ return
+ }
+
// First send a message, if applicable
if is_sending {
app.message_send(w, r)
diff --git a/internal/webserver/static/styles.css b/internal/webserver/static/styles.css
index 4ae79d5..c135039 100644
--- a/internal/webserver/static/styles.css
+++ b/internal/webserver/static/styles.css
@@ -184,6 +184,11 @@ h3 {
height: auto;
}
+.disappearing {
+ transition: opacity 2s ease;
+ opacity: 0;
+}
+
/***************************************************************************************************
*
diff --git a/internal/webserver/tpl/tweet_page_includes/chat_view.tpl b/internal/webserver/tpl/tweet_page_includes/chat_view.tpl
index 7798502..72b8f8e 100644
--- a/internal/webserver/tpl/tweet_page_includes/chat_view.tpl
+++ b/internal/webserver/tpl/tweet_page_includes/chat_view.tpl
@@ -131,6 +131,9 @@
+
+
+
{{end}}
diff --git a/pkg/scraper/api_request_utils.go b/pkg/scraper/api_request_utils.go
index b277a22..eff25a7 100644
--- a/pkg/scraper/api_request_utils.go
+++ b/pkg/scraper/api_request_utils.go
@@ -164,7 +164,11 @@ func (api *API) do_http_POST(remote_url string, body string, result interface{})
return fmt.Errorf("Error initializing HTTP POST request:\n %w", err)
}
- req.Header.Set("content-type", "application/json")
+ if body[0] == '{' {
+ req.Header.Set("content-type", "application/json")
+ } else {
+ req.Header.Set("content-type", "application/x-www-form-urlencoded")
+ }
api.add_authentication_headers(req)
@@ -191,6 +195,11 @@ func (api *API) do_http_POST(remote_url string, body string, result interface{})
panic(err)
}
+ if resp.StatusCode == 204 {
+ // No Content
+ return nil
+ }
+
if resp.StatusCode != 200 {
responseHeaders := ""
for header := range resp.Header {
diff --git a/pkg/scraper/api_types_dms.go b/pkg/scraper/api_types_dms.go
index 9988048..faa2243 100644
--- a/pkg/scraper/api_types_dms.go
+++ b/pkg/scraper/api_types_dms.go
@@ -521,3 +521,16 @@ func (api *API) SendDMMessage(room_id DMChatRoomID, text string, in_reply_to_id
err = api.do_http_POST(url.String(), post_data, &result)
return result, err
}
+
+// Mark a chat as read.
+func (api *API) MarkDMChatRead(room_id DMChatRoomID, read_message_id DMMessageID) {
+ url := fmt.Sprintf("https://twitter.com/i/api/1.1/dm/conversation/%s/mark_read.json", room_id)
+
+ // `do_http_POST` will set the "content-type" header based on whether the body starts with '{' or not.
+ data := fmt.Sprintf("conversationId=%s&last_read_event_id=%d", room_id, read_message_id)
+
+ err := api.do_http_POST(url, data, nil) // Expected: HTTP 204
+ if err != nil {
+ panic(err)
+ }
+}
diff --git a/pkg/scraper/dm_trove.go b/pkg/scraper/dm_trove.go
index 1f8d892..88bf1a0 100644
--- a/pkg/scraper/dm_trove.go
+++ b/pkg/scraper/dm_trove.go
@@ -111,3 +111,9 @@ func SendDMMessage(room_id DMChatRoomID, text string, in_reply_to_id DMMessageID
}
return dm_response.ToDMTrove()
}
+func MarkDMChatRead(room_id DMChatRoomID, read_message_id DMMessageID) {
+ if !the_api.IsAuthenticated {
+ log.Fatalf("Writing DMs can only be done when authenticated. Please provide `--session [user]`")
+ }
+ the_api.MarkDMChatRead(room_id, read_message_id)
+}