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

View file

@ -1,4 +1,4 @@
-- v0 -> v54: Latest revision
-- v0 -> v55: Latest revision
CREATE TABLE "user" (
mxid TEXT PRIMARY KEY,
@ -43,14 +43,15 @@ CREATE TABLE portal (
CREATE INDEX portal_parent_group_idx ON portal(parent_group);
CREATE TABLE puppet (
username TEXT PRIMARY KEY,
displayname TEXT,
name_quality SMALLINT,
avatar TEXT,
avatar_url TEXT,
name_set BOOLEAN NOT NULL DEFAULT false,
avatar_set BOOLEAN NOT NULL DEFAULT false,
last_sync BIGINT NOT NULL DEFAULT 0,
username TEXT PRIMARY KEY,
displayname TEXT,
name_quality SMALLINT,
avatar TEXT,
avatar_url TEXT,
name_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,
custom_mxid TEXT,
access_token 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
google.golang.org/protobuf v1.28.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 (

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/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL8=
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.20230405144343-a47718edca66/go.mod h1:Ei+ijYIMoQ3at2vJrMbEQq/pN2fB3h18clD8PyVyTD0=
maunium.net/go/mautrix v0.15.1-0.20230407141116-e5aa88ba0f9d h1:LdxNYgiE2J7Q2057MV30ogMHiivhLPU02aTVbcqQeC8=
maunium.net/go/mautrix v0.15.1-0.20230407141116-e5aa88ba0f9d/go.mod h1:Ei+ijYIMoQ3at2vJrMbEQq/pN2fB3h18clD8PyVyTD0=

21
main.go
View file

@ -151,6 +151,7 @@ func (br *WABridge) Start() {
br.Provisioning.Init()
}
go br.CheckWhatsAppUpdate()
go br.UpdatePuppetContactInfo()
go br.StartUsers()
if br.Config.Metrics.Enabled {
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() {
for {
br.SleepAndDeleteUpcoming()
@ -273,11 +282,13 @@ func main() {
puppetsByCustomMXID: make(map[id.UserID]*Puppet),
}
br.Bridge = bridge.Bridge{
Name: "mautrix-whatsapp",
URL: "https://github.com/mautrix/whatsapp",
Description: "A Matrix-WhatsApp puppeting bridge.",
Version: "0.8.3",
ProtocolName: "WhatsApp",
Name: "mautrix-whatsapp",
URL: "https://github.com/mautrix/whatsapp",
Description: "A Matrix-WhatsApp puppeting bridge.",
Version: "0.8.3",
ProtocolName: "WhatsApp",
BeeperServiceName: "whatsapp",
BeeperNetworkName: "whatsapp",
CryptoPickleKey: "maunium.net/go/mautrix-whatsapp",

View file

@ -28,6 +28,7 @@ import (
"maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/bridge"
"maunium.net/go/mautrix/bridge/bridgeconfig"
"maunium.net/go/mautrix/id"
"maunium.net/go/mautrix-whatsapp/config"
@ -262,6 +263,36 @@ func (puppet *Puppet) UpdateName(contact types.ContactInfo, forcePortalSync bool
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)) {
if puppet.bridge.Config.Bridge.PrivateChatPortalMeta || puppet.bridge.Config.Bridge.Encryption.Allow {
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 {
update = puppet.UpdateAvatar(source, forcePortalSync) || update
}
update = puppet.UpdateContactInfo() || update
if update || puppet.LastSync.Add(24*time.Hour).Before(time.Now()) {
puppet.LastSync = time.Now()
puppet.Update()