mirror of
https://mau.dev/mautrix/go.git
synced 2026-03-14 14:25:53 +01:00
WIP: Media table for direct media metadata
This commit is contained in:
parent
376fa1f368
commit
34ef1356a8
4 changed files with 142 additions and 0 deletions
|
|
@ -34,6 +34,7 @@ type Database struct {
|
|||
UserPortal *UserPortalQuery
|
||||
BackfillTask *BackfillTaskQuery
|
||||
KV *KVQuery
|
||||
Media *MediaQuery
|
||||
}
|
||||
|
||||
type MetaMerger interface {
|
||||
|
|
@ -48,6 +49,7 @@ type MetaTypes struct {
|
|||
Message MetaTypeCreator
|
||||
Reaction MetaTypeCreator
|
||||
UserLogin MetaTypeCreator
|
||||
Media MetaTypeCreator
|
||||
}
|
||||
|
||||
type blankMeta struct{}
|
||||
|
|
@ -74,6 +76,9 @@ func New(bridgeID networkid.BridgeID, mt MetaTypes, db *dbutil.Database) *Databa
|
|||
if mt.UserLogin == nil {
|
||||
mt.UserLogin = blankMetaCreator
|
||||
}
|
||||
if mt.Media == nil {
|
||||
mt.Media = blankMetaCreator
|
||||
}
|
||||
db.UpgradeTable = upgrades.Table
|
||||
return &Database{
|
||||
Database: db,
|
||||
|
|
@ -141,6 +146,12 @@ func New(bridgeID networkid.BridgeID, mt MetaTypes, db *dbutil.Database) *Databa
|
|||
BridgeID: bridgeID,
|
||||
Database: db,
|
||||
},
|
||||
Media: &MediaQuery{
|
||||
BridgeID: bridgeID,
|
||||
QueryHelper: dbutil.MakeQueryHelper(db, func(_ *dbutil.QueryHelper[*Media]) *Media {
|
||||
return &Media{}
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
114
bridgev2/database/media.go
Normal file
114
bridgev2/database/media.go
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) 2025 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"
|
||||
"database/sql/driver"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/util/dbutil"
|
||||
|
||||
"maunium.net/go/mautrix/bridgev2/networkid"
|
||||
)
|
||||
|
||||
type MediaQuery struct {
|
||||
BridgeID networkid.BridgeID
|
||||
MetaType MetaTypeCreator
|
||||
*dbutil.QueryHelper[*Media]
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
BridgeID networkid.BridgeID
|
||||
ID networkid.MediaID
|
||||
|
||||
Metadata any
|
||||
}
|
||||
|
||||
var _ driver.Value = (sqlMediaID)(nil)
|
||||
var _ sql.Scanner = (sqlMediaID)(nil)
|
||||
|
||||
type sqlMediaID networkid.MediaID
|
||||
|
||||
func (id sqlMediaID) Scan(src any) (err error) {
|
||||
var s string
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
s = v
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("invalid sql type for media id: %T", v)
|
||||
}
|
||||
|
||||
id, err = base64.RawStdEncoding.DecodeString(s)
|
||||
return
|
||||
}
|
||||
|
||||
func (id sqlMediaID) Value() (driver.Value, error) {
|
||||
return base64.RawStdEncoding.EncodeToString(id), nil
|
||||
}
|
||||
|
||||
const (
|
||||
getMediaQuery = `
|
||||
SELECT bridge_id, id, metadata FROM media
|
||||
`
|
||||
insertMediaQuery = `
|
||||
INSERT INTO media (
|
||||
bridge_id, id, metadata
|
||||
)
|
||||
VALUES ($1, $2, $3)
|
||||
`
|
||||
updateMediaQuery = `
|
||||
UPDATE media SET metadata=$3
|
||||
WHERE bridge_id=$1 AND id=$2
|
||||
`
|
||||
deleteMediaQuery = `
|
||||
DELETE FROM media WHERE bridge_id=$1 AND id=$2
|
||||
`
|
||||
)
|
||||
|
||||
func (mq *MediaQuery) GetByID(ctx context.Context, mediaID networkid.MediaID) (*Media, error) {
|
||||
return mq.QueryOne(ctx, getMediaQuery, mq.BridgeID, sqlMediaID(mediaID))
|
||||
}
|
||||
|
||||
func (mq *MediaQuery) Insert(ctx context.Context, media *Media) (err error) {
|
||||
ensureBridgeIDMatches(&media.BridgeID, mq.BridgeID)
|
||||
_, err = mq.GetDB().Exec(ctx, insertMediaQuery, media.ensureHasMetadata(mq.MetaType).sqlVariables()...)
|
||||
return
|
||||
}
|
||||
|
||||
func (mq *MediaQuery) Update(ctx context.Context, media *Media) error {
|
||||
ensureBridgeIDMatches(&media.BridgeID, mq.BridgeID)
|
||||
return mq.Exec(ctx, updateMediaQuery, media.ensureHasMetadata(mq.MetaType).sqlVariables()...)
|
||||
}
|
||||
|
||||
func (mq *MediaQuery) Delete(ctx context.Context, mediaID networkid.MediaID) error {
|
||||
return mq.Exec(ctx, deleteMediaQuery, mq.BridgeID, sqlMediaID(mediaID))
|
||||
}
|
||||
|
||||
func (m *Media) Scan(row dbutil.Scannable) (*Media, error) {
|
||||
err := row.Scan(
|
||||
&m.BridgeID, (*sqlMediaID)(&m.ID), dbutil.JSON{Data: m.Metadata},
|
||||
)
|
||||
return m, err
|
||||
}
|
||||
|
||||
func (m *Media) ensureHasMetadata(metaType MetaTypeCreator) *Media {
|
||||
if m.Metadata == nil {
|
||||
m.Metadata = metaType()
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Media) sqlVariables() []any {
|
||||
return []any{
|
||||
m.BridgeID, sqlMediaID(m.ID), dbutil.JSON{Data: m.Metadata},
|
||||
}
|
||||
}
|
||||
|
|
@ -215,3 +215,11 @@ CREATE TABLE kv_store (
|
|||
|
||||
PRIMARY KEY (bridge_id, key)
|
||||
);
|
||||
|
||||
CREATE TABLE media (
|
||||
bridge_id TEXT NOT NULL,
|
||||
id TEXT NOT NULL,
|
||||
metadata jsonb NOT NULL,
|
||||
|
||||
PRIMARY KEY (bridge_id, id)
|
||||
);
|
||||
|
|
|
|||
9
bridgev2/database/upgrades/23-media.sql
Normal file
9
bridgev2/database/upgrades/23-media.sql
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
-- v23 (compatible with v9+): Add media table
|
||||
|
||||
CREATE TABLE media (
|
||||
bridge_id TEXT NOT NULL,
|
||||
id TEXT NOT NULL,
|
||||
metadata jsonb NOT NULL,
|
||||
|
||||
PRIMARY KEY (bridge_id, id)
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue