mirror of https://github.com/mautrix/go.git
103 lines
3.3 KiB
Go
103 lines
3.3 KiB
Go
// Copyright (c) 2024 Tulir Asokan
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package database
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
|
|
"go.mau.fi/util/dbutil"
|
|
|
|
"maunium.net/go/mautrix/bridgev2/networkid"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
// DisappearingType represents the type of a disappearing message timer.
|
|
type DisappearingType string
|
|
|
|
const (
|
|
DisappearingTypeNone DisappearingType = ""
|
|
DisappearingTypeAfterRead DisappearingType = "after_read"
|
|
DisappearingTypeAfterSend DisappearingType = "after_send"
|
|
)
|
|
|
|
// DisappearingSetting represents a disappearing message timer setting
|
|
// by combining a type with a timer and an optional start timestamp.
|
|
type DisappearingSetting struct {
|
|
Type DisappearingType
|
|
Timer time.Duration
|
|
DisappearAt time.Time
|
|
}
|
|
|
|
type DisappearingMessageQuery struct {
|
|
BridgeID networkid.BridgeID
|
|
*dbutil.QueryHelper[*DisappearingMessage]
|
|
}
|
|
|
|
type DisappearingMessage struct {
|
|
BridgeID networkid.BridgeID
|
|
RoomID id.RoomID
|
|
EventID id.EventID
|
|
DisappearingSetting
|
|
}
|
|
|
|
const (
|
|
upsertDisappearingMessageQuery = `
|
|
INSERT INTO disappearing_message (bridge_id, mx_room, mxid, type, timer, disappear_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
ON CONFLICT (bridge_id, mxid) DO UPDATE SET timer=excluded.timer, disappear_at=excluded.disappear_at
|
|
`
|
|
startDisappearingMessagesQuery = `
|
|
UPDATE disappearing_message
|
|
SET disappear_at=$1 + timer
|
|
WHERE bridge_id=$2 AND mx_room=$3 AND disappear_at IS NULL AND type='after_read'
|
|
RETURNING bridge_id, mx_room, mxid, type, timer, disappear_at
|
|
`
|
|
getUpcomingDisappearingMessagesQuery = `
|
|
SELECT bridge_id, mx_room, mxid, type, timer, disappear_at
|
|
FROM disappearing_message WHERE bridge_id = $1 AND disappear_at IS NOT NULL AND disappear_at < $2
|
|
ORDER BY disappear_at
|
|
`
|
|
deleteDisappearingMessageQuery = `
|
|
DELETE FROM disappearing_message WHERE bridge_id=$1 AND mxid=$2
|
|
`
|
|
)
|
|
|
|
func (dmq *DisappearingMessageQuery) Put(ctx context.Context, dm *DisappearingMessage) error {
|
|
ensureBridgeIDMatches(&dm.BridgeID, dmq.BridgeID)
|
|
return dmq.Exec(ctx, upsertDisappearingMessageQuery, dm.sqlVariables()...)
|
|
}
|
|
|
|
func (dmq *DisappearingMessageQuery) StartAll(ctx context.Context, roomID id.RoomID) ([]*DisappearingMessage, error) {
|
|
return dmq.QueryMany(ctx, startDisappearingMessagesQuery, time.Now().UnixNano(), dmq.BridgeID, roomID)
|
|
}
|
|
|
|
func (dmq *DisappearingMessageQuery) GetUpcoming(ctx context.Context, duration time.Duration) ([]*DisappearingMessage, error) {
|
|
return dmq.QueryMany(ctx, getUpcomingDisappearingMessagesQuery, dmq.BridgeID, time.Now().Add(duration).UnixNano())
|
|
}
|
|
|
|
func (dmq *DisappearingMessageQuery) Delete(ctx context.Context, eventID id.EventID) error {
|
|
return dmq.Exec(ctx, deleteDisappearingMessageQuery, dmq.BridgeID, eventID)
|
|
}
|
|
|
|
func (d *DisappearingMessage) Scan(row dbutil.Scannable) (*DisappearingMessage, error) {
|
|
var disappearAt sql.NullInt64
|
|
err := row.Scan(&d.BridgeID, &d.RoomID, &d.EventID, &d.Type, &d.Timer, &disappearAt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if disappearAt.Valid {
|
|
d.DisappearAt = time.Unix(0, disappearAt.Int64)
|
|
}
|
|
return d, nil
|
|
}
|
|
|
|
func (d *DisappearingMessage) sqlVariables() []any {
|
|
return []any{d.BridgeID, d.RoomID, d.EventID, d.Type, d.Timer, dbutil.ConvertedPtr(d.DisappearAt, time.Time.UnixNano)}
|
|
}
|