Save client pickle automatically (messenger)

This commit is contained in:
Alex 2020-03-09 18:02:13 +01:00
parent f9e0c58f3c
commit 7c39436eda
4 changed files with 76 additions and 40 deletions

View file

@ -39,41 +39,40 @@ func SetAccount(mxid string, name string, protocol string, config map[string]str
} }
accounts := registeredAccounts[mxid] accounts := registeredAccounts[mxid]
if prev_acct, ok := accounts[name]; ok { // Check we can create connector
if protocol != prev_acct.Protocol { proto, ok := Protocols[protocol]
return fmt.Errorf("Wrong protocol") if !ok {
} return fmt.Errorf("Invalid protocol: %s", protocol)
if !reflect.DeepEqual(config, prev_acct.Config) {
go func() {
prev_acct.Conn.Close()
prev_acct.JoinedRooms = map[RoomID]bool{}
prev_acct.Config = config
prev_acct.connect()
}()
}
} else {
proto, ok := Protocols[protocol]
if !ok {
return fmt.Errorf("Invalid protocol: %s", protocol)
}
conn := proto.NewConnector()
if conn == nil {
return fmt.Errorf("Could not create connector for protocol %s", protocol)
}
account := &Account{
MatrixUser: mxid,
AccountName: name,
Protocol: protocol,
Config: config,
Conn: conn,
JoinedRooms: map[RoomID]bool{},
}
conn.SetHandler(account)
accounts[name] = account
go account.connect()
} }
conn := proto.NewConnector()
if conn == nil {
return fmt.Errorf("Could not create connector for protocol %s", protocol)
}
// If the account existed already, close and drop connector
if prev_acct, ok := accounts[name]; ok {
if prev_acct.Protocol == protocol && reflect.DeepEqual(config, prev_acct.Config) {
return nil
}
go prev_acct.Conn.Close()
delete(accounts, name)
}
// Configure and connect
account := &Account{
MatrixUser: mxid,
AccountName: name,
Protocol: protocol,
Config: config,
Conn: conn,
JoinedRooms: map[RoomID]bool{},
}
conn.SetHandler(account)
accounts[name] = account
go account.connect()
return nil return nil
} }
@ -232,6 +231,20 @@ func (a *Account) delAutojoin(roomId RoomID) {
// ---- Begin event handlers ---- // ---- Begin event handlers ----
func (a *Account) SaveConfig(config Configuration) {
a.Config = config
if key, ok := userKeys[a.MatrixUser]; ok {
var entry DbAccountConfig
db.Where(&DbAccountConfig{
MxUserID: a.MatrixUser,
Name: a.AccountName,
}).Assign(&DbAccountConfig{
Protocol: a.Protocol,
Config: encryptAccountConfig(a.Config, key),
}).FirstOrCreate(&entry)
}
}
func (a *Account) Joined(roomId RoomID) { func (a *Account) Joined(roomId RoomID) {
err := a.joinedInternal(roomId) err := a.joinedInternal(roomId)
if err != nil { if err != nil {

View file

@ -76,6 +76,9 @@ type Connector interface {
} }
type Handler interface { type Handler interface {
// Called to save updated configuration parameters
SaveConfig(config Configuration)
// Called when a room was joined (automatically or by call to Connector.Join) // Called when a room was joined (automatically or by call to Connector.Join)
Joined(roomId RoomID) Joined(roomId RoomID)

View file

@ -54,6 +54,7 @@ const (
CLOSE = "close" CLOSE = "close"
// external -> ezbr // external -> ezbr
SAVE_CONFIG = "save_config"
JOINED = "joined" JOINED = "joined"
LEFT = "left" LEFT = "left"
USER_INFO_UPDATED = "user_info_updated" USER_INFO_UPDATED = "user_info_updated"
@ -198,6 +199,16 @@ func (m *extMessageWithData) UnmarshalJSON(jj []byte) error {
} }
*m = extMessageWithData{extMessage: c} *m = extMessageWithData{extMessage: c}
switch c.MsgType { switch c.MsgType {
case SAVE_CONFIG:
var cf struct {
Data Configuration `json:"data"`
}
err := json.Unmarshal(jj, &cf)
if err != nil {
return err
}
m.Data = cf.Data
return nil
case USER_INFO_UPDATED: case USER_INFO_UPDATED:
var ui struct { var ui struct {
Data UserInfo `json:"data"` Data UserInfo `json:"data"`
@ -229,14 +240,14 @@ func (m *extMessageWithData) UnmarshalJSON(jj []byte) error {
m.Data = &ev.Data m.Data = &ev.Data
return nil return nil
case REP_SEARCH_RESULTS: case REP_SEARCH_RESULTS:
var ev struct { var sr struct {
Data []UserSearchResult `json:"data"` Data []UserSearchResult `json:"data"`
} }
err := json.Unmarshal(jj, &ev) err := json.Unmarshal(jj, &sr)
if err != nil { if err != nil {
return err return err
} }
m.Data = ev.Data m.Data = sr.Data
return nil return nil
case JOINED, LEFT, CACHE_PUT, CACHE_GET, REP_OK, REP_ERROR: case JOINED, LEFT, CACHE_PUT, CACHE_GET, REP_OK, REP_ERROR:
return nil return nil
@ -364,6 +375,8 @@ func (ext *External) Close() {
func (ext *External) handleCmd(msg *extMessageWithData) { func (ext *External) handleCmd(msg *extMessageWithData) {
switch msg.MsgType { switch msg.MsgType {
case SAVE_CONFIG:
ext.handler.SaveConfig(msg.Data.(Configuration))
case JOINED: case JOINED:
ext.handler.Joined(msg.Room) ext.handler.Joined(msg.Room)
case LEFT: case LEFT:

13
external/messenger.py vendored
View file

@ -1,7 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# @FIXME: store the client pickle in the config automatically
import sys import sys
import json import json
import signal import signal
@ -34,6 +32,7 @@ SEND = "send"
CLOSE = "close" CLOSE = "close"
# external -> ezbr # external -> ezbr
SAVE_CONFIG = "save_config"
JOINED = "joined" JOINED = "joined"
LEFT = "left" LEFT = "left"
USER_INFO_UPDATED = "user_info_updated" USER_INFO_UPDATED = "user_info_updated"
@ -228,7 +227,8 @@ class MessengerBridge:
if ty == CONFIGURE: if ty == CONFIGURE:
self.init_backlog_length = int(cmd["data"]["initial_backlog"]) self.init_backlog_length = int(cmd["data"]["initial_backlog"])
if "client_pickle" in cmd["data"] and len(cmd["data"]["client_pickle"]) > 0: has_pickle = "client_pickle" in cmd["data"] and len(cmd["data"]["client_pickle"]) > 0
if has_pickle:
data = base64.b64decode(cmd["data"]["client_pickle"]) data = base64.b64decode(cmd["data"]["client_pickle"])
data = zlib.decompress(data) data = zlib.decompress(data)
self.client = pickle.loads(data) self.client = pickle.loads(data)
@ -240,6 +240,13 @@ class MessengerBridge:
if not self.client.isLoggedIn(): if not self.client.isLoggedIn():
return {"_type": REP_ERROR, "error": "Unable to login (invalid pickle?)"} return {"_type": REP_ERROR, "error": "Unable to login (invalid pickle?)"}
if not has_pickle:
new_config = cmd["data"]
data = pickle.dumps(self.client)
data = zlib.compress(data)
new_config["client_pickle"] = base64.b64encode(data).decode('ascii')
self.write({"_type": SAVE_CONFIG, "data": new_config})
self.client.setBridge(self) self.client.setBridge(self)
self.my_user_id = self.getUserIdFromUid(self.client.uid) self.my_user_id = self.getUserIdFromUid(self.client.uid)