This repository has been archived on 2020-04-20. You can view files and clone it, but cannot push or open issues or pull requests.
libricochet-go/application/examples/echobot/main.go

133 lines
4.6 KiB
Go

package main
import (
"crypto/rand"
"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/identity"
"git.openprivacy.ca/openprivacy/log"
"time"
"git.openprivacy.ca/openprivacy/connectivity/tor"
"golang.org/x/crypto/ed25519"
"os"
)
// EchoBotInstance is an Instance of the EchoBot Application. One is created for every connected peer.
type EchoBotInstance struct {
rai *application.Instance
ra *application.RicochetApplication
}
// Init establishes an EchoBotInstance
func (ebi *EchoBotInstance) Init(rai *application.Instance, ra *application.RicochetApplication) {
ebi.rai = rai
ebi.ra = ra
}
// 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() {
log.Debugln("OpenInbound() ChatChannel handler called...")
outboutChatChannel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
if outboutChatChannel == nil {
ebi.rai.Connection.Do(func() error {
ebi.rai.Connection.RequestOpenChannel("im.ricochet.chat",
&channels.ChatChannel{
Handler: ebi,
})
return nil
})
}
}
// ChatMessage is called whenever a connected peer sends a message to EchoBot
func (ebi *EchoBotInstance) ChatMessage(messageID uint32, when time.Time, message string) bool {
log.Infof("message from %v - %v", ebi.rai.RemoteHostname, message)
ebi.SendChatMessage(ebi.rai, ebi.rai.RemoteHostname+" "+message)
return true
}
// ChatMessageAck is called whenever a connected peer acknowledges a message that EchoBot sent.
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) {
ebi.rai.Connection.Do(func() error {
channel := ebi.rai.Connection.Channel("im.ricochet.chat", channels.Outbound)
// We are swallowing the message id and the error here, in reality you will want to handle it.
channels.SendMessageOnChatChannel(channel, message)
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() {
// Set up Logging.
log.SetLevel(log.LevelInfo)
log.AddEverythingFromPattern("connectivity")
// Set up Tor
acn, err := tor.NewTorACN(".", "")
if err != nil {
log.Errorf("Unable to start Tor: %v", err)
os.Exit(1)
}
defer acn.Close()
// Set up the Echobot Server
echobot := new(application.RicochetApplication)
cpubk, cprivk, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Errorf("Error generating keys: %v", err)
os.Exit(1)
}
// Turn on the echobot onion service in Tor.
listenService, err := acn.Listen(cprivk, application.RicochetPort)
if err != nil {
log.Errorf("error setting up onion service: %v", err)
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.Init()
af.AddHandler("im.ricochet.chat", func(rai *application.Instance) func() channels.Handler {
ebi := new(EchoBotInstance)
ebi.Init(rai, echobot)
return func() channels.Handler {
chat := new(channels.ChatChannel)
chat.Handler = ebi
return chat
}
})
// 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))
log.Infof("echobot listening on %v", listenService.AddressFull())
go echobot.Run(listenService)
// Now we wait a little bit for everything to wire itself together.
log.Infoln("counting to five ...")
time.Sleep(time.Second * 5)
// Finally, in these last few lines we setup an AliceBot who simply sends messages to echobot
alice := alicebot.NewAliceBot(acn, listenService.AddressIdentity())
alice.SendMessage("be gay")
alice.SendMessage("do crime")
// stick around and see what happens
time.Sleep(time.Second * 30)
}