Tutorial: Chat Service ====================== This page walks you through the full process of building the backend for a simple P2P Chat application. In this example we'll build a class called ``Chat`` which can be used by a front-end GUI. We'll start with the basics of initializing the API and connecting to a Network; see the `QuickStart `_ for more detail on this process. .. code-block:: python import json import time from pipes import PlatformAPI class Chat(object): def __init__(self, apiPath): self.api = PlatformAPI(apiPath) self.node = None self._listener = None def isUserConfigured(self): return self.api.hasLocalIdentity() def setupUser(self, userName): if self.isUserConfigured(): raise Exception("User is already configured: {}".format(self.api.localIdentity().name)) self.api.addIdentity(userName) def connectToNetwork(self, networkId): if self.node: raise Exception("Already connected!") network = self.api.networkWithId(networkId) self.identity = self.api.localIdentity() self.node = network.nodeWithIdentity(self.identity) self._setupPipeline() self.node.connect() This provides an API for configuring the user name and the basics of connecting to a network. This assumes that the indicated ``networkId`` is already configured in the API; see the `QuickStart `_ for more detail on this process. We need to define the ``_setupPipeline()`` method, which configures a Pipeline on the network for use with our chat application: .. code-block:: python def _setupPipeline(self): self.pipeline = self.node.pipelineNamed('CHAT') if not self.pipeline: self.pipeline = self.node.createPipeline(name = 'CHAT') self.pipeline.addPacketListener(self._packetListener) And finally, we need to manage the sending and receiving of messages. For simplicity we use JSON payloads for the messages: .. code-block:: python def sendMessage(self, text): assert(self.node) message = { "text" : text, "sender" : self.identity.name, "timestamp" : time.time() } self.pipeline.putPacket(json.dumps(message).encode()) def _packetListener(self, packet, pipeline): message = json.loads(packet.data.decode()) if self._listener: self._listener(message) def setListener(self, listener): self._listener = listener The ``sendMessage`` method creates a JSON dictionary using the indicated text, the local username, and a timestamp to indicate the time the message was entered. This is then placed on the pipeline using the ``putPacket`` method. The ``_packetListener`` method is attached to the Pipeline, and is called anytime a Packet is put on the pipeline, from any Node in the Network. This decodes the JSON dictionary from the packet and passes it on to the UI listener, which is configured using ``setListener()``. So, for a UI to use this backend, it simply needs to: - Create an instance of the ``Chat`` service - Initialize it with the proper path, and do some one-time setup including querying the user for a username - Use ``setListener()`` to receive callbacks whenever messages are available - Use ``sendMessage()`` to send a chat from the local user upon request The Pipes API takes care of connecting the Nodes and routing Packets between them. This Chat application will already support an arbitrary number of Nodes. As it is now, messages are only received if you are on the Network when they are sent; the next step is to use persistent Pipelines to ensure messages are always delivered. Persistent Chat --------------- For persistent chat, we only need to change the one line in the ``_setupPipeline`` method where we configure the pipeline: .. code-block:: python self.pipeline = self.node.createPipeline(name = 'CHAT', persistent = True) That's it! This backend now guarantees that chats are published to the Network and delivered to all Nodes as soon as possible. This includes offline work: if you send a chat when your Node is not connected, it will be cached locally and delivered when you next connect. History and Search ------------------ TODO: state caching Multiple Channels ----------------- TODO: brief overview Private Chat ------------ TODO: using a point-to-point pipeline Encrypted Chat -------------- TODO: using encrypted Pipelines and sharing secrets