markqvist/LXMF

add Examples?

trosel opened this issue · 6 comments

similar to the reticulum examples https://github.com/markqvist/Reticulum/tree/master/Examples

It would be good to see some basic examples for how to

  • create a new user
  • log a user back in
  • create a new conversation (different conversation types like group chat vs public channel?)

Yes! This is definitely needed, and I will add a much more complete set of docs to LXMF very soon. Now that RNS 0.3.7 has been released, I can focus a bit more on LXMF and related programs.

I am interested in some examples and code snippets as well for getting started. Is there already some draft document how to establish connection to a sideband contact for example to send messages, commands or files?

I posted some examples on the forum a while back... Hmm.. But can't seem to find it right now. I'll add some examples soon, I promise ;)

Ok, until we get this in the docs somewhere, here's a short receiver/sender example. Should be pretty self-explanatory:

Receiver

import RNS
import LXMF
import time

def delivery_callback(message):
	time_string      = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.timestamp))
	signature_string = "Signature is invalid, reason undetermined"
	if message.signature_validated:
		signature_string = "Validated"
	else:
		if message.unverified_reason == LXMF.LXMessage.SIGNATURE_INVALID:
			signature_string = "Invalid signature"
		if message.unverified_reason == LXMF.LXMessage.SOURCE_UNKNOWN:
			signature_string = "Cannot verify, source is unknown"

	RNS.log("\t+--- LXMF Delivery ---------------------------------------------")
	RNS.log("\t| Source hash            : "+RNS.prettyhexrep(message.source_hash))
	RNS.log("\t| Source instance        : "+str(message.get_source()))
	RNS.log("\t| Destination hash       : "+RNS.prettyhexrep(message.destination_hash))
	RNS.log("\t| Destination instance   : "+str(message.get_destination()))
	RNS.log("\t| Transport Encryption   : "+str(message.transport_encryption))
	RNS.log("\t| Timestamp              : "+time_string)
	RNS.log("\t| Title                  : "+message.title_as_string())
	RNS.log("\t| Content                : "+message.content_as_string())
	RNS.log("\t| Fields                 : "+str(message.fields))
	RNS.log("\t| Message signature      : "+signature_string)
	RNS.log("\t+---------------------------------------------------------------")

r = RNS.Reticulum()

router = LXMF.LXMRouter(storagepath="./tmp1")
identity = RNS.Identity()
my_lxmf_destination = router.register_delivery_identity(identity)
router.register_delivery_callback(delivery_callback)

RNS.log("Ready to receive on: "+RNS.prettyhexrep(my_lxmf_destination.hash))
input()

Sender

import LXMF
import RNS
import time
import random

random_names = ["Tom", "Delilah", "Nancey", "Williams", "Neomi", "Curtis", "Alexa", "Theodora", "Ted", "Dinorah", "Nicol", "Drusilla", "Annalisa", "Verlene", "Latesha", "Tina", "Mia", "Brock", "Timothy", "Philip", "Willian", "Reyna", "Simona", "Mimi", "Stanford", "Ferne", "Catalina", "Lucie", "Jaye", "Natasha", "Willetta", "Isabel", "Esperanza", "Ciara", "Eusebio", "William", "Elma", "Angelica", "Coreen", "Melani", "Jonathan", "Maryland", "Caroline", "Gregg", "Ora", "Jacqui", "Letty", "Roselle", "Oralee", "Angla"]
random_titles = ["Long time", "Hi again", "Re: Hi there", "Test message", "", "", "Something different"]
random_msgs = ["If wishes were horses then beggars might fly. Stuff like that. It's enough to drive you crazy.", "'My ident cards were stolen,' Jason said. 'That fivehundred-dollar bill is yours if you can get me to someone who can replace them. If you're going to do it, do it right now; I'm not going to wait.' Wait to be picked up by a pol or a nat, he thought. Caught here in this rundown dingy hotel.", "A six, no matter what the external circumstances, will always prevail. Because that's the way they genetically defined us.", "'Should be there in an hour,' he called back over his shoulder to Chuck. Then he added, in an afterthought, 'Wonder if the computer’s finished its run. It was due about now.'. Chuck didn’t reply, so George swung round in his saddle. He could just see Chuck’s face, a white oval turned toward the sky."]

def delivery_callback(message):
    pass

r = RNS.Reticulum()
router = LXMF.LXMRouter(storagepath="./tmp2")
router.register_delivery_callback(delivery_callback)
ident = RNS.Identity()
source = router.register_delivery_identity(ident, display_name=random_names[random.randint(0,len(random_names)-1)])
router.announce(source.hash)
RNS.log("Source announced")

print("Recipient: ", end=" ")
recipient_hexhash = input()
recipient_hash = bytes.fromhex(recipient_hexhash)

if not RNS.Transport.has_path(recipient_hash):
		RNS.log("Destination is not yet known. Requesting path and waiting for announce to arrive...")
		RNS.Transport.request_path(recipient_hash)
		while not RNS.Transport.has_path(recipient_hash):
			time.sleep(0.1)

# Recall the server identity
recipient_identity = RNS.Identity.recall(recipient_hash)

dest = RNS.Destination(recipient_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "lxmf", "delivery")

while True:
    lxm = LXMF.LXMessage(dest, source, random_msgs[random.randint(0,len(random_msgs)-1)], random_titles[random.randint(0,len(random_titles)-1)], desired_method=LXMF.LXMessage.DIRECT)
    router.handle_outbound(lxm)
    input()

Great thanks a lot - basic tests work well :-)
Do you also have a snipped how to add an tcpinterface, such as the sideband.connect.reticulum.network to the sender code, to receive the message for example via the Android Sideband app?

Do you also have a snipped how to add an tcpinterface, such as the sideband.connect.reticulum.network to the sender code, to receive the message for example via the Android Sideband app?

That should definitely not be done hardcoded in the application code.

You add interfaces in the Reticulum configuration on the system the program is running on.

Sideband is a distributed messaging application, so there is no guarantee that anyone using Sideband is using the testnet entrypoint at sideband.connect.reticulum.network. Relying on a hardcoded TCP connection in your program would be a very bad idea, and especially using a testnet entrypoint.

If you want to provide a default TCP connection option in your program, I'd suggest setting up your own Reticulum Transport Instance that is publicly accessible over TCP, and have that as a default.

Otherwise, if you are just experimenting around and testing, just add an interface in your local Reticulum config (as described in the Reticulum documentation, or on the front of the github repo), and you're good to go.