My friends and I don't want to use Slack or Gitter, but instead a pure-Mathematica chat system.
Now that the ChannelFramework
exists, how could we do this?
Mathematica Stack Exchange is a question and answer site for users of Wolfram Mathematica. It only takes a minute to sign up.
Sign up to join this communityMy friends and I don't want to use Slack or Gitter, but instead a pure-Mathematica chat system.
Now that the ChannelFramework
exists, how could we do this?
This is place where OOP comes in very useful, so I'll use my latest OOP framework to implement this. I've cooked this into an entire package here
But before we get into the OOP, we should establish how this should work. My thought is that we should be as unrestrictive as possible, and the best way to do that is by simply passing Cell
objects through our channel.
So if we think about what we expect to receive, we'll want to Compress
our Cell
, send it through, and then decompress at the other end.
Each message is passed with a few metadata parameters, including "Timestamp"
and "RequesterWolframID"
. We'll use these to build a CellFrameLabel
to attach to each Cell
.
In the linked package this can be seen here
The heart of this system is just a plain notebook that will act as our interface. The way I built this out was just having something that would NotebookPut
a "ChatLog"
into a notebook to start and then write new Cells
after the final chat cell in the notebook.
These functions are implemented here and here
We'll also stick on a DockedCell
which will check for updates to our baseline object and call our "Write"
function and NotebookEventActions
to catch "HandleShiftReturn"
when it's called outside of a cell.
With our Notebook
out of the way we can move to handling our ChannelObject
. The ChannelObject
we'll build based on config options we cook into our underlying object. The ChannelListener
we make will simply dump new messages to our object's "ChatLog"
.
The set up functions to these are here
Everything before this has been really standard, but this part will be new for pretty much everyone (but not hard in anyway). So I'll go over it in a bit more detail.
Basically we're going to build a class for instantiating chat objects. In my newest OOP framework this is handled by creating a basic object with a "New"
member function that calls SObjInstantiate
.
SObjInstantiate
then takes the attributes cooked into "ObjectInstanceProperties"
and just wraps them in.
You can see the entire class declaration here but there are a few things to note. First off, most of the object properties are basically just wrappers on the package functions we defined, e.g. in our "ObjectInstanceProperties"
we'll have:
"StartChat" ->
SObjMethod@
Function[chatObjectCreateChannel[#];
chatObjectChannelListen[#];
#["OpenChat"][]
]
The SObjMethod
just declares that when accessed this should be bound to the instance it's called from.
We do the same for our other parameters and implementation functions.
Finally, we add a single method to the class itself, which is simply a convenience function so that we can create and start a chat in one call:
"StartChat" ->
SObjMethod[
With[{n = #["New"][##]},
n["StartChat"][];
n
] &
]
This is a classic thing to do in python, adding a classmethod
that both instantiates and does something--and python is what this OOP system is inspired by.
Finally, the fun part, we can see how we can use this package.
First we'll make a new chat instance:
(* Just a Check to see if you have the ChatSystem installed already *)
Quiet[
Check[
<<ChatSystem`,
Get["https://github.com/b3m2a1/mathematica-tools/raw/master/ChatSystem.wl"]
],
Get::noopen
];
(* Makes a new ChatObject instance and opens the chat notebook *)
ChatObject["StartChat"][]
And we can use it like a normal NotebookObject
:
And press Shift-Enter at the bottom of the NB to send the data to the ChannelObject
:
Cells
that have been sent through or received from the ChannelObject
get a timestamp attached to them and lose their Editability
.
As a test we can send ourselves a message from a cloud notebook. First we'll add the other users as allowed contributors to our channel via the "AddChannelMember"
method of our chat object, then I can log into my cloud account and send myself a message:
And the chat system supports relatively few features at the moment (it's only been alive for about a day), but it has the big ones I see, like changing the usernames and messages display.
You do this with the "ChatCellSettings"
option, which can take any basic Cell
options and two for the timestamp, "NameMapping"
, and "NameStyling"
.
Hope this is a decent example of how OOP and the ChannelFramework
can play nicely together.
If you have questions or want clarification on how things work let me know.
Version 11.3 is supposed to have a chat client built-in, but I can't get it to work:
The documentation is empty and there's no obvious way to "create a chat room":
I prefer your implementation!