2026-04-06 09:12:59 +02:00
|
|
|
// Code generated by sqlc. DO NOT EDIT.
|
|
|
|
|
// versions:
|
|
|
|
|
// sqlc v1.30.0
|
|
|
|
|
// source: dm.sql
|
|
|
|
|
|
|
|
|
|
package dbgen
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const closeDM = `-- name: CloseDM :exec
|
|
|
|
|
DELETE FROM dm_open_state WHERE user_id = ? AND channel_id = ?
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type CloseDMParams struct {
|
|
|
|
|
UserID int64 `json:"userId"`
|
|
|
|
|
ChannelID int64 `json:"channelId"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queries) CloseDM(ctx context.Context, arg CloseDMParams) error {
|
|
|
|
|
_, err := q.db.ExecContext(ctx, closeDM, arg.UserID, arg.ChannelID)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-01 22:06:14 +02:00
|
|
|
const countDMParticipants = `-- name: CountDMParticipants :one
|
|
|
|
|
SELECT COUNT(*) FROM dm_participants WHERE channel_id = ?
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
func (q *Queries) CountDMParticipants(ctx context.Context, channelID int64) (int64, error) {
|
|
|
|
|
row := q.db.QueryRowContext(ctx, countDMParticipants, channelID)
|
|
|
|
|
var count int64
|
|
|
|
|
err := row.Scan(&count)
|
|
|
|
|
return count, err
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-20 03:49:13 +02:00
|
|
|
const findDMChannelIDBetween = `-- name: FindDMChannelIDBetween :one
|
|
|
|
|
SELECT dp1.channel_id FROM dm_participants dp1
|
|
|
|
|
JOIN dm_participants dp2 ON dp1.channel_id = dp2.channel_id
|
|
|
|
|
JOIN channels c ON c.id = dp1.channel_id
|
|
|
|
|
WHERE dp1.user_id = ? AND dp2.user_id = ? AND c.type = 'dm' AND c.is_group = 0
|
|
|
|
|
ORDER BY dp1.channel_id ASC
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type FindDMChannelIDBetweenParams struct {
|
|
|
|
|
UserID int64 `json:"userId"`
|
|
|
|
|
UserID_2 int64 `json:"userId2"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The 1:1 DM channel between two users, if one exists. Mirrors the lookup
|
|
|
|
|
// inside GetOrCreateDMChannel (raw, transactional) without creating anything:
|
|
|
|
|
// the is_group clause keeps group DMs out, matching the block-enforcement
|
|
|
|
|
// boundary (blocks never gate group DMs). ORDER BY makes the row choice
|
|
|
|
|
// deterministic should duplicates ever exist.
|
|
|
|
|
func (q *Queries) FindDMChannelIDBetween(ctx context.Context, arg FindDMChannelIDBetweenParams) (int64, error) {
|
|
|
|
|
row := q.db.QueryRowContext(ctx, findDMChannelIDBetween, arg.UserID, arg.UserID_2)
|
|
|
|
|
var channel_id int64
|
|
|
|
|
err := row.Scan(&channel_id)
|
|
|
|
|
return channel_id, err
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-06 09:12:59 +02:00
|
|
|
const getDMParticipantIDs = `-- name: GetDMParticipantIDs :many
|
|
|
|
|
SELECT user_id FROM dm_participants WHERE channel_id = ?
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
func (q *Queries) GetDMParticipantIDs(ctx context.Context, channelID int64) ([]int64, error) {
|
|
|
|
|
rows, err := q.db.QueryContext(ctx, getDMParticipantIDs, channelID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
items := []int64{}
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var user_id int64
|
|
|
|
|
if err := rows.Scan(&user_id); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
items = append(items, user_id)
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Close(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return items, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-01 22:06:14 +02:00
|
|
|
const getDMParticipants = `-- 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
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type GetDMParticipantsRow struct {
|
|
|
|
|
ID int64 `json:"id"`
|
|
|
|
|
Username string `json:"username"`
|
|
|
|
|
DisplayName string `json:"displayName"`
|
|
|
|
|
Avatar string `json:"avatar"`
|
|
|
|
|
Status string `json:"status"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queries) GetDMParticipants(ctx context.Context, channelID int64) ([]GetDMParticipantsRow, error) {
|
|
|
|
|
rows, err := q.db.QueryContext(ctx, getDMParticipants, channelID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
items := []GetDMParticipantsRow{}
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var i GetDMParticipantsRow
|
|
|
|
|
if err := rows.Scan(
|
|
|
|
|
&i.ID,
|
|
|
|
|
&i.Username,
|
|
|
|
|
&i.DisplayName,
|
|
|
|
|
&i.Avatar,
|
|
|
|
|
&i.Status,
|
|
|
|
|
); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
items = append(items, i)
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Close(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return items, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const getDMParticipantsForUser = `-- 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
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type GetDMParticipantsForUserRow struct {
|
|
|
|
|
ChannelID int64 `json:"channelId"`
|
|
|
|
|
ID int64 `json:"id"`
|
|
|
|
|
Username string `json:"username"`
|
|
|
|
|
DisplayName string `json:"displayName"`
|
|
|
|
|
Avatar string `json:"avatar"`
|
|
|
|
|
Status string `json:"status"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
func (q *Queries) GetDMParticipantsForUser(ctx context.Context, userID int64) ([]GetDMParticipantsForUserRow, error) {
|
|
|
|
|
rows, err := q.db.QueryContext(ctx, getDMParticipantsForUser, userID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
items := []GetDMParticipantsForUserRow{}
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var i GetDMParticipantsForUserRow
|
|
|
|
|
if err := rows.Scan(
|
|
|
|
|
&i.ChannelID,
|
|
|
|
|
&i.ID,
|
|
|
|
|
&i.Username,
|
|
|
|
|
&i.DisplayName,
|
|
|
|
|
&i.Avatar,
|
|
|
|
|
&i.Status,
|
|
|
|
|
); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
items = append(items, i)
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Close(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return items, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-31 15:41:57 +02:00
|
|
|
const getUserDMChannelIDs = `-- name: GetUserDMChannelIDs :many
|
|
|
|
|
SELECT channel_id FROM dm_open_state WHERE user_id = ?
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
func (q *Queries) GetUserDMChannelIDs(ctx context.Context, userID int64) ([]int64, error) {
|
|
|
|
|
rows, err := q.db.QueryContext(ctx, getUserDMChannelIDs, userID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
items := []int64{}
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var channel_id int64
|
|
|
|
|
if err := rows.Scan(&channel_id); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
items = append(items, channel_id)
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Close(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return items, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-06 09:12:59 +02:00
|
|
|
const getUserDMChannels = `-- 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
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type GetUserDMChannelsRow struct {
|
2026-08-01 22:06:14 +02:00
|
|
|
ChannelID int64 `json:"channelId"`
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
IsGroup int64 `json:"isGroup"`
|
|
|
|
|
LastMessageID *int64 `json:"lastMessageId"`
|
|
|
|
|
LastMessage string `json:"lastMessage"`
|
|
|
|
|
LastMessageAt string `json:"lastMessageAt"`
|
|
|
|
|
UnreadCount int64 `json:"unreadCount"`
|
2026-04-06 09:12:59 +02:00
|
|
|
}
|
|
|
|
|
|
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.
|
|
|
|
|
func (q *Queries) GetUserDMChannels(ctx context.Context, userID int64) ([]GetUserDMChannelsRow, error) {
|
|
|
|
|
rows, err := q.db.QueryContext(ctx, getUserDMChannels, userID)
|
2026-04-06 09:12:59 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
defer rows.Close()
|
|
|
|
|
items := []GetUserDMChannelsRow{}
|
|
|
|
|
for rows.Next() {
|
|
|
|
|
var i GetUserDMChannelsRow
|
|
|
|
|
if err := rows.Scan(
|
|
|
|
|
&i.ChannelID,
|
2026-08-01 22:06:14 +02:00
|
|
|
&i.Name,
|
|
|
|
|
&i.IsGroup,
|
2026-04-06 09:12:59 +02:00
|
|
|
&i.LastMessageID,
|
|
|
|
|
&i.LastMessage,
|
|
|
|
|
&i.LastMessageAt,
|
|
|
|
|
&i.UnreadCount,
|
|
|
|
|
); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
items = append(items, i)
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Close(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
return items, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const isDMParticipant = `-- name: IsDMParticipant :one
|
|
|
|
|
SELECT user_id FROM dm_participants WHERE user_id = ? AND channel_id = ?
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type IsDMParticipantParams struct {
|
|
|
|
|
UserID int64 `json:"userId"`
|
|
|
|
|
ChannelID int64 `json:"channelId"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queries) IsDMParticipant(ctx context.Context, arg IsDMParticipantParams) (int64, error) {
|
|
|
|
|
row := q.db.QueryRowContext(ctx, isDMParticipant, arg.UserID, arg.ChannelID)
|
|
|
|
|
var user_id int64
|
|
|
|
|
err := row.Scan(&user_id)
|
|
|
|
|
return user_id, err
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-01 22:06:14 +02:00
|
|
|
const isGroupDM = `-- name: IsGroupDM :one
|
|
|
|
|
SELECT is_group FROM channels WHERE id = ? AND type = 'dm'
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
func (q *Queries) IsGroupDM(ctx context.Context, id int64) (int64, error) {
|
|
|
|
|
row := q.db.QueryRowContext(ctx, isGroupDM, id)
|
|
|
|
|
var is_group int64
|
|
|
|
|
err := row.Scan(&is_group)
|
|
|
|
|
return is_group, err
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-14 10:05:40 +02:00
|
|
|
const openDM = `-- name: OpenDM :execrows
|
2026-04-06 09:12:59 +02:00
|
|
|
INSERT OR IGNORE INTO dm_open_state (user_id, channel_id) VALUES (?, ?)
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type OpenDMParams struct {
|
|
|
|
|
UserID int64 `json:"userId"`
|
|
|
|
|
ChannelID int64 `json:"channelId"`
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-14 10:05:40 +02:00
|
|
|
func (q *Queries) OpenDM(ctx context.Context, arg OpenDMParams) (int64, error) {
|
|
|
|
|
result, err := q.db.ExecContext(ctx, openDM, arg.UserID, arg.ChannelID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
return result.RowsAffected()
|
2026-04-06 09:12:59 +02:00
|
|
|
}
|
2026-08-01 22:06:14 +02:00
|
|
|
|
|
|
|
|
const removeDMParticipant = `-- name: RemoveDMParticipant :exec
|
|
|
|
|
DELETE FROM dm_participants WHERE channel_id = ? AND user_id = ?
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type RemoveDMParticipantParams struct {
|
|
|
|
|
ChannelID int64 `json:"channelId"`
|
|
|
|
|
UserID int64 `json:"userId"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queries) RemoveDMParticipant(ctx context.Context, arg RemoveDMParticipantParams) error {
|
|
|
|
|
_, err := q.db.ExecContext(ctx, removeDMParticipant, arg.ChannelID, arg.UserID)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setDMChannelName = `-- name: SetDMChannelName :exec
|
|
|
|
|
UPDATE channels SET name = ? WHERE id = ? AND type = 'dm'
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
type SetDMChannelNameParams struct {
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
ID int64 `json:"id"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *Queries) SetDMChannelName(ctx context.Context, arg SetDMChannelNameParams) error {
|
|
|
|
|
_, err := q.db.ExecContext(ctx, setDMChannelName, arg.Name, arg.ID)
|
|
|
|
|
return err
|
|
|
|
|
}
|