forked from openprivacy/libricochet-go
Cleaning up and documenting examples
This commit is contained in:
parent
8f00e26b81
commit
64ce11d436
|
@ -15,7 +15,7 @@ pipeline:
|
||||||
image: golang
|
image: golang
|
||||||
commands:
|
commands:
|
||||||
- go list ./... | xargs go vet
|
- go list ./... | xargs go vet
|
||||||
- go list ./... | grep -v "/wire/" | grep -v "/examples/" | xargs golint -set_exit_status
|
- go list ./... | grep -v "/wire/" | xargs golint -set_exit_status
|
||||||
units-tests:
|
units-tests:
|
||||||
image: golang
|
image: golang
|
||||||
commands:
|
commands:
|
||||||
|
|
|
@ -4,3 +4,6 @@ go-ricochet-coverage.out
|
||||||
.idea
|
.idea
|
||||||
.reviewboardrc
|
.reviewboardrc
|
||||||
/vendor/
|
/vendor/
|
||||||
|
/testing/tor/
|
||||||
|
/connectivity/tor/
|
||||||
|
/tor/
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
package alicebot
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewAliceBot creates a new AliceBot and establishes a connection to the given onion server.
|
||||||
|
func NewAliceBot(acn connectivity.ACN, onion string) AliceBot {
|
||||||
|
alice := new(alicebot)
|
||||||
|
alice.messages = make(map[uint32]string)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
alice.pub, alice.priv, err = ed25519.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("[alice] error generating key: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
rc, err := goricochet.Open(acn, onion)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("[alice] error connecting to echobot: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = connection.HandleOutboundConnection(rc).ProcessAuthAsV3Client(identity.InitializeV3("alice", &alice.priv, &alice.pub))
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("[alice] failed to authenticate connection: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
alice.rc = rc
|
||||||
|
|
||||||
|
ach := connection.AutoConnectionHandler{}
|
||||||
|
ach.Init()
|
||||||
|
|
||||||
|
ach.RegisterChannelHandler("im.ricochet.chat", func() channels.Handler {
|
||||||
|
chat := new(channels.ChatChannel)
|
||||||
|
chat.Handler = alice
|
||||||
|
return chat
|
||||||
|
})
|
||||||
|
|
||||||
|
go alice.rc.Process(&ach)
|
||||||
|
|
||||||
|
log.Infof("[alice] requesting channel...")
|
||||||
|
alice.rc.Do(func() error {
|
||||||
|
chatchannel := channels.ChatChannel{}
|
||||||
|
chatchannel.Handler = alice
|
||||||
|
|
||||||
|
_, err := alice.rc.RequestOpenChannel("im.ricochet.chat", &chatchannel)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed requestopenchannel: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return alice
|
||||||
|
}
|
||||||
|
|
||||||
|
type alicebot struct {
|
||||||
|
messages map[uint32]string
|
||||||
|
pub ed25519.PublicKey
|
||||||
|
priv ed25519.PrivateKey
|
||||||
|
mID int
|
||||||
|
rc *connection.Connection
|
||||||
|
}
|
||||||
|
|
||||||
|
// AliceBot is an interface for alicebot, allowing callers to send and receive messages.
|
||||||
|
type AliceBot interface {
|
||||||
|
channels.ChatChannelHandler
|
||||||
|
SendMessage(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendMessage can be called to send a message to EchoBot
|
||||||
|
func (ab *alicebot) SendMessage(message string) {
|
||||||
|
// The following code opens (or creates) a new im.ricochet.chat channel to the connected service
|
||||||
|
// and sends a message.
|
||||||
|
log.Infof("[alice] sending...")
|
||||||
|
ab.rc.Do(func() error {
|
||||||
|
channel := ab.rc.Channel("im.ricochet.chat", channels.Outbound)
|
||||||
|
id, err := channels.SendMessageOnChatChannel(channel, message)
|
||||||
|
if err == nil {
|
||||||
|
ab.messages[id] = message
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenInbound is called when EchoBot attempts to open a channel with AliceBot
|
||||||
|
func (ab *alicebot) OpenInbound() {
|
||||||
|
log.Infof("[alice] inbound connection established")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChatMessage is called whenever AliceBot receives a message from EchoBot
|
||||||
|
func (ab *alicebot) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
||||||
|
log.Infof("[alice] got message from echobot: %s", message)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChatMessageAck is called whenever AliceBot received an acknowledgement of a previously sent message.
|
||||||
|
func (ab *alicebot) ChatMessageAck(messageID uint32, accepted bool) {
|
||||||
|
log.Infof("[alice] message \"%s\" ack'd", ab.messages[messageID])
|
||||||
|
}
|
|
@ -2,10 +2,9 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go/application/examples/echobot/alicebot"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
"git.openprivacy.ca/openprivacy/libricochet-go/channels"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/connection"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||||
"time"
|
"time"
|
||||||
|
@ -15,17 +14,20 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EchoBotInstance is an Instance of the EchoBot Application. One is created for every connected peer.
|
||||||
type EchoBotInstance struct {
|
type EchoBotInstance struct {
|
||||||
rai *application.Instance
|
rai *application.Instance
|
||||||
ra *application.RicochetApplication
|
ra *application.RicochetApplication
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init establishes an EchoBotInstance
|
||||||
func (ebi *EchoBotInstance) Init(rai *application.Instance, ra *application.RicochetApplication) {
|
func (ebi *EchoBotInstance) Init(rai *application.Instance, ra *application.RicochetApplication) {
|
||||||
ebi.rai = rai
|
ebi.rai = rai
|
||||||
ebi.ra = ra
|
ebi.ra = ra
|
||||||
}
|
}
|
||||||
|
|
||||||
// We always want bidirectional chat channels
|
// OpenInbound is called when AliceBot opens a ChatChannel. In this case, because we want EchoBot to respond we
|
||||||
|
// need to open a new channel in the other direction.
|
||||||
func (ebi *EchoBotInstance) OpenInbound() {
|
func (ebi *EchoBotInstance) OpenInbound() {
|
||||||
log.Debugln("OpenInbound() ChatChannel handler called...")
|
log.Debugln("OpenInbound() ChatChannel handler called...")
|
||||||
outboutChatChannel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
outboutChatChannel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
||||||
|
@ -40,39 +42,39 @@ func (ebi *EchoBotInstance) OpenInbound() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChatMessage is called whenever a connected peer sends a message to EchoBot
|
||||||
func (ebi *EchoBotInstance) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
func (ebi *EchoBotInstance) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
||||||
log.Infof("message from %v - %v", ebi.rai.RemoteHostname, message)
|
log.Infof("message from %v - %v", ebi.rai.RemoteHostname, message)
|
||||||
ebi.SendChatMessage(ebi.rai, ebi.rai.RemoteHostname+" "+message)
|
ebi.SendChatMessage(ebi.rai, ebi.rai.RemoteHostname+" "+message)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChatMessageAck is called whenever a connected peer acknolwedges a message that EchoBot sent.
|
||||||
func (ebi *EchoBotInstance) ChatMessageAck(messageID uint32, accepted bool) {
|
func (ebi *EchoBotInstance) ChatMessageAck(messageID uint32, accepted bool) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendChatMessage sends a chat message to the given echobot instance
|
||||||
func (ebi *EchoBotInstance) SendChatMessage(rai *application.Instance, message string) {
|
func (ebi *EchoBotInstance) SendChatMessage(rai *application.Instance, message string) {
|
||||||
ebi.rai.Connection.Do(func() error {
|
ebi.rai.Connection.Do(func() error {
|
||||||
channel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
channel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
||||||
if channel != nil {
|
// We are swallowing the message id and the error here, in reality you will want to handle it.
|
||||||
chatchannel, ok := channel.Handler.(*channels.ChatChannel)
|
channels.SendMessageOnChatChannel(channel, message)
|
||||||
if ok {
|
|
||||||
chatchannel.SendMessage(message)
|
|
||||||
}
|
|
||||||
} //TODO: else?
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// main() encapsulates an entire ricochet ecosystem, from starting tor, to generating onion service keys to managing
|
||||||
|
// the launching of both the echobot server and the alicebot peer.
|
||||||
|
// In most systems you will only be handling one or two of these subsystems at any given time so this example might seem
|
||||||
|
// bloated, but we have tried to highlight the most interesting aspects to allow easy application to new domains.
|
||||||
func main() {
|
func main() {
|
||||||
////////////
|
|
||||||
// SERVER //
|
// Set up Logging.
|
||||||
////////////
|
|
||||||
log.SetLevel(log.LevelInfo)
|
log.SetLevel(log.LevelInfo)
|
||||||
log.AddEverythingFromPattern("connectivity")
|
log.AddEverythingFromPattern("connectivity")
|
||||||
|
|
||||||
echobot := new(application.RicochetApplication)
|
// Set up Tor
|
||||||
cpubk, cprivk, err := ed25519.GenerateKey(rand.Reader)
|
|
||||||
|
|
||||||
acn, err := connectivity.StartTor(".", "")
|
acn, err := connectivity.StartTor(".", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Unable to start Tor: %v", err)
|
log.Errorf("Unable to start Tor: %v", err)
|
||||||
|
@ -80,13 +82,19 @@ func main() {
|
||||||
}
|
}
|
||||||
defer acn.Close()
|
defer acn.Close()
|
||||||
|
|
||||||
listenService, err := acn.Listen(cprivk, application.RicochetPort)
|
// Set up the Echobot Server
|
||||||
|
echobot := new(application.RicochetApplication)
|
||||||
|
cpubk, cprivk, err := ed25519.GenerateKey(rand.Reader)
|
||||||
|
|
||||||
|
// Turn on the echobot onion service in Tor.
|
||||||
|
listenService, err := acn.Listen(cprivk, application.RicochetPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("error setting up onion service: %v", err)
|
log.Errorf("error setting up onion service: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This next section looks complicated (and it is a little), but all it is doing is allowing echobot to handle
|
||||||
|
// im.ricochet.chat type channels.
|
||||||
af := application.InstanceFactory{}
|
af := application.InstanceFactory{}
|
||||||
af.Init()
|
af.Init()
|
||||||
af.AddHandler("im.ricochet.chat", func(rai *application.Instance) func() channels.Handler {
|
af.AddHandler("im.ricochet.chat", func(rai *application.Instance) func() channels.Handler {
|
||||||
|
@ -99,116 +107,21 @@ func main() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Thee next few lines turn on echobot and make it available to listen to new connections.
|
||||||
|
// Note that we initialize a V3 identity for echobot.
|
||||||
echobot.Init(acn, "echobot", identity.InitializeV3("echobot", &cprivk, &cpubk), af, new(application.AcceptAllContactManager))
|
echobot.Init(acn, "echobot", identity.InitializeV3("echobot", &cprivk, &cpubk), af, new(application.AcceptAllContactManager))
|
||||||
log.Infof("echobot listening on %v", listenService.AddressFull())
|
log.Infof("echobot listening on %v", listenService.AddressFull())
|
||||||
go echobot.Run(listenService)
|
go echobot.Run(listenService)
|
||||||
|
|
||||||
|
// Now we wait a little bit for everything to wire itself together.
|
||||||
log.Infoln("counting to five ...")
|
log.Infoln("counting to five ...")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
|
|
||||||
////////////
|
// Finally, in these last few lines we setup an AliceBot who simply sends messages to echobot
|
||||||
// CLIENT //
|
alice := alicebot.NewAliceBot(acn, listenService.AddressIdentity())
|
||||||
////////////
|
|
||||||
|
|
||||||
//alicebot should nominally be in another package to prevent initializing it directly
|
|
||||||
alice := NewAliceBot(acn, listenService.AddressIdentity())
|
|
||||||
alice.SendMessage("be gay")
|
alice.SendMessage("be gay")
|
||||||
alice.SendMessage("do crime")
|
alice.SendMessage("do crime")
|
||||||
|
|
||||||
// stick around and see what happens
|
// stick around and see what happens
|
||||||
time.Sleep(time.Second * 30)
|
time.Sleep(time.Second * 30)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAliceBot(acn connectivity.ACN, onion string) alicebot {
|
|
||||||
alice := alicebot{}
|
|
||||||
alice.messages = make(map[uint32]string)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
alice.pub, alice.priv, err = ed25519.GenerateKey(rand.Reader)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("[alice] error generating key: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
rc, err := goricochet.Open(acn, onion)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("[alice] error connecting to echobot: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = connection.HandleOutboundConnection(rc).ProcessAuthAsV3Client(identity.InitializeV3("alice", &alice.priv, &alice.pub))
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("[alice] failed to authenticate connection: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
alice.rc = rc
|
|
||||||
|
|
||||||
ach := connection.AutoConnectionHandler{}
|
|
||||||
ach.Init()
|
|
||||||
|
|
||||||
ach.RegisterChannelHandler("im.ricochet.chat", func() channels.Handler {
|
|
||||||
chat := new(channels.ChatChannel)
|
|
||||||
chat.Handler = &alice
|
|
||||||
return chat
|
|
||||||
})
|
|
||||||
|
|
||||||
go alice.rc.Process(&ach)
|
|
||||||
|
|
||||||
log.Infof("[alice] requesting channel...")
|
|
||||||
alice.rc.Do(func() error {
|
|
||||||
chatchannel := channels.ChatChannel{}
|
|
||||||
chatchannel.Handler = &alice
|
|
||||||
|
|
||||||
_, err := alice.rc.RequestOpenChannel("im.ricochet.chat", &chatchannel)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed requestopenchannel: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return alice
|
|
||||||
}
|
|
||||||
|
|
||||||
type alicebot struct {
|
|
||||||
messages map[uint32]string
|
|
||||||
pub ed25519.PublicKey
|
|
||||||
priv ed25519.PrivateKey
|
|
||||||
mID int
|
|
||||||
rc *connection.Connection
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *alicebot) SendMessage(message string) {
|
|
||||||
log.Infof("[alice] sending...")
|
|
||||||
this.rc.Do(func() error {
|
|
||||||
channel := this.rc.Channel("im.ricochet.chat", channels.Outbound)
|
|
||||||
if channel != nil {
|
|
||||||
peerchannel, ok := channel.Handler.(*channels.ChatChannel)
|
|
||||||
if ok {
|
|
||||||
log.Infof("[alice] sending '%s' to echobot", message)
|
|
||||||
this.messages[peerchannel.SendMessage(message)] = message
|
|
||||||
} else {
|
|
||||||
log.Errorf("couldn't cast channel:")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Errorf("couldn't create channel")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *alicebot) OpenInbound() {
|
|
||||||
log.Infof("[alice] inbound connection established")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *alicebot) ChatMessage(messageID uint32, when time.Time, message string) bool {
|
|
||||||
log.Infof("[alice] got message from echobot: %s", message)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *alicebot) ChatMessageAck(messageID uint32, accepted bool) {
|
|
||||||
log.Infof("[alice] message \"%s\" ack'd", this.messages[messageID])
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/base32"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
|
||||||
"golang.org/x/crypto/ed25519"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// An example of how to setup a v3 onion service in go
|
|
||||||
func main() {
|
|
||||||
log.SetLevel(log.LevelInfo)
|
|
||||||
tm, err := connectivity.StartTor(".", "")
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Unable to start Tor: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer tm.Close()
|
|
||||||
|
|
||||||
cpubk, cprivk, _ := ed25519.GenerateKey(rand.Reader)
|
|
||||||
onion, err := tm.Listen(cprivk, application.RicochetPort)
|
|
||||||
utils.CheckError(err)
|
|
||||||
defer onion.Close()
|
|
||||||
log.Infof("Got Listener %v", onion.AddressFull())
|
|
||||||
decodedPub, err := base32.StdEncoding.DecodeString(strings.ToUpper(onion.AddressIdentity()))
|
|
||||||
log.Infof("Decoded Public Key: %x %v", decodedPub[:32], err)
|
|
||||||
log.Infof("ed25519 Public Key: %x", cpubk)
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
package channels
|
package channels
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/chat"
|
"git.openprivacy.ca/openprivacy/libricochet-go/wire/chat"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/wire/control"
|
"git.openprivacy.ca/openprivacy/libricochet-go/wire/control"
|
||||||
|
@ -57,6 +58,19 @@ func (cc *ChatChannel) SendMessageWithTime(message string, when time.Time) uint3
|
||||||
return messageID
|
return messageID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendMessageOnChatChannel is a wrapper function which performs some necessary boilerplate
|
||||||
|
// to make sending messages easier.
|
||||||
|
func SendMessageOnChatChannel(channel *Channel, message string) (uint32, error) {
|
||||||
|
if channel != nil {
|
||||||
|
peerchannel, ok := channel.Handler.(*ChatChannel)
|
||||||
|
if ok {
|
||||||
|
return peerchannel.SendMessage(message), nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("channel is not an im.ricochet.chat channel")
|
||||||
|
}
|
||||||
|
return 0, errors.New("channel pointer is nil")
|
||||||
|
}
|
||||||
|
|
||||||
// Acknowledge indicates that the given messageID was received, and whether
|
// Acknowledge indicates that the given messageID was received, and whether
|
||||||
// it was accepted.
|
// it was accepted.
|
||||||
func (cc *ChatChannel) Acknowledge(messageID uint32, accepted bool) {
|
func (cc *ChatChannel) Acknowledge(messageID uint32, accepted bool) {
|
||||||
|
|
|
@ -80,13 +80,8 @@ func SendMessage(rai *application.Instance, message string) error {
|
||||||
|
|
||||||
log.Infof("Finding Chat Channel")
|
log.Infof("Finding Chat Channel")
|
||||||
channel := rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
channel := rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
|
||||||
if channel != nil {
|
_, err := channels.SendMessageOnChatChannel(channel, message)
|
||||||
log.Infof("Found Chat Channel")
|
if err != nil {
|
||||||
chatchannel, ok := channel.Handler.(*channels.ChatChannel)
|
|
||||||
if ok {
|
|
||||||
chatchannel.SendMessage(message)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Infof("Could not find chat channel")
|
log.Infof("Could not find chat channel")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -12,6 +12,4 @@ echo ""
|
||||||
echo "Linting:"
|
echo "Linting:"
|
||||||
|
|
||||||
# Ignore wire packages as they are autogenerated
|
# Ignore wire packages as they are autogenerated
|
||||||
# Ignore examples as they are illustrative
|
go list ./... | grep -v "/wire/" | xargs golint
|
||||||
# TODO Consider Renaming ApplicationInstance and ApplicationInstanceFactory to remove the last grep
|
|
||||||
go list ./... | grep -v "/wire/" | grep -v "/examples/" | xargs golint
|
|
Loading…
Reference in New Issue