Merge pull request #32 from status-im/contact

Contact management
This commit is contained in:
Adrià Cidre 2018-06-15 09:29:08 +02:00 committed by GitHub
commit 537a851a94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 160 additions and 24 deletions

View File

@ -12,6 +12,7 @@ type Account struct {
PubKey string
Mnemonic string
Username string
Image string
channels []*Channel
}
@ -39,19 +40,58 @@ func (a *Account) createAndJoin(name, password string) (*Channel, error) {
return a.Join(name, topicID, symKey)
}
// OnContactRequest executes specified ContactRequestHandler logic when a contact
// request is received
func (a *Account) OnContactRequest(fn ContactRequestHandler) error {
topicID, err := a.calculatePublicChannelTopicID(discoveryChannelName)
if err != nil {
return err
}
filterID, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, "", a.PubKey)
if err != nil {
println(err.Error())
return err
}
discoveryChannel := &Channel{
account: a,
name: discoveryChannelName,
filterID: filterID,
TopicID: topicID,
ChannelPubKey: a.PubKey,
}
_, err = discoveryChannel.Subscribe(func(msg *Msg) {
switch c := msg.Properties.(type) {
case *NewContactKeyMsg:
fn(&Contact{
account: a,
SymKey: c.Address,
TopicID: c.Topic,
Name: c.Contact.Name,
Address: c.Contact.Address,
Image: c.Contact.Image,
})
}
})
return err
}
// Join joins a status channel
func (a *Account) Join(channelName, topicID, symKey string) (*Channel, error) {
filterID, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, symKey)
filterID, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, symKey, "")
if err != nil {
return nil, err
}
ch := &Channel{
account: a,
name: channelName,
filterID: filterID,
TopicID: topicID,
ChannelKey: symKey,
account: a,
name: channelName,
filterID: filterID,
TopicID: topicID,
ChannelSymKey: symKey,
}
a.channels = append(a.channels, ch)

11
chan.go
View File

@ -7,12 +7,15 @@ import (
"time"
)
const discoveryChannelName = "contact-discovery"
// Channel : ...
type Channel struct {
account *Account
name string
filterID string
ChannelKey string
ChannelSymKey string
ChannelPubKey string
TopicID string
visibility string
subscriptions []*Subscription
@ -69,9 +72,9 @@ func (c *Channel) ContactRequest(username, image string) error {
// contact accepts the contact request. It will be sent on the topic that
// was provided in the NewContactKey message and use the sym-key.
// Both users will therefore have the same filter.
func (c *Channel) ConfirmedContactRequest(username, image string) error {
func (c *Channel) ConfirmedContactRequest(ct *Contact) error {
format := `["%s",["%s","%s","%s","%s"]]`
msg := fmt.Sprintf(format, ConfirmedContactRequestType, username, image, c.account.Address, "")
msg := fmt.Sprintf(format, ConfirmedContactRequestType, c.account.Username, c.account.Image, c.account.Address, "")
return c.SendPostRawMsg(msg)
}
@ -118,7 +121,7 @@ func (c *Channel) ContactUpdateRequest(username, image string) error {
func (c *Channel) SendPostRawMsg(body string) error {
msg := Message{
Signature: c.account.AddressKeyID,
SymKeyID: c.ChannelKey,
SymKeyID: c.ChannelSymKey,
Payload: rawrChatMessage(body),
Topic: c.TopicID,
TTL: 10,

30
contact.go Normal file
View File

@ -0,0 +1,30 @@
package sdk
// Contact details for a known user
type Contact struct {
account *Account
ch *Channel
SymKey string
TopicID string
Name string
Image string
Address string
}
// Accept accepts a contact as a friend, sends back a ConfirmedContactRequest
func (c *Contact) Accept() error {
// Add the proposed symkey
symkey, err := addSymKey(c.account.conn, c.SymKey)
if err != nil {
return err
}
c.ch, err = c.account.Join(c.Name, c.TopicID, symkey)
if err != nil {
return err
}
return c.ch.ConfirmedContactRequest(c)
}
// ContactRequestHandler handler for contact requests
type ContactRequestHandler func(*Contact)

View File

@ -7,20 +7,28 @@ func shhGenerateSymKeyFromPasswordRequest(sdk *SDK, password string) (string, er
}
type shhFilterFormatParam struct {
AllowP2P bool `json:"allowP2P"`
Topics []string `json:"topics"`
Type string `json:"type"`
SymKeyID string `json:"symKeyID"`
AllowP2P bool `json:"allowP2P"`
Topics []string `json:"topics"`
Type string `json:"type"`
SymKeyID string `json:"symKeyID"`
PrivateKeyID string `json:"privateKeyID"`
}
func newShhMessageFilterFormatRequest(sdk *SDK, topics []string, symKey string) (string, error) {
func newShhMessageFilterFormatRequest(sdk *SDK, topics []string, symKey, privateKeyID string) (string, error) {
// `{"jsonrpc":"2.0","id":2,"method":"shh_newMessageFilter","params":[{"allowP2P":true,"topics":["%s"],"type":"sym","symKeyID":"%s"}]}`
var res string
params := &shhFilterFormatParam{
AllowP2P: true,
Topics: topics,
Type: "sym",
SymKeyID: symKey,
AllowP2P: true,
Topics: topics,
Type: "sym",
SymKeyID: symKey,
PrivateKeyID: privateKeyID,
}
if len(symKey) > 0 {
params.SymKeyID = symKey
}
if len(privateKeyID) > 0 {
params.PrivateKeyID = privateKeyID
}
return res, sdk.RPCClient.Call(&res, "shh_newMessageFilter", params)
@ -83,7 +91,8 @@ func shhGetFilterMessagesRequest(sdk *SDK, filter string) (interface{}, error) {
// Message message to be sent though ssh_post calls
type Message struct {
Signature string `json:"sig"`
SymKeyID string `json:"symKeyID"`
SymKeyID string `json:"symKeyID,omitempty"`
PubKey string `json:"pubKey,omitempty"`
Payload string `json:"payload"`
Topic string `json:"topic"`
TTL uint32 `json:"ttl"`
@ -93,5 +102,11 @@ type Message struct {
func shhPostRequest(sdk *SDK, msg *Message) (string, error) {
var res string
return res, sdk.RPCClient.Call(&res, "shh_post", msg)
return res, sdk.RPCClient.Call(&res, "shhext_post", msg)
}
func addSymKey(sdk *SDK, symKey string) (string, error) {
// {"jsonrpc":"2.0","method":"shh_addSymKey", "params":["` + symkey + `"], "id":1}
var res string
return res, sdk.RPCClient.Call(&res, "shh_addSymKey", symKey)
}

View File

@ -59,7 +59,7 @@ func TestDictionaryMethods(t *testing.T) {
{
Description: "shhPostRequest",
Response: &str,
Method: "shh_post",
Method: "shhext_post",
Params: &Message{},
Callback: func(sdk *SDK) {
response, err := shhPostRequest(sdk, &Message{})
@ -100,7 +100,7 @@ func TestDictionaryMethods(t *testing.T) {
SymKeyID: "",
},
Callback: func(sdk *SDK) {
response, err := newShhMessageFilterFormatRequest(sdk, []string{}, "")
response, err := newShhMessageFilterFormatRequest(sdk, []string{}, "", "")
assert.NoError(t, err)
assert.NotNil(t, response)
},

48
examples/contact/main.go Normal file

File diff suppressed because one or more lines are too long

2
msg.go
View File

@ -166,7 +166,7 @@ type ContactMsg struct {
}
func contactMsgFromProperties(properties []interface{}) *ContactMsg {
crProperties := properties[2].([]interface{})
crProperties := properties[1].([]interface{})
return &ContactMsg{
Name: crProperties[0].(string),