Initial desegregation of users and automatic config updating

This commit is contained in:
Tulir Asokan
2018-08-29 00:40:54 +03:00
parent 55c3ab2d4f
commit c7348f29b0
24 changed files with 806 additions and 475 deletions

View File

@ -30,12 +30,13 @@ type MessageQuery struct {
func (mq *MessageQuery) CreateTable() error {
_, err := mq.db.Exec(`CREATE TABLE IF NOT EXISTS message (
owner VARCHAR(255),
jid VARCHAR(255),
mxid VARCHAR(255) NOT NULL UNIQUE,
chat_jid VARCHAR(25) NOT NULL,
chat_receiver VARCHAR(25) NOT NULL,
jid VARCHAR(255) NOT NULL,
mxid VARCHAR(255) NOT NULL UNIQUE,
PRIMARY KEY (owner, jid),
FOREIGN KEY (owner) REFERENCES user(mxid)
PRIMARY KEY (chat_jid, jid),
FOREIGN KEY (chat_jid, chat_receiver) REFERENCES portal(jid, receiver)
)`)
return err
}
@ -47,8 +48,8 @@ func (mq *MessageQuery) New() *Message {
}
}
func (mq *MessageQuery) GetAll(owner types.MatrixUserID) (messages []*Message) {
rows, err := mq.db.Query("SELECT * FROM message WHERE owner=?", owner)
func (mq *MessageQuery) GetAll(chat PortalKey) (messages []*Message) {
rows, err := mq.db.Query("SELECT * FROM message WHERE chat_jid=? AND chat_receiver=?", chat.JID, chat.Receiver)
if err != nil || rows == nil {
return nil
}
@ -59,8 +60,8 @@ func (mq *MessageQuery) GetAll(owner types.MatrixUserID) (messages []*Message) {
return
}
func (mq *MessageQuery) GetByJID(owner types.MatrixUserID, jid types.WhatsAppMessageID) *Message {
return mq.get("SELECT * FROM message WHERE owner=? AND jid=?", owner, jid)
func (mq *MessageQuery) GetByJID(chat PortalKey, jid types.WhatsAppMessageID) *Message {
return mq.get("SELECT * FROM message WHERE chat_jid=? AND chat_receiver=? AND jid=?", chat.JID, chat.Receiver, jid)
}
func (mq *MessageQuery) GetByMXID(mxid types.MatrixEventID) *Message {
@ -79,13 +80,13 @@ type Message struct {
db *Database
log log.Logger
Owner types.MatrixUserID
JID types.WhatsAppMessageID
MXID types.MatrixEventID
Chat PortalKey
JID types.WhatsAppMessageID
MXID types.MatrixEventID
}
func (msg *Message) Scan(row Scannable) *Message {
err := row.Scan(&msg.Owner, &msg.JID, &msg.MXID)
err := row.Scan(&msg.Chat.JID, &msg.Chat.Receiver, &msg.JID, &msg.MXID)
if err != nil {
if err != sql.ErrNoRows {
msg.log.Errorln("Database scan failed:", err)
@ -96,17 +97,17 @@ func (msg *Message) Scan(row Scannable) *Message {
}
func (msg *Message) Insert() error {
_, err := msg.db.Exec("INSERT INTO message VALUES (?, ?, ?)", msg.Owner, msg.JID, msg.MXID)
_, err := msg.db.Exec("INSERT INTO message VALUES (?, ?, ?)", msg.Chat.JID, msg.Chat.Receiver, msg.JID, msg.MXID)
if err != nil {
msg.log.Warnfln("Failed to update %s->%s: %v", msg.Owner, msg.JID, err)
msg.log.Warnfln("Failed to update %s: %v", msg.Chat, msg.JID, err)
}
return err
}
func (msg *Message) Update() error {
_, err := msg.db.Exec("UPDATE portal SET mxid=? WHERE owner=? AND jid=?", msg.MXID, msg.Owner, msg.JID)
_, err := msg.db.Exec("UPDATE portal SET mxid=? WHERE chat_jid=? AND chat_receiver=? AND jid=?", msg.MXID, msg.Chat.JID, msg.Chat.Receiver, msg.JID)
if err != nil {
msg.log.Warnfln("Failed to update %s->%s: %v", msg.Owner, msg.JID, err)
msg.log.Warnfln("Failed to update %s: %v", msg.Chat, msg.JID, err)
}
return err
}

View File

@ -18,11 +18,41 @@ package database
import (
"database/sql"
"strings"
log "maunium.net/go/maulogger"
"maunium.net/go/mautrix-whatsapp/types"
)
type PortalKey struct {
JID types.WhatsAppID
Receiver types.WhatsAppID
}
func GroupPortalKey(jid types.WhatsAppID) PortalKey {
return PortalKey{
JID: jid,
Receiver: jid,
}
}
func NewPortalKey(jid, receiver types.WhatsAppID) PortalKey {
if strings.HasSuffix(jid, "@g.us") {
receiver = jid
}
return PortalKey{
JID: jid,
Receiver: receiver,
}
}
func (key PortalKey) String() string {
if key.Receiver == key.JID {
return key.JID
}
return key.JID + "-" + key.Receiver
}
type PortalQuery struct {
db *Database
log log.Logger
@ -30,16 +60,16 @@ type PortalQuery struct {
func (pq *PortalQuery) CreateTable() error {
_, err := pq.db.Exec(`CREATE TABLE IF NOT EXISTS portal (
jid VARCHAR(255),
owner VARCHAR(255),
mxid VARCHAR(255) UNIQUE,
jid VARCHAR(25),
receiver VARCHAR(25),
mxid VARCHAR(255) UNIQUE,
name VARCHAR(255) NOT NULL,
topic VARCHAR(255) NOT NULL,
avatar VARCHAR(255) NOT NULL,
PRIMARY KEY (jid, owner),
FOREIGN KEY (owner) REFERENCES user(mxid)
PRIMARY KEY (jid, receiver),
FOREIGN KEY (receiver) REFERENCES user(mxid)
)`)
return err
}
@ -51,8 +81,8 @@ func (pq *PortalQuery) New() *Portal {
}
}
func (pq *PortalQuery) GetAll(owner types.MatrixUserID) (portals []*Portal) {
rows, err := pq.db.Query("SELECT * FROM portal WHERE owner=?", owner)
func (pq *PortalQuery) GetAll() (portals []*Portal) {
rows, err := pq.db.Query("SELECT * FROM portal")
if err != nil || rows == nil {
return nil
}
@ -63,8 +93,8 @@ func (pq *PortalQuery) GetAll(owner types.MatrixUserID) (portals []*Portal) {
return
}
func (pq *PortalQuery) GetByJID(owner types.MatrixUserID, jid types.WhatsAppID) *Portal {
return pq.get("SELECT * FROM portal WHERE jid=? AND owner=?", jid, owner)
func (pq *PortalQuery) GetByJID(key PortalKey) *Portal {
return pq.get("SELECT * FROM portal WHERE jid=? AND receiver=?", key.JID, key.Receiver)
}
func (pq *PortalQuery) GetByMXID(mxid types.MatrixRoomID) *Portal {
@ -83,9 +113,8 @@ type Portal struct {
db *Database
log log.Logger
JID types.WhatsAppID
MXID types.MatrixRoomID
Owner types.MatrixUserID
Key PortalKey
MXID types.MatrixRoomID
Name string
Topic string
@ -93,7 +122,7 @@ type Portal struct {
}
func (portal *Portal) Scan(row Scannable) *Portal {
err := row.Scan(&portal.JID, &portal.Owner, &portal.MXID, &portal.Name, &portal.Topic, &portal.Avatar)
err := row.Scan(&portal.Key.JID, &portal.Key.Receiver, &portal.MXID, &portal.Name, &portal.Topic, &portal.Avatar)
if err != nil {
if err != sql.ErrNoRows {
portal.log.Errorln("Database scan failed:", err)
@ -103,15 +132,18 @@ func (portal *Portal) Scan(row Scannable) *Portal {
return portal
}
func (portal *Portal) Insert() error {
var mxid *string
func (portal *Portal) mxidPtr() *string {
if len(portal.MXID) > 0 {
mxid = &portal.MXID
return &portal.MXID
}
return nil
}
func (portal *Portal) Insert() error {
_, err := portal.db.Exec("INSERT INTO portal VALUES (?, ?, ?, ?, ?, ?)",
portal.JID, portal.Owner, mxid, portal.Name, portal.Topic, portal.Avatar)
portal.Key.JID, portal.Key.Receiver, portal.mxidPtr(), portal.Name, portal.Topic, portal.Avatar)
if err != nil {
portal.log.Warnfln("Failed to insert %s->%s: %v", portal.JID, portal.Owner, err)
portal.log.Warnfln("Failed to insert %s: %v", portal.Key, err)
}
return err
}
@ -121,10 +153,10 @@ func (portal *Portal) Update() error {
if len(portal.MXID) > 0 {
mxid = &portal.MXID
}
_, err := portal.db.Exec("UPDATE portal SET mxid=?, name=?, topic=?, avatar=? WHERE jid=? AND owner=?",
mxid, portal.Name, portal.Topic, portal.Avatar, portal.JID, portal.Owner)
_, err := portal.db.Exec("UPDATE portal SET mxid=?, name=?, topic=?, avatar=? WHERE jid=? AND receiver=?",
mxid, portal.Name, portal.Topic, portal.Avatar, portal.Key.JID, portal.Key.Receiver)
if err != nil {
portal.log.Warnfln("Failed to update %s->%s: %v", portal.JID, portal.Owner, err)
portal.log.Warnfln("Failed to update %s: %v", portal.Key, err)
}
return err
}

View File

@ -30,13 +30,9 @@ type PuppetQuery struct {
func (pq *PuppetQuery) CreateTable() error {
_, err := pq.db.Exec(`CREATE TABLE IF NOT EXISTS puppet (
jid VARCHAR(255),
receiver VARCHAR(255),
jid VARCHAR(25) PRIMARY KEY,
displayname VARCHAR(255),
avatar VARCHAR(255),
PRIMARY KEY(jid, receiver)
avatar VARCHAR(255)
)`)
return err
}
@ -48,8 +44,8 @@ func (pq *PuppetQuery) New() *Puppet {
}
}
func (pq *PuppetQuery) GetAll(receiver types.MatrixUserID) (puppets []*Puppet) {
rows, err := pq.db.Query("SELECT * FROM puppet WHERE receiver=%s")
func (pq *PuppetQuery) GetAll() (puppets []*Puppet) {
rows, err := pq.db.Query("SELECT * FROM puppet")
if err != nil || rows == nil {
return nil
}
@ -60,8 +56,8 @@ func (pq *PuppetQuery) GetAll(receiver types.MatrixUserID) (puppets []*Puppet) {
return
}
func (pq *PuppetQuery) Get(jid types.WhatsAppID, receiver types.MatrixUserID) *Puppet {
row := pq.db.QueryRow("SELECT * FROM puppet WHERE jid=? AND receiver=?", jid, receiver)
func (pq *PuppetQuery) Get(jid types.WhatsAppID) *Puppet {
row := pq.db.QueryRow("SELECT * FROM puppet WHERE jid=?", jid)
if row == nil {
return nil
}
@ -72,15 +68,13 @@ type Puppet struct {
db *Database
log log.Logger
JID types.WhatsAppID
Receiver types.MatrixUserID
JID types.WhatsAppID
Displayname string
Avatar string
}
func (puppet *Puppet) Scan(row Scannable) *Puppet {
err := row.Scan(&puppet.JID, &puppet.Receiver, &puppet.Displayname, &puppet.Avatar)
err := row.Scan(&puppet.JID, &puppet.Displayname, &puppet.Avatar)
if err != nil {
if err != sql.ErrNoRows {
puppet.log.Errorln("Database scan failed:", err)
@ -91,20 +85,19 @@ func (puppet *Puppet) Scan(row Scannable) *Puppet {
}
func (puppet *Puppet) Insert() error {
_, err := puppet.db.Exec("INSERT INTO puppet VALUES (?, ?, ?, ?)",
puppet.JID, puppet.Receiver, puppet.Displayname, puppet.Avatar)
_, err := puppet.db.Exec("INSERT INTO puppet VALUES (?, ?, ?)",
puppet.JID, puppet.Displayname, puppet.Avatar)
if err != nil {
puppet.log.Errorfln("Failed to insert %s->%s: %v", puppet.JID, puppet.Receiver, err)
puppet.log.Errorfln("Failed to insert %s: %v", puppet.JID, err)
}
return err
}
func (puppet *Puppet) Update() error {
_, err := puppet.db.Exec("UPDATE puppet SET displayname=?, avatar=? WHERE jid=? AND receiver=?",
puppet.Displayname, puppet.Avatar,
puppet.JID, puppet.Receiver)
_, err := puppet.db.Exec("UPDATE puppet SET displayname=?, avatar=? WHERE jid=?",
puppet.Displayname, puppet.Avatar, puppet.JID)
if err != nil {
puppet.log.Errorfln("Failed to update %s->%s: %v", puppet.JID, puppet.Receiver, err)
puppet.log.Errorfln("Failed to update %s->%s: %v", puppet.JID, err)
}
return err
}

View File

@ -32,6 +32,7 @@ type UserQuery struct {
func (uq *UserQuery) CreateTable() error {
_, err := uq.db.Exec(`CREATE TABLE IF NOT EXISTS user (
mxid VARCHAR(255) PRIMARY KEY,
jid VARCHAR(25) UNIQUE,
management_room VARCHAR(255),
@ -64,7 +65,7 @@ func (uq *UserQuery) GetAll() (users []*User) {
return
}
func (uq *UserQuery) Get(userID types.MatrixUserID) *User {
func (uq *UserQuery) GetByMXID(userID types.MatrixUserID) *User {
row := uq.db.QueryRow("SELECT * FROM user WHERE mxid=?", userID)
if row == nil {
return nil
@ -72,18 +73,27 @@ func (uq *UserQuery) Get(userID types.MatrixUserID) *User {
return uq.New().Scan(row)
}
func (uq *UserQuery) GetByJID(userID types.WhatsAppID) *User {
row := uq.db.QueryRow("SELECT * FROM user WHERE jid=?", userID)
if row == nil {
return nil
}
return uq.New().Scan(row)
}
type User struct {
db *Database
log log.Logger
ID types.MatrixUserID
MXID types.MatrixUserID
JID types.WhatsAppID
ManagementRoom types.MatrixRoomID
Session *whatsapp.Session
}
func (user *User) Scan(row Scannable) *User {
sess := whatsapp.Session{}
err := row.Scan(&user.ID, &user.ManagementRoom, &sess.ClientId, &sess.ClientToken, &sess.ServerToken,
err := row.Scan(&user.MXID, &user.JID, &user.ManagementRoom, &sess.ClientId, &sess.ClientToken, &sess.ServerToken,
&sess.EncKey, &sess.MacKey, &sess.Wid)
if err != nil {
if err != sql.ErrNoRows {
@ -99,23 +109,32 @@ func (user *User) Scan(row Scannable) *User {
return user
}
func (user *User) Insert() error {
var sess whatsapp.Session
func (user *User) jidPtr() *string {
if len(user.JID) > 0 {
return &user.JID
}
return nil
}
func (user *User) sessionUnptr() (sess whatsapp.Session) {
if user.Session != nil {
sess = *user.Session
}
_, err := user.db.Exec("INSERT INTO user VALUES (?, ?, ?, ?, ?, ?, ?, ?)", user.ID, user.ManagementRoom,
return
}
func (user *User) Insert() error {
sess := user.sessionUnptr()
_, err := user.db.Exec("INSERT INTO user VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", user.MXID, user.jidPtr(), user.ManagementRoom,
sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey, sess.Wid)
return err
}
func (user *User) Update() error {
var sess whatsapp.Session
if user.Session != nil {
sess = *user.Session
}
_, err := user.db.Exec("UPDATE user SET management_room=?, client_id=?, client_token=?, server_token=?, enc_key=?, mac_key=?, wid=? WHERE mxid=?",
user.ManagementRoom,
sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey, sess.Wid, user.ID)
sess := user.sessionUnptr()
_, err := user.db.Exec("UPDATE user SET jid=?, management_room=?, client_id=?, client_token=?, server_token=?, enc_key=?, mac_key=?, wid=? WHERE mxid=?",
user.jidPtr(), user.ManagementRoom,
sess.ClientId, sess.ClientToken, sess.ServerToken, sess.EncKey, sess.MacKey, sess.Wid,
user.MXID)
return err
}