mirror of
https://github.com/tulir/mautrix-whatsapp
synced 2024-12-04 12:43:10 +01:00
legacymigrate: fix things
This commit is contained in:
parent
86ffca8a6b
commit
91fbf6f609
15 changed files with 311 additions and 38 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,10 +4,10 @@
|
|||
!.pre-commit-config.yaml
|
||||
!example-config.yaml
|
||||
|
||||
*.session
|
||||
*.json
|
||||
*.db
|
||||
*.log
|
||||
*.bak
|
||||
|
||||
/mautrix-whatsapp
|
||||
/start
|
||||
|
|
|
@ -2,8 +2,10 @@ package main
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"strings"
|
||||
|
||||
up "go.mau.fi/util/configupgrade"
|
||||
"go.mau.fi/util/dbutil/litestream"
|
||||
"maunium.net/go/mautrix/bridgev2/bridgeconfig"
|
||||
)
|
||||
|
||||
|
@ -26,9 +28,41 @@ ALTER TABLE "user" RENAME TO user_old;
|
|||
//go:embed legacymigrate.sql
|
||||
var legacyMigrateCopyData string
|
||||
|
||||
//lint:ignore U1000 - TODO use this function
|
||||
func init() {
|
||||
litestream.Functions["split_part"] = func(input, delimiter string, partNum int) string {
|
||||
// split_part is 1-indexed
|
||||
partNum++
|
||||
parts := strings.Split(input, delimiter)
|
||||
if len(parts) <= partNum {
|
||||
return ""
|
||||
}
|
||||
return parts[partNum]
|
||||
}
|
||||
}
|
||||
|
||||
func migrateLegacyConfig(helper up.Helper) {
|
||||
helper.Set(up.Str, "maunium.net/go/mautrix-whatsapp", "encryption", "pickle_key")
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Str, []string{"whatsapp", "os_name"}, []string{"network", "os_name"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Str, []string{"whatsapp", "browser_name"}, []string{"network", "browser_name"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Str, []string{"whatsapp", "proxy"}, []string{"network", "proxy"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Str, []string{"whatsapp", "get_proxy_url"}, []string{"network", "get_proxy_url"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"whatsapp", "proxy_only_login"}, []string{"network", "proxy_only_login"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Str, []string{"bridge", "displayname_template"}, []string{"network", "displayname_template"})
|
||||
// TODO other fields
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "call_start_notices"}, []string{"network", "call_start_notices"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "send_presence_on_typing"}, []string{"network", "send_presence_on_typing"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "enable_status_broadcast"}, []string{"network", "enable_status_broadcast"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "disable_status_broadcast_send"}, []string{"network", "disable_status_broadcast_send"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "mute_status_broadcast"}, []string{"network", "mute_status_broadcast"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Str, []string{"bridge", "status_broadcast_tag"}, []string{"network", "status_broadcast_tag"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "whatsapp_thumbnail"}, []string{"network", "whatsapp_thumbnail"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "url_previews"}, []string{"network", "url_previews"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "force_active_delivery_receipts"}, []string{"network", "force_active_delivery_receipts"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "history_sync", "request_full_sync"}, []string{"network", "history_sync", "request_full_sync"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Int, []string{"bridge", "history_sync", "full_sync_config", "days_limit"}, []string{"network", "history_sync", "full_sync_config", "days_limit"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Int, []string{"bridge", "history_sync", "full_sync_config", "size_limit_mb"}, []string{"network", "history_sync", "full_sync_config", "size_limit_mb"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Int, []string{"bridge", "history_sync", "full_sync_config", "storage_quota_mb"}, []string{"network", "history_sync", "full_sync_config", "storage_quota_mb"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Bool, []string{"bridge", "history_sync", "media_requests", "auto_request_media"}, []string{"network", "history_sync", "media_requests", "auto_request_media"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Str, []string{"bridge", "history_sync", "media_requests", "request_method"}, []string{"network", "history_sync", "media_requests", "request_method"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Int, []string{"bridge", "history_sync", "media_requests", "request_local_time"}, []string{"network", "history_sync", "media_requests", "request_local_time"})
|
||||
bridgeconfig.CopyToOtherLocation(helper, up.Int, []string{"bridge", "history_sync", "media_requests", "max_async_handle"}, []string{"network", "history_sync", "media_requests", "max_async_handle"})
|
||||
}
|
||||
|
|
|
@ -20,7 +20,8 @@ SELECT
|
|||
'phone_last_seen', phone_last_seen,
|
||||
'phone_last_pinged', phone_last_pinged,
|
||||
'timezone', timezone
|
||||
) -- metadata
|
||||
), -- metadata
|
||||
'{}' -- remote_profile
|
||||
FROM user_old
|
||||
WHERE username<>'' AND device<>0;
|
||||
|
||||
|
@ -51,6 +52,9 @@ SELECT
|
|||
) -- metadata
|
||||
FROM puppet_old;
|
||||
|
||||
INSERT INTO ghost (bridge_id, id, name, avatar_id, avatar_hash, avatar_mxc, name_set, avatar_set, contact_info_set, is_bot, identifiers, metadata)
|
||||
VALUES ('', '', '', '', '', '', false, false, false, false, '[]', '{}');
|
||||
|
||||
INSERT INTO portal (
|
||||
bridge_id, id, receiver, mxid, parent_id, parent_receiver, relay_bridge_id, relay_login_id, other_user_id,
|
||||
name, topic, avatar_id, avatar_hash, avatar_mxc, name_set, avatar_set, topic_set,
|
||||
|
@ -98,21 +102,35 @@ SELECT
|
|||
last_read_ts * 1000000000 -- last_read TODO check multiplier
|
||||
FROM user_portal_old;
|
||||
|
||||
ALTER TABLE message_old ADD COLUMN combined_id TEXT;
|
||||
UPDATE message_old SET combined_id = chat_jid || ':' || (
|
||||
CASE WHEN sender LIKE '%:%@s.whatsapp.net'
|
||||
THEN (split_part(replace(sender, '@s.whatsapp.net', ''), ':', 1) || '@s.whatsapp.net')
|
||||
ELSE sender
|
||||
END
|
||||
) || ':' || jid;
|
||||
|
||||
INSERT INTO message (
|
||||
bridge_id, id, part_id, mxid, room_id, room_receiver, sender_id, sender_mxid, timestamp, edit_count, metadata
|
||||
)
|
||||
SELECT
|
||||
'', -- bridge_id
|
||||
jid, -- id FIXME requires prefix
|
||||
combined_id, -- id
|
||||
'', -- part_id
|
||||
mxid,
|
||||
chat_jid, -- room_id
|
||||
CASE WHEN chat_receiver LIKE '%@s.whatsapp.net' THEN chat_receiver ELSE '' END, -- room_receiver
|
||||
sender, -- sender_id
|
||||
CASE WHEN sender=chat_jid THEN '' ELSE split_part(replace(sender, '@s.whatsapp.net', ''), ':', 1) END, -- sender_id
|
||||
sender_mxid, -- sender_mxid
|
||||
timestamp * 1000000000, -- timestamp TODO check multiplier
|
||||
0, -- edit_count
|
||||
'{}' -- metadata
|
||||
-- only: postgres
|
||||
jsonb_build_object
|
||||
-- only: sqlite (line commented)
|
||||
-- json_object
|
||||
(
|
||||
'sender_device_id', CAST(nullif(split_part(replace(sender, '@s.whatsapp.net', ''), ':', 2), '') AS INTEGER)
|
||||
) -- metadata
|
||||
FROM message_old;
|
||||
|
||||
INSERT INTO reaction (
|
||||
|
@ -120,17 +138,27 @@ INSERT INTO reaction (
|
|||
)
|
||||
SELECT
|
||||
'', -- bridge_id
|
||||
target_jid, -- message_id FIXME requires prefix
|
||||
message_old.combined_id, -- message_id
|
||||
'', -- message_part_id
|
||||
sender, -- sender_id
|
||||
replace(reaction_old.sender, '@s.whatsapp.net', ''), -- sender_id
|
||||
'', -- emoji_id
|
||||
chat_jid, -- room_id
|
||||
CASE WHEN chat_receiver LIKE '%@s.whatsapp.net' THEN chat_receiver ELSE '' END, -- room_receiver
|
||||
mxid,
|
||||
reaction_old.chat_jid, -- room_id
|
||||
CASE WHEN reaction_old.chat_receiver LIKE '%@s.whatsapp.net' THEN reaction_old.chat_receiver ELSE '' END, -- room_receiver
|
||||
reaction_old.mxid,
|
||||
0, -- timestamp
|
||||
'', -- emoji
|
||||
'{}' -- metadata
|
||||
FROM reaction_old;
|
||||
-- only: postgres
|
||||
jsonb_build_object
|
||||
-- only: sqlite (line commented)
|
||||
-- json_object
|
||||
(
|
||||
'sender_device_id', CAST(nullif(split_part(replace(reaction_old.sender, '@s.whatsapp.net', ''), ':', 2), '') AS INTEGER)
|
||||
) -- metadata
|
||||
FROM reaction_old
|
||||
LEFT JOIN message_old
|
||||
ON reaction_old.chat_jid = message_old.chat_jid
|
||||
AND reaction_old.chat_receiver = message_old.chat_receiver
|
||||
AND reaction_old.target_jid = message_old.jid;
|
||||
|
||||
INSERT INTO disappearing_message (bridge_id, mx_room, mxid, type, timer, disappear_at)
|
||||
SELECT
|
||||
|
@ -152,7 +180,7 @@ SELECT
|
|||
CASE WHEN portal_receiver LIKE '%@s.whatsapp.net' THEN portal_receiver ELSE '' END, -- portal_receiver
|
||||
(SELECT id FROM user_login WHERE user_login.user_mxid=backfill_queue_old.user_mxid), -- user_login_id
|
||||
COUNT(*), -- batch_count
|
||||
COUNT(*) == COUNT(completed_at), -- is_done
|
||||
COUNT(*) = COUNT(completed_at), -- is_done
|
||||
'', -- cursor
|
||||
'', -- oldest_message_id
|
||||
-- only: postgres
|
||||
|
@ -165,14 +193,81 @@ FROM backfill_queue_old
|
|||
WHERE type IN (0, 200)
|
||||
GROUP BY user_mxid, portal_jid, portal_receiver;
|
||||
|
||||
INSERT INTO whatsapp_poll_option_id (bridge_id, msg_mxid, opt_id, opt_hash)
|
||||
SELECT '', msg_mxid, opt_id, opt_hash
|
||||
FROM poll_option_id_old;
|
||||
|
||||
INSERT INTO whatsapp_history_sync_conversation (
|
||||
bridge_id, user_login_id, chat_jid, last_message_timestamp, archived, pinned, mute_end_time,
|
||||
end_of_history_transfer_type, ephemeral_expiration, ephemeral_setting_timestamp, marked_as_unread, unread_count
|
||||
)
|
||||
SELECT
|
||||
'',
|
||||
user_login.id,
|
||||
portal_jid,
|
||||
-- only: postgres
|
||||
CAST(EXTRACT(EPOCH FROM last_message_timestamp) AS BIGINT),
|
||||
-- only: sqlite (line commented)
|
||||
-- unixepoch(last_message_timestamp),
|
||||
archived,
|
||||
CASE WHEN pinned > 0 THEN true ELSE false END,
|
||||
-- only: postgres
|
||||
CAST(EXTRACT(EPOCH FROM mute_end_time) AS BIGINT),
|
||||
-- only: sqlite (line commented)
|
||||
-- unixepoch(mute_end_time),
|
||||
end_of_history_transfer_type,
|
||||
ephemeral_expiration,
|
||||
0,
|
||||
marked_as_unread,
|
||||
unread_count
|
||||
FROM history_sync_conversation_old
|
||||
LEFT JOIN user_login ON user_login.user_mxid = history_sync_conversation_old.user_mxid
|
||||
WHERE user_login.id IS NOT NULL;
|
||||
|
||||
INSERT INTO whatsapp_history_sync_message (
|
||||
bridge_id, user_login_id, chat_jid, message_id, timestamp, data, inserted_time
|
||||
)
|
||||
SELECT
|
||||
'',
|
||||
user_login.id,
|
||||
conversation_id,
|
||||
message_id,
|
||||
-- only: postgres
|
||||
CAST(EXTRACT(EPOCH FROM timestamp) AS BIGINT),
|
||||
-- only: sqlite (line commented)
|
||||
-- unixepoch(timestamp),
|
||||
data,
|
||||
-- only: postgres
|
||||
CAST(EXTRACT(EPOCH FROM inserted_time) AS BIGINT)
|
||||
-- only: sqlite (line commented)
|
||||
-- unixepoch(inserted_time)
|
||||
FROM history_sync_message_old
|
||||
LEFT JOIN user_login ON user_login.user_mxid = history_sync_message_old.user_mxid
|
||||
WHERE user_login.id IS NOT NULL;
|
||||
|
||||
INSERT INTO whatsapp_media_backfill_request (
|
||||
bridge_id, user_login_id, portal_id, portal_receiver, event_id, media_key, status, error
|
||||
)
|
||||
SELECT
|
||||
'',
|
||||
user_login.id,
|
||||
portal_jid,
|
||||
CASE WHEN portal_receiver LIKE '%@s.whatsapp.net' THEN portal_receiver ELSE '' END,
|
||||
event_id,
|
||||
media_key,
|
||||
status,
|
||||
error
|
||||
FROM media_backfill_requests_old
|
||||
LEFT JOIN user_login ON user_login.user_mxid = media_backfill_requests_old.user_mxid
|
||||
WHERE user_login.id IS NOT NULL;
|
||||
|
||||
DROP TABLE backfill_queue_old;
|
||||
DROP TABLE backfill_state_old;
|
||||
DROP TABLE disappearing_message_old;
|
||||
-- TODO migrate these tables
|
||||
-- DROP TABLE history_sync_message_old;
|
||||
-- DROP TABLE history_sync_conversation_old;
|
||||
-- DROP TABLE media_backfill_requests_old;
|
||||
-- DROP TABLE poll_option_id_old;
|
||||
DROP TABLE history_sync_message_old;
|
||||
DROP TABLE history_sync_conversation_old;
|
||||
DROP TABLE media_backfill_requests_old;
|
||||
DROP TABLE poll_option_id_old;
|
||||
DROP TABLE user_portal_old;
|
||||
DROP TABLE reaction_old;
|
||||
DROP TABLE message_old;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"maunium.net/go/mautrix/bridgev2/bridgeconfig"
|
||||
"maunium.net/go/mautrix/bridgev2/matrix/mxmain"
|
||||
|
||||
"maunium.net/go/mautrix-whatsapp/pkg/connector"
|
||||
"maunium.net/go/mautrix-whatsapp/pkg/connector/wadb/upgrades"
|
||||
)
|
||||
|
||||
// Information to find out exactly which commit the bridge was built from.
|
||||
|
@ -24,12 +26,16 @@ var m = mxmain.BridgeMain{
|
|||
}
|
||||
|
||||
func main() {
|
||||
bridgeconfig.HackyMigrateLegacyNetworkConfig = migrateLegacyConfig
|
||||
m.PostInit = func() {
|
||||
m.CheckLegacyDB(
|
||||
57,
|
||||
"v0.8.6",
|
||||
"v0.11.0",
|
||||
m.LegacyMigrateSimple(legacyMigrateRenameTables, legacyMigrateCopyData, 16),
|
||||
m.LegacyMigrateWithAnotherUpgrader(
|
||||
legacyMigrateRenameTables, legacyMigrateCopyData, 17,
|
||||
upgrades.Table, "whatsapp_version", 1,
|
||||
),
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -20,7 +20,7 @@ require (
|
|||
golang.org/x/sync v0.8.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
maunium.net/go/mautrix v0.20.1-0.20240906145130-6b055b1475bd
|
||||
maunium.net/go/mautrix v0.20.1-0.20240910112932-ffdb1d575e5f
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
4
go.sum
4
go.sum
|
@ -114,5 +114,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
|
||||
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
||||
maunium.net/go/mautrix v0.20.1-0.20240906145130-6b055b1475bd h1:gfiJD2cPS9iUek1UI+DOUn08zogF4kmu7XYfBqSrAU4=
|
||||
maunium.net/go/mautrix v0.20.1-0.20240906145130-6b055b1475bd/go.mod h1:l6nYvD5/FMSrAZ/IP1AqJV0b47SRl/0uQNRiy4CcSVk=
|
||||
maunium.net/go/mautrix v0.20.1-0.20240910112932-ffdb1d575e5f h1:T4K6V2Ige2mshH7FW69xLep23GBrW7xS1sxomaKe1Hg=
|
||||
maunium.net/go/mautrix v0.20.1-0.20240910112932-ffdb1d575e5f/go.mod h1:l6nYvD5/FMSrAZ/IP1AqJV0b47SRl/0uQNRiy4CcSVk=
|
||||
|
|
|
@ -79,8 +79,8 @@ func upgradeConfig(helper up.Helper) {
|
|||
helper.Copy(up.Str, "os_name")
|
||||
helper.Copy(up.Str, "browser_name")
|
||||
|
||||
helper.Copy(up.Str, "proxy")
|
||||
helper.Copy(up.Str, "get_proxy_url")
|
||||
helper.Copy(up.Str|up.Null, "proxy")
|
||||
helper.Copy(up.Str|up.Null, "get_proxy_url")
|
||||
helper.Copy(up.Bool, "proxy_only_login")
|
||||
|
||||
helper.Copy(up.Str, "displayname_template")
|
||||
|
@ -95,9 +95,9 @@ func upgradeConfig(helper up.Helper) {
|
|||
helper.Copy(up.Bool, "url_previews")
|
||||
|
||||
helper.Copy(up.Bool, "history_sync", "request_full_sync")
|
||||
helper.Copy(up.Int, "history_sync", "full_sync_config", "days_limit")
|
||||
helper.Copy(up.Int, "history_sync", "full_sync_config", "size_mb_limit")
|
||||
helper.Copy(up.Int, "history_sync", "full_sync_config", "storage_quota_mb")
|
||||
helper.Copy(up.Int|up.Null, "history_sync", "full_sync_config", "days_limit")
|
||||
helper.Copy(up.Int|up.Null, "history_sync", "full_sync_config", "size_mb_limit")
|
||||
helper.Copy(up.Int|up.Null, "history_sync", "full_sync_config", "storage_quota_mb")
|
||||
helper.Copy(up.Bool, "history_sync", "media_requests", "auto_request_media")
|
||||
helper.Copy(up.Str, "history_sync", "media_requests", "request_method")
|
||||
helper.Copy(up.Int, "history_sync", "media_requests", "request_local_time")
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"google.golang.org/protobuf/proto"
|
||||
"maunium.net/go/mautrix/bridgev2"
|
||||
|
||||
"maunium.net/go/mautrix-whatsapp/pkg/connector/wadb"
|
||||
"maunium.net/go/mautrix-whatsapp/pkg/msgconv"
|
||||
"maunium.net/go/mautrix-whatsapp/pkg/waid"
|
||||
)
|
||||
|
@ -21,6 +22,7 @@ type WhatsAppConnector struct {
|
|||
Config Config
|
||||
DeviceStore *sqlstore.Container
|
||||
MsgConv *msgconv.MessageConverter
|
||||
DB *wadb.Database
|
||||
}
|
||||
|
||||
var _ bridgev2.NetworkConnector = (*WhatsAppConnector)(nil)
|
||||
|
@ -44,6 +46,7 @@ func (wa *WhatsAppConnector) GetName() bridgev2.BridgeName {
|
|||
func (wa *WhatsAppConnector) Init(bridge *bridgev2.Bridge) {
|
||||
wa.Bridge = bridge
|
||||
wa.MsgConv = msgconv.New(bridge)
|
||||
wa.DB = wadb.New(bridge.DB.Database, bridge.Log.With().Str("db_section", "whatsapp").Logger())
|
||||
|
||||
wa.DeviceStore = sqlstore.NewWithDB(
|
||||
bridge.DB.RawDB,
|
||||
|
@ -66,11 +69,15 @@ func (wa *WhatsAppConnector) Init(bridge *bridgev2.Bridge) {
|
|||
}
|
||||
}
|
||||
|
||||
func (wa *WhatsAppConnector) Start(_ context.Context) error {
|
||||
func (wa *WhatsAppConnector) Start(ctx context.Context) error {
|
||||
err := wa.DeviceStore.Upgrade()
|
||||
if err != nil {
|
||||
return bridgev2.DBUpgradeError{Err: err, Section: "whatsmeow"}
|
||||
}
|
||||
err = wa.DB.Upgrade(ctx)
|
||||
if err != nil {
|
||||
return bridgev2.DBUpgradeError{Err: err, Section: "whatsapp"}
|
||||
}
|
||||
|
||||
ver, err := whatsmeow.GetLatestVersion(nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -10,8 +10,12 @@ func (wa *WhatsAppConnector) GetDBMetaTypes() database.MetaTypes {
|
|||
Ghost: func() any {
|
||||
return &GhostMetadata{}
|
||||
},
|
||||
Message: nil,
|
||||
Reaction: nil,
|
||||
Message: func() any {
|
||||
return &MessageMetadata{}
|
||||
},
|
||||
Reaction: func() any {
|
||||
return &ReactionMetadata{}
|
||||
},
|
||||
Portal: func() any {
|
||||
return &PortalMetadata{}
|
||||
},
|
||||
|
@ -26,6 +30,14 @@ type UserLoginMetadata struct {
|
|||
//TODO: Add phone last ping/seen
|
||||
}
|
||||
|
||||
type MessageMetadata struct {
|
||||
SenderDeviceID uint16 `json:"sender_device_id,omitempty"`
|
||||
}
|
||||
|
||||
type ReactionMetadata struct {
|
||||
SenderDeviceID uint16 `json:"sender_device_id,omitempty"`
|
||||
}
|
||||
|
||||
type PortalMetadata struct {
|
||||
DisappearingTimerSetAt int64 `json:"disappearing_timer_set_at,omitempty"`
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ var (
|
|||
_ bridgev2.RemoteEventThatMayCreatePortal = (*WAMessageEvent)(nil)
|
||||
_ bridgev2.RemoteReaction = (*WAMessageEvent)(nil)
|
||||
_ bridgev2.RemoteReactionRemove = (*WAMessageEvent)(nil)
|
||||
_ bridgev2.RemoteReactionWithMeta = (*WAMessageEvent)(nil)
|
||||
_ bridgev2.RemoteEdit = (*WAMessageEvent)(nil)
|
||||
_ bridgev2.RemoteMessageRemove = (*WAMessageEvent)(nil)
|
||||
)
|
||||
|
@ -77,6 +78,12 @@ func (evt *WAMessageEvent) GetReactionEmoji() (string, networkid.EmojiID) {
|
|||
return evt.Message.Message.GetReactionMessage().GetText(), ""
|
||||
}
|
||||
|
||||
func (evt *WAMessageEvent) GetReactionDBMetadata() any {
|
||||
return &ReactionMetadata{
|
||||
SenderDeviceID: evt.Info.Sender.Device,
|
||||
}
|
||||
}
|
||||
|
||||
func (evt *WAMessageEvent) GetRemovedEmojiID() networkid.EmojiID {
|
||||
return ""
|
||||
}
|
||||
|
@ -129,5 +136,11 @@ func (evt *WAMessageEvent) GetTransactionID() networkid.TransactionID {
|
|||
}
|
||||
|
||||
func (evt *WAMessageEvent) ConvertMessage(ctx context.Context, portal *bridgev2.Portal, intent bridgev2.MatrixAPI) (*bridgev2.ConvertedMessage, error) {
|
||||
return evt.wa.Main.MsgConv.ToMatrix(ctx, portal, evt.wa.Client, intent, evt.Message.Message), nil
|
||||
converted := evt.wa.Main.MsgConv.ToMatrix(ctx, portal, evt.wa.Client, intent, evt.Message.Message)
|
||||
for _, part := range converted.Parts {
|
||||
part.DBMetadata = &MessageMetadata{
|
||||
SenderDeviceID: evt.Info.Sender.Device,
|
||||
}
|
||||
}
|
||||
return converted, nil
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ proxy_only_login: false
|
|||
# {{.PushName}} - nickname set by the WhatsApp user
|
||||
# {{.BusinessName}} - validated WhatsApp business name
|
||||
# {{.Phone}} - phone number (international format)
|
||||
# {{.FullName}} - Name you set in the contacts list
|
||||
# {{.FullName}} - Name you set in the contacts list
|
||||
displayname_template: "{{or .FullName .BusinessName .PushName .Phone}} (WA)"
|
||||
|
||||
# Should incoming calls send a message to the Matrix room?
|
||||
|
|
|
@ -47,8 +47,11 @@ func (wa *WhatsAppClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2
|
|||
return &bridgev2.MatrixMessageResponse{
|
||||
DB: &database.Message{
|
||||
ID: wrappedMsgID,
|
||||
SenderID: networkid.UserID(wa.UserLogin.ID),
|
||||
SenderID: waid.MakeUserID(wa.JID),
|
||||
Timestamp: resp.Timestamp,
|
||||
Metadata: &MessageMetadata{
|
||||
SenderDeviceID: wa.JID.Device,
|
||||
},
|
||||
},
|
||||
RemovePending: networkid.TransactionID(wrappedMsgID),
|
||||
}, nil
|
||||
|
@ -56,7 +59,7 @@ func (wa *WhatsAppClient) HandleMatrixMessage(ctx context.Context, msg *bridgev2
|
|||
|
||||
func (wa *WhatsAppClient) PreHandleMatrixReaction(_ context.Context, msg *bridgev2.MatrixReaction) (bridgev2.MatrixReactionPreResponse, error) {
|
||||
return bridgev2.MatrixReactionPreResponse{
|
||||
SenderID: networkid.UserID(wa.UserLogin.ID),
|
||||
SenderID: waid.MakeUserID(wa.JID),
|
||||
Emoji: variationselector.Remove(msg.Content.RelatesTo.Key),
|
||||
MaxReactions: 1,
|
||||
}, nil
|
||||
|
@ -82,7 +85,11 @@ func (wa *WhatsAppClient) HandleMatrixReaction(ctx context.Context, msg *bridgev
|
|||
|
||||
resp, err := wa.Client.SendMessage(ctx, portalJID, reactionMsg)
|
||||
zerolog.Ctx(ctx).Trace().Any("response", resp).Msg("WhatsApp reaction response")
|
||||
return nil, err
|
||||
return &database.Reaction{
|
||||
Metadata: &ReactionMetadata{
|
||||
SenderDeviceID: wa.JID.Device,
|
||||
},
|
||||
}, err
|
||||
}
|
||||
|
||||
func (wa *WhatsAppClient) HandleMatrixReactionRemove(ctx context.Context, msg *bridgev2.MatrixReactionRemove) error {
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
package wadb
|
||||
|
||||
// TODO: ADD POLL AND HISTORYSYNC AND MEDIABACKFILLREQUEST DBs
|
||||
import (
|
||||
"github.com/rs/zerolog"
|
||||
"go.mau.fi/util/dbutil"
|
||||
|
||||
"maunium.net/go/mautrix-whatsapp/pkg/connector/wadb/upgrades"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
*dbutil.Database
|
||||
}
|
||||
|
||||
func New(db *dbutil.Database, log zerolog.Logger) *Database {
|
||||
db = db.Child("whatsapp_version", upgrades.Table, dbutil.ZeroLogger(log))
|
||||
return &Database{
|
||||
Database: db,
|
||||
}
|
||||
}
|
||||
|
|
67
pkg/connector/wadb/upgrades/00-latest-schema.sql
Normal file
67
pkg/connector/wadb/upgrades/00-latest-schema.sql
Normal file
|
@ -0,0 +1,67 @@
|
|||
-- v0 -> v1 (compatible with v1+): Latest revision
|
||||
|
||||
CREATE TABLE whatsapp_poll_option_id (
|
||||
bridge_id TEXT,
|
||||
msg_mxid TEXT,
|
||||
opt_id TEXT,
|
||||
opt_hash bytea CHECK ( length(opt_hash) = 32 ),
|
||||
|
||||
PRIMARY KEY (bridge_id, msg_mxid, opt_id),
|
||||
CONSTRAINT whatsapp_poll_option_unique_hash UNIQUE (bridge_id, msg_mxid, opt_hash),
|
||||
CONSTRAINT message_mxid_fkey FOREIGN KEY (bridge_id, msg_mxid)
|
||||
REFERENCES message(bridge_id, mxid) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE whatsapp_history_sync_conversation (
|
||||
bridge_id TEXT,
|
||||
user_login_id TEXT,
|
||||
chat_jid TEXT,
|
||||
|
||||
last_message_timestamp BIGINT,
|
||||
archived BOOLEAN,
|
||||
pinned BOOLEAN,
|
||||
mute_end_time BIGINT,
|
||||
end_of_history_transfer_type INTEGER,
|
||||
ephemeral_expiration INTEGER,
|
||||
ephemeral_setting_timestamp BIGINT,
|
||||
marked_as_unread BOOLEAN,
|
||||
unread_count INTEGER,
|
||||
|
||||
PRIMARY KEY (bridge_id, user_login_id, chat_jid),
|
||||
CONSTRAINT whatsapp_history_sync_conversation_user_login_fkey FOREIGN KEY (bridge_id, user_login_id)
|
||||
REFERENCES user_login(bridge_id, id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE whatsapp_history_sync_message (
|
||||
bridge_id TEXT,
|
||||
user_login_id TEXT,
|
||||
chat_jid TEXT,
|
||||
message_id TEXT,
|
||||
timestamp BIGINT,
|
||||
data bytea,
|
||||
inserted_time BIGINT,
|
||||
|
||||
PRIMARY KEY (bridge_id, user_login_id, chat_jid, message_id),
|
||||
CONSTRAINT whatsapp_history_sync_message_user_login_fkey FOREIGN KEY (bridge_id, user_login_id)
|
||||
REFERENCES user_login(bridge_id, id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
CONSTRAINT whatsapp_history_sync_message_conversation_fkey FOREIGN KEY (bridge_id, user_login_id, chat_jid)
|
||||
REFERENCES whatsapp_history_sync_conversation(bridge_id, user_login_id, chat_jid) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE whatsapp_media_backfill_request (
|
||||
bridge_id TEXT,
|
||||
user_login_id TEXT,
|
||||
portal_id TEXT,
|
||||
portal_receiver TEXT,
|
||||
|
||||
event_id TEXT,
|
||||
media_key bytea,
|
||||
status INTEGER,
|
||||
error TEXT,
|
||||
|
||||
PRIMARY KEY (bridge_id, user_login_id, portal_id, portal_receiver, event_id),
|
||||
CONSTRAINT whatsapp_media_backfill_request_user_login_fkey FOREIGN KEY (bridge_id, user_login_id)
|
||||
REFERENCES user_login(bridge_id, id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
CONSTRAINT whatsapp_media_backfill_request_portal_fkey FOREIGN KEY (bridge_id, portal_id, portal_receiver)
|
||||
REFERENCES portal(bridge_id, id, receiver) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
);
|
16
pkg/connector/wadb/upgrades/upgrades.go
Normal file
16
pkg/connector/wadb/upgrades/upgrades.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package upgrades
|
||||
|
||||
import (
|
||||
"embed"
|
||||
|
||||
"go.mau.fi/util/dbutil"
|
||||
)
|
||||
|
||||
var Table dbutil.UpgradeTable
|
||||
|
||||
//go:embed *.sql
|
||||
var rawUpgrades embed.FS
|
||||
|
||||
func init() {
|
||||
Table.RegisterFS(rawUpgrades)
|
||||
}
|
Loading…
Reference in a new issue