Create DM pagination function and reimplement 'GetChatRoomContents' using it
This commit is contained in:
parent
8410182129
commit
cc4da5e2a5
@ -83,6 +83,14 @@ func (o SortOrder) NextCursorValue(r CursorResult) int {
|
|||||||
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
panic(fmt.Sprintf("Invalid sort order: %d", o))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (o SortOrder) NextDMCursorValue(m scraper.DMMessage) int64 {
|
||||||
|
switch o {
|
||||||
|
case SORT_ORDER_NEWEST, SORT_ORDER_OLDEST:
|
||||||
|
return m.SentAt.UnixMilli()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Invalid sort order for DMs: %d", o))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Position in the feed (i.e., whether scrolling up/down is possible)
|
// Position in the feed (i.e., whether scrolling up/down is possible)
|
||||||
type CursorPosition int
|
type CursorPosition int
|
||||||
|
@ -194,6 +194,7 @@ func (p Profile) GetChatMessage(id DMMessageID) (ret DMMessage, err error) {
|
|||||||
|
|
||||||
type DMChatView struct {
|
type DMChatView struct {
|
||||||
DMTrove
|
DMTrove
|
||||||
|
Cursor DMCursor
|
||||||
RoomIDs []DMChatRoomID
|
RoomIDs []DMChatRoomID
|
||||||
MessageIDs []DMMessageID
|
MessageIDs []DMMessageID
|
||||||
ActiveRoomID DMChatRoomID
|
ActiveRoomID DMChatRoomID
|
||||||
@ -212,6 +213,7 @@ func (p Profile) GetChatRoomsPreview(id UserID) DMChatView {
|
|||||||
ret := NewDMChatView()
|
ret := NewDMChatView()
|
||||||
|
|
||||||
// Get the list of rooms
|
// Get the list of rooms
|
||||||
|
// DUPE: get-room-list
|
||||||
var rooms []DMChatRoom
|
var rooms []DMChatRoom
|
||||||
err := p.DB.Select(&rooms, `
|
err := p.DB.Select(&rooms, `
|
||||||
select `+CHAT_ROOMS_ALL_SQL_FIELDS+`
|
select `+CHAT_ROOMS_ALL_SQL_FIELDS+`
|
||||||
@ -260,7 +262,10 @@ func (p Profile) GetChatRoomsPreview(id UserID) DMChatView {
|
|||||||
|
|
||||||
// Get chat room detail, including participants and messages
|
// Get chat room detail, including participants and messages
|
||||||
func (p Profile) GetChatRoomContents(id DMChatRoomID, latest_timestamp int) DMChatView {
|
func (p Profile) GetChatRoomContents(id DMChatRoomID, latest_timestamp int) DMChatView {
|
||||||
ret := NewDMChatView()
|
c := NewConversationCursor(id)
|
||||||
|
c.SinceTimestamp = TimestampFromUnixMilli(int64(latest_timestamp))
|
||||||
|
ret := p.NextDMPage(c)
|
||||||
|
|
||||||
var room DMChatRoom
|
var room DMChatRoom
|
||||||
err := p.DB.Get(&room, `
|
err := p.DB.Get(&room, `
|
||||||
select `+CHAT_ROOMS_ALL_SQL_FIELDS+`
|
select `+CHAT_ROOMS_ALL_SQL_FIELDS+`
|
||||||
@ -271,28 +276,13 @@ func (p Profile) GetChatRoomContents(id DMChatRoomID, latest_timestamp int) DMCh
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all messages
|
// Reverse the order. Can't just use `SORT_ORDER_OLDEST` because that will get the wrong messages!
|
||||||
var msgs []DMMessage
|
// We want the newest messages, but with the oldest newest-message first and the newest newest-message last.
|
||||||
err = p.DB.Select(&msgs, `
|
reverse_msg_ids := make([]DMMessageID, len(ret.MessageIDs))
|
||||||
select `+CHAT_MESSAGES_ALL_SQL_FIELDS+`
|
for i := range ret.MessageIDs {
|
||||||
from chat_messages
|
reverse_msg_ids[i] = ret.MessageIDs[len(ret.MessageIDs)-i-1]
|
||||||
where chat_room_id = ?
|
|
||||||
and sent_at > ?
|
|
||||||
order by sent_at desc
|
|
||||||
limit 50
|
|
||||||
`, room.ID, latest_timestamp)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
ret.MessageIDs = make([]DMMessageID, len(msgs))
|
ret.MessageIDs = reverse_msg_ids
|
||||||
for i, msg := range msgs {
|
|
||||||
ret.MessageIDs[len(ret.MessageIDs)-i-1] = msg.ID // Reverse order
|
|
||||||
msg.Reactions = make(map[UserID]DMReaction)
|
|
||||||
ret.Messages[msg.ID] = msg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the participants
|
|
||||||
p.fill_chat_room_participants(&room, &ret.DMTrove)
|
|
||||||
|
|
||||||
// Set last message ID on chat room
|
// Set last message ID on chat room
|
||||||
if len(ret.MessageIDs) > 0 {
|
if len(ret.MessageIDs) > 0 {
|
||||||
@ -301,9 +291,13 @@ func (p Profile) GetChatRoomContents(id DMChatRoomID, latest_timestamp int) DMCh
|
|||||||
room.LastMessageID = ret.MessageIDs[len(ret.MessageIDs)-1]
|
room.LastMessageID = ret.MessageIDs[len(ret.MessageIDs)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch the participants
|
||||||
|
p.fill_chat_room_participants(&room, &ret.DMTrove)
|
||||||
|
|
||||||
// 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
|
||||||
p.fill_dm_contents(&ret.DMTrove)
|
p.fill_dm_contents(&ret.DMTrove)
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -460,3 +454,175 @@ func (p Profile) fill_dm_contents(trove *DMTrove) {
|
|||||||
|
|
||||||
p.fill_content(&trove.TweetTrove, UserID(0))
|
p.fill_content(&trove.TweetTrove, UserID(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DMCursor struct {
|
||||||
|
CursorPosition
|
||||||
|
CursorValue int64
|
||||||
|
SortOrder
|
||||||
|
PageSize int
|
||||||
|
|
||||||
|
// Search params
|
||||||
|
Keywords []string
|
||||||
|
FromUserHandle UserHandle // Sent by this user
|
||||||
|
ToUserHandle UserHandle // Replying to this user
|
||||||
|
ReaccedByUserHandle UserHandle // Reacted to by this user
|
||||||
|
ConversationId DMChatRoomID // In this conversation
|
||||||
|
SinceTimestamp Timestamp
|
||||||
|
UntilTimestamp Timestamp
|
||||||
|
FilterLinks Filter
|
||||||
|
FilterImages Filter
|
||||||
|
FilterVideos Filter
|
||||||
|
FilterMedia Filter
|
||||||
|
FilterSpaces Filter
|
||||||
|
FilterReplies Filter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a DMCursor for a conversation
|
||||||
|
func NewConversationCursor(id DMChatRoomID) DMCursor {
|
||||||
|
return DMCursor{
|
||||||
|
CursorPosition: CURSOR_START,
|
||||||
|
CursorValue: 0,
|
||||||
|
SortOrder: SORT_ORDER_NEWEST,
|
||||||
|
PageSize: 50,
|
||||||
|
|
||||||
|
ConversationId: id,
|
||||||
|
SinceTimestamp: TimestampFromUnix(0),
|
||||||
|
UntilTimestamp: TimestampFromUnix(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Profile) NextDMPage(c DMCursor) DMChatView {
|
||||||
|
where_clauses := []string{}
|
||||||
|
bind_values := []interface{}{}
|
||||||
|
|
||||||
|
// Keywords
|
||||||
|
for _, kw := range c.Keywords {
|
||||||
|
where_clauses = append(where_clauses, "text like ?")
|
||||||
|
bind_values = append(bind_values, fmt.Sprintf("%%%s%%", kw))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conversation
|
||||||
|
if c.ConversationId != DMChatRoomID("") {
|
||||||
|
where_clauses = append(where_clauses, "chat_room_id = ?")
|
||||||
|
bind_values = append(bind_values, c.ConversationId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since and until timestamps
|
||||||
|
if c.SinceTimestamp.Unix() != 0 {
|
||||||
|
where_clauses = append(where_clauses, "sent_at > ?")
|
||||||
|
bind_values = append(bind_values, c.SinceTimestamp)
|
||||||
|
}
|
||||||
|
if c.UntilTimestamp.Unix() != 0 {
|
||||||
|
where_clauses = append(where_clauses, "sent_at < ?")
|
||||||
|
bind_values = append(bind_values, c.UntilTimestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... etc
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
if c.CursorPosition != CURSOR_START {
|
||||||
|
where_clauses = append(where_clauses, c.SortOrder.PaginationWhereClause())
|
||||||
|
bind_values = append(bind_values, c.CursorValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble the full where-clause
|
||||||
|
where_clause := ""
|
||||||
|
if len(where_clauses) > 0 {
|
||||||
|
where_clause = "where " + strings.Join(where_clauses, " and ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add in page size parameter
|
||||||
|
bind_values = append(bind_values, c.PageSize)
|
||||||
|
|
||||||
|
// Fetch all messages
|
||||||
|
var msgs []struct {
|
||||||
|
DMMessage
|
||||||
|
Chrono int64 `db:"chrono"`
|
||||||
|
}
|
||||||
|
q := `
|
||||||
|
select ` + CHAT_MESSAGES_ALL_SQL_FIELDS + `, sent_at chrono
|
||||||
|
from chat_messages
|
||||||
|
` + where_clause + `
|
||||||
|
` + c.SortOrder.OrderByClause() + `
|
||||||
|
limit ?
|
||||||
|
`
|
||||||
|
fmt.Printf("query: %s\n", q)
|
||||||
|
fmt.Printf("Bind values: %#v\n", bind_values)
|
||||||
|
|
||||||
|
err := p.DB.Select(&msgs, q, bind_values...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret := NewDMChatView()
|
||||||
|
ret.MessageIDs = []DMMessageID{}
|
||||||
|
for _, _msg := range msgs {
|
||||||
|
msg := _msg.DMMessage // XXX: this is messy
|
||||||
|
ret.MessageIDs = append(ret.MessageIDs, msg.ID)
|
||||||
|
msg.Reactions = make(map[UserID]DMReaction)
|
||||||
|
ret.Messages[msg.ID] = msg
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the new cursor position and value
|
||||||
|
ret.Cursor = c // Copy cursor values over
|
||||||
|
if len(msgs) < c.PageSize {
|
||||||
|
ret.Cursor.CursorPosition = CURSOR_END
|
||||||
|
} else {
|
||||||
|
ret.Cursor.CursorPosition = CURSOR_MIDDLE
|
||||||
|
last_item := msgs[len(msgs)-1].DMMessage
|
||||||
|
ret.Cursor.CursorValue = c.SortOrder.NextDMCursorValue(last_item)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the list of rooms
|
||||||
|
var room_ids []interface{}
|
||||||
|
for _, msg := range ret.Messages {
|
||||||
|
room_ids = append(room_ids, msg.DMChatRoomID)
|
||||||
|
}
|
||||||
|
if len(room_ids) > 0 {
|
||||||
|
// DUPE: get-room-list
|
||||||
|
var rooms []DMChatRoom
|
||||||
|
err = p.DB.Select(&rooms, `
|
||||||
|
select `+CHAT_ROOMS_ALL_SQL_FIELDS+`
|
||||||
|
from chat_rooms
|
||||||
|
where id in (`+strings.Repeat("?,", len(room_ids)-1)+`?)
|
||||||
|
`, room_ids...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill data for the rooms
|
||||||
|
for _, room := range rooms {
|
||||||
|
// // Fetch the latest message
|
||||||
|
// var msg DMMessage
|
||||||
|
// q, args, err := sqlx.Named(`
|
||||||
|
// select `+CHAT_MESSAGES_ALL_SQL_FIELDS+`
|
||||||
|
// from chat_messages
|
||||||
|
// where chat_room_id = :room_id
|
||||||
|
// and sent_at = (select max(sent_at) from chat_messages where chat_room_id = :room_id)
|
||||||
|
// `, struct {
|
||||||
|
// ID DMChatRoomID `db:"room_id"`
|
||||||
|
// }{ID: room.ID})
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// err = p.DB.Get(&msg, q, args...)
|
||||||
|
// if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
// // TODO
|
||||||
|
// fmt.Printf("No messages found in chat; skipping preview\n")
|
||||||
|
// } else if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Fetch the participants
|
||||||
|
p.fill_chat_room_participants(&room, &ret.DMTrove)
|
||||||
|
// Add to the Trove
|
||||||
|
// room.LastMessageID = msg.ID
|
||||||
|
ret.Rooms[room.ID] = room
|
||||||
|
// Add everything to the Trove
|
||||||
|
// ret.Messages[msg.ID] = msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.fill_dm_contents(&ret.DMTrove)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user