Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion pkg/connector/chatinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"go.mau.fi/util/jsontime"
"go.mau.fi/util/ptr"
"go.mau.fi/whatsmeow/types"
"maunium.net/go/mautrix/bridgev2"
Expand Down Expand Up @@ -107,7 +108,7 @@ func (m *MetaClient) wrapWAGroupInfo(chatInfo *types.GroupInfo) *bridgev2.ChatIn
Type: ptr.Ptr(database.RoomTypeDefault),
Disappear: &disappear,
CanBackfill: false,
ExtraUpdates: updateServerAndThreadType(chatInfo.JID, table.ENCRYPTED_OVER_WA_GROUP),
ExtraUpdates: bridgev2.MergeExtraUpdaters(updateServerAndThreadType(chatInfo.JID, table.ENCRYPTED_OVER_WA_GROUP), updatePortalSyncMeta),
}
}

Expand All @@ -126,6 +127,12 @@ func updateServerAndThreadType(jid types.JID, threadType table.ThreadType) func(
}
}

func updatePortalSyncMeta(ctx context.Context, portal *bridgev2.Portal) bool {
meta := portal.Metadata.(*metaid.PortalMetadata)
meta.LastSync = jsontime.UnixNow()
return true
}

func (m *MetaClient) makeMinimalChatInfo(threadID int64, threadType table.ThreadType) *bridgev2.ChatInfo {
selfEvtSender := m.selfEventSender()
members := &bridgev2.ChatMemberList{
Expand Down
54 changes: 46 additions & 8 deletions pkg/connector/handlematrix.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/bridgev2/database"
"maunium.net/go/mautrix/bridgev2/networkid"
"maunium.net/go/mautrix/bridgev2/simplevent"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"

Expand Down Expand Up @@ -564,11 +565,51 @@ func (m *MetaClient) HandleMatrixReadReceipt(ctx context.Context, receipt *bridg
return nil
}

// Note: the handling of typing notifications for facebook E2EE is
// very similar to the handling of typing notifications in the
// whatsapp bridge, because they both use the same API.
// When to trigger user/group refresh on chat view
var ViewChatUserInfoRefreshInterval = 5 * time.Minute
var ViewChatGroupInfoRefreshInterval = 24 * time.Hour

func (m *MetaClient) HandleMatrixViewingChat(ctx context.Context, msg *bridgev2.MatrixViewingChat) error {
if msg.Portal == nil {
return nil
}

// Sync the other users ghost in DMs
if msg.Portal.OtherUserID != "" {
ghost, err := m.Main.Bridge.GetExistingGhostByID(ctx, msg.Portal.OtherUserID)
if err != nil {
return fmt.Errorf("failed to get ghost for sync: %w", err)
} else if ghost == nil {
zerolog.Ctx(ctx).Warn().
Str("other_user_id", string(msg.Portal.OtherUserID)).
Msg("No ghost found for other user in portal")
} else {
meta := ghost.Metadata.(*metaid.GhostMetadata)
if meta.ProfileFetchedAt.Time.Add(ViewChatUserInfoRefreshInterval).Before(time.Now()) {
info, err := m.GetUserInfo(ctx, ghost)
if err != nil {
return fmt.Errorf("failed to get user info: %w", err)
}
ghost.UpdateInfo(ctx, info)
}
}
}

// always resync the portal if its stale
portalMeta := msg.Portal.Metadata.(*metaid.PortalMetadata)
if portalMeta.LastSync.Add(ViewChatGroupInfoRefreshInterval).Before(time.Now()) {
m.UserLogin.QueueRemoteEvent(&simplevent.ChatResync{
EventMeta: simplevent.EventMeta{
Type: bridgev2.RemoteEventChatResync,
PortalKey: msg.Portal.PortalKey,
},
GetChatInfoFunc: m.GetChatInfo,
})
}

// Note: the handling of typing notifications for facebook E2EE is
// very similar to the handling of typing notifications in the
// whatsapp bridge, because they both use the same API.
if m.E2EEClient == nil {
return nil
}
Expand All @@ -578,11 +619,8 @@ func (m *MetaClient) HandleMatrixViewingChat(ctx context.Context, msg *bridgev2.
// therefore we need to set online status for typing
// notifications to work properly.
presence := waTypes.PresenceUnavailable
if msg.Portal != nil {
portalMeta := msg.Portal.Metadata.(*metaid.PortalMetadata)
if portalMeta.ThreadType.IsWhatsApp() {
presence = waTypes.PresenceAvailable
}
if portalMeta.ThreadType.IsWhatsApp() {
presence = waTypes.PresenceAvailable
}

if m.waLastPresence != presence {
Expand Down
2 changes: 2 additions & 0 deletions pkg/connector/userinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net/url"
"path"
"time"

"github.com/rs/zerolog"
"go.mau.fi/util/ptr"
Expand Down Expand Up @@ -118,6 +119,7 @@ func (m *MetaClient) wrapUserInfo(info types.UserInfo) *bridgev2.UserInfo {
IsBot: ptr.Ptr(info.GetFBID() == MetaAIInstagramID || info.GetFBID() == MetaAIMessengerID), // TODO do this in a less hardcoded way?
ExtraUpdates: func(ctx context.Context, ghost *bridgev2.Ghost) (changed bool) {
meta := ghost.Metadata.(*metaid.GhostMetadata)
meta.ProfileFetchedAt.Time = time.Now()
if m.LoginMeta.Platform == types.Instagram && meta.Username != info.GetUsername() {
meta.Username = info.GetUsername()
changed = true
Expand Down
7 changes: 6 additions & 1 deletion pkg/metaid/dbmeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync/atomic"

"go.mau.fi/util/exerrors"
"go.mau.fi/util/jsontime"
"go.mau.fi/util/random"
waTypes "go.mau.fi/whatsmeow/types"
"maunium.net/go/mautrix/bridgev2/networkid"
Expand All @@ -22,7 +23,8 @@ type MessageMetadata struct {
}

type GhostMetadata struct {
Username string `json:"username,omitempty"`
Username string `json:"username,omitempty"`
ProfileFetchedAt jsontime.UnixMilli `json:"profile_fetched_at"`
}

type UserLoginMetadata struct {
Expand Down Expand Up @@ -55,6 +57,9 @@ type PortalMetadata struct {
EphemeralSettingTimestamp int64 `json:"ephemeral_setting_timestamp,omitempty"`

FetchAttempted atomic.Bool `json:"-"`

// Lazy resync tracking
LastSync jsontime.Unix `json:"last_sync,omitempty"`
}

func (meta *PortalMetadata) JID(id networkid.PortalID) waTypes.JID {
Expand Down