REFACTOR: remove DMTrove type, merge it into TweetTrove

This commit is contained in:
Alessio 2024-07-28 08:01:58 -07:00
parent 821d36b116
commit 98015ddf0c
13 changed files with 167 additions and 166 deletions

View File

@ -518,7 +518,7 @@ func start_webserver(addr string, should_auto_open bool) {
func fetch_inbox(how_many int) {
trove, _ := scraper.GetInbox(how_many)
profile.SaveDMTrove(trove, true)
profile.SaveTweetTrove(trove, true)
happy_exit(fmt.Sprintf("Saved %d messages from %d chats", len(trove.Messages), len(trove.Rooms)), nil)
}
@ -529,7 +529,7 @@ func fetch_dm(id string, how_many int) {
}
max_id := scraper.DMMessageID(^uint(0) >> 1)
trove := scraper.GetConversation(room.ID, max_id, how_many)
profile.SaveDMTrove(trove, true)
profile.SaveTweetTrove(trove, true)
happy_exit(
fmt.Sprintf("Saved %d messages from %d chats", len(trove.Messages), len(trove.Rooms)),
err,
@ -539,10 +539,10 @@ func fetch_dm(id string, how_many int) {
func send_dm(room_id string, text string, in_reply_to_id int) {
room, err := profile.GetChatRoom(scraper.DMChatRoomID(room_id))
if err != nil {
panic(err)
die(fmt.Sprintf("No such chat room: %d", in_reply_to_id), false, 1)
}
trove := scraper.SendDMMessage(room.ID, text, scraper.DMMessageID(in_reply_to_id))
profile.SaveDMTrove(trove, true)
profile.SaveTweetTrove(trove, true)
happy_exit(fmt.Sprintf("Saved %d messages from %d chats", len(trove.Messages), len(trove.Rooms)), nil)
}

View File

@ -60,8 +60,8 @@ func (app *Application) message_send(w http.ResponseWriter, r *http.Request) {
panic_if(json.Unmarshal(body, &message_data))
trove := scraper.SendDMMessage(room_id, message_data.Text, 0)
app.Profile.SaveDMTrove(trove, false)
go app.Profile.SaveDMTrove(trove, true)
app.Profile.SaveTweetTrove(trove, false)
go app.Profile.SaveTweetTrove(trove, true)
}
func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) {
@ -85,8 +85,8 @@ func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) {
if r.URL.Query().Has("scrape") && !app.IsScrapingDisabled {
max_id := scraper.DMMessageID(^uint(0) >> 1)
trove := scraper.GetConversation(room_id, max_id, 50) // TODO: parameterizable
app.Profile.SaveDMTrove(trove, false)
go app.Profile.SaveDMTrove(trove, true) // Download the content in the background
app.Profile.SaveTweetTrove(trove, false)
go app.Profile.SaveTweetTrove(trove, true) // Download the content in the background
}
// `LatestPollingTimestamp` sort of passes-through the function; if we're not updating it, it
@ -110,7 +110,7 @@ func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) {
c.UntilTimestamp = scraper.TimestampFromUnixMilli(int64(until_time))
}
chat_contents := app.Profile.GetChatRoomMessagesByCursor(c)
chat_view_data.DMChatView.MergeWith(chat_contents.DMTrove)
chat_view_data.DMChatView.MergeWith(chat_contents.TweetTrove)
chat_view_data.MessageIDs = chat_contents.MessageIDs
chat_view_data.Cursor = chat_contents.Cursor
if len(chat_view_data.MessageIDs) > 0 {

View File

@ -39,6 +39,12 @@ func (d PageGlobalData) Retweet(id scraper.TweetID) scraper.Retweet {
func (d PageGlobalData) Space(id scraper.SpaceID) scraper.Space {
return d.Spaces[id]
}
func (d PageGlobalData) Message(id scraper.DMMessageID) scraper.DMMessage {
return d.Messages[id]
}
func (d PageGlobalData) ChatRoom(id scraper.DMChatRoomID) scraper.DMChatRoom {
return d.Rooms[id]
}
func (d PageGlobalData) GetFocusedTweetID() scraper.TweetID {
return d.FocusedTweetID
}
@ -120,6 +126,8 @@ func (app *Application) make_funcmap(global_data PageGlobalData) template.FuncMa
"user": global_data.User,
"retweet": global_data.Retweet,
"space": global_data.Space,
"dm_message": global_data.Message,
"chat_room": global_data.ChatRoom,
"focused_tweet_id": global_data.GetFocusedTweetID,
"search_text": global_data.GetSearchText,
"global_data": global_data.GlobalData, // This fucking sucks

View File

@ -102,15 +102,15 @@ func (app *Application) background_dm_polling_scrape() {
}
fmt.Println("Scraping user DMs...")
var trove scraper.DMTrove
var trove scraper.TweetTrove
if inbox_cursor == "" {
trove, inbox_cursor = scraper.GetInbox(0)
} else {
trove, inbox_cursor = scraper.PollInboxUpdates(inbox_cursor)
}
fmt.Println("Saving DM results...")
app.Profile.SaveDMTrove(trove, false)
go app.Profile.SaveDMTrove(trove, true)
app.Profile.SaveTweetTrove(trove, false)
go app.Profile.SaveTweetTrove(trove, true)
fmt.Println("Scraping DMs succeeded.")
}

View File

@ -2,8 +2,7 @@
<div class="chat-list" hx-get="/messages/refresh-list?active-chat={{.ActiveRoomID}}" hx-swap="outerHTML" hx-trigger="load delay:3s">
{{range .RoomIDs}}
{{template "chat-list-entry" (dict
"room" (index $.Rooms .)
"messages" $.DMTrove.Messages
"room" (chat_room .)
"is_active" (eq $.ActiveRoomID .)
"is_unread" (index $.UnreadRoomIDs .)
) }}

View File

@ -18,7 +18,7 @@
</div>
<div class="chat-list-entry__preview-and-unread-container row">
<p class="chat-list-entry__message-preview">
{{ $message := (index $.messages $room.LastMessageID)}}
{{ $message := (dm_message $room.LastMessageID)}}
{{ $sender := (user $message.SenderID) }}
{{if ne $message.Text ""}}
{{if eq $room.Type "GROUP_DM"}}

View File

@ -1,93 +1,93 @@
{{define "messages"}}
{{range .MessageIDs}}
{{$message := (index $.DMTrove.Messages .)}}
{{$user := (user $message.SenderID)}}
{{$is_us := (eq $message.SenderID (active_user).ID)}}
<div class="dm-message {{if $is_us}} our-message {{end}}" data-message-id="{{ $message.ID }}">
<div class="dm-message__row row">
<div class="dm-message__sender-profile-img">
{{template "circle-profile-img" $user}}
</div>
<div class="dm-message__contents">
{{if (ne $message.InReplyToID 0)}}
<div class="dm-message__replying-to">
<div class="dm-message__replying-to-label labelled-icon">
<img class="svg-icon" src="/static/icons/replying_to.svg" width="24" height="24" />
<label>Replying to</label>
</div>
<div class="replying-to-message"
data-replying-to-message-id="{{ $message.InReplyToID }}"
onclick="doReplyTo(this)"
>
{{(index $.DMTrove.Messages $message.InReplyToID).Text}}
</div>
</div>
{{end}}
{{if (ne $message.EmbeddedTweetID 0)}}
<div class="dm-message__tweet-preview">
{{template "tweet" (dict
"TweetID" $message.EmbeddedTweetID
"RetweetID" 0
"QuoteNestingLevel" 1)
}}
</div>
{{end}}
{{range $message.Images}}
<img class="dm-message__embedded-image"
{{if .IsDownloaded}}
src="/content/images/{{.LocalFilename}}"
{{else}}
src="{{.RemoteURL}}"
{{end}}
width="{{.Width}}" height="{{.Height}}"
onclick="image_carousel.querySelector('img').src = this.src; image_carousel.showModal();"
>
{{end}}
{{range $message.Videos}}
<video class="dm-message__embedded-video" controls width="{{.Width}}" height="{{.Height}}"
{{if .IsDownloaded}}
poster="/content/video_thumbnails/{{.ThumbnailLocalPath}}"
{{else}}
poster="{{.ThumbnailRemoteUrl}}"
{{end}}
>
{{if .IsDownloaded}}
<source src="/content/videos/{{.LocalFilename}}">
{{else}}
<source src="{{.RemoteURL}}">
{{end}}
</video>
{{end}}
{{range $message.Urls}}
{{template "embedded-link" .}}
{{end}}
{{if $message.Text}}
<div class="dm-message__text-content">
{{template "text-with-entities" $message.Text}}
</div>
{{end}}
</div>
<div class="dm-message__emoji-button-container">
<div class="dm-message__emoji-button button" onclick="show_emoji_picker(console.log)">
<img class="svg-icon" src="/static/icons/emoji-react.svg" width="24" height="24"/>
</div>
</div>
{{define "message"}}
{{$user := (user .SenderID)}}
{{$is_us := (eq .SenderID (active_user).ID)}}
<div class="dm-message {{if $is_us}} our-message {{end}}" data-message-id="{{ .ID }}" hx-ext="json-enc">
<div class="dm-message__row row">
<div class="dm-message__sender-profile-img">
{{template "circle-profile-img" $user}}
</div>
<div class="dm-message__reactions">
{{range $message.Reactions}}
{{$sender := (user .SenderID)}}
<span title="{{$sender.DisplayName}} (@{{$sender.Handle}})">{{.Emoji}}</span>
<div class="dm-message__contents">
{{if (ne .InReplyToID 0)}}
<div class="dm-message__replying-to">
<div class="dm-message__replying-to-label labelled-icon">
<img class="svg-icon" src="/static/icons/replying_to.svg" width="24" height="24" />
<label>Replying to</label>
</div>
<div class="replying-to-message"
data-replying-to-message-id="{{ .InReplyToID }}"
onclick="doReplyTo(this)"
>
{{(dm_message .InReplyToID).Text}}
</div>
</div>
{{end}}
{{if (ne .EmbeddedTweetID 0)}}
<div class="dm-message__tweet-preview">
{{template "tweet" (dict
"TweetID" .EmbeddedTweetID
"RetweetID" 0
"QuoteNestingLevel" 1)
}}
</div>
{{end}}
{{range .Images}}
<img class="dm-message__embedded-image"
{{if .IsDownloaded}}
src="/content/images/{{.LocalFilename}}"
{{else}}
src="{{.RemoteURL}}"
{{end}}
width="{{.Width}}" height="{{.Height}}"
onclick="image_carousel.querySelector('img').src = this.src; image_carousel.showModal();"
>
{{end}}
{{range .Videos}}
<video class="dm-message__embedded-video" controls width="{{.Width}}" height="{{.Height}}"
{{if .IsDownloaded}}
poster="/content/video_thumbnails/{{.ThumbnailLocalPath}}"
{{else}}
poster="{{.ThumbnailRemoteUrl}}"
{{end}}
>
{{if .IsDownloaded}}
<source src="/content/videos/{{.LocalFilename}}">
{{else}}
<source src="{{.RemoteURL}}">
{{end}}
</video>
{{end}}
{{range .Urls}}
{{template "embedded-link" .}}
{{end}}
{{if .Text}}
<div class="dm-message__text-content">
{{template "text-with-entities" .Text}}
</div>
{{end}}
</div>
<div class="sent-at">
<p class="sent-at__text">
{{$message.SentAt.Time.Format "Jan 2, 2006 @ 3:04 pm"}}
</p>
</div>
</div>
<div class="dm-message__reactions">
{{range .Reactions}}
{{$sender := (user .SenderID)}}
<span title="{{$sender.DisplayName}} (@{{$sender.Handle}})">{{.Emoji}}</span>
{{end}}
</div>
<div class="sent-at">
<p class="sent-at__text">
{{.SentAt.Time.Format "Jan 2, 2006 @ 3:04 pm"}}
</p>
</div>
</div>
{{end}}
{{define "messages"}}
{{range .MessageIDs}}
{{template "message" (dm_message .)}}
{{end}}
{{end}}
{{define "messages-with-poller"}}
{{template "messages" .}}
@ -120,6 +120,7 @@
</script>
{{end}}
{{define "chat-view"}}
<div id="chat-view">
{{if .ActiveRoomID}}
@ -298,6 +299,7 @@
</script>
{{end}}
{{define "conversation-top"}}
<div class="show-more conversation-top">
{{if .Cursor.CursorPosition.IsEnd}}
@ -312,6 +314,7 @@
</div>
{{end}}
{{/* convenience template for htmx requests */}}
{{define "messages-top"}}
{{template "conversation-top" .}}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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
}
}
/**