REFACTOR: remove DMTrove type, merge it into TweetTrove
This commit is contained in:
parent
821d36b116
commit
98015ddf0c
@ -518,7 +518,7 @@ func start_webserver(addr string, should_auto_open bool) {
|
|||||||
|
|
||||||
func fetch_inbox(how_many int) {
|
func fetch_inbox(how_many int) {
|
||||||
trove, _ := scraper.GetInbox(how_many)
|
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)
|
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)
|
max_id := scraper.DMMessageID(^uint(0) >> 1)
|
||||||
trove := scraper.GetConversation(room.ID, max_id, how_many)
|
trove := scraper.GetConversation(room.ID, max_id, how_many)
|
||||||
profile.SaveDMTrove(trove, true)
|
profile.SaveTweetTrove(trove, true)
|
||||||
happy_exit(
|
happy_exit(
|
||||||
fmt.Sprintf("Saved %d messages from %d chats", len(trove.Messages), len(trove.Rooms)),
|
fmt.Sprintf("Saved %d messages from %d chats", len(trove.Messages), len(trove.Rooms)),
|
||||||
err,
|
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) {
|
func send_dm(room_id string, text string, in_reply_to_id int) {
|
||||||
room, err := profile.GetChatRoom(scraper.DMChatRoomID(room_id))
|
room, err := profile.GetChatRoom(scraper.DMChatRoomID(room_id))
|
||||||
if err != nil {
|
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))
|
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)
|
happy_exit(fmt.Sprintf("Saved %d messages from %d chats", len(trove.Messages), len(trove.Rooms)), nil)
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,8 @@ func (app *Application) message_send(w http.ResponseWriter, r *http.Request) {
|
|||||||
panic_if(json.Unmarshal(body, &message_data))
|
panic_if(json.Unmarshal(body, &message_data))
|
||||||
|
|
||||||
trove := scraper.SendDMMessage(room_id, message_data.Text, 0)
|
trove := scraper.SendDMMessage(room_id, message_data.Text, 0)
|
||||||
app.Profile.SaveDMTrove(trove, false)
|
app.Profile.SaveTweetTrove(trove, false)
|
||||||
go app.Profile.SaveDMTrove(trove, true)
|
go app.Profile.SaveTweetTrove(trove, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *Application) message_detail(w http.ResponseWriter, r *http.Request) {
|
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 {
|
if r.URL.Query().Has("scrape") && !app.IsScrapingDisabled {
|
||||||
max_id := scraper.DMMessageID(^uint(0) >> 1)
|
max_id := scraper.DMMessageID(^uint(0) >> 1)
|
||||||
trove := scraper.GetConversation(room_id, max_id, 50) // TODO: parameterizable
|
trove := scraper.GetConversation(room_id, max_id, 50) // TODO: parameterizable
|
||||||
app.Profile.SaveDMTrove(trove, false)
|
app.Profile.SaveTweetTrove(trove, false)
|
||||||
go app.Profile.SaveDMTrove(trove, true) // Download the content in the background
|
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
|
// `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))
|
c.UntilTimestamp = scraper.TimestampFromUnixMilli(int64(until_time))
|
||||||
}
|
}
|
||||||
chat_contents := app.Profile.GetChatRoomMessagesByCursor(c)
|
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.MessageIDs = chat_contents.MessageIDs
|
||||||
chat_view_data.Cursor = chat_contents.Cursor
|
chat_view_data.Cursor = chat_contents.Cursor
|
||||||
if len(chat_view_data.MessageIDs) > 0 {
|
if len(chat_view_data.MessageIDs) > 0 {
|
||||||
|
@ -39,6 +39,12 @@ func (d PageGlobalData) Retweet(id scraper.TweetID) scraper.Retweet {
|
|||||||
func (d PageGlobalData) Space(id scraper.SpaceID) scraper.Space {
|
func (d PageGlobalData) Space(id scraper.SpaceID) scraper.Space {
|
||||||
return d.Spaces[id]
|
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 {
|
func (d PageGlobalData) GetFocusedTweetID() scraper.TweetID {
|
||||||
return d.FocusedTweetID
|
return d.FocusedTweetID
|
||||||
}
|
}
|
||||||
@ -120,6 +126,8 @@ func (app *Application) make_funcmap(global_data PageGlobalData) template.FuncMa
|
|||||||
"user": global_data.User,
|
"user": global_data.User,
|
||||||
"retweet": global_data.Retweet,
|
"retweet": global_data.Retweet,
|
||||||
"space": global_data.Space,
|
"space": global_data.Space,
|
||||||
|
"dm_message": global_data.Message,
|
||||||
|
"chat_room": global_data.ChatRoom,
|
||||||
"focused_tweet_id": global_data.GetFocusedTweetID,
|
"focused_tweet_id": global_data.GetFocusedTweetID,
|
||||||
"search_text": global_data.GetSearchText,
|
"search_text": global_data.GetSearchText,
|
||||||
"global_data": global_data.GlobalData, // This fucking sucks
|
"global_data": global_data.GlobalData, // This fucking sucks
|
||||||
|
@ -102,15 +102,15 @@ func (app *Application) background_dm_polling_scrape() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Scraping user DMs...")
|
fmt.Println("Scraping user DMs...")
|
||||||
var trove scraper.DMTrove
|
var trove scraper.TweetTrove
|
||||||
if inbox_cursor == "" {
|
if inbox_cursor == "" {
|
||||||
trove, inbox_cursor = scraper.GetInbox(0)
|
trove, inbox_cursor = scraper.GetInbox(0)
|
||||||
} else {
|
} else {
|
||||||
trove, inbox_cursor = scraper.PollInboxUpdates(inbox_cursor)
|
trove, inbox_cursor = scraper.PollInboxUpdates(inbox_cursor)
|
||||||
}
|
}
|
||||||
fmt.Println("Saving DM results...")
|
fmt.Println("Saving DM results...")
|
||||||
app.Profile.SaveDMTrove(trove, false)
|
app.Profile.SaveTweetTrove(trove, false)
|
||||||
go app.Profile.SaveDMTrove(trove, true)
|
go app.Profile.SaveTweetTrove(trove, true)
|
||||||
fmt.Println("Scraping DMs succeeded.")
|
fmt.Println("Scraping DMs succeeded.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
<div class="chat-list" hx-get="/messages/refresh-list?active-chat={{.ActiveRoomID}}" hx-swap="outerHTML" hx-trigger="load delay:3s">
|
<div class="chat-list" hx-get="/messages/refresh-list?active-chat={{.ActiveRoomID}}" hx-swap="outerHTML" hx-trigger="load delay:3s">
|
||||||
{{range .RoomIDs}}
|
{{range .RoomIDs}}
|
||||||
{{template "chat-list-entry" (dict
|
{{template "chat-list-entry" (dict
|
||||||
"room" (index $.Rooms .)
|
"room" (chat_room .)
|
||||||
"messages" $.DMTrove.Messages
|
|
||||||
"is_active" (eq $.ActiveRoomID .)
|
"is_active" (eq $.ActiveRoomID .)
|
||||||
"is_unread" (index $.UnreadRoomIDs .)
|
"is_unread" (index $.UnreadRoomIDs .)
|
||||||
) }}
|
) }}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="chat-list-entry__preview-and-unread-container row">
|
<div class="chat-list-entry__preview-and-unread-container row">
|
||||||
<p class="chat-list-entry__message-preview">
|
<p class="chat-list-entry__message-preview">
|
||||||
{{ $message := (index $.messages $room.LastMessageID)}}
|
{{ $message := (dm_message $room.LastMessageID)}}
|
||||||
{{ $sender := (user $message.SenderID) }}
|
{{ $sender := (user $message.SenderID) }}
|
||||||
{{if ne $message.Text ""}}
|
{{if ne $message.Text ""}}
|
||||||
{{if eq $room.Type "GROUP_DM"}}
|
{{if eq $room.Type "GROUP_DM"}}
|
||||||
|
@ -1,38 +1,36 @@
|
|||||||
{{define "messages"}}
|
{{define "message"}}
|
||||||
{{range .MessageIDs}}
|
{{$user := (user .SenderID)}}
|
||||||
{{$message := (index $.DMTrove.Messages .)}}
|
{{$is_us := (eq .SenderID (active_user).ID)}}
|
||||||
{{$user := (user $message.SenderID)}}
|
<div class="dm-message {{if $is_us}} our-message {{end}}" data-message-id="{{ .ID }}" hx-ext="json-enc">
|
||||||
{{$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__row row">
|
||||||
<div class="dm-message__sender-profile-img">
|
<div class="dm-message__sender-profile-img">
|
||||||
{{template "circle-profile-img" $user}}
|
{{template "circle-profile-img" $user}}
|
||||||
</div>
|
</div>
|
||||||
<div class="dm-message__contents">
|
<div class="dm-message__contents">
|
||||||
{{if (ne $message.InReplyToID 0)}}
|
{{if (ne .InReplyToID 0)}}
|
||||||
<div class="dm-message__replying-to">
|
<div class="dm-message__replying-to">
|
||||||
<div class="dm-message__replying-to-label labelled-icon">
|
<div class="dm-message__replying-to-label labelled-icon">
|
||||||
<img class="svg-icon" src="/static/icons/replying_to.svg" width="24" height="24" />
|
<img class="svg-icon" src="/static/icons/replying_to.svg" width="24" height="24" />
|
||||||
<label>Replying to</label>
|
<label>Replying to</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="replying-to-message"
|
<div class="replying-to-message"
|
||||||
data-replying-to-message-id="{{ $message.InReplyToID }}"
|
data-replying-to-message-id="{{ .InReplyToID }}"
|
||||||
onclick="doReplyTo(this)"
|
onclick="doReplyTo(this)"
|
||||||
>
|
>
|
||||||
{{(index $.DMTrove.Messages $message.InReplyToID).Text}}
|
{{(dm_message .InReplyToID).Text}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if (ne $message.EmbeddedTweetID 0)}}
|
{{if (ne .EmbeddedTweetID 0)}}
|
||||||
<div class="dm-message__tweet-preview">
|
<div class="dm-message__tweet-preview">
|
||||||
{{template "tweet" (dict
|
{{template "tweet" (dict
|
||||||
"TweetID" $message.EmbeddedTweetID
|
"TweetID" .EmbeddedTweetID
|
||||||
"RetweetID" 0
|
"RetweetID" 0
|
||||||
"QuoteNestingLevel" 1)
|
"QuoteNestingLevel" 1)
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range $message.Images}}
|
{{range .Images}}
|
||||||
<img class="dm-message__embedded-image"
|
<img class="dm-message__embedded-image"
|
||||||
{{if .IsDownloaded}}
|
{{if .IsDownloaded}}
|
||||||
src="/content/images/{{.LocalFilename}}"
|
src="/content/images/{{.LocalFilename}}"
|
||||||
@ -43,7 +41,7 @@
|
|||||||
onclick="image_carousel.querySelector('img').src = this.src; image_carousel.showModal();"
|
onclick="image_carousel.querySelector('img').src = this.src; image_carousel.showModal();"
|
||||||
>
|
>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range $message.Videos}}
|
{{range .Videos}}
|
||||||
<video class="dm-message__embedded-video" controls width="{{.Width}}" height="{{.Height}}"
|
<video class="dm-message__embedded-video" controls width="{{.Width}}" height="{{.Height}}"
|
||||||
{{if .IsDownloaded}}
|
{{if .IsDownloaded}}
|
||||||
poster="/content/video_thumbnails/{{.ThumbnailLocalPath}}"
|
poster="/content/video_thumbnails/{{.ThumbnailLocalPath}}"
|
||||||
@ -58,36 +56,38 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</video>
|
</video>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range $message.Urls}}
|
{{range .Urls}}
|
||||||
{{template "embedded-link" .}}
|
{{template "embedded-link" .}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $message.Text}}
|
{{if .Text}}
|
||||||
<div class="dm-message__text-content">
|
<div class="dm-message__text-content">
|
||||||
{{template "text-with-entities" $message.Text}}
|
{{template "text-with-entities" .Text}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</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>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="dm-message__reactions">
|
<div class="dm-message__reactions">
|
||||||
{{range $message.Reactions}}
|
{{range .Reactions}}
|
||||||
{{$sender := (user .SenderID)}}
|
{{$sender := (user .SenderID)}}
|
||||||
<span title="{{$sender.DisplayName}} (@{{$sender.Handle}})">{{.Emoji}}</span>
|
<span title="{{$sender.DisplayName}} (@{{$sender.Handle}})">{{.Emoji}}</span>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<div class="sent-at">
|
<div class="sent-at">
|
||||||
<p class="sent-at__text">
|
<p class="sent-at__text">
|
||||||
{{$message.SentAt.Time.Format "Jan 2, 2006 @ 3:04 pm"}}
|
{{.SentAt.Time.Format "Jan 2, 2006 @ 3:04 pm"}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
|
{{define "messages"}}
|
||||||
|
{{range .MessageIDs}}
|
||||||
|
{{template "message" (dm_message .)}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
{{define "messages-with-poller"}}
|
{{define "messages-with-poller"}}
|
||||||
{{template "messages" .}}
|
{{template "messages" .}}
|
||||||
|
|
||||||
@ -120,6 +120,7 @@
|
|||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
{{define "chat-view"}}
|
{{define "chat-view"}}
|
||||||
<div id="chat-view">
|
<div id="chat-view">
|
||||||
{{if .ActiveRoomID}}
|
{{if .ActiveRoomID}}
|
||||||
@ -298,6 +299,7 @@
|
|||||||
</script>
|
</script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
{{define "conversation-top"}}
|
{{define "conversation-top"}}
|
||||||
<div class="show-more conversation-top">
|
<div class="show-more conversation-top">
|
||||||
{{if .Cursor.CursorPosition.IsEnd}}
|
{{if .Cursor.CursorPosition.IsEnd}}
|
||||||
@ -312,6 +314,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|
||||||
{{/* convenience template for htmx requests */}}
|
{{/* convenience template for htmx requests */}}
|
||||||
{{define "messages-top"}}
|
{{define "messages-top"}}
|
||||||
{{template "conversation-top" .}}
|
{{template "conversation-top" .}}
|
||||||
|
@ -185,7 +185,7 @@ func (p Profile) GetChatMessage(id DMMessageID) (ret DMMessage, err error) {
|
|||||||
ret.Reactions = make(map[UserID]DMReaction)
|
ret.Reactions = make(map[UserID]DMReaction)
|
||||||
|
|
||||||
// This is a bit circuitous, but it doesn't matter because this function is only used in tests
|
// 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
|
trove.Messages[ret.ID] = ret
|
||||||
p.fill_dm_contents(&trove)
|
p.fill_dm_contents(&trove)
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ func (p Profile) GetChatMessage(id DMMessageID) (ret DMMessage, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DMChatView struct {
|
type DMChatView struct {
|
||||||
DMTrove
|
TweetTrove
|
||||||
Cursor DMCursor
|
Cursor DMCursor
|
||||||
RoomIDs []DMChatRoomID
|
RoomIDs []DMChatRoomID
|
||||||
MessageIDs []DMMessageID
|
MessageIDs []DMMessageID
|
||||||
@ -202,7 +202,7 @@ type DMChatView struct {
|
|||||||
|
|
||||||
func NewDMChatView() DMChatView {
|
func NewDMChatView() DMChatView {
|
||||||
return DMChatView{
|
return DMChatView{
|
||||||
DMTrove: NewDMTrove(),
|
TweetTrove: NewTweetTrove(),
|
||||||
RoomIDs: []DMChatRoomID{},
|
RoomIDs: []DMChatRoomID{},
|
||||||
MessageIDs: []DMMessageID{},
|
MessageIDs: []DMMessageID{},
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ func (p Profile) GetChatRoomsPreview(id UserID) DMChatView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the participants
|
// Fetch the participants
|
||||||
p.fill_chat_room_participants(&room, &ret.DMTrove)
|
p.fill_chat_room_participants(&room, &ret.TweetTrove)
|
||||||
|
|
||||||
// Add everything to the Trove
|
// Add everything to the Trove
|
||||||
room.LastMessageID = msg.ID
|
room.LastMessageID = msg.ID
|
||||||
@ -259,7 +259,7 @@ func (p Profile) GetChatRoomsPreview(id UserID) DMChatView {
|
|||||||
ret.RoomIDs = append(ret.RoomIDs, room.ID)
|
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
|
// 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
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,19 +300,19 @@ func (p Profile) GetChatRoomMessagesByCursor(c DMCursor) DMChatView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the participants
|
// 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
|
// Put the room in the Trove
|
||||||
ret.Rooms[room.ID] = room
|
ret.Rooms[room.ID] = room
|
||||||
|
|
||||||
// Fetch reaccs, attachments, and replied-to messages
|
// Fetch reaccs, attachments, and replied-to messages
|
||||||
p.fill_dm_contents(&ret.DMTrove)
|
p.fill_dm_contents(&ret.TweetTrove)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the chat participants and insert it into the DMChatRoom. Inserts user information
|
// Fetch the chat participants and insert it into the DMChatRoom. Inserts user information
|
||||||
// into the DMTrove.
|
// into the TweetTrove.
|
||||||
func (p Profile) fill_chat_room_participants(room *DMChatRoom, trove *DMTrove) {
|
func (p Profile) fill_chat_room_participants(room *DMChatRoom, trove *TweetTrove) {
|
||||||
var participants []struct {
|
var participants []struct {
|
||||||
DMChatParticipant
|
DMChatParticipant
|
||||||
User
|
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
|
// Fetch reaccs, attachments/embeds and replied-to messages and add them to the TweetTrove
|
||||||
func (p Profile) fill_dm_contents(trove *DMTrove) {
|
func (p Profile) fill_dm_contents(trove *TweetTrove) {
|
||||||
// Skip processing if there's no messages whomst'd've contents to fetch
|
// Skip processing if there's no messages whomst'd've contents to fetch
|
||||||
if len(trove.Messages) == 0 {
|
if len(trove.Messages) == 0 {
|
||||||
return
|
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 {
|
type DMCursor struct {
|
||||||
@ -620,7 +620,7 @@ func (p Profile) NextDMPage(c DMCursor) DMChatView {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Fetch the participants
|
// Fetch the participants
|
||||||
p.fill_chat_room_participants(&room, &ret.DMTrove)
|
p.fill_chat_room_participants(&room, &ret.TweetTrove)
|
||||||
// Add to the Trove
|
// Add to the Trove
|
||||||
// room.LastMessageID = msg.ID
|
// room.LastMessageID = msg.ID
|
||||||
ret.Rooms[room.ID] = room
|
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
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
// Panics if anything goes wrong.
|
// Panics if anything goes wrong.
|
||||||
//
|
//
|
||||||
// TODO: a lot of this function contains duplicated code and should be extracted to functions
|
// TODO: a lot of this function contains duplicated code and should be extracted to functions
|
||||||
func (p Profile) SaveDMTrove(trove DMTrove, should_download bool) {
|
func (p Profile) SaveDMTrove(trove TweetTrove, should_download bool) {
|
||||||
p.SaveTweetTrove(trove.TweetTrove, should_download)
|
p.SaveTweetTrove(trove, should_download)
|
||||||
|
|
||||||
for _, r := range trove.Rooms {
|
for _, r := range trove.Rooms {
|
||||||
err := p.SaveChatRoom(r)
|
err := p.SaveChatRoom(r)
|
||||||
|
@ -77,8 +77,8 @@ func (m *APIDMMessage) NormalizeContent() {
|
|||||||
m.MessageData.Text = strings.TrimSpace(m.MessageData.Text)
|
m.MessageData.Text = strings.TrimSpace(m.MessageData.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m APIDMMessage) ToDMTrove() DMTrove {
|
func (m APIDMMessage) ToTweetTrove() TweetTrove {
|
||||||
ret := NewDMTrove()
|
ret := NewTweetTrove()
|
||||||
if m.ID == 0 {
|
if m.ID == 0 {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -186,8 +186,8 @@ type APIDMResponse struct {
|
|||||||
UserEvents APIInbox `json:"user_events"`
|
UserEvents APIInbox `json:"user_events"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r APIInbox) ToDMTrove() DMTrove {
|
func (r APIInbox) ToTweetTrove() TweetTrove {
|
||||||
ret := NewDMTrove()
|
ret := NewTweetTrove()
|
||||||
|
|
||||||
for _, entry := range r.Entries {
|
for _, entry := range r.Entries {
|
||||||
if entry.JoinConversation.ID != 0 || entry.TrustConversation.ID != 0 ||
|
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))
|
// panic("Already in the trove: " + fmt.Sprint(result.ID))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
ret.MergeWith(entry.Message.ToDMTrove())
|
ret.MergeWith(entry.Message.ToTweetTrove())
|
||||||
}
|
}
|
||||||
for _, room := range r.Conversations {
|
for _, room := range r.Conversations {
|
||||||
result := ParseAPIDMChatRoom(room)
|
result := ParseAPIDMChatRoom(room)
|
||||||
@ -220,7 +220,7 @@ func (r APIInbox) ToDMTrove() DMTrove {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
ret.TweetTrove.Users[result.ID] = result
|
ret.Users[result.ID] = result
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ func TestParseAPIDMMessageWithEmbeddedTweet(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &api_message)
|
err = json.Unmarshal(data, &api_message)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
trove := api_message.ToDMTrove()
|
trove := api_message.ToTweetTrove()
|
||||||
|
|
||||||
assert.Len(trove.Messages, 1)
|
assert.Len(trove.Messages, 1)
|
||||||
m, is_ok := trove.Messages[DMMessageID(1665936253483614212)]
|
m, is_ok := trove.Messages[DMMessageID(1665936253483614212)]
|
||||||
@ -92,7 +92,7 @@ func TestParseAPIDMMessageWithEmbeddedImage(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &api_message)
|
err = json.Unmarshal(data, &api_message)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
trove := api_message.ToDMTrove()
|
trove := api_message.ToTweetTrove()
|
||||||
|
|
||||||
assert.Len(trove.Messages, 1)
|
assert.Len(trove.Messages, 1)
|
||||||
m, is_ok := trove.Messages[DMMessageID(1766224476729995648)]
|
m, is_ok := trove.Messages[DMMessageID(1766224476729995648)]
|
||||||
@ -117,7 +117,7 @@ func TestParseAPIDMMessageWithEmbeddedVideo(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &api_message)
|
err = json.Unmarshal(data, &api_message)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
trove := api_message.ToDMTrove()
|
trove := api_message.ToTweetTrove()
|
||||||
|
|
||||||
assert.Len(trove.Messages, 1)
|
assert.Len(trove.Messages, 1)
|
||||||
m, is_ok := trove.Messages[DMMessageID(1766248283901776125)]
|
m, is_ok := trove.Messages[DMMessageID(1766248283901776125)]
|
||||||
@ -144,7 +144,7 @@ func TestParseAPIDMMessageWithUrlCard(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &api_message)
|
err = json.Unmarshal(data, &api_message)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
trove := api_message.ToDMTrove()
|
trove := api_message.ToTweetTrove()
|
||||||
|
|
||||||
assert.Len(trove.Messages, 1)
|
assert.Len(trove.Messages, 1)
|
||||||
m, is_ok := trove.Messages[DMMessageID(1766255994668191902)]
|
m, is_ok := trove.Messages[DMMessageID(1766255994668191902)]
|
||||||
@ -232,7 +232,7 @@ func TestParseInbox(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &inbox)
|
err = json.Unmarshal(data, &inbox)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
trove := inbox.InboxInitialState.ToDMTrove()
|
trove := inbox.InboxInitialState.ToTweetTrove()
|
||||||
|
|
||||||
for _, id := range []DMMessageID{1663623062195957773, 1663623203644751885, 1665922180176044037, 1665936253483614212} {
|
for _, id := range []DMMessageID{1663623062195957773, 1663623203644751885, 1665922180176044037, 1665936253483614212} {
|
||||||
m, is_ok := trove.Messages[id]
|
m, is_ok := trove.Messages[id]
|
||||||
@ -240,7 +240,7 @@ func TestParseInbox(t *testing.T) {
|
|||||||
assert.Equal(m.ID, id)
|
assert.Equal(m.ID, id)
|
||||||
}
|
}
|
||||||
for _, id := range []UserID{1458284524761075714, 1488963321701171204} {
|
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.True(is_ok, "User with ID %d not in the trove!")
|
||||||
assert.Equal(u.ID, id)
|
assert.Equal(u.ID, id)
|
||||||
}
|
}
|
||||||
@ -259,7 +259,7 @@ func TestParseDMRoomResponse(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &inbox)
|
err = json.Unmarshal(data, &inbox)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
trove := inbox.ConversationTimeline.ToDMTrove()
|
trove := inbox.ConversationTimeline.ToTweetTrove()
|
||||||
|
|
||||||
for _, id := range []DMMessageID{
|
for _, id := range []DMMessageID{
|
||||||
1663623062195957773,
|
1663623062195957773,
|
||||||
@ -273,7 +273,7 @@ func TestParseDMRoomResponse(t *testing.T) {
|
|||||||
assert.Equal(m.ID, id)
|
assert.Equal(m.ID, id)
|
||||||
}
|
}
|
||||||
for _, id := range []UserID{1458284524761075714, 1488963321701171204} {
|
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.True(is_ok, "User with ID %d not in the trove!")
|
||||||
assert.Equal(u.ID, id)
|
assert.Equal(u.ID, id)
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ func TestParseInboxUpdates(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &inbox)
|
err = json.Unmarshal(data, &inbox)
|
||||||
require.NoError(t, err)
|
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
|
assert.Len(trove.Messages, 2) // Should ignore stuff that isn't a message
|
||||||
|
|
||||||
|
@ -4,31 +4,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DMTrove struct {
|
func (t TweetTrove) GetOldestMessage(id DMChatRoomID) DMMessageID {
|
||||||
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 {
|
|
||||||
oldest := DMMessageID(^uint(0) >> 1) // Max integer
|
oldest := DMMessageID(^uint(0) >> 1) // Max integer
|
||||||
for _, m := range t.Messages {
|
for _, m := range t.Messages {
|
||||||
if m.ID < oldest && m.DMChatRoomID == id {
|
if m.ID < oldest && m.DMChatRoomID == id {
|
||||||
@ -38,8 +14,10 @@ func (t DMTrove) GetOldestMessage(id DMChatRoomID) DMMessageID {
|
|||||||
return oldest
|
return oldest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a DMTrove and the cursor for the next update
|
// TODO: Why are these all here? =>
|
||||||
func GetInbox(how_many int) (DMTrove, string) {
|
|
||||||
|
// Returns a TweetTrove and the cursor for the next update
|
||||||
|
func GetInbox(how_many int) (TweetTrove, string) {
|
||||||
if !the_api.IsAuthenticated {
|
if !the_api.IsAuthenticated {
|
||||||
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
|
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)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trove := dm_response.ToDMTrove()
|
trove := dm_response.ToTweetTrove()
|
||||||
cursor := dm_response.Cursor
|
cursor := dm_response.Cursor
|
||||||
next_cursor_id := dm_response.InboxTimelines.Trusted.MinEntryID
|
next_cursor_id := dm_response.InboxTimelines.Trusted.MinEntryID
|
||||||
for len(trove.Rooms) < how_many && dm_response.Status != "AT_END" {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
next_trove := dm_response.ToDMTrove()
|
next_trove := dm_response.ToTweetTrove()
|
||||||
next_cursor_id = dm_response.MinEntryID
|
next_cursor_id = dm_response.MinEntryID
|
||||||
trove.MergeWith(next_trove)
|
trove.MergeWith(next_trove)
|
||||||
}
|
}
|
||||||
@ -64,7 +42,7 @@ func GetInbox(how_many int) (DMTrove, string) {
|
|||||||
return trove, cursor
|
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 {
|
if !the_api.IsAuthenticated {
|
||||||
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
|
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)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trove := dm_response.ToDMTrove()
|
trove := dm_response.ToTweetTrove()
|
||||||
oldest := trove.GetOldestMessage(id)
|
oldest := trove.GetOldestMessage(id)
|
||||||
for len(trove.Messages) < how_many && dm_response.Status != "AT_END" {
|
for len(trove.Messages) < how_many && dm_response.Status != "AT_END" {
|
||||||
dm_response, err = the_api.GetDMConversation(id, oldest)
|
dm_response, err = the_api.GetDMConversation(id, oldest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
next_trove := dm_response.ToDMTrove()
|
next_trove := dm_response.ToTweetTrove()
|
||||||
oldest = next_trove.GetOldestMessage(id)
|
oldest = next_trove.GetOldestMessage(id)
|
||||||
trove.MergeWith(next_trove)
|
trove.MergeWith(next_trove)
|
||||||
}
|
}
|
||||||
@ -88,8 +66,8 @@ func GetConversation(id DMChatRoomID, max_id DMMessageID, how_many int) DMTrove
|
|||||||
return trove
|
return trove
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a DMTrove and the cursor for the next update
|
// Returns a TweetTrove and the cursor for the next update
|
||||||
func PollInboxUpdates(cursor string) (DMTrove, string) {
|
func PollInboxUpdates(cursor string) (TweetTrove, string) {
|
||||||
if !the_api.IsAuthenticated {
|
if !the_api.IsAuthenticated {
|
||||||
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
|
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)
|
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 {
|
if !the_api.IsAuthenticated {
|
||||||
log.Fatalf("Fetching DMs can only be done when authenticated. Please provide `--session [user]`")
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return dm_response.ToDMTrove()
|
return dm_response.ToTweetTrove()
|
||||||
}
|
}
|
||||||
func MarkDMChatRead(room_id DMChatRoomID, read_message_id DMMessageID) {
|
func MarkDMChatRead(room_id DMChatRoomID, read_message_id DMMessageID) {
|
||||||
if !the_api.IsAuthenticated {
|
if !the_api.IsAuthenticated {
|
||||||
|
@ -16,6 +16,10 @@ type TweetTrove struct {
|
|||||||
Bookmarks map[BookmarkSortID]Bookmark
|
Bookmarks map[BookmarkSortID]Bookmark
|
||||||
|
|
||||||
TombstoneUsers []UserHandle
|
TombstoneUsers []UserHandle
|
||||||
|
|
||||||
|
// For DMs
|
||||||
|
Rooms map[DMChatRoomID]DMChatRoom
|
||||||
|
Messages map[DMMessageID]DMMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTweetTrove() TweetTrove {
|
func NewTweetTrove() TweetTrove {
|
||||||
@ -27,6 +31,8 @@ func NewTweetTrove() TweetTrove {
|
|||||||
ret.Likes = make(map[LikeSortID]Like)
|
ret.Likes = make(map[LikeSortID]Like)
|
||||||
ret.Bookmarks = make(map[BookmarkSortID]Bookmark)
|
ret.Bookmarks = make(map[BookmarkSortID]Bookmark)
|
||||||
ret.TombstoneUsers = []UserHandle{}
|
ret.TombstoneUsers = []UserHandle{}
|
||||||
|
ret.Rooms = make(map[DMChatRoomID]DMChatRoom)
|
||||||
|
ret.Messages = make(map[DMMessageID]DMMessage)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +72,13 @@ func (t1 *TweetTrove) MergeWith(t2 TweetTrove) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t1.TombstoneUsers = append(t1.TombstoneUsers, t2.TombstoneUsers...)
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user