diff --git a/connector/connector.go b/connector/connector.go index f332dc5e..7e24be67 100644 --- a/connector/connector.go +++ b/connector/connector.go @@ -21,6 +21,7 @@ import ( "fmt" "strconv" "strings" + "text/template" "time" "github.com/google/uuid" @@ -47,17 +48,65 @@ import ( "go.mau.fi/mautrix-signal/pkg/signalmeow/types" ) +type SignalConfig struct { + DisplaynameTemplate string `yaml:"displayname_template"` + UseContactAvatars bool `yaml:"use_contact_avatars"` + UseOutdatedProfiles bool `yaml:"use_outdated_profiles"` + NumberInTopic bool `yaml:"number_in_topic"` + DeviceName string `yaml:"device_name"` + + displaynameTemplate *template.Template `yaml:"-"` +} + +type DisplaynameParams struct { + ProfileName string + ContactName string + Username string + PhoneNumber string + UUID string + ACI string + PNI string + AboutEmoji string +} + +func (c *SignalConfig) FormatDisplayname(contact *types.Recipient) string { + var nameBuf strings.Builder + err := c.displaynameTemplate.Execute(&nameBuf, &DisplaynameParams{ + ProfileName: contact.Profile.Name, + ContactName: contact.ContactName, + Username: "", + PhoneNumber: contact.E164, + UUID: contact.ACI.String(), + ACI: contact.ACI.String(), + PNI: contact.PNI.String(), + AboutEmoji: contact.Profile.AboutEmoji, + }) + if err != nil { + panic(err) + } + return nameBuf.String() +} + type SignalConnector struct { MsgConv *msgconv.MessageConverter Store *store.Container Bridge *bridgev2.Bridge + Config *SignalConfig } func NewConnector() *SignalConnector { - return &SignalConnector{} + return &SignalConnector{ + Config: &SignalConfig{}, + } } func (s *SignalConnector) Init(bridge *bridgev2.Bridge) { + var err error + s.Config.displaynameTemplate, err = template.New("displayname").Parse(s.Config.DisplaynameTemplate) + if err != nil { + // TODO return error or do this later? + panic(err) + } s.Store = store.NewStore(bridge.DB.Database, dbutil.ZeroLogger(bridge.Log.With().Str("db_section", "signalmeow").Logger())) s.Bridge = bridge s.MsgConv = &msgconv.MessageConverter{ @@ -150,16 +199,9 @@ func (s *SignalClient) contactToUserInfo(contact *types.Recipient) *bridgev2.Use ui := &bridgev2.UserInfo{ IsBot: &isBot, } - // TODO use template for name - if contact.ContactName != "" { - ui.Name = &contact.ContactName - } else if contact.Profile.Name != "" { - ui.Name = &contact.Profile.Name - } else if contact.E164 != "" { - ui.Name = &contact.E164 - } - // TODO only use this if contact avatars are allowed - if contact.ContactAvatar.Hash != "" { + name := s.Main.Config.FormatDisplayname(contact) + ui.Name = &name + if s.Main.Config.UseContactAvatars && contact.ContactAvatar.Hash != "" { ui.Avatar = &bridgev2.Avatar{ ID: networkid.AvatarID("hash:" + contact.ContactAvatar.Hash), Get: func(ctx context.Context) ([]byte, error) { @@ -235,17 +277,34 @@ func (s *SignalClient) GetChatInfo(ctx context.Context, portal *bridgev2.Portal) IsSpace: &isSpace, }, nil } else if userID.Type == libsignalgo.ServiceIDTypePNI { + contact, err := s.Client.Store.RecipientStore.LoadAndUpdateRecipient(ctx, uuid.Nil, userID.UUID, nil) + if err != nil { + return nil, err + } + var topic, name string + name = s.Main.Config.FormatDisplayname(contact) + if s.Main.Config.NumberInTopic && contact.E164 != "" { + topic = fmt.Sprintf("") + // TODO set topic + } isDM := true - // TODO set name/avatar because we don't have the recipient user ID return &bridgev2.PortalInfo{ Members: []networkid.UserID{makeUserID(s.Client.Store.ACI)}, + Name: &name, + Topic: &topic, IsDirectChat: &isDM, IsSpace: &isSpace, }, nil } else { + var topic, name string + if s.Main.Config.NumberInTopic { + // TODO set topic + } isDM := true return &bridgev2.PortalInfo{ Members: []networkid.UserID{makeUserID(userID.UUID), makeUserID(s.Client.Store.ACI)}, + Name: &name, + Topic: &topic, IsDirectChat: &isDM, IsSpace: &isSpace, }, nil diff --git a/connector/mautrix-signal-v2/main.go b/connector/mautrix-signal-v2/main.go index 929a9c1a..1ea34d93 100644 --- a/connector/mautrix-signal-v2/main.go +++ b/connector/mautrix-signal-v2/main.go @@ -48,7 +48,9 @@ func main() { log := exerrors.Must(cfg.Logging.Compile()) exzerolog.SetupDefaults(log) db := exerrors.Must(dbutil.NewFromConfig("mautrix-signal", cfg.Database, dbutil.ZeroLogger(log.With().Str("db_section", "main").Logger()))) - bridge := bridgev2.NewBridge("", db, *log, matrix.NewConnector(&cfg), connector.NewConnector()) + signalConnector := connector.NewConnector() + exerrors.PanicIfNotNil(cfg.Network.Decode(signalConnector.Config)) + bridge := bridgev2.NewBridge("", db, *log, matrix.NewConnector(&cfg), signalConnector) bridge.CommandPrefix = "!signal" bridge.Commands.AddHandlers(&bridgev2.FullHandler{ Func: fnLogin, diff --git a/go.mod b/go.mod index 22b07b36..913d3c1c 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( golang.org/x/net v0.25.0 google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.18.2-0.20240528174923-3c7b3e13efe4 + maunium.net/go/mautrix v0.18.2-0.20240529135554-248de0e6adb2 nhooyr.io/websocket v1.8.11 ) diff --git a/go.sum b/go.sum index 4d6c887f..641b71f3 100644 --- a/go.sum +++ b/go.sum @@ -95,7 +95,7 @@ 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.18.2-0.20240528174923-3c7b3e13efe4 h1:b+pK+EJL2XsweSKlwhd8eeqD4v395dKrcJZmCFTBmBY= -maunium.net/go/mautrix v0.18.2-0.20240528174923-3c7b3e13efe4/go.mod h1:Ln4XquIKL5MttTUGNUSbiEGX3XYC0P6jzT9XjLFFPdY= +maunium.net/go/mautrix v0.18.2-0.20240529135554-248de0e6adb2 h1:AUKv3tqpdFerCw2X8m05BGfhtP3vH8cDuEtAGxwuUl0= +maunium.net/go/mautrix v0.18.2-0.20240529135554-248de0e6adb2/go.mod h1:Ln4XquIKL5MttTUGNUSbiEGX3XYC0P6jzT9XjLFFPdY= nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0= nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=