Add queries for DM chat rooms and participants

This commit is contained in:
Alessio 2023-06-22 18:03:42 -03:00
parent 1538605e23
commit 891ce75479
3 changed files with 289 additions and 0 deletions

View File

@ -0,0 +1,133 @@
package persistence
import (
"fmt"
"offline_twitter/scraper"
)
func (p Profile) SaveChatRoom(r scraper.DMChatRoom) error {
_, err := p.DB.NamedExec(`
insert into chat_rooms (id, type, last_messaged_at, is_nsfw)
values (:id, :type, :last_messaged_at, :is_nsfw)
on conflict do update
set last_messaged_at=:last_messaged_at
`, r,
)
if err != nil {
return fmt.Errorf("Error executing SaveChatRoom(ID %s). Info: %#v:\n %w", r.ID, r, err)
}
for _, participant := range r.Participants {
_, err = p.DB.NamedExec(`
insert into chat_room_participants (
chat_room_id,
user_id,
last_read_event_id,
is_chat_settings_valid,
is_notifications_disabled,
is_mention_notifications_disabled,
is_read_only,
is_trusted,
is_muted,
status)
values (
:chat_room_id,
:user_id,
:last_read_event_id,
:is_chat_settings_valid,
:is_notifications_disabled,
:is_mention_notifications_disabled,
:is_read_only,
:is_trusted,
:is_muted,
:status)
on conflict do update
set last_read_event_id=:last_read_event_id,
is_chat_settings_valid=:is_chat_settings_valid,
is_notifications_disabled=:is_notifications_disabled,
is_mention_notifications_disabled=:is_mention_notifications_disabled,
is_read_only=:is_read_only,
is_trusted=:is_trusted,
is_muted=:is_muted,
status=:status
`, participant,
)
}
if err != nil {
return fmt.Errorf("Error saving chat participant: %#v\n %w", r, err)
}
// }
return nil
}
func (p Profile) GetChatRoom(id scraper.DMChatRoomID) (ret scraper.DMChatRoom, err error) {
err = p.DB.Get(&ret, `
select id, type, last_messaged_at, is_nsfw
from chat_rooms
where id = ?
`, id)
if err != nil {
return ret, fmt.Errorf("Error getting chat room (%s):\n %w", id, err)
}
participants := []scraper.DMChatParticipant{}
err = p.DB.Select(&participants, `
select chat_room_id, user_id, last_read_event_id, is_chat_settings_valid, is_notifications_disabled,
is_mention_notifications_disabled, is_read_only, is_trusted, is_muted, status
from chat_room_participants
where chat_room_id = ?
`, id,
)
if err != nil {
return ret, fmt.Errorf("Error getting chat room participants (%s):\n %w", id, err)
}
ret.Participants = make(map[scraper.UserID]scraper.DMChatParticipant)
for _, p := range participants {
ret.Participants[p.UserID] = p
}
return ret, nil
}
func (p Profile) SaveChatMessage(m scraper.DMMessage) error {
_, err := p.DB.NamedExec(`
insert into chat_messages (id, chat_room_id, sender_id, sent_at, request_id, in_reply_to_id, text)
values (:id, :chat_room_id, :sender_id, :sent_at, :request_id, :in_reply_to_id, :text)
`, m,
)
if err != nil {
return fmt.Errorf("Error saving message: %#v\n %w", m, err)
}
_, err = p.DB.NamedExec(`
insert into chat_message_reactions (id, message_id, sender_id, sent_at, emoji)
values (:id, :message_id, :sender_id, :sent_at, :emoji)
`, m.Reactions,
)
if err != nil {
return fmt.Errorf("Error saving message reactions: %#v\n %w", m, err)
}
return nil
}
func (p Profile) GetChatMessage(id scraper.DMMessageID) (ret scraper.DMMessage, err error) {
err = p.DB.Get(&ret, `
select id, chat_room_id, sender_id, sent_at, request_id, text, in_reply_to_id
where id = ?
`, id,
)
if err != nil {
return ret, fmt.Errorf("Error getting chat message (%d):\n %w", id, err)
}
err = p.DB.Select(&ret.Reactions, `
select id, message_id, sender_id, sent_at, emoji
from chat_message_reactions
where message_id = ?
`, id,
)
if err != nil {
return ret, fmt.Errorf("Error getting reactions to chat message (%d):\n %w", id, err)
}
return ret, nil
}

View File

@ -0,0 +1,101 @@
package persistence_test
import (
"fmt"
"testing"
// "math/rand"
// "time"
"github.com/go-test/deep"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"offline_twitter/scraper"
)
func TestSaveAndLoadChatRoom(t *testing.T) {
require := require.New(t)
profile_path := "test_profiles/TestDMs"
profile := create_or_load_profile(profile_path)
chat_room := create_dummy_chat_room()
chat_room.Type = "fnort"
primary_user, is_ok := chat_room.Participants[scraper.UserID(-1)]
require.True(is_ok)
primary_user.Status = fmt.Sprintf("status for %s", chat_room.ID)
chat_room.Participants[primary_user.UserID] = primary_user
// Save it
err := profile.SaveChatRoom(chat_room)
require.NoError(err)
// Reload it
new_chat_room, err := profile.GetChatRoom(chat_room.ID)
require.NoError(err)
if diff := deep.Equal(chat_room, new_chat_room); diff != nil {
t.Error(diff)
}
}
func TestModifyChatRoom(t *testing.T) {
require := require.New(t)
profile_path := "test_profiles/TestDMs"
profile := create_or_load_profile(profile_path)
// Save it
chat_room := create_dummy_chat_room()
chat_room.LastMessagedAt = scraper.TimestampFromUnix(2)
err := profile.SaveChatRoom(chat_room)
require.NoError(err)
// Modify it
chat_room.LastMessagedAt = scraper.TimestampFromUnix(35)
err = profile.SaveChatRoom(chat_room)
require.NoError(err)
// Reload it
new_chat_room, err := profile.GetChatRoom(chat_room.ID)
require.NoError(err)
assert.Equal(t, new_chat_room.LastMessagedAt, scraper.TimestampFromUnix(35))
}
func TestModifyChatParticipant(t *testing.T) {
require := require.New(t)
profile_path := "test_profiles/TestDMs"
profile := create_or_load_profile(profile_path)
// Save it
chat_room := create_dummy_chat_room()
err := profile.SaveChatRoom(chat_room)
require.NoError(err)
// Add a participant and modify the existing one
primary_user, is_ok := chat_room.Participants[scraper.UserID(-1)]
require.True(is_ok)
primary_user.IsReadOnly = true
primary_user.LastReadEventID = scraper.DMMessageID(1500)
chat_room.Participants[primary_user.UserID] = primary_user
new_user := create_dummy_user()
chat_room.Participants[new_user.ID] = scraper.DMChatParticipant{
DMChatRoomID: chat_room.ID,
UserID: new_user.ID,
LastReadEventID: scraper.DMMessageID(0),
IsChatSettingsValid: false,
}
// Save again
err = profile.SaveUser(&new_user)
require.NoError(err)
err = profile.SaveChatRoom(chat_room)
require.NoError(err)
// Reload it
new_chat_room, err := profile.GetChatRoom(chat_room.ID)
require.NoError(err)
if diff := deep.Equal(chat_room, new_chat_room); diff != nil {
t.Error(diff)
}
}

View File

@ -29,6 +29,10 @@ func create_or_load_profile(profile_path string) persistence.Profile {
panic(err)
}
err = profile.SaveRetweet(create_stable_retweet())
if err != nil {
panic(err)
}
err = profile.SaveChatRoom(create_stable_chat_room())
} else {
profile, err = persistence.LoadProfile(profile_path)
}
@ -299,3 +303,54 @@ func create_dummy_like() scraper.Like {
SortID: scraper.LikeSortID(12345),
}
}
func create_stable_chat_room() scraper.DMChatRoom {
id := scraper.DMChatRoomID("some chat room ID")
return scraper.DMChatRoom{
ID: id,
Type: "ONE_ON_ONE",
LastMessagedAt: scraper.TimestampFromUnix(123),
IsNSFW: false,
Participants: map[scraper.UserID]scraper.DMChatParticipant{
scraper.UserID(-1): {
DMChatRoomID: id,
UserID: scraper.UserID(-1),
LastReadEventID: scraper.DMMessageID(0),
IsChatSettingsValid: true,
IsNotificationsDisabled: false,
IsMentionNotificationsDisabled: false,
IsReadOnly: false,
IsTrusted: true,
IsMuted: false,
Status: "some status",
},
},
}
}
func create_dummy_chat_room() scraper.DMChatRoom {
rand.Seed(time.Now().UnixNano())
id := scraper.DMChatRoomID(fmt.Sprintf("Chat Room #%d", rand.Int()))
return scraper.DMChatRoom{
ID: id,
Type: "ONE_ON_ONE",
LastMessagedAt: scraper.TimestampFromUnix(10000),
IsNSFW: false,
Participants: map[scraper.UserID]scraper.DMChatParticipant{
scraper.UserID(-1): {
DMChatRoomID: id,
UserID: scraper.UserID(-1),
LastReadEventID: scraper.DMMessageID(0),
IsChatSettingsValid: true,
IsNotificationsDisabled: false,
IsMentionNotificationsDisabled: false,
IsReadOnly: false,
IsTrusted: true,
IsMuted: false,
Status: "some status",
},
},
}
}