+{{end}}
+
+
+{{define "messages"}}
+ {{range .MessageIDs}}
+ {{template "message" (dm_message .)}}
{{end}}
{{end}}
+
{{define "messages-with-poller"}}
{{template "messages" .}}
@@ -120,6 +120,7 @@
{{end}}
+
{{define "chat-view"}}
{{if .ActiveRoomID}}
@@ -298,6 +299,7 @@
{{end}}
+
{{define "conversation-top"}}
{{if .Cursor.CursorPosition.IsEnd}}
@@ -312,6 +314,7 @@
{{end}}
+
{{/* convenience template for htmx requests */}}
{{define "messages-top"}}
{{template "conversation-top" .}}
diff --git a/pkg/persistence/dm_queries.go b/pkg/persistence/dm_queries.go
index bc2094e..8c7dca9 100644
--- a/pkg/persistence/dm_queries.go
+++ b/pkg/persistence/dm_queries.go
@@ -185,7 +185,7 @@ func (p Profile) GetChatMessage(id DMMessageID) (ret DMMessage, err error) {
ret.Reactions = make(map[UserID]DMReaction)
// This is a bit circuitous, but it doesn't matter because this function is only used in tests
- trove := NewDMTrove()
+ trove := NewTweetTrove()
trove.Messages[ret.ID] = ret
p.fill_dm_contents(&trove)
@@ -193,7 +193,7 @@ func (p Profile) GetChatMessage(id DMMessageID) (ret DMMessage, err error) {
}
type DMChatView struct {
- DMTrove
+ TweetTrove
Cursor DMCursor
RoomIDs []DMChatRoomID
MessageIDs []DMMessageID
@@ -202,7 +202,7 @@ type DMChatView struct {
func NewDMChatView() DMChatView {
return DMChatView{
- DMTrove: NewDMTrove(),
+ TweetTrove: NewTweetTrove(),
RoomIDs: []DMChatRoomID{},
MessageIDs: []DMMessageID{},
}
@@ -250,7 +250,7 @@ func (p Profile) GetChatRoomsPreview(id UserID) DMChatView {
}
// Fetch the participants
- p.fill_chat_room_participants(&room, &ret.DMTrove)
+ p.fill_chat_room_participants(&room, &ret.TweetTrove)
// Add everything to the Trove
room.LastMessageID = msg.ID
@@ -259,7 +259,7 @@ func (p Profile) GetChatRoomsPreview(id UserID) DMChatView {
ret.RoomIDs = append(ret.RoomIDs, room.ID)
}
// Since the message text might be empty, fetch contents (images, tweets etc) so we can still create a preview
- p.fill_dm_contents(&ret.DMTrove)
+ p.fill_dm_contents(&ret.TweetTrove)
return ret
}
@@ -300,19 +300,19 @@ func (p Profile) GetChatRoomMessagesByCursor(c DMCursor) DMChatView {
}
// Fetch the participants
- p.fill_chat_room_participants(&room, &ret.DMTrove)
+ p.fill_chat_room_participants(&room, &ret.TweetTrove)
// Put the room in the Trove
ret.Rooms[room.ID] = room
// Fetch reaccs, attachments, and replied-to messages
- p.fill_dm_contents(&ret.DMTrove)
+ p.fill_dm_contents(&ret.TweetTrove)
return ret
}
// Fetch the chat participants and insert it into the DMChatRoom. Inserts user information
-// into the DMTrove.
-func (p Profile) fill_chat_room_participants(room *DMChatRoom, trove *DMTrove) {
+// into the TweetTrove.
+func (p Profile) fill_chat_room_participants(room *DMChatRoom, trove *TweetTrove) {
var participants []struct {
DMChatParticipant
User
@@ -332,8 +332,8 @@ func (p Profile) fill_chat_room_participants(room *DMChatRoom, trove *DMTrove) {
}
}
-// Fetch reaccs, attachments/embeds and replied-to messages and add them to the DMTrove
-func (p Profile) fill_dm_contents(trove *DMTrove) {
+// Fetch reaccs, attachments/embeds and replied-to messages and add them to the TweetTrove
+func (p Profile) fill_dm_contents(trove *TweetTrove) {
// Skip processing if there's no messages whomst'd've contents to fetch
if len(trove.Messages) == 0 {
return
@@ -460,7 +460,7 @@ func (p Profile) fill_dm_contents(trove *DMTrove) {
}
}
- p.fill_content(&trove.TweetTrove, UserID(0))
+ p.fill_content(trove, UserID(0))
}
type DMCursor struct {
@@ -620,7 +620,7 @@ func (p Profile) NextDMPage(c DMCursor) DMChatView {
// }
// Fetch the participants
- p.fill_chat_room_participants(&room, &ret.DMTrove)
+ p.fill_chat_room_participants(&room, &ret.TweetTrove)
// Add to the Trove
// room.LastMessageID = msg.ID
ret.Rooms[room.ID] = room
@@ -629,7 +629,7 @@ func (p Profile) NextDMPage(c DMCursor) DMChatView {
}
}
- p.fill_dm_contents(&ret.DMTrove)
+ p.fill_dm_contents(&ret.TweetTrove)
return ret
}
diff --git a/pkg/persistence/dm_trove_queries.go b/pkg/persistence/dm_trove_queries.go
index 013d054..2440804 100644
--- a/pkg/persistence/dm_trove_queries.go
+++ b/pkg/persistence/dm_trove_queries.go
@@ -12,8 +12,8 @@ import (
// Panics if anything goes wrong.
//
// TODO: a lot of this function contains duplicated code and should be extracted to functions
-func (p Profile) SaveDMTrove(trove DMTrove, should_download bool) {
- p.SaveTweetTrove(trove.TweetTrove, should_download)
+func (p Profile) SaveDMTrove(trove TweetTrove, should_download bool) {
+ p.SaveTweetTrove(trove, should_download)
for _, r := range trove.Rooms {
err := p.SaveChatRoom(r)
diff --git a/pkg/scraper/api_types_dms.go b/pkg/scraper/api_types_dms.go
index faa2243..b5b5f68 100644
--- a/pkg/scraper/api_types_dms.go
+++ b/pkg/scraper/api_types_dms.go
@@ -77,8 +77,8 @@ func (m *APIDMMessage) NormalizeContent() {
m.MessageData.Text = strings.TrimSpace(m.MessageData.Text)
}
-func (m APIDMMessage) ToDMTrove() DMTrove {
- ret := NewDMTrove()
+func (m APIDMMessage) ToTweetTrove() TweetTrove {
+ ret := NewTweetTrove()
if m.ID == 0 {
return ret
}
@@ -186,8 +186,8 @@ type APIDMResponse struct {
UserEvents APIInbox `json:"user_events"`
}
-func (r APIInbox) ToDMTrove() DMTrove {
- ret := NewDMTrove()
+func (r APIInbox) ToTweetTrove() TweetTrove {
+ ret := NewTweetTrove()
for _, entry := range r.Entries {
if entry.JoinConversation.ID != 0 || entry.TrustConversation.ID != 0 ||
@@ -209,7 +209,7 @@ func (r APIInbox) ToDMTrove() DMTrove {
// panic("Already in the trove: " + fmt.Sprint(result.ID))
// }
- ret.MergeWith(entry.Message.ToDMTrove())
+ ret.MergeWith(entry.Message.ToTweetTrove())
}
for _, room := range r.Conversations {
result := ParseAPIDMChatRoom(room)
@@ -220,7 +220,7 @@ func (r APIInbox) ToDMTrove() DMTrove {
if err != nil {
panic(err)
}
- ret.TweetTrove.Users[result.ID] = result
+ ret.Users[result.ID] = result
}
return ret
}
diff --git a/pkg/scraper/api_types_dms_test.go b/pkg/scraper/api_types_dms_test.go
index cbc81f1..4f1c55c 100644
--- a/pkg/scraper/api_types_dms_test.go
+++ b/pkg/scraper/api_types_dms_test.go
@@ -64,7 +64,7 @@ func TestParseAPIDMMessageWithEmbeddedTweet(t *testing.T) {
err = json.Unmarshal(data, &api_message)
require.NoError(t, err)
- trove := api_message.ToDMTrove()
+ trove := api_message.ToTweetTrove()
assert.Len(trove.Messages, 1)
m, is_ok := trove.Messages[DMMessageID(1665936253483614212)]
@@ -92,7 +92,7 @@ func TestParseAPIDMMessageWithEmbeddedImage(t *testing.T) {
err = json.Unmarshal(data, &api_message)
require.NoError(t, err)
- trove := api_message.ToDMTrove()
+ trove := api_message.ToTweetTrove()
assert.Len(trove.Messages, 1)
m, is_ok := trove.Messages[DMMessageID(1766224476729995648)]
@@ -117,7 +117,7 @@ func TestParseAPIDMMessageWithEmbeddedVideo(t *testing.T) {
err = json.Unmarshal(data, &api_message)
require.NoError(t, err)
- trove := api_message.ToDMTrove()
+ trove := api_message.ToTweetTrove()
assert.Len(trove.Messages, 1)
m, is_ok := trove.Messages[DMMessageID(1766248283901776125)]
@@ -144,7 +144,7 @@ func TestParseAPIDMMessageWithUrlCard(t *testing.T) {
err = json.Unmarshal(data, &api_message)
require.NoError(t, err)
- trove := api_message.ToDMTrove()
+ trove := api_message.ToTweetTrove()
assert.Len(trove.Messages, 1)
m, is_ok := trove.Messages[DMMessageID(1766255994668191902)]
@@ -232,7 +232,7 @@ func TestParseInbox(t *testing.T) {
err = json.Unmarshal(data, &inbox)
require.NoError(t, err)
- trove := inbox.InboxInitialState.ToDMTrove()
+ trove := inbox.InboxInitialState.ToTweetTrove()
for _, id := range []DMMessageID{1663623062195957773, 1663623203644751885, 1665922180176044037, 1665936253483614212} {
m, is_ok := trove.Messages[id]
@@ -240,7 +240,7 @@ func TestParseInbox(t *testing.T) {
assert.Equal(m.ID, id)
}
for _, id := range []UserID{1458284524761075714, 1488963321701171204} {
- u, is_ok := trove.TweetTrove.Users[id]
+ u, is_ok := trove.Users[id]
assert.True(is_ok, "User with ID %d not in the trove!")
assert.Equal(u.ID, id)
}
@@ -259,7 +259,7 @@ func TestParseDMRoomResponse(t *testing.T) {
err = json.Unmarshal(data, &inbox)
require.NoError(t, err)
- trove := inbox.ConversationTimeline.ToDMTrove()
+ trove := inbox.ConversationTimeline.ToTweetTrove()
for _, id := range []DMMessageID{
1663623062195957773,
@@ -273,7 +273,7 @@ func TestParseDMRoomResponse(t *testing.T) {
assert.Equal(m.ID, id)
}
for _, id := range []UserID{1458284524761075714, 1488963321701171204} {
- u, is_ok := trove.TweetTrove.Users[id]
+ u, is_ok := trove.Users[id]
assert.True(is_ok, "User with ID %d not in the trove!")
assert.Equal(u.ID, id)
}
@@ -293,7 +293,7 @@ func TestParseInboxUpdates(t *testing.T) {
err = json.Unmarshal(data, &inbox)
require.NoError(t, err)
- trove := inbox.UserEvents.ToDMTrove()
+ trove := inbox.UserEvents.ToTweetTrove()
assert.Len(trove.Messages, 2) // Should ignore stuff that isn't a message
diff --git a/pkg/scraper/dm_trove.go b/pkg/scraper/dm_trove.go
index 88bf1a0..bd186d5 100644
--- a/pkg/scraper/dm_trove.go
+++ b/pkg/scraper/dm_trove.go
@@ -4,31 +4,7 @@ import (
log "github.com/sirupsen/logrus"
)
-type DMTrove struct {
- Rooms map[DMChatRoomID]DMChatRoom
- Messages map[DMMessageID]DMMessage
- TweetTrove
-}
-
-func NewDMTrove() DMTrove {
- ret := DMTrove{}
- ret.Rooms = make(map[DMChatRoomID]DMChatRoom)
- ret.Messages = make(map[DMMessageID]DMMessage)
- ret.TweetTrove = NewTweetTrove()
- return ret
-}
-
-func (t1 *DMTrove) MergeWith(t2 DMTrove) {
- for id, val := range t2.Rooms {
- t1.Rooms[id] = val
- }
- for id, val := range t2.Messages {
- t1.Messages[id] = val
- }
- t1.TweetTrove.MergeWith(t2.TweetTrove)
-}
-
-func (t DMTrove) GetOldestMessage(id DMChatRoomID) DMMessageID {
+func (t TweetTrove) GetOldestMessage(id DMChatRoomID) DMMessageID {
oldest := DMMessageID(^uint(0) >> 1) // Max integer
for _, m := range t.Messages {
if m.ID < oldest && m.DMChatRoomID == id {
@@ -38,8 +14,10 @@ func (t DMTrove) GetOldestMessage(id DMChatRoomID) DMMessageID {
return oldest
}
-// Returns a DMTrove and the cursor for the next update
-func GetInbox(how_many int) (DMTrove, string) {
+// TODO: Why are these all here? =>
+
+// Returns a TweetTrove and the cursor for the next update
+func GetInbox(how_many int) (TweetTrove, string) {
if !the_api.IsAuthenticated {
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
}
@@ -48,7 +26,7 @@ func GetInbox(how_many int) (DMTrove, string) {
panic(err)
}
- trove := dm_response.ToDMTrove()
+ trove := dm_response.ToTweetTrove()
cursor := dm_response.Cursor
next_cursor_id := dm_response.InboxTimelines.Trusted.MinEntryID
for len(trove.Rooms) < how_many && dm_response.Status != "AT_END" {
@@ -56,7 +34,7 @@ func GetInbox(how_many int) (DMTrove, string) {
if err != nil {
panic(err)
}
- next_trove := dm_response.ToDMTrove()
+ next_trove := dm_response.ToTweetTrove()
next_cursor_id = dm_response.MinEntryID
trove.MergeWith(next_trove)
}
@@ -64,7 +42,7 @@ func GetInbox(how_many int) (DMTrove, string) {
return trove, cursor
}
-func GetConversation(id DMChatRoomID, max_id DMMessageID, how_many int) DMTrove {
+func GetConversation(id DMChatRoomID, max_id DMMessageID, how_many int) TweetTrove {
if !the_api.IsAuthenticated {
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
}
@@ -73,14 +51,14 @@ func GetConversation(id DMChatRoomID, max_id DMMessageID, how_many int) DMTrove
panic(err)
}
- trove := dm_response.ToDMTrove()
+ trove := dm_response.ToTweetTrove()
oldest := trove.GetOldestMessage(id)
for len(trove.Messages) < how_many && dm_response.Status != "AT_END" {
dm_response, err = the_api.GetDMConversation(id, oldest)
if err != nil {
panic(err)
}
- next_trove := dm_response.ToDMTrove()
+ next_trove := dm_response.ToTweetTrove()
oldest = next_trove.GetOldestMessage(id)
trove.MergeWith(next_trove)
}
@@ -88,8 +66,8 @@ func GetConversation(id DMChatRoomID, max_id DMMessageID, how_many int) DMTrove
return trove
}
-// Returns a DMTrove and the cursor for the next update
-func PollInboxUpdates(cursor string) (DMTrove, string) {
+// Returns a TweetTrove and the cursor for the next update
+func PollInboxUpdates(cursor string) (TweetTrove, string) {
if !the_api.IsAuthenticated {
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
}
@@ -98,10 +76,10 @@ func PollInboxUpdates(cursor string) (DMTrove, string) {
panic(err)
}
- return dm_response.ToDMTrove(), dm_response.Cursor
+ return dm_response.ToTweetTrove(), dm_response.Cursor
}
-func SendDMMessage(room_id DMChatRoomID, text string, in_reply_to_id DMMessageID) DMTrove {
+func SendDMMessage(room_id DMChatRoomID, text string, in_reply_to_id DMMessageID) TweetTrove {
if !the_api.IsAuthenticated {
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
}
@@ -109,7 +87,7 @@ func SendDMMessage(room_id DMChatRoomID, text string, in_reply_to_id DMMessageID
if err != nil {
panic(err)
}
- return dm_response.ToDMTrove()
+ return dm_response.ToTweetTrove()
}
func MarkDMChatRead(room_id DMChatRoomID, read_message_id DMMessageID) {
if !the_api.IsAuthenticated {
diff --git a/pkg/scraper/tweet_trove.go b/pkg/scraper/tweet_trove.go
index 4c35bad..9783906 100644
--- a/pkg/scraper/tweet_trove.go
+++ b/pkg/scraper/tweet_trove.go
@@ -16,6 +16,10 @@ type TweetTrove struct {
Bookmarks map[BookmarkSortID]Bookmark
TombstoneUsers []UserHandle
+
+ // For DMs
+ Rooms map[DMChatRoomID]DMChatRoom
+ Messages map[DMMessageID]DMMessage
}
func NewTweetTrove() TweetTrove {
@@ -27,6 +31,8 @@ func NewTweetTrove() TweetTrove {
ret.Likes = make(map[LikeSortID]Like)
ret.Bookmarks = make(map[BookmarkSortID]Bookmark)
ret.TombstoneUsers = []UserHandle{}
+ ret.Rooms = make(map[DMChatRoomID]DMChatRoom)
+ ret.Messages = make(map[DMMessageID]DMMessage)
return ret
}
@@ -66,6 +72,13 @@ func (t1 *TweetTrove) MergeWith(t2 TweetTrove) {
}
t1.TombstoneUsers = append(t1.TombstoneUsers, t2.TombstoneUsers...)
+
+ for id, val := range t2.Rooms {
+ t1.Rooms[id] = val
+ }
+ for id, val := range t2.Messages {
+ t1.Messages[id] = val
+ }
}
/**