Contact management
This commit is contained in:
parent
8ccfeccba9
commit
c49fe5ac93
52
account.go
52
account.go
|
@ -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
11
chan.go
|
@ -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,
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue