Add queries for DM chat rooms and participants
This commit is contained in:
parent
1538605e23
commit
891ce75479
133
pkg/persistence/dm_queries.go
Normal file
133
pkg/persistence/dm_queries.go
Normal 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
|
||||||
|
}
|
101
pkg/persistence/dm_queries_test.go
Normal file
101
pkg/persistence/dm_queries_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
@ -29,6 +29,10 @@ func create_or_load_profile(profile_path string) persistence.Profile {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
err = profile.SaveRetweet(create_stable_retweet())
|
err = profile.SaveRetweet(create_stable_retweet())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = profile.SaveChatRoom(create_stable_chat_room())
|
||||||
} else {
|
} else {
|
||||||
profile, err = persistence.LoadProfile(profile_path)
|
profile, err = persistence.LoadProfile(profile_path)
|
||||||
}
|
}
|
||||||
@ -299,3 +303,54 @@ func create_dummy_like() scraper.Like {
|
|||||||
SortID: scraper.LikeSortID(12345),
|
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",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user