fix: align private and channel update semantics
(cherry picked from commit c65f76f56278f74082c4fa792ed49104d5d33c38)
This commit is contained in:
parent
dce7b92772
commit
d84fa6e126
36 changed files with 1765 additions and 382 deletions
|
|
@ -6570,6 +6570,9 @@ LIMIT $`+fmt.Sprint(len(args)), args...)
|
|||
if err := rows.Err(); err != nil {
|
||||
return domain.ChannelDifference{}, err
|
||||
}
|
||||
if err := populateChannelMessageUnreadFlags(ctx, s.db, req.UserID, diff.NewMessages); err != nil {
|
||||
return domain.ChannelDifference{}, err
|
||||
}
|
||||
if preview {
|
||||
diff.Dialog = previewChannelDialog(req.UserID, channel, member)
|
||||
} else {
|
||||
|
|
@ -6634,6 +6637,19 @@ LIMIT $3`, req.ChannelID, req.Pts, limit)
|
|||
} else if lastPts > diff.Pts {
|
||||
diff.Pts = lastPts
|
||||
}
|
||||
if err := populateChannelMessageUnreadFlags(ctx, s.db, req.UserID, diff.NewMessages); err != nil {
|
||||
return domain.ChannelDifference{}, err
|
||||
}
|
||||
for i := range diff.OtherUpdates {
|
||||
if diff.OtherUpdates[i].Message.ID == 0 {
|
||||
continue
|
||||
}
|
||||
messages := []domain.ChannelMessage{diff.OtherUpdates[i].Message}
|
||||
if err := populateChannelMessageUnreadFlags(ctx, s.db, req.UserID, messages); err != nil {
|
||||
return domain.ChannelDifference{}, err
|
||||
}
|
||||
diff.OtherUpdates[i].Message = messages[0]
|
||||
}
|
||||
users, err := listUsersByIDs(ctx, s.db, mapKeysInt64(userRefs))
|
||||
if err != nil {
|
||||
return domain.ChannelDifference{}, err
|
||||
|
|
@ -6687,6 +6703,45 @@ LIMIT $3`, userID, afterChannelID, limit)
|
|||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (s *ChannelStore) ListDirtyActiveChannelsForUser(ctx context.Context, userID int64, sinceDate int, afterChannelID int64, limit int) ([]domain.DirtyChannel, error) {
|
||||
if userID == 0 || sinceDate <= 0 || afterChannelID < 0 {
|
||||
return nil, domain.ErrChannelInvalid
|
||||
}
|
||||
if limit <= 0 || limit > domain.MaxChannelDifferenceLimit {
|
||||
limit = domain.MaxChannelDifferenceLimit
|
||||
}
|
||||
rows, err := s.db.Query(ctx, `
|
||||
SELECT i.channel_id, c.pts
|
||||
FROM user_channel_member_index i
|
||||
JOIN channels c ON c.id = i.channel_id AND NOT c.deleted
|
||||
WHERE i.user_id = $1
|
||||
AND i.status = 'active'
|
||||
AND NOT i.deleted
|
||||
AND i.channel_id > $3
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM channel_update_events e
|
||||
WHERE e.channel_id = i.channel_id
|
||||
AND e.date > $2
|
||||
LIMIT 1
|
||||
)
|
||||
ORDER BY i.channel_id ASC
|
||||
LIMIT $4`, userID, sinceDate, afterChannelID, limit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list dirty active channels for user: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
out := make([]domain.DirtyChannel, 0, limit)
|
||||
for rows.Next() {
|
||||
var item domain.DirtyChannel
|
||||
if err := rows.Scan(&item.ChannelID, &item.Pts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, item)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (s *ChannelStore) ListActiveChannelMemberIDs(ctx context.Context, viewerUserID, channelID int64, limit int) ([]int64, error) {
|
||||
if _, _, err := s.getChannelForMember(ctx, s.db, viewerUserID, channelID); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -7119,6 +7174,9 @@ func (s *ChannelStore) populateChannelMessagesReactions(ctx context.Context, db
|
|||
if len(messages) == 0 {
|
||||
return nil
|
||||
}
|
||||
if err := populateChannelMessageUnreadFlags(ctx, db, viewerUserID, messages); err != nil {
|
||||
return err
|
||||
}
|
||||
channelsByID := make(map[int64]domain.Channel, len(channels))
|
||||
for _, ch := range channels {
|
||||
if ch.ID != 0 {
|
||||
|
|
@ -7230,6 +7288,54 @@ ORDER BY message_id ASC, reaction_date DESC, reacted_user_id DESC, reaction_valu
|
|||
return nil
|
||||
}
|
||||
|
||||
func populateChannelMessageUnreadFlags(ctx context.Context, db sqlcgen.DBTX, viewerUserID int64, messages []domain.ChannelMessage) error {
|
||||
if viewerUserID == 0 || len(messages) == 0 {
|
||||
return nil
|
||||
}
|
||||
indexes := make(map[channelReactionMessageKey][]int)
|
||||
idsByChannel := make(map[int64][]int32)
|
||||
for i := range messages {
|
||||
if messages[i].ChannelID == 0 || messages[i].ID <= 0 {
|
||||
continue
|
||||
}
|
||||
key := channelReactionMessageKey{channelID: messages[i].ChannelID, messageID: messages[i].ID}
|
||||
if _, ok := indexes[key]; !ok {
|
||||
idsByChannel[messages[i].ChannelID] = append(idsByChannel[messages[i].ChannelID], int32(messages[i].ID))
|
||||
}
|
||||
indexes[key] = append(indexes[key], i)
|
||||
}
|
||||
for channelID, ids := range idsByChannel {
|
||||
rows, err := db.Query(ctx, `
|
||||
SELECT message_id, COALESCE(media_unread, false)
|
||||
FROM channel_unread_mentions
|
||||
WHERE user_id = $1
|
||||
AND channel_id = $2
|
||||
AND message_id = ANY($3::int[])`, viewerUserID, channelID, ids)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load channel message unread flags: %w", err)
|
||||
}
|
||||
for rows.Next() {
|
||||
var messageID int
|
||||
var mediaUnread bool
|
||||
if err := rows.Scan(&messageID, &mediaUnread); err != nil {
|
||||
rows.Close()
|
||||
return err
|
||||
}
|
||||
key := channelReactionMessageKey{channelID: channelID, messageID: messageID}
|
||||
for _, idx := range indexes[key] {
|
||||
messages[idx].Mentioned = true
|
||||
messages[idx].MediaUnread = mediaUnread
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
rows.Close()
|
||||
return err
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func channelReactionOffset(row domain.ChannelMessagePeerReaction) string {
|
||||
return strconv.Itoa(row.Date) + ":" + strconv.FormatInt(row.UserID, 10) + ":" + row.Reaction.Emoticon
|
||||
}
|
||||
|
|
@ -8611,6 +8717,7 @@ func insertChannelUnreadMentionsTx(ctx context.Context, tx pgx.Tx, channelID int
|
|||
candidates = candidates[:domain.MaxChannelMentionRecipients]
|
||||
}
|
||||
topID := channelMentionTopID(msg)
|
||||
mediaUnread := !msg.Media.IsZero()
|
||||
if _, err := tx.Exec(ctx, `
|
||||
WITH input(user_id) AS (
|
||||
SELECT DISTINCT unnest($4::bigint[])
|
||||
|
|
@ -8626,8 +8733,8 @@ active AS (
|
|||
LIMIT $6
|
||||
),
|
||||
inserted AS (
|
||||
INSERT INTO channel_unread_mentions (user_id, channel_id, message_id, top_message_id)
|
||||
SELECT user_id, $1, $2, $3
|
||||
INSERT INTO channel_unread_mentions (user_id, channel_id, message_id, top_message_id, media_unread)
|
||||
SELECT user_id, $1, $2, $3, $7
|
||||
FROM active
|
||||
ON CONFLICT DO NOTHING
|
||||
RETURNING user_id
|
||||
|
|
@ -8641,7 +8748,7 @@ ON CONFLICT (user_id, channel_id) DO UPDATE SET
|
|||
top_message_id = GREATEST(channel_dialogs.top_message_id, EXCLUDED.top_message_id),
|
||||
top_message_date = GREATEST(channel_dialogs.top_message_date, EXCLUDED.top_message_date),
|
||||
unread_mentions_count = channel_dialogs.unread_mentions_count + 1,
|
||||
updated_at = now()`, channelID, msg.ID, topID, candidates, msg.Date, domain.MaxChannelMentionRecipients); err != nil {
|
||||
updated_at = now()`, channelID, msg.ID, topID, candidates, msg.Date, domain.MaxChannelMentionRecipients, mediaUnread); err != nil {
|
||||
return fmt.Errorf("insert channel unread mentions: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -366,6 +366,118 @@ func contactFromFields(id, accessHash int64, phone, firstName, lastName, usernam
|
|||
}
|
||||
}
|
||||
|
||||
func (s *ContactStore) Block(ctx context.Context, userID, blockedUserID int64, date int) (bool, error) {
|
||||
if userID == 0 || blockedUserID == 0 || userID == blockedUserID {
|
||||
return false, nil
|
||||
}
|
||||
tag, err := s.db.Exec(ctx, `
|
||||
INSERT INTO contact_blocks (owner_user_id, blocked_user_id, date)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (owner_user_id, blocked_user_id) DO UPDATE SET
|
||||
date = EXCLUDED.date,
|
||||
created_at = contact_blocks.created_at`, userID, blockedUserID, date)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("block contact: %w", err)
|
||||
}
|
||||
return tag.RowsAffected() > 0, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) Unblock(ctx context.Context, userID, blockedUserID int64) (bool, error) {
|
||||
if userID == 0 || blockedUserID == 0 {
|
||||
return false, nil
|
||||
}
|
||||
tag, err := s.db.Exec(ctx, `
|
||||
DELETE FROM contact_blocks
|
||||
WHERE owner_user_id = $1
|
||||
AND blocked_user_id = $2`, userID, blockedUserID)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("unblock contact: %w", err)
|
||||
}
|
||||
return tag.RowsAffected() > 0, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) IsBlocked(ctx context.Context, userID, blockedUserID int64) (bool, error) {
|
||||
if userID == 0 || blockedUserID == 0 {
|
||||
return false, nil
|
||||
}
|
||||
var blocked bool
|
||||
if err := s.db.QueryRow(ctx, `
|
||||
SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM contact_blocks
|
||||
WHERE owner_user_id = $1
|
||||
AND blocked_user_id = $2
|
||||
)`, userID, blockedUserID).Scan(&blocked); err != nil {
|
||||
return false, fmt.Errorf("check contact block: %w", err)
|
||||
}
|
||||
return blocked, nil
|
||||
}
|
||||
|
||||
func (s *ContactStore) ListBlocked(ctx context.Context, userID int64, offset, limit int) (domain.BlockedContactList, error) {
|
||||
if userID == 0 {
|
||||
return domain.BlockedContactList{}, nil
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
if limit <= 0 || limit > 100 {
|
||||
limit = 100
|
||||
}
|
||||
var count int
|
||||
if err := s.db.QueryRow(ctx, `
|
||||
SELECT COUNT(*)::int
|
||||
FROM contact_blocks
|
||||
WHERE owner_user_id = $1`, userID).Scan(&count); err != nil {
|
||||
return domain.BlockedContactList{}, fmt.Errorf("count blocked contacts: %w", err)
|
||||
}
|
||||
rows, err := s.db.Query(ctx, `
|
||||
SELECT
|
||||
b.blocked_user_id,
|
||||
b.date,
|
||||
u.access_hash,
|
||||
u.phone,
|
||||
u.first_name,
|
||||
u.last_name,
|
||||
u.username,
|
||||
u.country_code,
|
||||
u.verified,
|
||||
u.support,
|
||||
u.last_seen_at
|
||||
FROM contact_blocks b
|
||||
JOIN users u ON u.id = b.blocked_user_id
|
||||
WHERE b.owner_user_id = $1
|
||||
ORDER BY b.date DESC, b.blocked_user_id DESC
|
||||
OFFSET $2
|
||||
LIMIT $3`, userID, offset, limit)
|
||||
if err != nil {
|
||||
return domain.BlockedContactList{}, fmt.Errorf("list blocked contacts: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
out := domain.BlockedContactList{Count: count, Blocked: make([]domain.BlockedContact, 0, limit)}
|
||||
for rows.Next() {
|
||||
var item domain.BlockedContact
|
||||
var lastSeen int64
|
||||
if err := rows.Scan(
|
||||
&item.User.ID,
|
||||
&item.Date,
|
||||
&item.User.AccessHash,
|
||||
&item.User.Phone,
|
||||
&item.User.FirstName,
|
||||
&item.User.LastName,
|
||||
&item.User.Username,
|
||||
&item.User.CountryCode,
|
||||
&item.User.Verified,
|
||||
&item.User.Support,
|
||||
&lastSeen,
|
||||
); err != nil {
|
||||
return domain.BlockedContactList{}, err
|
||||
}
|
||||
item.User.LastSeenAt = int(lastSeen)
|
||||
out.Blocked = append(out.Blocked, item)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func contactListHash(contacts []domain.Contact) int64 {
|
||||
if len(contacts) == 0 {
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@ func (s *MessageStore) SendPrivateText(ctx context.Context, req domain.SendPriva
|
|||
|
||||
var recipientBoxID, recipientPts int
|
||||
selfMessage := req.RecipientUserID == req.SenderUserID
|
||||
if !selfMessage {
|
||||
deliverRecipient := !selfMessage && !req.RecipientBlocked
|
||||
if deliverRecipient {
|
||||
recipientBoxID, err = s.boxIDs.NextBoxID(ctx, req.RecipientUserID)
|
||||
if err != nil {
|
||||
s.recordPtsGaps(ctx, reserved, req.Date)
|
||||
|
|
@ -249,6 +250,8 @@ func (s *MessageStore) SendPrivateText(ctx context.Context, req domain.SendPriva
|
|||
EntitiesJson: entities,
|
||||
Pts: int32(senderPts),
|
||||
MediaJson: mediaJSON,
|
||||
MediaUnread: false,
|
||||
ReactionUnread: false,
|
||||
}
|
||||
applyCreateMessageBoxMetadata(&senderArg, senderMeta)
|
||||
senderRow, err := qtx.CreateMessageBox(ctx, senderArg)
|
||||
|
|
@ -278,8 +281,11 @@ func (s *MessageStore) SendPrivateText(ctx context.Context, req domain.SendPriva
|
|||
return domain.SendPrivateTextResult{}, fmt.Errorf("enqueue sender dispatch: %w", err)
|
||||
}
|
||||
|
||||
recipient := sender
|
||||
if !selfMessage {
|
||||
recipient := domain.Message{}
|
||||
if selfMessage {
|
||||
recipient = sender
|
||||
}
|
||||
if deliverRecipient {
|
||||
recipientArg := sqlcgen.CreateMessageBoxParams{
|
||||
OwnerUserID: req.RecipientUserID,
|
||||
BoxID: int32(recipientBoxID),
|
||||
|
|
@ -294,6 +300,8 @@ func (s *MessageStore) SendPrivateText(ctx context.Context, req domain.SendPriva
|
|||
EntitiesJson: entities,
|
||||
Pts: int32(recipientPts),
|
||||
MediaJson: mediaJSON,
|
||||
MediaUnread: !req.Media.IsZero(),
|
||||
ReactionUnread: false,
|
||||
}
|
||||
applyCreateMessageBoxMetadata(&recipientArg, recipientMeta)
|
||||
recipientRow, err := qtx.CreateMessageBox(ctx, recipientArg)
|
||||
|
|
@ -352,13 +360,23 @@ func (s *MessageStore) duplicateSendResult(ctx context.Context, senderUserID, re
|
|||
return domain.SendPrivateTextResult{}, fmt.Errorf("get duplicate sender box: %w", err)
|
||||
}
|
||||
sender := messageFromGetBoxRow(senderRow)
|
||||
recipient := sender
|
||||
recipient := domain.Message{}
|
||||
if recipientUserID == senderUserID {
|
||||
recipient = sender
|
||||
}
|
||||
if recipientUserID != senderUserID {
|
||||
recipientRow, err := s.q.GetMessageBoxByPrivateMessage(ctx, sqlcgen.GetMessageBoxByPrivateMessageParams{
|
||||
OwnerUserID: recipientUserID,
|
||||
PrivateMessageID: pm.ID,
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return domain.SendPrivateTextResult{
|
||||
SenderMessage: sender,
|
||||
SenderEvent: eventFromMessage(sender),
|
||||
RecipientEvent: domain.UpdateEvent{},
|
||||
}, nil
|
||||
}
|
||||
return domain.SendPrivateTextResult{}, fmt.Errorf("get duplicate recipient box: %w", err)
|
||||
}
|
||||
recipient = messageFromGetBoxRow(recipientRow)
|
||||
|
|
@ -514,19 +532,20 @@ func (s *MessageStore) ForwardPrivateMessages(ctx context.Context, req domain.Fo
|
|||
}
|
||||
}
|
||||
sent, err := s.SendPrivateText(ctx, domain.SendPrivateTextRequest{
|
||||
SenderUserID: req.OwnerUserID,
|
||||
RecipientUserID: req.ToUserID,
|
||||
RandomID: req.RandomIDs[i],
|
||||
Message: source.Body,
|
||||
Entities: append([]domain.MessageEntity(nil), source.Entities...),
|
||||
Media: source.Media,
|
||||
Silent: req.Silent,
|
||||
NoForwards: req.NoForwards,
|
||||
ReplyTo: req.ReplyTo,
|
||||
Forward: forward,
|
||||
Date: req.Date,
|
||||
OriginAuthKeyID: req.OriginAuthKeyID,
|
||||
OriginSessionID: req.OriginSessionID,
|
||||
SenderUserID: req.OwnerUserID,
|
||||
RecipientUserID: req.ToUserID,
|
||||
RandomID: req.RandomIDs[i],
|
||||
Message: source.Body,
|
||||
Entities: append([]domain.MessageEntity(nil), source.Entities...),
|
||||
Media: source.Media,
|
||||
Silent: req.Silent,
|
||||
NoForwards: req.NoForwards,
|
||||
ReplyTo: req.ReplyTo,
|
||||
Forward: forward,
|
||||
Date: req.Date,
|
||||
OriginAuthKeyID: req.OriginAuthKeyID,
|
||||
OriginSessionID: req.OriginSessionID,
|
||||
RecipientBlocked: req.RecipientBlocked,
|
||||
})
|
||||
if err != nil {
|
||||
return res, err
|
||||
|
|
@ -640,22 +659,24 @@ func (s *MessageStore) ListByUser(ctx context.Context, userID int64, filter doma
|
|||
return domain.MessageList{}, fmt.Errorf("decode message media: %w", err)
|
||||
}
|
||||
out.Messages = append(out.Messages, domain.Message{
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
})
|
||||
if out.Count == 0 {
|
||||
out.Count = int(row.TotalCount)
|
||||
|
|
@ -832,6 +853,9 @@ func (s *MessageStore) ReadMessageContents(ctx context.Context, req domain.ReadM
|
|||
if req.OwnerUserID == 0 {
|
||||
return res, fmt.Errorf("read message contents: missing owner user id")
|
||||
}
|
||||
if req.Date == 0 {
|
||||
req.Date = int(time.Now().Unix())
|
||||
}
|
||||
if len(req.IDs) > domain.MaxGetMessageIDs {
|
||||
return res, domain.ErrMessageIDInvalid
|
||||
}
|
||||
|
|
@ -850,27 +874,128 @@ func (s *MessageStore) ReadMessageContents(ctx context.Context, req domain.ReadM
|
|||
if len(ids) == 0 {
|
||||
return res, nil
|
||||
}
|
||||
rows, err := s.db.Query(ctx, `
|
||||
SELECT box_id
|
||||
FROM message_boxes
|
||||
WHERE owner_user_id = $1
|
||||
AND box_id = ANY($2::int[])
|
||||
AND NOT deleted
|
||||
beginner, ok := s.db.(txBeginner)
|
||||
if !ok {
|
||||
return res, fmt.Errorf("read message contents: db does not support transactions")
|
||||
}
|
||||
tx, err := beginner.Begin(ctx)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("begin read message contents tx: %w", err)
|
||||
}
|
||||
qtx := sqlcgen.New(tx)
|
||||
committed := false
|
||||
var reserved []reservedPts
|
||||
defer func() {
|
||||
if committed {
|
||||
return
|
||||
}
|
||||
_ = tx.Rollback(ctx)
|
||||
s.recordPtsGaps(ctx, reserved, req.Date)
|
||||
}()
|
||||
if err := lockUsersForUpdate(ctx, tx, req.OwnerUserID); err != nil {
|
||||
return res, fmt.Errorf("lock read message contents user: %w", err)
|
||||
}
|
||||
rows, err := tx.Query(ctx, `
|
||||
WITH target AS (
|
||||
SELECT owner_user_id, box_id, peer_type, peer_id, reaction_unread
|
||||
FROM message_boxes
|
||||
WHERE owner_user_id = $1
|
||||
AND box_id = ANY($2::int[])
|
||||
AND NOT deleted
|
||||
AND (media_unread OR reaction_unread)
|
||||
FOR UPDATE
|
||||
),
|
||||
updated AS (
|
||||
UPDATE message_boxes
|
||||
SET media_unread = false,
|
||||
reaction_unread = false
|
||||
FROM target t
|
||||
WHERE message_boxes.owner_user_id = t.owner_user_id
|
||||
AND message_boxes.box_id = t.box_id
|
||||
RETURNING message_boxes.box_id, t.peer_type, t.peer_id, t.reaction_unread
|
||||
)
|
||||
SELECT box_id, peer_type, peer_id, reaction_unread
|
||||
FROM updated
|
||||
ORDER BY box_id`, req.OwnerUserID, ids)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("read message contents: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
affectedPeers := make(map[domain.Peer]struct{})
|
||||
for rows.Next() {
|
||||
var id int32
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
var peerType string
|
||||
var peerID int64
|
||||
var reactionUnread bool
|
||||
if err := rows.Scan(&id, &peerType, &peerID, &reactionUnread); err != nil {
|
||||
return res, fmt.Errorf("scan read message contents: %w", err)
|
||||
}
|
||||
res.MessageIDs = append(res.MessageIDs, int(id))
|
||||
if reactionUnread && peerID != 0 {
|
||||
affectedPeers[domain.Peer{Type: domain.PeerType(peerType), ID: peerID}] = struct{}{}
|
||||
}
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return res, fmt.Errorf("read message contents rows: %w", err)
|
||||
}
|
||||
if len(res.MessageIDs) == 0 {
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return res, fmt.Errorf("commit read message contents noop: %w", err)
|
||||
}
|
||||
committed = true
|
||||
return res, nil
|
||||
}
|
||||
for peer := range affectedPeers {
|
||||
if peer.Type != domain.PeerTypeUser || peer.ID == 0 {
|
||||
continue
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE dialogs d
|
||||
SET unread_reactions_count = (
|
||||
SELECT COUNT(*)::int
|
||||
FROM message_boxes m
|
||||
WHERE m.owner_user_id = d.user_id
|
||||
AND m.peer_type = d.peer_type
|
||||
AND m.peer_id = d.peer_id
|
||||
AND NOT m.deleted
|
||||
AND m.reaction_unread
|
||||
),
|
||||
updated_at = now()
|
||||
WHERE d.user_id = $1
|
||||
AND d.peer_type = $2
|
||||
AND d.peer_id = $3`, req.OwnerUserID, string(peer.Type), peer.ID); err != nil {
|
||||
return res, fmt.Errorf("refresh dialog unread reactions after content read: %w", err)
|
||||
}
|
||||
}
|
||||
pts, err := s.nextPtsN(ctx, req.OwnerUserID, len(res.MessageIDs))
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("allocate read message contents pts: %w", err)
|
||||
}
|
||||
reserved = append(reserved, reservedPts{userID: req.OwnerUserID, pts: pts, count: len(res.MessageIDs)})
|
||||
res.Event = domain.UpdateEvent{
|
||||
UserID: req.OwnerUserID,
|
||||
Type: domain.UpdateEventReadMessageContents,
|
||||
Pts: pts,
|
||||
PtsCount: len(res.MessageIDs),
|
||||
Date: req.Date,
|
||||
MessageIDs: append([]int(nil), res.MessageIDs...),
|
||||
}
|
||||
if err := appendUserUpdateEvent(ctx, qtx, req.OwnerUserID, res.Event); err != nil {
|
||||
return res, fmt.Errorf("append read message contents event: %w", err)
|
||||
}
|
||||
if err := qtx.EnqueueDispatch(ctx, sqlcgen.EnqueueDispatchParams{
|
||||
TargetUserID: req.OwnerUserID,
|
||||
Pts: int32(pts),
|
||||
EventType: string(domain.UpdateEventReadMessageContents),
|
||||
ExcludeAuthKeyID: authKeyIDToInt64(req.OriginAuthKeyID),
|
||||
ExcludeSessionID: req.OriginSessionID,
|
||||
}); err != nil {
|
||||
return res, fmt.Errorf("enqueue read message contents dispatch: %w", err)
|
||||
}
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return res, fmt.Errorf("commit read message contents tx: %w", err)
|
||||
}
|
||||
committed = true
|
||||
return res, nil
|
||||
}
|
||||
|
||||
|
|
@ -996,6 +1121,39 @@ DO UPDATE SET
|
|||
return domain.PrivateMessageReactionsResult{}, fmt.Errorf("insert message reaction: %w", err)
|
||||
}
|
||||
}
|
||||
if target.messageSenderID != 0 && target.messageSenderID != req.UserID {
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE message_boxes b
|
||||
SET reaction_unread = EXISTS (
|
||||
SELECT 1
|
||||
FROM private_message_reactions r
|
||||
WHERE r.message_sender_id = b.message_sender_id
|
||||
AND r.private_message_id = b.private_message_id
|
||||
AND r.user_id <> b.owner_user_id
|
||||
)
|
||||
WHERE b.owner_user_id = $1
|
||||
AND b.message_sender_id = $2
|
||||
AND b.private_message_id = $3`, target.messageSenderID, target.messageSenderID, target.privateMessageID); err != nil {
|
||||
return domain.PrivateMessageReactionsResult{}, fmt.Errorf("update private reaction unread: %w", err)
|
||||
}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
UPDATE dialogs d
|
||||
SET unread_reactions_count = (
|
||||
SELECT COUNT(*)::int
|
||||
FROM message_boxes m
|
||||
WHERE m.owner_user_id = d.user_id
|
||||
AND m.peer_type = d.peer_type
|
||||
AND m.peer_id = d.peer_id
|
||||
AND NOT m.deleted
|
||||
AND m.reaction_unread
|
||||
),
|
||||
updated_at = now()
|
||||
WHERE d.user_id = $1
|
||||
AND d.peer_type = $2
|
||||
AND d.peer_id = $3`, target.messageSenderID, string(domain.PeerTypeUser), req.UserID); err != nil {
|
||||
return domain.PrivateMessageReactionsResult{}, fmt.Errorf("refresh private reaction unread dialog: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
boxes, err := qtx.ListVisibleMessageBoxesByPrivateMessage(ctx, sqlcgen.ListVisibleMessageBoxesByPrivateMessageParams{
|
||||
MessageSenderID: target.messageSenderID,
|
||||
|
|
@ -1911,22 +2069,24 @@ func messageFromBoxRow(row sqlcgen.CreateMessageBoxRow) domain.Message {
|
|||
row.FwdDate,
|
||||
)
|
||||
return domain.Message{
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1949,22 +2109,24 @@ func messageFromGetBoxRow(row sqlcgen.GetMessageBoxByPrivateMessageRow) domain.M
|
|||
row.FwdDate,
|
||||
)
|
||||
return domain.Message{
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1996,22 +2158,24 @@ func messageFromVisibleBoxRow(row sqlcgen.ListVisibleMessageBoxesByPrivateMessag
|
|||
return domain.Message{}, fmt.Errorf("decode visible message media: %w", err)
|
||||
}
|
||||
return domain.Message{
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -2043,22 +2207,24 @@ func messageFromUpdateEditRow(row sqlcgen.UpdateMessageBoxEditRow) (domain.Messa
|
|||
return domain.Message{}, fmt.Errorf("decode edited message media: %w", err)
|
||||
}
|
||||
return domain.Message{
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -2090,22 +2256,24 @@ func messageFromForwardRow(row sqlcgen.GetMessageBoxesForForwardRow) (domain.Mes
|
|||
return domain.Message{}, fmt.Errorf("decode forward message media: %w", err)
|
||||
}
|
||||
return domain.Message{
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -2137,22 +2305,24 @@ func messageFromIDRow(row sqlcgen.GetMessageBoxesByIDsRow) (domain.Message, erro
|
|||
return domain.Message{}, fmt.Errorf("decode message media: %w", err)
|
||||
}
|
||||
return domain.Message{
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
Media: media,
|
||||
ID: int(row.BoxID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Pts: int(row.Pts),
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,9 @@ INSERT INTO message_boxes (
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media
|
||||
media,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, sqlc.arg(entities_json)::jsonb,
|
||||
sqlc.arg(silent)::boolean,
|
||||
|
|
@ -184,7 +186,9 @@ INSERT INTO message_boxes (
|
|||
sqlc.arg(fwd_from_name)::text,
|
||||
sqlc.arg(fwd_date)::int,
|
||||
sqlc.arg(pts)::int,
|
||||
sqlc.arg(media_json)::jsonb
|
||||
sqlc.arg(media_json)::jsonb,
|
||||
sqlc.arg(media_unread)::boolean,
|
||||
sqlc.arg(reaction_unread)::boolean
|
||||
)
|
||||
RETURNING
|
||||
box_id,
|
||||
|
|
@ -212,7 +216,9 @@ RETURNING
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json;
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread;
|
||||
|
||||
-- name: GetMessageBoxByPrivateMessage :one
|
||||
SELECT
|
||||
|
|
@ -241,7 +247,9 @@ SELECT
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
FROM message_boxes
|
||||
WHERE owner_user_id = $1
|
||||
AND private_message_id = $2
|
||||
|
|
@ -295,7 +303,9 @@ SELECT
|
|||
m.fwd_from_name,
|
||||
m.fwd_date,
|
||||
m.pts,
|
||||
m.media::text AS media_json
|
||||
m.media::text AS media_json,
|
||||
m.media_unread,
|
||||
m.reaction_unread
|
||||
FROM requested r
|
||||
JOIN message_boxes m
|
||||
ON m.owner_user_id = sqlc.arg(owner_user_id)::bigint
|
||||
|
|
@ -351,6 +361,8 @@ base AS NOT MATERIALIZED (
|
|||
m.fwd_date,
|
||||
m.pts,
|
||||
m.media::text AS media_json,
|
||||
m.media_unread,
|
||||
m.reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
@ -483,6 +495,8 @@ SELECT
|
|||
fwd_date,
|
||||
pts,
|
||||
media_json,
|
||||
media_unread,
|
||||
reaction_unread,
|
||||
peer_user_id,
|
||||
peer_access_hash,
|
||||
peer_phone,
|
||||
|
|
@ -537,6 +551,8 @@ SELECT
|
|||
m.fwd_date,
|
||||
m.pts,
|
||||
m.media::text AS media_json,
|
||||
m.media_unread,
|
||||
m.reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
@ -594,7 +610,9 @@ SELECT
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
FROM message_boxes
|
||||
WHERE owner_user_id = sqlc.arg(owner_user_id)::bigint
|
||||
AND box_id = sqlc.arg(box_id)::int
|
||||
|
|
@ -632,7 +650,9 @@ SELECT
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
FROM message_boxes
|
||||
WHERE message_sender_id = sqlc.arg(message_sender_id)::bigint
|
||||
AND private_message_id = sqlc.arg(private_message_id)::bigint
|
||||
|
|
@ -684,7 +704,9 @@ RETURNING
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json;
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread;
|
||||
|
||||
-- name: GetDialogReadStateForUpdate :one
|
||||
SELECT
|
||||
|
|
|
|||
|
|
@ -87,6 +87,8 @@ SELECT
|
|||
COALESCE(m.fwd_from_name, '')::text AS fwd_from_name,
|
||||
COALESCE(m.fwd_date, 0)::int AS fwd_date,
|
||||
COALESCE(m.media::text, '{}')::text AS media_json,
|
||||
COALESCE(m.media_unread, false)::boolean AS media_unread,
|
||||
COALESCE(m.reaction_unread, false)::boolean AS reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
@ -341,6 +343,8 @@ SELECT
|
|||
COALESCE(m.fwd_from_name, '')::text AS fwd_from_name,
|
||||
COALESCE(m.fwd_date, 0)::int AS fwd_date,
|
||||
COALESCE(m.media::text, '{}')::text AS media_json,
|
||||
COALESCE(m.media_unread, false)::boolean AS media_unread,
|
||||
COALESCE(m.reaction_unread, false)::boolean AS reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
|
|||
|
|
@ -173,7 +173,9 @@ INSERT INTO message_boxes (
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media
|
||||
media,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11::jsonb,
|
||||
$12::boolean,
|
||||
|
|
@ -190,7 +192,9 @@ INSERT INTO message_boxes (
|
|||
$23::text,
|
||||
$24::int,
|
||||
$25::int,
|
||||
$26::jsonb
|
||||
$26::jsonb,
|
||||
$27::boolean,
|
||||
$28::boolean
|
||||
)
|
||||
RETURNING
|
||||
box_id,
|
||||
|
|
@ -218,7 +222,9 @@ RETURNING
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
`
|
||||
|
||||
type CreateMessageBoxParams struct {
|
||||
|
|
@ -248,6 +254,8 @@ type CreateMessageBoxParams struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson []byte
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
type CreateMessageBoxRow struct {
|
||||
|
|
@ -277,6 +285,8 @@ type CreateMessageBoxRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
func (q *Queries) CreateMessageBox(ctx context.Context, arg CreateMessageBoxParams) (CreateMessageBoxRow, error) {
|
||||
|
|
@ -307,6 +317,8 @@ func (q *Queries) CreateMessageBox(ctx context.Context, arg CreateMessageBoxPara
|
|||
arg.FwdDate,
|
||||
arg.Pts,
|
||||
arg.MediaJson,
|
||||
arg.MediaUnread,
|
||||
arg.ReactionUnread,
|
||||
)
|
||||
var i CreateMessageBoxRow
|
||||
err := row.Scan(
|
||||
|
|
@ -336,6 +348,8 @@ func (q *Queries) CreateMessageBox(ctx context.Context, arg CreateMessageBoxPara
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -845,7 +859,9 @@ SELECT
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
FROM message_boxes
|
||||
WHERE owner_user_id = $1
|
||||
AND private_message_id = $2
|
||||
|
|
@ -884,6 +900,8 @@ type GetMessageBoxByPrivateMessageRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
func (q *Queries) GetMessageBoxByPrivateMessage(ctx context.Context, arg GetMessageBoxByPrivateMessageParams) (GetMessageBoxByPrivateMessageRow, error) {
|
||||
|
|
@ -916,6 +934,8 @@ func (q *Queries) GetMessageBoxByPrivateMessage(ctx context.Context, arg GetMess
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -948,7 +968,9 @@ SELECT
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
FROM message_boxes
|
||||
WHERE owner_user_id = $1::bigint
|
||||
AND box_id = $2::int
|
||||
|
|
@ -994,6 +1016,8 @@ type GetMessageBoxForEditRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
func (q *Queries) GetMessageBoxForEdit(ctx context.Context, arg GetMessageBoxForEditParams) (GetMessageBoxForEditRow, error) {
|
||||
|
|
@ -1032,6 +1056,8 @@ func (q *Queries) GetMessageBoxForEdit(ctx context.Context, arg GetMessageBoxFor
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
@ -1104,6 +1130,8 @@ SELECT
|
|||
m.fwd_date,
|
||||
m.pts,
|
||||
m.media::text AS media_json,
|
||||
m.media_unread,
|
||||
m.reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
@ -1167,6 +1195,8 @@ type GetMessageBoxesByIDsRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
PeerUserID int64
|
||||
PeerAccessHash int64
|
||||
PeerPhone string
|
||||
|
|
@ -1226,6 +1256,8 @@ func (q *Queries) GetMessageBoxesByIDs(ctx context.Context, arg GetMessageBoxesB
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
&i.PeerUserID,
|
||||
&i.PeerAccessHash,
|
||||
&i.PeerPhone,
|
||||
|
|
@ -1292,7 +1324,9 @@ SELECT
|
|||
m.fwd_from_name,
|
||||
m.fwd_date,
|
||||
m.pts,
|
||||
m.media::text AS media_json
|
||||
m.media::text AS media_json,
|
||||
m.media_unread,
|
||||
m.reaction_unread
|
||||
FROM requested r
|
||||
JOIN message_boxes m
|
||||
ON m.owner_user_id = $1::bigint
|
||||
|
|
@ -1339,6 +1373,8 @@ type GetMessageBoxesForForwardRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
func (q *Queries) GetMessageBoxesForForward(ctx context.Context, arg GetMessageBoxesForForwardParams) ([]GetMessageBoxesForForwardRow, error) {
|
||||
|
|
@ -1384,6 +1420,8 @@ func (q *Queries) GetMessageBoxesForForward(ctx context.Context, arg GetMessageB
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -1633,6 +1671,8 @@ base AS NOT MATERIALIZED (
|
|||
m.fwd_date,
|
||||
m.pts,
|
||||
m.media::text AS media_json,
|
||||
m.media_unread,
|
||||
m.reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
@ -1675,7 +1715,7 @@ total AS (
|
|||
WHERE $12::boolean
|
||||
),
|
||||
backward AS (
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.media_unread, b.reaction_unread, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
FROM base b
|
||||
CROSS JOIN load_params p
|
||||
WHERE p.load_type = 'backward'
|
||||
|
|
@ -1688,9 +1728,9 @@ backward AS (
|
|||
LIMIT (SELECT limit_count FROM load_params)
|
||||
),
|
||||
around_forward AS (
|
||||
SELECT f.box_id, f.private_message_id, f.owner_user_id, f.peer_type, f.peer_id, f.from_user_id, f.message_date, f.edit_date, f.outgoing, f.body, f.entities_json, f.silent, f.noforwards, f.reply_to_msg_id, f.reply_to_peer_type, f.reply_to_peer_id, f.reply_to_top_id, f.quote_text, f.quote_entities_json, f.quote_offset, f.fwd_from_peer_type, f.fwd_from_peer_id, f.fwd_from_name, f.fwd_date, f.pts, f.media_json, f.peer_user_id, f.peer_access_hash, f.peer_phone, f.peer_first_name, f.peer_last_name, f.peer_username, f.peer_country_code, f.peer_verified, f.peer_support, f.peer_last_seen_at, f.from_user_user_id, f.from_user_access_hash, f.from_user_phone, f.from_user_first_name, f.from_user_last_name, f.from_user_username, f.from_user_country_code, f.from_user_verified, f.from_user_support, f.from_user_last_seen_at
|
||||
SELECT f.box_id, f.private_message_id, f.owner_user_id, f.peer_type, f.peer_id, f.from_user_id, f.message_date, f.edit_date, f.outgoing, f.body, f.entities_json, f.silent, f.noforwards, f.reply_to_msg_id, f.reply_to_peer_type, f.reply_to_peer_id, f.reply_to_top_id, f.quote_text, f.quote_entities_json, f.quote_offset, f.fwd_from_peer_type, f.fwd_from_peer_id, f.fwd_from_name, f.fwd_date, f.pts, f.media_json, f.media_unread, f.reaction_unread, f.peer_user_id, f.peer_access_hash, f.peer_phone, f.peer_first_name, f.peer_last_name, f.peer_username, f.peer_country_code, f.peer_verified, f.peer_support, f.peer_last_seen_at, f.from_user_user_id, f.from_user_access_hash, f.from_user_phone, f.from_user_first_name, f.from_user_last_name, f.from_user_username, f.from_user_country_code, f.from_user_verified, f.from_user_support, f.from_user_last_seen_at
|
||||
FROM (
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.media_unread, b.reaction_unread, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
FROM base b
|
||||
CROSS JOIN load_params p
|
||||
WHERE p.load_type = 'around'
|
||||
|
|
@ -1703,7 +1743,7 @@ around_forward AS (
|
|||
) f
|
||||
),
|
||||
around_backward AS (
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.media_unread, b.reaction_unread, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
FROM base b
|
||||
CROSS JOIN load_params p
|
||||
WHERE p.load_type = 'around'
|
||||
|
|
@ -1715,9 +1755,9 @@ around_backward AS (
|
|||
LIMIT GREATEST((SELECT limit_count + add_offset FROM load_params), 0)
|
||||
),
|
||||
forward AS (
|
||||
SELECT f.box_id, f.private_message_id, f.owner_user_id, f.peer_type, f.peer_id, f.from_user_id, f.message_date, f.edit_date, f.outgoing, f.body, f.entities_json, f.silent, f.noforwards, f.reply_to_msg_id, f.reply_to_peer_type, f.reply_to_peer_id, f.reply_to_top_id, f.quote_text, f.quote_entities_json, f.quote_offset, f.fwd_from_peer_type, f.fwd_from_peer_id, f.fwd_from_name, f.fwd_date, f.pts, f.media_json, f.peer_user_id, f.peer_access_hash, f.peer_phone, f.peer_first_name, f.peer_last_name, f.peer_username, f.peer_country_code, f.peer_verified, f.peer_support, f.peer_last_seen_at, f.from_user_user_id, f.from_user_access_hash, f.from_user_phone, f.from_user_first_name, f.from_user_last_name, f.from_user_username, f.from_user_country_code, f.from_user_verified, f.from_user_support, f.from_user_last_seen_at
|
||||
SELECT f.box_id, f.private_message_id, f.owner_user_id, f.peer_type, f.peer_id, f.from_user_id, f.message_date, f.edit_date, f.outgoing, f.body, f.entities_json, f.silent, f.noforwards, f.reply_to_msg_id, f.reply_to_peer_type, f.reply_to_peer_id, f.reply_to_top_id, f.quote_text, f.quote_entities_json, f.quote_offset, f.fwd_from_peer_type, f.fwd_from_peer_id, f.fwd_from_name, f.fwd_date, f.pts, f.media_json, f.media_unread, f.reaction_unread, f.peer_user_id, f.peer_access_hash, f.peer_phone, f.peer_first_name, f.peer_last_name, f.peer_username, f.peer_country_code, f.peer_verified, f.peer_support, f.peer_last_seen_at, f.from_user_user_id, f.from_user_access_hash, f.from_user_phone, f.from_user_first_name, f.from_user_last_name, f.from_user_username, f.from_user_country_code, f.from_user_verified, f.from_user_support, f.from_user_last_seen_at
|
||||
FROM (
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
SELECT b.box_id, b.private_message_id, b.owner_user_id, b.peer_type, b.peer_id, b.from_user_id, b.message_date, b.edit_date, b.outgoing, b.body, b.entities_json, b.silent, b.noforwards, b.reply_to_msg_id, b.reply_to_peer_type, b.reply_to_peer_id, b.reply_to_top_id, b.quote_text, b.quote_entities_json, b.quote_offset, b.fwd_from_peer_type, b.fwd_from_peer_id, b.fwd_from_name, b.fwd_date, b.pts, b.media_json, b.media_unread, b.reaction_unread, b.peer_user_id, b.peer_access_hash, b.peer_phone, b.peer_first_name, b.peer_last_name, b.peer_username, b.peer_country_code, b.peer_verified, b.peer_support, b.peer_last_seen_at, b.from_user_user_id, b.from_user_access_hash, b.from_user_phone, b.from_user_first_name, b.from_user_last_name, b.from_user_username, b.from_user_country_code, b.from_user_verified, b.from_user_support, b.from_user_last_seen_at
|
||||
FROM base b
|
||||
CROSS JOIN load_params p
|
||||
WHERE p.load_type = 'forward'
|
||||
|
|
@ -1730,13 +1770,13 @@ forward AS (
|
|||
) f
|
||||
),
|
||||
paged AS (
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM backward
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, media_unread, reaction_unread, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM backward
|
||||
UNION ALL
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM around_forward
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, media_unread, reaction_unread, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM around_forward
|
||||
UNION ALL
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM around_backward
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, media_unread, reaction_unread, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM around_backward
|
||||
UNION ALL
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM forward
|
||||
SELECT box_id, private_message_id, owner_user_id, peer_type, peer_id, from_user_id, message_date, edit_date, outgoing, body, entities_json, silent, noforwards, reply_to_msg_id, reply_to_peer_type, reply_to_peer_id, reply_to_top_id, quote_text, quote_entities_json, quote_offset, fwd_from_peer_type, fwd_from_peer_id, fwd_from_name, fwd_date, pts, media_json, media_unread, reaction_unread, peer_user_id, peer_access_hash, peer_phone, peer_first_name, peer_last_name, peer_username, peer_country_code, peer_verified, peer_support, peer_last_seen_at, from_user_user_id, from_user_access_hash, from_user_phone, from_user_first_name, from_user_last_name, from_user_username, from_user_country_code, from_user_verified, from_user_support, from_user_last_seen_at FROM forward
|
||||
)
|
||||
SELECT
|
||||
box_id,
|
||||
|
|
@ -1765,6 +1805,8 @@ SELECT
|
|||
fwd_date,
|
||||
pts,
|
||||
media_json,
|
||||
media_unread,
|
||||
reaction_unread,
|
||||
peer_user_id,
|
||||
peer_access_hash,
|
||||
peer_phone,
|
||||
|
|
@ -1833,6 +1875,8 @@ type ListMessagesByUserRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
PeerUserID int64
|
||||
PeerAccessHash int64
|
||||
PeerPhone string
|
||||
|
|
@ -1905,6 +1949,8 @@ func (q *Queries) ListMessagesByUser(ctx context.Context, arg ListMessagesByUser
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
&i.PeerUserID,
|
||||
&i.PeerAccessHash,
|
||||
&i.PeerPhone,
|
||||
|
|
@ -1965,7 +2011,9 @@ SELECT
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
FROM message_boxes
|
||||
WHERE message_sender_id = $1::bigint
|
||||
AND private_message_id = $2::bigint
|
||||
|
|
@ -2007,6 +2055,8 @@ type ListVisibleMessageBoxesByPrivateMessageRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
func (q *Queries) ListVisibleMessageBoxesByPrivateMessage(ctx context.Context, arg ListVisibleMessageBoxesByPrivateMessageParams) ([]ListVisibleMessageBoxesByPrivateMessageRow, error) {
|
||||
|
|
@ -2046,6 +2096,8 @@ func (q *Queries) ListVisibleMessageBoxesByPrivateMessage(ctx context.Context, a
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -2218,7 +2270,9 @@ RETURNING
|
|||
fwd_from_name,
|
||||
fwd_date,
|
||||
pts,
|
||||
media::text AS media_json
|
||||
media::text AS media_json,
|
||||
media_unread,
|
||||
reaction_unread
|
||||
`
|
||||
|
||||
type UpdateMessageBoxEditParams struct {
|
||||
|
|
@ -2258,6 +2312,8 @@ type UpdateMessageBoxEditRow struct {
|
|||
FwdDate int32
|
||||
Pts int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateMessageBoxEdit(ctx context.Context, arg UpdateMessageBoxEditParams) (UpdateMessageBoxEditRow, error) {
|
||||
|
|
@ -2298,6 +2354,8 @@ func (q *Queries) UpdateMessageBoxEdit(ctx context.Context, arg UpdateMessageBox
|
|||
&i.FwdDate,
|
||||
&i.Pts,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ type ChannelUnreadMention struct {
|
|||
MessageID int32
|
||||
TopMessageID int32
|
||||
CreatedAt pgtype.Timestamptz
|
||||
MediaUnread bool
|
||||
}
|
||||
|
||||
type ChannelUpdateEvent struct {
|
||||
|
|
@ -357,6 +358,13 @@ type Contact struct {
|
|||
StoriesHidden bool
|
||||
}
|
||||
|
||||
type ContactBlock struct {
|
||||
OwnerUserID int64
|
||||
BlockedUserID int64
|
||||
Date int32
|
||||
CreatedAt pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type Country struct {
|
||||
Iso2 string
|
||||
DefaultName string
|
||||
|
|
@ -514,6 +522,8 @@ type MessageBox struct {
|
|||
FwdFromName string
|
||||
FwdDate int32
|
||||
Media []byte
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
}
|
||||
|
||||
type Photo struct {
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ SELECT
|
|||
COALESCE(m.fwd_from_name, '')::text AS fwd_from_name,
|
||||
COALESCE(m.fwd_date, 0)::int AS fwd_date,
|
||||
COALESCE(m.media::text, '{}')::text AS media_json,
|
||||
COALESCE(m.media_unread, false)::boolean AS media_unread,
|
||||
COALESCE(m.reaction_unread, false)::boolean AS reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
@ -291,6 +293,8 @@ type BatchListDispatchEventsRow struct {
|
|||
FwdFromName string
|
||||
FwdDate int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
PeerUserID int64
|
||||
PeerAccessHash int64
|
||||
PeerPhone string
|
||||
|
|
@ -432,6 +436,8 @@ func (q *Queries) BatchListDispatchEvents(ctx context.Context, arg BatchListDisp
|
|||
&i.FwdFromName,
|
||||
&i.FwdDate,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
&i.PeerUserID,
|
||||
&i.PeerAccessHash,
|
||||
&i.PeerPhone,
|
||||
|
|
@ -737,6 +743,8 @@ SELECT
|
|||
COALESCE(m.fwd_from_name, '')::text AS fwd_from_name,
|
||||
COALESCE(m.fwd_date, 0)::int AS fwd_date,
|
||||
COALESCE(m.media::text, '{}')::text AS media_json,
|
||||
COALESCE(m.media_unread, false)::boolean AS media_unread,
|
||||
COALESCE(m.reaction_unread, false)::boolean AS reaction_unread,
|
||||
COALESCE(peer_u.id, 0)::bigint AS peer_user_id,
|
||||
COALESCE(peer_u.access_hash, 0)::bigint AS peer_access_hash,
|
||||
COALESCE(peer_u.phone, '')::text AS peer_phone,
|
||||
|
|
@ -885,6 +893,8 @@ type ListUserUpdateEventsAfterRow struct {
|
|||
FwdFromName string
|
||||
FwdDate int32
|
||||
MediaJson string
|
||||
MediaUnread bool
|
||||
ReactionUnread bool
|
||||
PeerUserID int64
|
||||
PeerAccessHash int64
|
||||
PeerPhone string
|
||||
|
|
@ -1024,6 +1034,8 @@ func (q *Queries) ListUserUpdateEventsAfter(ctx context.Context, arg ListUserUpd
|
|||
&i.FwdFromName,
|
||||
&i.FwdDate,
|
||||
&i.MediaJson,
|
||||
&i.MediaUnread,
|
||||
&i.ReactionUnread,
|
||||
&i.PeerUserID,
|
||||
&i.PeerAccessHash,
|
||||
&i.PeerPhone,
|
||||
|
|
|
|||
|
|
@ -260,21 +260,23 @@ func (s *UpdateEventStore) ListAfter(ctx context.Context, userID int64, pts, lim
|
|||
FolderPeers: folderPeers,
|
||||
TagsEnabled: row.TagsEnabled,
|
||||
Message: domain.Message{
|
||||
ID: int(row.MessageID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Media: media,
|
||||
ID: int(row.MessageID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Media: media,
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
},
|
||||
Users: usersFromUpdateEventRow(row),
|
||||
Channels: channelsFromUpdateEventRow(row),
|
||||
|
|
@ -519,21 +521,23 @@ func (s *UpdateEventStore) BatchByCursor(ctx context.Context, cursors []store.Ev
|
|||
FolderPeers: folderPeers,
|
||||
TagsEnabled: row.TagsEnabled,
|
||||
Message: domain.Message{
|
||||
ID: int(row.MessageID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Media: media,
|
||||
ID: int(row.MessageID),
|
||||
UID: row.PrivateMessageID,
|
||||
OwnerUserID: row.OwnerUserID,
|
||||
Peer: domain.Peer{Type: domain.PeerType(row.PeerType), ID: row.PeerID},
|
||||
From: domain.Peer{Type: domain.PeerTypeUser, ID: row.FromUserID},
|
||||
Date: int(row.MessageDate),
|
||||
EditDate: int(row.EditDate),
|
||||
Out: row.Outgoing,
|
||||
Silent: silent,
|
||||
NoForwards: noforwards,
|
||||
Body: row.Body,
|
||||
Entities: entities,
|
||||
ReplyTo: reply,
|
||||
Forward: forward,
|
||||
Media: media,
|
||||
MediaUnread: row.MediaUnread,
|
||||
ReactionUnread: row.ReactionUnread,
|
||||
},
|
||||
Users: usersFromBatchDispatchRow(row),
|
||||
Channels: channelsFromBatchDispatchRow(row),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue