Merge pull request #37 from status-im/1to1

Add support for 1 to 1 conversations
This commit is contained in:
Adrià Cidre 2018-07-16 16:52:49 +02:00 committed by GitHub
commit b1a2ec4d2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 140 additions and 27 deletions

View File

@ -62,7 +62,8 @@ func (a *Account) OnContactRequest(fn ContactRequestHandler) error {
ChannelPubKey: a.PubKey,
}
_, err = discoveryChannel.Subscribe(func(msg *Msg) {
var sub *Subscription
sub, err = discoveryChannel.Subscribe(func(msg *Msg) {
switch c := msg.Properties.(type) {
case *NewContactKeyMsg:
fn(&Contact{
@ -72,6 +73,9 @@ func (a *Account) OnContactRequest(fn ContactRequestHandler) error {
Name: c.Contact.Name,
Address: c.Contact.Address,
Image: c.Contact.Image,
ch: discoveryChannel,
sub: sub,
PubKey: msg.PubKey,
})
}
})

View File

@ -86,6 +86,10 @@ func (c *Channel) Publish(body string) error {
visibility = c.visibility
}
return c.publish(body, visibility)
}
func (c *Channel) publish(body, visibility string) error {
now := time.Now().Unix() * 1000
format := `["%s",["%s","text/plain","%s",%d,%d]]`

View File

@ -4,11 +4,13 @@ package sdk
type Contact struct {
account *Account
ch *Channel
sub *Subscription
SymKey string
TopicID string
Name string
Image string
Address string
PubKey string
}
// Accept accepts a contact as a friend, sends back a ConfirmedContactRequest
@ -18,6 +20,7 @@ func (c *Contact) Accept() error {
if err != nil {
return err
}
c.ch, err = c.account.Join(c.Name, c.TopicID, symkey)
if err != nil {
return err
@ -28,3 +31,14 @@ func (c *Contact) Accept() error {
// ContactRequestHandler handler for contact requests
type ContactRequestHandler func(*Contact)
// Subscribe to 1 to 1 messages from he current contact.
func (c *Contact) Subscribe(fn MsgHandler) (*Subscription, error) {
c.sub.AddHook(c.PubKey, fn)
return c.sub, nil
}
// Publish send a 1 to 1 message to the current contact.
func (c *Contact) Publish(body string) error {
return c.ch.publish(body, "~:user-message")
}

60
examples/1to1/main.go Normal file
View File

@ -0,0 +1,60 @@
package main
import (
"log"
"runtime"
"github.com/ethereum/go-ethereum/rpc"
"github.com/status-im/status-go-sdk"
"github.com/status-im/status-go-sdk/examples/lib"
)
const (
botUsername = "1to1bot"
)
func main() {
rpcClient, err := rpc.Dial("http://localhost:8545")
checkErr(err)
client := sdk.New(rpcClient)
bot, err := client.SignupAndLogin("password")
bot.Username = botUsername
bot.Image = lib.BotImage
// Wait for contact requests
err = bot.OnContactRequest(func(ct *sdk.Contact) {
log.Println("Received contact request from " + ct.Name)
log.Println("Accepting " + ct.Name + "'s contact request'")
checkErr(ct.Accept())
_, err = ct.Subscribe(func(m *sdk.Msg) {
if m.Type != sdk.StandardMessageType {
return
}
properties := m.Properties.(*sdk.PublishMsg)
log.Println(properties.Text)
// Print the response.
err = ct.Publish(lib.AskMitsuku(properties.Text))
checkErr(err)
})
checkErr(err)
})
checkErr(err)
log.Println("Making the bot visible on a public channel so you can easily get its address")
ch, err := bot.JoinPublicChannel("supu")
checkErr(err)
err = ch.Publish("hey there! I'm " + botUsername + ", and I am accepting contact requests :P")
checkErr(err)
runtime.Goexit()
}
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}

File diff suppressed because one or more lines are too long

29
examples/lib/mitsuku.go Normal file

File diff suppressed because one or more lines are too long

View File

@ -4,15 +4,12 @@
package main
import (
"io/ioutil"
"log"
"net/http"
"net/url"
"runtime"
"strings"
"github.com/ethereum/go-ethereum/rpc"
sdk "github.com/status-im/status-go-sdk"
"github.com/status-im/status-go-sdk/examples/lib"
)
func checkErr(err error) {
@ -45,26 +42,9 @@ func main() {
properties := m.Properties.(*sdk.PublishMsg)
// Print the response.
err := ch.Publish(askMitsuku(properties.Text))
err := ch.Publish(lib.AskMitsuku(properties.Text))
checkErr(err)
})
runtime.Goexit()
}
func askMitsuku(question string) string {
hc := http.Client{}
uri := "https://kakko.pandorabots.com/pandora/talk?botid=87437a824e345a0d&skin=chat"
form := url.Values{}
form.Add("message", question)
req, _ := http.NewRequest("POST", uri, strings.NewReader(form.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, _ := hc.Do(req)
body, _ := ioutil.ReadAll(resp.Body)
parts := strings.Split(string(body), "</B>")
parts = strings.Split(parts[2], "<br>")
return strings.Trim(parts[0], " ")
}

1
msg.go
View File

@ -145,6 +145,7 @@ type PublishMsg struct {
Visibility string
ClockValue float64
Timestamp float64
Address string
}
func publishMsgFromProperties(properties []interface{}) *PublishMsg {

View File

@ -12,6 +12,7 @@ type MsgHandler func(msg *Msg)
type Subscription struct {
unsubscribe chan bool
channel *Channel
hooks map[string]MsgHandler
}
// Subscribe polls on specific channel topic and executes given function if
@ -23,8 +24,19 @@ func (s *Subscription) Subscribe(channel *Channel, fn MsgHandler) {
case <-s.unsubscribe:
return
default:
if msg := channel.pollMessages(); msg != nil {
fn(msg)
if m := channel.pollMessages(); m != nil {
if properties, ok := m.Properties.(*PublishMsg); ok {
if properties.Visibility == "~:user-message" {
for k := range s.hooks {
println(k)
}
if hook, ok := s.hooks[m.PubKey]; ok {
hook(m)
continue
}
}
}
fn(m)
}
}
// TODO(adriacidre) : move this period to configuration
@ -37,3 +49,12 @@ func (s *Subscription) Unsubscribe() {
s.unsubscribe <- true
s.channel.removeSubscription(s)
}
// AddHook adds a hook to the current subscription to be exectuted when the
// message is received from a specific address.
func (s *Subscription) AddHook(pubkey string, fn MsgHandler) {
if s.hooks == nil {
s.hooks = make(map[string]MsgHandler)
}
s.hooks[pubkey] = fn
}