docs.cwtch.im/developing/building-a-cwtch-app/building-an-echobot.md

4.0 KiB

sidebar_position
3

Building a Cwtch Echobot

In this tutorial we will walk through building a simple Cwtch Echobot. A bot that, when messaged, simply responds with the message it was sent.

For completeness, we will build an Echobot in multiple difference Cwtch frameworks to get a feel for the different levels of functionality offered by each library or framework.

Using CwtchBot (Go)

:::info CwtchBot Framework

This tutorial uses the CwtchBot framework. :::

Start by creating a new Go project, and a file main.go. In the main function:

package main

import (
	"cwtch.im/cwtch/event"
	"cwtch.im/cwtch/model"
	"cwtch.im/cwtch/model/attr"
	"cwtch.im/cwtch/model/constants"
	"fmt"
	"git.openprivacy.ca/sarah/cwtchbot"
	_ "github.com/mutecomm/go-sqlcipher/v4"
	"os/user"
	"path"
)

func main() {
	user, _ := user.Current()
	cwtchbot := bot.NewCwtchBot(path.Join(user.HomeDir, "/.echobot/"), "echobot")
	cwtchbot.Launch()

	// Set Some Profile Information
	cwtchbot.Peer.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.Name, "echobot2")
	cwtchbot.Peer.SetScopedZonedAttribute(attr.PublicScope, attr.ProfileZone, constants.ProfileAttribute1, "A Cwtchbot Echobot")

	fmt.Printf("echobot address: %v\n", cwtchbot.Peer.GetOnion())

	for {
		message := cwtchbot.Queue.Next()
		cid, _ := cwtchbot.Peer.FetchConversationInfo(message.Data[event.RemotePeer])
		switch message.EventType {
		case event.NewMessageFromPeer:
			msg := cwtchbot.UnpackMessage(message.Data[event.Data])
			fmt.Printf("Message: %v\n", msg)
			reply := string(cwtchbot.PackMessage(msg.Overlay, msg.Data))
			cwtchbot.Peer.SendMessage(cid.ID, reply)
		case event.ContactCreated:
			fmt.Printf("Auto approving stranger %v %v\n", cid, message.Data[event.RemotePeer])
			// accept the stranger as a new contact
			cwtchbot.Peer.AcceptConversation(cid.ID)
			// Send Hello...
			reply := string(cwtchbot.PackMessage(model.OverlayChat, "Hello!"))
			cwtchbot.Peer.SendMessage(cid.ID, reply)
		}
	}
}

Using Imp (Rust)

:::info Imp (Rust) Bot Framework

This tutorial uses the Imp Cwtch Bot framework (Rust). This framework is currently a work-in-progress and the API design is subject to change. IMP is also based on libcwtch-rs which is currently based on an older pre-stable API version of Cwtch. We are planning in updating libcwtch-rs in Summer 2023. :::

use std::borrow::BorrowMut;
use std::thread;
use chrono::{DateTime, FixedOffset};
use libcwtch;
use libcwtch::CwtchLib;
use libcwtch::structs::*;
use libcwtch::event::*;
use cwtch_imp::imp;
use cwtch_imp::behaviour::*;
use cwtch_imp::imp::Imp;

const BOT_HOME: &str = "~/.cwtch/bots/echobot";
const BOT_NAME: &str = "echobot";

struct Echobot {}

fn main() {
    let behaviour: Behaviour = BehaviourBuilder::new().name(BOT_NAME.to_string()).new_contact_policy(NewContactPolicy::Accept).build();
    let event_loop_handle = thread::spawn(move || {
        let mut echobot = Echobot {};
        let mut bot = Imp::spawn(behaviour,String::new(), BOT_HOME.to_string());
        bot.event_loop::<Echobot>(echobot.borrow_mut());
    });
    event_loop_handle.join().expect("Error running event loop");
}

impl imp::EventHandler for Echobot {
    fn on_new_message_from_contact(&self, cwtch: &dyn libcwtch::CwtchLib, profile: &Profile, conversation_id: ConversationID, handle: String, timestamp_received: DateTime<FixedOffset>, message: Message) {
        let response = Message {
            o: MessageType::TextMessage,
            d: message.d,
        };
        cwtch.send_message(&profile.profile_id, conversation_id, &response);
    }

    fn handle(&mut self, cwtch: &dyn CwtchLib, profile_opt: Option<&Profile>, event: &Event) {
        match event {
            Event::NewPeer { profile_id, tag, created, name, default_picture, picture, online, profile_data } => {
                println!(
                    "\n***** {} at {} *****\n",
                    name, profile_id.as_str()
                );
            }
            _ => (),
        };
    }
}