diff --git a/database/database.go b/database/database.go
index cb1a1db..26da8da 100644
--- a/database/database.go
+++ b/database/database.go
@@ -57,7 +57,7 @@ func New(dbType string, uri string, baseLog log.Logger) (*Database, error) {
}
gdb, err := gorm.Open(conn, &gorm.Config{
- // Logger: logger.Default.LogMode(logger.Info),
+ //Logger: logger.Default.LogMode(logger.Info),
// Logger: baseLog,
DisableForeignKeyConstraintWhenMigrating: true,
@@ -113,7 +113,7 @@ func (db *Database) Init() error {
return err
}
- err = db.AutoMigrate(&mxRegistered{}, &mxUserProfile{})
+ err = db.AutoMigrate(&mxRegistered{}, &MxUserProfile{})
if err != nil {
return err
}
diff --git a/database/puppet.go b/database/puppet.go
index 5ff4fae..7994b1b 100644
--- a/database/puppet.go
+++ b/database/puppet.go
@@ -45,8 +45,7 @@ func (pq *PuppetQuery) GetAll() (puppets []*Puppet) {
return nil
}
for _, puppet := range puppets {
- puppet.db = pq.db
- puppet.log = pq.log
+ pq.initializePuppet(puppet)
}
// defer rows.Close()
// for rows.Next() {
@@ -61,8 +60,7 @@ func (pq *PuppetQuery) Get(jid types.GroupMeID) *Puppet {
if ans.Error != nil || ans.RowsAffected == 0 {
return nil
}
- puppet.db = pq.db
- puppet.log = pq.log
+ pq.initializePuppet(&puppet)
return &puppet
}
@@ -72,8 +70,7 @@ func (pq *PuppetQuery) GetByCustomMXID(mxid id.UserID) *Puppet {
if ans.Error != nil || ans.RowsAffected == 0 {
return nil
}
- puppet.db = pq.db
- puppet.log = pq.log
+ pq.initializePuppet(&puppet)
return &puppet
}
@@ -84,8 +81,7 @@ func (pq *PuppetQuery) GetAllWithCustomMXID() (puppets []*Puppet) {
return nil
}
for _, puppet := range puppets {
- puppet.db = pq.db
- puppet.log = pq.log
+ pq.initializePuppet(puppet)
}
// defer rows.Close()
// for rows.Next() {
@@ -94,16 +90,21 @@ func (pq *PuppetQuery) GetAllWithCustomMXID() (puppets []*Puppet) {
return
}
+func (pq *PuppetQuery) initializePuppet(p *Puppet) {
+ p.db = pq.db
+ p.log = pq.log
+}
+
//Puppet is comment
type Puppet struct {
db *Database
log log.Logger
- JID types.GroupMeID `gorm:"primaryKey"`
- Avatar string
- AvatarURL types.ContentURI
- Displayname string
- NameQuality int8
+ JID types.GroupMeID `gorm:"primaryKey"`
+ //Avatar string
+ //AvatarURL types.ContentURI
+ //Displayname string
+ //NameQuality int8
CustomMXID id.UserID `gorm:"column:custom_mxid;"`
AccessToken string
diff --git a/database/statestore.go b/database/statestore.go
index dd73fe4..833915a 100644
--- a/database/statestore.go
+++ b/database/statestore.go
@@ -76,18 +76,19 @@ func (store *SQLStateStore) MarkRegistered(userID id.UserID) {
}
}
-type mxUserProfile struct {
+type MxUserProfile struct {
RoomID string `gorm:"primaryKey"`
UserID string `gorm:"primaryKey"`
Membership string `gorm:"notNull"`
DisplayName string
AvatarURL string
+ Avatar string
}
func (store *SQLStateStore) GetRoomMembers(roomID id.RoomID) map[id.UserID]*event.MemberEventContent {
members := make(map[id.UserID]*event.MemberEventContent)
- var users []mxUserProfile
+ var users []MxUserProfile
ans := store.db.Where("room_id = ?", roomID.String()).Find(&users)
if ans.Error != nil {
return members
@@ -113,7 +114,7 @@ func (store *SQLStateStore) GetRoomMembers(roomID id.RoomID) map[id.UserID]*even
}
func (store *SQLStateStore) GetMembership(roomID id.RoomID, userID id.UserID) event.Membership {
- var user mxUserProfile
+ var user MxUserProfile
ans := store.db.Where("room_id = ? AND user_id = ?", roomID, userID).Limit(1).Find(&user)
membership := event.MembershipLeave
if ans.Error != nil && ans.Error != gorm.ErrRecordNotFound {
@@ -133,7 +134,7 @@ func (store *SQLStateStore) GetMember(roomID id.RoomID, userID id.UserID) *event
}
func (store *SQLStateStore) TryGetMember(roomID id.RoomID, userID id.UserID) (*event.MemberEventContent, bool) {
- var user mxUserProfile
+ var user MxUserProfile
ans := store.db.Where("room_id = ? AND user_id = ?", roomID, userID).Take(&user)
if ans.Error != nil && ans.Error != gorm.ErrRecordNotFound {
@@ -148,6 +149,32 @@ func (store *SQLStateStore) TryGetMember(roomID id.RoomID, userID id.UserID) (*e
return &eventMember, ans.Error != nil
}
+func (store *SQLStateStore) TryGetMemberRaw(roomID id.RoomID, userID id.UserID) (user MxUserProfile, err bool) {
+ ans := store.db.Where("room_id = ? AND user_id = ?", roomID, userID).Take(&user)
+
+ if ans.Error == gorm.ErrRecordNotFound {
+ err = true
+ return
+ }
+ if ans.Error != nil && ans.Error != gorm.ErrRecordNotFound {
+ store.log.Warnfln("Failed to scan member info of %s in %s: %v", userID, roomID, ans.Error)
+ err = true
+ return
+ }
+
+ return user, false
+}
+
+func (store *SQLStateStore) SetMemberRaw(member *MxUserProfile) {
+ ans := store.db.Clauses(clause.OnConflict{
+ UpdateAll: true,
+ }).Create(member)
+
+ if ans.Error != nil {
+ store.log.Warnfln("Failed to set membership of %s in %s to %s: %v", member.UserID, member.RoomID, member, ans.Error)
+ }
+}
+
func (store *SQLStateStore) FindSharedRooms(userID id.UserID) (rooms []id.RoomID) {
rows, err := store.db.Table("mx_user_profile").Select("room_id").
@@ -192,7 +219,7 @@ func (store *SQLStateStore) IsMembership(roomID id.RoomID, userID id.UserID, all
func (store *SQLStateStore) SetMembership(roomID id.RoomID, userID id.UserID, membership event.Membership) {
var err error
- user := mxUserProfile{
+ user := MxUserProfile{
RoomID: roomID.String(),
UserID: userID.String(),
Membership: string(membership),
@@ -208,19 +235,18 @@ func (store *SQLStateStore) SetMembership(roomID id.RoomID, userID id.UserID, me
store.log.Warnfln("Failed to set membership of %s in %s to %s: %v", userID, roomID, membership, err)
}
}
-
func (store *SQLStateStore) SetMember(roomID id.RoomID, userID id.UserID, member *event.MemberEventContent) {
- user := mxUserProfile{
+ user := MxUserProfile{
RoomID: roomID.String(),
UserID: userID.String(),
Membership: string(member.Membership),
DisplayName: member.Displayname,
- AvatarURL: string(member.AvatarURL),
+ // AvatarURL: string(member.AvatarURL),//try ignoring
}
ans := store.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "room_id"}, {Name: "user_id"}},
- DoUpdates: clause.AssignmentColumns([]string{"membership"}),
+ DoUpdates: clause.AssignmentColumns([]string{"membership", "display_name"}),
}).Create(&user)
if ans.Error != nil {
diff --git a/formatting.go b/formatting.go
index 3d1d544..03b21d1 100644
--- a/formatting.go
+++ b/formatting.go
@@ -18,16 +18,13 @@ package main
import (
"fmt"
- "html"
"regexp"
"strings"
- "maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id"
"github.com/karmanyaahm/matrix-groupme-go/types"
- whatsappExt "github.com/karmanyaahm/matrix-groupme-go/whatsapp-ext"
)
var italicRegex = regexp.MustCompile("([\\s>~*]|^)_(.+?)_([^a-zA-Z\\d]|$)")
@@ -104,40 +101,40 @@ func NewFormatter(bridge *Bridge) *Formatter {
return formatter
}
-func (formatter *Formatter) getMatrixInfoByJID(jid types.GroupMeID) (mxid id.UserID, displayname string) {
- if user := formatter.bridge.GetUserByJID(jid); user != nil {
- mxid = user.MXID
- displayname = string(user.MXID)
- } else if puppet := formatter.bridge.GetPuppetByJID(jid); puppet != nil {
- mxid = puppet.MXID
- displayname = puppet.Displayname
- }
- return
-}
+//func (formatter *Formatter) getMatrixInfoByJID(jid types.GroupMeID) (mxid id.UserID, displayname string) {
+// if user := formatter.bridge.GetUserByJID(jid); user != nil {
+// mxid = user.MXID
+// displayname = string(user.MXID)
+// } else if puppet := formatter.bridge.GetPuppetByJID(jid); puppet != nil {
+// mxid = puppet.MXID
+// displayname = puppet.Displayname
+// }
+// return
+//}
-func (formatter *Formatter) ParseWhatsApp(content *event.MessageEventContent, mentionedJIDs []types.GroupMeID) {
- output := html.EscapeString(content.Body)
- for regex, replacement := range formatter.waReplString {
- output = regex.ReplaceAllString(output, replacement)
- }
- for regex, replacer := range formatter.waReplFunc {
- output = regex.ReplaceAllStringFunc(output, replacer)
- }
- for _, jid := range mentionedJIDs {
- mxid, displayname := formatter.getMatrixInfoByJID(jid)
- number := "@" + strings.Replace(jid, whatsappExt.NewUserSuffix, "", 1)
- output = strings.Replace(output, number, fmt.Sprintf(`%s`, mxid, displayname), -1)
- content.Body = strings.Replace(content.Body, number, displayname, -1)
- }
- if output != content.Body {
- output = strings.Replace(output, "\n", "
", -1)
- content.FormattedBody = output
- content.Format = event.FormatHTML
- for regex, replacer := range formatter.waReplFuncText {
- content.Body = regex.ReplaceAllStringFunc(content.Body, replacer)
- }
- }
-}
+//func (formatter *Formatter) ParseWhatsApp(content *event.MessageEventContent, mentionedJIDs []types.GroupMeID) {
+// output := html.EscapeString(content.Body)
+// for regex, replacement := range formatter.waReplString {
+// output = regex.ReplaceAllString(output, replacement)
+// }
+// for regex, replacer := range formatter.waReplFunc {
+// output = regex.ReplaceAllStringFunc(output, replacer)
+// }
+// for _, jid := range mentionedJIDs {
+// mxid, displayname := formatter.getMatrixInfoByJID(jid)
+// number := "@" + strings.Replace(jid, whatsappExt.NewUserSuffix, "", 1)
+// output = strings.Replace(output, number, fmt.Sprintf(`%s`, mxid, displayname), -1)
+// content.Body = strings.Replace(content.Body, number, displayname, -1)
+// }
+// if output != content.Body {
+// output = strings.Replace(output, "\n", "
", -1)
+// content.FormattedBody = output
+// content.Format = event.FormatHTML
+// for regex, replacer := range formatter.waReplFuncText {
+// content.Body = regex.ReplaceAllStringFunc(content.Body, replacer)
+// }
+// }
+//}
func (formatter *Formatter) ParseMatrix(html string) (string, []types.GroupMeID) {
ctx := make(format.Context)
diff --git a/go.mod b/go.mod
index 1b5961f..f72403c 100644
--- a/go.mod
+++ b/go.mod
@@ -31,3 +31,5 @@ require (
replace github.com/karmanyaahm/groupme => ../groupme
replace github.com/karmanyaahm/wray => ../wray
+
+replace maunium.net/go/mautrix => ../mautrix
diff --git a/matrix.go b/matrix.go
index a4900e9..5526291 100644
--- a/matrix.go
+++ b/matrix.go
@@ -31,6 +31,7 @@ import (
"maunium.net/go/mautrix/id"
"github.com/karmanyaahm/matrix-groupme-go/database"
+ "github.com/karmanyaahm/matrix-groupme-go/types"
)
type MatrixHandler struct {
@@ -166,10 +167,11 @@ func (mx *MatrixHandler) createPrivatePortalFromInvite(roomID id.RoomID, inviter
portal.Topic = "WhatsApp private chat"
_, _ = portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
if portal.bridge.Config.Bridge.PrivateChatPortalMeta {
- portal.Name = puppet.Displayname
- portal.AvatarURL = puppet.AvatarURL
+ m, _ := mx.bridge.StateStore.TryGetMemberRaw(portal.MXID, puppet.MXID)
+ portal.Name = m.DisplayName
+ portal.AvatarURL = types.ContentURI{id.MustParseContentURI(m.AvatarURL)}
print("possible bug with pointer above")
- portal.Avatar = puppet.Avatar
+ portal.Avatar = m.Avatar
_, _ = portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
_, _ = portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL.ContentURI)
} else {
diff --git a/portal.go b/portal.go
index 9ae656c..32e7b6b 100644
--- a/portal.go
+++ b/portal.go
@@ -348,7 +348,7 @@ func (portal *Portal) SyncParticipants(metadata *groupme.Group) {
if user != nil {
changed = levels.EnsureUserLevel(user.MXID, expectedLevel) || changed
}
- go puppet.Sync(nil, *participant) //why nil whynot
+ puppet.Sync(nil, portal.MXID, *participant) //why nil whynot
}
if changed {
_, err = portal.MainIntent().SetPowerLevels(portal.MXID, levels)
@@ -940,10 +940,11 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
var metadata *groupme.Group
if portal.IsPrivateChat() {
puppet := portal.bridge.GetPuppetByJID(portal.Key.JID)
+ m, _ := portal.bridge.StateStore.TryGetMemberRaw(portal.MXID, puppet.MXID)
if portal.bridge.Config.Bridge.PrivateChatPortalMeta {
- portal.Name = puppet.Displayname
- portal.AvatarURL = puppet.AvatarURL
- portal.Avatar = puppet.Avatar
+ portal.Name = m.DisplayName
+ portal.AvatarURL = types.ContentURI{id.MustParseContentURI(m.AvatarURL)}
+ portal.Avatar = m.Avatar
} else {
portal.Name = ""
}
diff --git a/puppet.go b/puppet.go
index 6e3cc75..489d03b 100644
--- a/puppet.go
+++ b/puppet.go
@@ -18,6 +18,7 @@ package main
import (
"fmt"
+ "os"
"regexp"
"strings"
@@ -181,19 +182,32 @@ func (puppet *Puppet) DefaultIntent() *appservice.IntentAPI {
return puppet.bridge.AS.Intent(puppet.MXID)
}
-func (puppet *Puppet) UpdateAvatar(source *User, avatar string) bool {
+//func (puppet *Puppet) SetRoomMetadata(name, avatarURL string) bool {
+//
+//}
+
+func (puppet *Puppet) UpdateAvatar(source *User, portalMXID id.RoomID, avatar string) bool {
+ memberRaw, _ := puppet.bridge.StateStore.TryGetMemberRaw(portalMXID, puppet.MXID) //TODO Handle
+ fmt.Println(len(avatar), avatar, memberRaw.Avatar)
+
if len(avatar) == 0 {
- err := puppet.DefaultIntent().SetAvatarURL(id.ContentURI{})
+ var err error
+ err = puppet.DefaultIntent().SetRoomAvatarURL(portalMXID, id.ContentURI{})
+
if err != nil {
- puppet.log.Warnln("Failed to remove avatar:", err)
+ puppet.log.Warnln("Failed to remove avatar:", err, puppet.MXID)
+ os.Exit(1)
}
- puppet.AvatarURL = types.ContentURI{}
- puppet.Avatar = avatar
+ memberRaw.Avatar = avatar
+ memberRaw.AvatarURL = ""
+
go puppet.updatePortalAvatar()
+
+ puppet.bridge.StateStore.SetMemberRaw(&memberRaw) //TODO handle
return true
}
- if puppet.Avatar == avatar {
+ if memberRaw.Avatar == avatar {
return false // up to date
}
@@ -209,24 +223,32 @@ func (puppet *Puppet) UpdateAvatar(source *User, avatar string) bool {
puppet.log.Warnln("Failed to upload avatar:", err)
return false
}
-
- puppet.AvatarURL = types.ContentURI{resp.ContentURI}
- err = puppet.DefaultIntent().SetAvatarURL(resp.ContentURI)
+ err = puppet.DefaultIntent().SetRoomAvatarURL(portalMXID, resp.ContentURI)
if err != nil {
puppet.log.Warnln("Failed to set avatar:", err)
}
- puppet.Avatar = avatar
+
+ memberRaw.AvatarURL = resp.ContentURI.String()
+ memberRaw.Avatar = avatar
+
+ puppet.bridge.StateStore.SetMemberRaw(&memberRaw) //TODO handle
+
go puppet.updatePortalAvatar()
return true
}
-func (puppet *Puppet) UpdateName(source *User, contact groupme.Member) bool {
+func (puppet *Puppet) UpdateName(source *User, portalMXID id.RoomID, contact groupme.Member) bool {
newName, quality := puppet.bridge.Config.Bridge.FormatDisplayname(contact)
- if puppet.Displayname != newName && quality >= puppet.NameQuality {
- err := puppet.DefaultIntent().SetDisplayName(newName)
+
+ memberRaw, _ := puppet.bridge.StateStore.TryGetMemberRaw(portalMXID, puppet.MXID) //TODO Handle
+ quality = quality //quality not used
+ if memberRaw.DisplayName != newName { //&& quality >= puppet.NameQuality[portalMXID] {
+ var err error
+ err = puppet.DefaultIntent().SetRoomDisplayName(portalMXID, newName)
+
if err == nil {
- puppet.Displayname = newName
- puppet.NameQuality = quality
+ memberRaw.DisplayName = newName
+ // puppet.NameQuality[portalMXID] = quality
go puppet.updatePortalName()
puppet.Update()
} else {
@@ -247,38 +269,37 @@ func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) {
func (puppet *Puppet) updatePortalAvatar() {
puppet.updatePortalMeta(func(portal *Portal) {
+
+ m, _ := puppet.bridge.StateStore.TryGetMemberRaw(portal.MXID, puppet.MXID)
if len(portal.MXID) > 0 {
- _, err := portal.MainIntent().SetRoomAvatar(portal.MXID, puppet.AvatarURL.ContentURI)
+ _, err := portal.MainIntent().SetRoomAvatar(portal.MXID, id.MustParseContentURI(m.AvatarURL))
if err != nil {
portal.log.Warnln("Failed to set avatar:", err)
}
}
- portal.AvatarURL = puppet.AvatarURL
- portal.Avatar = puppet.Avatar
+ portal.AvatarURL = types.ContentURI{id.MustParseContentURI(m.AvatarURL)}
+ portal.Avatar = m.Avatar
portal.Update()
})
}
func (puppet *Puppet) updatePortalName() {
puppet.updatePortalMeta(func(portal *Portal) {
+ m, _ := puppet.bridge.StateStore.TryGetMemberRaw(portal.MXID, puppet.MXID)
if len(portal.MXID) > 0 {
- _, err := portal.MainIntent().SetRoomName(portal.MXID, puppet.Displayname)
+ _, err := portal.MainIntent().SetRoomName(portal.MXID, m.DisplayName)
if err != nil {
portal.log.Warnln("Failed to set name:", err)
}
}
- portal.Name = puppet.Displayname
+ portal.Name = m.DisplayName
portal.Update()
})
}
-func (puppet *Puppet) Sync(source *User, contact groupme.Member) {
+func (puppet *Puppet) Sync(source *User, portalMXID id.RoomID, contact groupme.Member) {
if contact.UserID.String() == "system" {
puppet.log.Warnln("Trying to sync system puppet")
-
- // portal.Sync(puppet.bridge.GetUserByJID(portal.Key.Receiver), groupme.Group{})
- //TODO permissoins idk if its fine to use portal owner
-
return
}
@@ -287,14 +308,9 @@ func (puppet *Puppet) Sync(source *User, contact groupme.Member) {
puppet.log.Errorln("Failed to ensure registered:", err)
}
- //if contact.ID.String() == source.JID {
- //TODO What is this
- // contact.Notify = source.Conn.Info.Pushname
- //}
-
update := false
- update = puppet.UpdateName(source, contact) || update
- update = puppet.UpdateAvatar(source, contact.ImageURL) || update
+ update = puppet.UpdateName(source, portalMXID, contact) || update
+ update = puppet.UpdateAvatar(source, portalMXID, contact.ImageURL) || update
if update {
puppet.Update()
}
diff --git a/user.go b/user.go
index 9a59cea..ab288d2 100644
--- a/user.go
+++ b/user.go
@@ -817,14 +817,15 @@ func (user *User) handleMessageLoop() {
case msg := <-user.messageOutput:
user.bridge.Metrics.TrackBufferLength(user.MXID, len(user.messageOutput))
puppet := user.bridge.GetPuppetByJID(msg.data.UserID.String())
+ portal := user.bridge.GetPortalByJID(database.GroupPortalKey(msg.chat))
if puppet != nil {
- puppet.Sync(user, groupme.Member{
+ puppet.Sync(user, portal.MXID, groupme.Member{
UserID: msg.data.UserID,
Nickname: msg.data.Name,
ImageURL: msg.data.AvatarURL,
}) //TODO: add params or docs?
}
- user.bridge.GetPortalByJID(database.GroupPortalKey(msg.chat)).messages <- msg
+ portal.messages <- msg
case <-user.syncStart:
user.log.Debugln("Processing of incoming messages is locked")
user.bridge.Metrics.TrackSyncLock(user.JID, true)