2026-04-06 09:12:59 +02:00
|
|
|
-- name: OpenDM :exec
|
|
|
|
|
INSERT OR IGNORE INTO dm_open_state (user_id, channel_id) VALUES (?, ?);
|
|
|
|
|
|
|
|
|
|
-- name: CloseDM :exec
|
|
|
|
|
DELETE FROM dm_open_state WHERE user_id = ? AND channel_id = ?;
|
|
|
|
|
|
|
|
|
|
-- name: IsDMParticipant :one
|
|
|
|
|
SELECT user_id FROM dm_participants WHERE user_id = ? AND channel_id = ?;
|
|
|
|
|
|
|
|
|
|
-- name: GetDMParticipantIDs :many
|
|
|
|
|
SELECT user_id FROM dm_participants WHERE channel_id = ?;
|
|
|
|
|
|
2026-08-01 22:06:14 +02:00
|
|
|
-- name: CountDMParticipants :one
|
|
|
|
|
SELECT COUNT(*) FROM dm_participants WHERE channel_id = ?;
|
|
|
|
|
|
|
|
|
|
-- name: IsGroupDM :one
|
|
|
|
|
SELECT is_group FROM channels WHERE id = ? AND type = 'dm';
|
|
|
|
|
|
|
|
|
|
-- name: RemoveDMParticipant :exec
|
|
|
|
|
DELETE FROM dm_participants WHERE channel_id = ? AND user_id = ?;
|
|
|
|
|
|
|
|
|
|
-- name: SetDMChannelName :exec
|
|
|
|
|
UPDATE channels SET name = ? WHERE id = ? AND type = 'dm';
|
|
|
|
|
|
|
|
|
|
-- name: GetDMParticipants :many
|
|
|
|
|
SELECT
|
|
|
|
|
u.id AS id,
|
|
|
|
|
u.username AS username,
|
|
|
|
|
COALESCE(u.display_name, '') AS display_name,
|
|
|
|
|
COALESCE(u.avatar, '') AS avatar,
|
|
|
|
|
u.status AS status
|
|
|
|
|
FROM dm_participants dp
|
|
|
|
|
JOIN users u ON u.id = dp.user_id
|
|
|
|
|
WHERE dp.channel_id = ?
|
|
|
|
|
ORDER BY u.id ASC;
|
|
|
|
|
|
2026-07-31 15:41:57 +02:00
|
|
|
-- name: GetUserDMChannelIDs :many
|
|
|
|
|
SELECT channel_id FROM dm_open_state WHERE user_id = ?;
|
|
|
|
|
|
2026-08-01 22:06:14 +02:00
|
|
|
-- A DM row carries no recipient any more: dm_participants holds N users, so
|
|
|
|
|
-- "the other one" is only well defined for a two-person DM. The participant
|
|
|
|
|
-- set comes from GetDMParticipantsForUser below, one extra query for the whole
|
|
|
|
|
-- list rather than one per channel, and the Go layer stitches them together.
|
2026-04-06 09:12:59 +02:00
|
|
|
-- name: GetUserDMChannels :many
|
|
|
|
|
SELECT
|
|
|
|
|
c.id AS channel_id,
|
2026-08-01 22:06:14 +02:00
|
|
|
c.name AS name,
|
|
|
|
|
c.is_group AS is_group,
|
2026-04-06 09:12:59 +02:00
|
|
|
lm.id AS last_message_id,
|
|
|
|
|
COALESCE(lm.content, '') AS last_message,
|
|
|
|
|
COALESCE(lm.timestamp, '') AS last_message_at,
|
2026-07-31 15:41:57 +02:00
|
|
|
(SELECT COUNT(*) FROM messages mu
|
|
|
|
|
WHERE mu.channel_id = c.id AND mu.deleted = 0
|
|
|
|
|
AND mu.id > COALESCE((SELECT rs.last_message_id FROM read_states rs
|
|
|
|
|
WHERE rs.channel_id = c.id AND rs.user_id = dos.user_id), 0)
|
|
|
|
|
) AS unread_count
|
2026-04-06 09:12:59 +02:00
|
|
|
FROM dm_open_state dos
|
|
|
|
|
JOIN channels c ON c.id = dos.channel_id AND c.type = 'dm'
|
|
|
|
|
LEFT JOIN messages lm ON lm.id = (
|
|
|
|
|
SELECT MAX(id) FROM messages WHERE channel_id = c.id AND deleted = 0
|
|
|
|
|
)
|
|
|
|
|
WHERE dos.user_id = ?
|
|
|
|
|
ORDER BY COALESCE(lm.timestamp, dos.opened_at) DESC;
|
2026-08-01 22:06:14 +02:00
|
|
|
|
|
|
|
|
-- Every participant of every DM the user has open, in one pass. Includes the
|
|
|
|
|
-- user themselves so a caller can tell "group of three" from "group of three
|
|
|
|
|
-- others"; the Go layer filters when it needs the others.
|
|
|
|
|
-- name: GetDMParticipantsForUser :many
|
|
|
|
|
SELECT
|
|
|
|
|
dp.channel_id AS channel_id,
|
|
|
|
|
u.id AS id,
|
|
|
|
|
u.username AS username,
|
|
|
|
|
COALESCE(u.display_name, '') AS display_name,
|
|
|
|
|
COALESCE(u.avatar, '') AS avatar,
|
|
|
|
|
u.status AS status
|
|
|
|
|
FROM dm_open_state dos
|
|
|
|
|
JOIN dm_participants dp ON dp.channel_id = dos.channel_id
|
|
|
|
|
JOIN users u ON u.id = dp.user_id
|
|
|
|
|
WHERE dos.user_id = ?
|
|
|
|
|
ORDER BY dp.channel_id ASC, u.id ASC;
|