Add custom contact info fields to puppet profile (#605)

* Add custom contact info fields to puppet profile

* Rename the field names in the new contact info

* Set contact info for puppets on startup

* Check for hungry inside the contact info function

* appservice bot: add contact info to bridge bot

Signed-off-by: Sumner Evans <sumner@beeper.com>

* go.sum: tidy

Signed-off-by: Sumner Evans <sumner@beeper.com>

* puppet/UpdateContactInfo: reduce nesting

Signed-off-by: Sumner Evans <sumner@beeper.com>

---------

Signed-off-by: Sumner Evans <sumner@beeper.com>
Co-authored-by: Sumner Evans <sumner@beeper.com>
This commit is contained in:
vurpo 2023-04-10 18:39:05 +03:00 committed by GitHub
parent f24f3bcb79
commit a6dca47740
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 88 additions and 39 deletions

View file

@ -44,7 +44,7 @@ func (pq *PuppetQuery) New() *Puppet {
} }
func (pq *PuppetQuery) GetAll() (puppets []*Puppet) { func (pq *PuppetQuery) GetAll() (puppets []*Puppet) {
rows, err := pq.db.Query("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet") rows, err := pq.db.Query("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, contact_info_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet")
if err != nil || rows == nil { if err != nil || rows == nil {
return nil return nil
} }
@ -56,7 +56,7 @@ func (pq *PuppetQuery) GetAll() (puppets []*Puppet) {
} }
func (pq *PuppetQuery) Get(jid types.JID) *Puppet { func (pq *PuppetQuery) Get(jid types.JID) *Puppet {
row := pq.db.QueryRow("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet WHERE username=$1", jid.User) row := pq.db.QueryRow("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, contact_info_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet WHERE username=$1", jid.User)
if row == nil { if row == nil {
return nil return nil
} }
@ -64,7 +64,7 @@ func (pq *PuppetQuery) Get(jid types.JID) *Puppet {
} }
func (pq *PuppetQuery) GetByCustomMXID(mxid id.UserID) *Puppet { func (pq *PuppetQuery) GetByCustomMXID(mxid id.UserID) *Puppet {
row := pq.db.QueryRow("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet WHERE custom_mxid=$1", mxid) row := pq.db.QueryRow("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, contact_info_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet WHERE custom_mxid=$1", mxid)
if row == nil { if row == nil {
return nil return nil
} }
@ -72,7 +72,7 @@ func (pq *PuppetQuery) GetByCustomMXID(mxid id.UserID) *Puppet {
} }
func (pq *PuppetQuery) GetAllWithCustomMXID() (puppets []*Puppet) { func (pq *PuppetQuery) GetAllWithCustomMXID() (puppets []*Puppet) {
rows, err := pq.db.Query("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet WHERE custom_mxid<>''") rows, err := pq.db.Query("SELECT username, avatar, avatar_url, displayname, name_quality, name_set, avatar_set, contact_info_set, last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts FROM puppet WHERE custom_mxid<>''")
if err != nil || rows == nil { if err != nil || rows == nil {
return nil return nil
} }
@ -94,6 +94,7 @@ type Puppet struct {
Displayname string Displayname string
NameQuality int8 NameQuality int8
NameSet bool NameSet bool
ContactInfoSet bool
LastSync time.Time LastSync time.Time
CustomMXID id.UserID CustomMXID id.UserID
@ -106,9 +107,9 @@ type Puppet struct {
func (puppet *Puppet) Scan(row dbutil.Scannable) *Puppet { func (puppet *Puppet) Scan(row dbutil.Scannable) *Puppet {
var displayname, avatar, avatarURL, customMXID, accessToken, nextBatch sql.NullString var displayname, avatar, avatarURL, customMXID, accessToken, nextBatch sql.NullString
var quality, lastSync sql.NullInt64 var quality, lastSync sql.NullInt64
var enablePresence, enableReceipts, nameSet, avatarSet sql.NullBool var enablePresence, enableReceipts, nameSet, avatarSet, contactInfoSet sql.NullBool
var username string var username string
err := row.Scan(&username, &avatar, &avatarURL, &displayname, &quality, &nameSet, &avatarSet, &lastSync, &customMXID, &accessToken, &nextBatch, &enablePresence, &enableReceipts) err := row.Scan(&username, &avatar, &avatarURL, &displayname, &quality, &nameSet, &avatarSet, &contactInfoSet, &lastSync, &customMXID, &accessToken, &nextBatch, &enablePresence, &enableReceipts)
if err != nil { if err != nil {
if err != sql.ErrNoRows { if err != sql.ErrNoRows {
puppet.log.Errorln("Database scan failed:", err) puppet.log.Errorln("Database scan failed:", err)
@ -122,6 +123,7 @@ func (puppet *Puppet) Scan(row dbutil.Scannable) *Puppet {
puppet.NameQuality = int8(quality.Int64) puppet.NameQuality = int8(quality.Int64)
puppet.NameSet = nameSet.Bool puppet.NameSet = nameSet.Bool
puppet.AvatarSet = avatarSet.Bool puppet.AvatarSet = avatarSet.Bool
puppet.ContactInfoSet = contactInfoSet.Bool
if lastSync.Int64 > 0 { if lastSync.Int64 > 0 {
puppet.LastSync = time.Unix(lastSync.Int64, 0) puppet.LastSync = time.Unix(lastSync.Int64, 0)
} }
@ -143,11 +145,11 @@ func (puppet *Puppet) Insert() {
lastSyncTs = puppet.LastSync.Unix() lastSyncTs = puppet.LastSync.Unix()
} }
_, err := puppet.db.Exec(` _, err := puppet.db.Exec(`
INSERT INTO puppet (username, avatar, avatar_url, avatar_set, displayname, name_quality, name_set, last_sync, INSERT INTO puppet (username, avatar, avatar_url, avatar_set, displayname, name_quality, name_set, contact_info_set,
custom_mxid, access_token, next_batch, enable_presence, enable_receipts) last_sync, custom_mxid, access_token, next_batch, enable_presence, enable_receipts)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
`, puppet.JID.User, puppet.Avatar, puppet.AvatarURL.String(), puppet.AvatarSet, puppet.Displayname, `, puppet.JID.User, puppet.Avatar, puppet.AvatarURL.String(), puppet.AvatarSet, puppet.Displayname,
puppet.NameQuality, puppet.NameSet, lastSyncTs, puppet.CustomMXID, puppet.AccessToken, puppet.NextBatch, puppet.NameQuality, puppet.NameSet, puppet.ContactInfoSet, lastSyncTs, puppet.CustomMXID, puppet.AccessToken, puppet.NextBatch,
puppet.EnablePresence, puppet.EnableReceipts, puppet.EnablePresence, puppet.EnableReceipts,
) )
if err != nil { if err != nil {
@ -162,10 +164,10 @@ func (puppet *Puppet) Update() {
} }
_, err := puppet.db.Exec(` _, err := puppet.db.Exec(`
UPDATE puppet UPDATE puppet
SET displayname=$1, name_quality=$2, name_set=$3, avatar=$4, avatar_url=$5, avatar_set=$6, last_sync=$7, SET displayname=$1, name_quality=$2, name_set=$3, avatar=$4, avatar_url=$5, avatar_set=$6, contact_info_set=$7, last_sync=$8,
custom_mxid=$8, access_token=$9, next_batch=$10, enable_presence=$11, enable_receipts=$12 custom_mxid=$9, access_token=$10, next_batch=$11, enable_presence=$12, enable_receipts=$13
WHERE username=$13 WHERE username=$14
`, puppet.Displayname, puppet.NameQuality, puppet.NameSet, puppet.Avatar, puppet.AvatarURL.String(), puppet.AvatarSet, `, puppet.Displayname, puppet.NameQuality, puppet.NameSet, puppet.Avatar, puppet.AvatarURL.String(), puppet.AvatarSet, puppet.ContactInfoSet,
lastSyncTs, puppet.CustomMXID, puppet.AccessToken, puppet.NextBatch, puppet.EnablePresence, puppet.EnableReceipts, lastSyncTs, puppet.CustomMXID, puppet.AccessToken, puppet.NextBatch, puppet.EnablePresence, puppet.EnableReceipts,
puppet.JID.User) puppet.JID.User)
if err != nil { if err != nil {

View file

@ -1,4 +1,4 @@
-- v0 -> v54: Latest revision -- v0 -> v55: Latest revision
CREATE TABLE "user" ( CREATE TABLE "user" (
mxid TEXT PRIMARY KEY, mxid TEXT PRIMARY KEY,
@ -50,6 +50,7 @@ CREATE TABLE puppet (
avatar_url TEXT, avatar_url TEXT,
name_set BOOLEAN NOT NULL DEFAULT false, name_set BOOLEAN NOT NULL DEFAULT false,
avatar_set BOOLEAN NOT NULL DEFAULT false, avatar_set BOOLEAN NOT NULL DEFAULT false,
contact_info_set BOOLEAN NOT NULL DEFAULT false,
last_sync BIGINT NOT NULL DEFAULT 0, last_sync BIGINT NOT NULL DEFAULT 0,
custom_mxid TEXT, custom_mxid TEXT,

View file

@ -0,0 +1,3 @@
-- v55: Store whether custom contact info has been set for a puppet
ALTER TABLE puppet ADD COLUMN contact_info_set BOOLEAN NOT NULL DEFAULT false;

2
go.mod
View file

@ -16,7 +16,7 @@ require (
golang.org/x/net v0.8.0 golang.org/x/net v0.8.0
google.golang.org/protobuf v1.28.1 google.golang.org/protobuf v1.28.1
maunium.net/go/maulogger/v2 v2.4.1 maunium.net/go/maulogger/v2 v2.4.1
maunium.net/go/mautrix v0.15.1-0.20230405144343-a47718edca66 maunium.net/go/mautrix v0.15.1-0.20230407141116-e5aa88ba0f9d
) )
require ( require (

4
go.sum
View file

@ -134,5 +134,5 @@ 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/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8= maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho= maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho=
maunium.net/go/mautrix v0.15.1-0.20230405144343-a47718edca66 h1:P+UbO87hsxpY0HyzAS36VmzuEqz/vzhmO0wClaAlxl0= maunium.net/go/mautrix v0.15.1-0.20230407141116-e5aa88ba0f9d h1:LdxNYgiE2J7Q2057MV30ogMHiivhLPU02aTVbcqQeC8=
maunium.net/go/mautrix v0.15.1-0.20230405144343-a47718edca66/go.mod h1:Ei+ijYIMoQ3at2vJrMbEQq/pN2fB3h18clD8PyVyTD0= maunium.net/go/mautrix v0.15.1-0.20230407141116-e5aa88ba0f9d/go.mod h1:Ei+ijYIMoQ3at2vJrMbEQq/pN2fB3h18clD8PyVyTD0=

11
main.go
View file

@ -151,6 +151,7 @@ func (br *WABridge) Start() {
br.Provisioning.Init() br.Provisioning.Init()
} }
go br.CheckWhatsAppUpdate() go br.CheckWhatsAppUpdate()
go br.UpdatePuppetContactInfo()
go br.StartUsers() go br.StartUsers()
if br.Config.Metrics.Enabled { if br.Config.Metrics.Enabled {
go br.Metrics.Start() go br.Metrics.Start()
@ -181,6 +182,14 @@ func (br *WABridge) CheckWhatsAppUpdate() {
} }
} }
func (br *WABridge) UpdatePuppetContactInfo() {
for _, puppet := range br.GetAllPuppets() {
if puppet.UpdateContactInfo() {
puppet.Update()
}
}
}
func (br *WABridge) Loop() { func (br *WABridge) Loop() {
for { for {
br.SleepAndDeleteUpcoming() br.SleepAndDeleteUpcoming()
@ -278,6 +287,8 @@ func main() {
Description: "A Matrix-WhatsApp puppeting bridge.", Description: "A Matrix-WhatsApp puppeting bridge.",
Version: "0.8.3", Version: "0.8.3",
ProtocolName: "WhatsApp", ProtocolName: "WhatsApp",
BeeperServiceName: "whatsapp",
BeeperNetworkName: "whatsapp",
CryptoPickleKey: "maunium.net/go/mautrix-whatsapp", CryptoPickleKey: "maunium.net/go/mautrix-whatsapp",

View file

@ -28,6 +28,7 @@ import (
"maunium.net/go/mautrix/appservice" "maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/bridge" "maunium.net/go/mautrix/bridge"
"maunium.net/go/mautrix/bridge/bridgeconfig"
"maunium.net/go/mautrix/id" "maunium.net/go/mautrix/id"
"maunium.net/go/mautrix-whatsapp/config" "maunium.net/go/mautrix-whatsapp/config"
@ -262,6 +263,36 @@ func (puppet *Puppet) UpdateName(contact types.ContactInfo, forcePortalSync bool
return false return false
} }
func (puppet *Puppet) UpdateContactInfo() bool {
if puppet.bridge.Config.Homeserver.Software != bridgeconfig.SoftwareHungry {
return false
}
if puppet.ContactInfoSet {
return false
}
contactInfo := map[string]any{
"com.beeper.bridge.identifiers": []string{
fmt.Sprintf("tel:+%s", puppet.JID.User),
fmt.Sprintf("whatsapp:%s", puppet.JID.String()),
},
"com.beeper.bridge.remote_id": puppet.JID.String(),
"com.beeper.bridge.service": "whatsapp",
"com.beeper.bridge.network": "whatsapp",
"com.beeper.bridge.is_bridge_bot": false,
"com.beeper.bridge.is_bot": false,
}
err := puppet.DefaultIntent().BeeperUpdateProfile(contactInfo)
if err != nil {
puppet.log.Warnln("Failed to store custom contact info in profile:", err)
return false
} else {
puppet.ContactInfoSet = true
return true
}
}
func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) { func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) {
if puppet.bridge.Config.Bridge.PrivateChatPortalMeta || puppet.bridge.Config.Bridge.Encryption.Allow { if puppet.bridge.Config.Bridge.PrivateChatPortalMeta || puppet.bridge.Config.Bridge.Encryption.Allow {
for _, portal := range puppet.bridge.GetAllPortalsByJID(puppet.JID) { for _, portal := range puppet.bridge.GetAllPortalsByJID(puppet.JID) {
@ -338,6 +369,7 @@ func (puppet *Puppet) Sync(source *User, contact *types.ContactInfo, forceAvatar
if len(puppet.Avatar) == 0 || forceAvatarSync || puppet.bridge.Config.Bridge.UserAvatarSync { if len(puppet.Avatar) == 0 || forceAvatarSync || puppet.bridge.Config.Bridge.UserAvatarSync {
update = puppet.UpdateAvatar(source, forcePortalSync) || update update = puppet.UpdateAvatar(source, forcePortalSync) || update
} }
update = puppet.UpdateContactInfo() || update
if update || puppet.LastSync.Add(24*time.Hour).Before(time.Now()) { if update || puppet.LastSync.Add(24*time.Hour).Before(time.Now()) {
puppet.LastSync = time.Now() puppet.LastSync = time.Now()
puppet.Update() puppet.Update()