~singpolyma/cheogram

ref: 7385a44116380706e82c18f879d8979708fcfcbe cheogram/Main.hs -rw-r--r-- 100.2 KiB
Set up structure to cache OOB coming from a direct message route

Does not actually fetch or cache any OOB data yet, but detects all such data and
has the right types to be able to do it. Replaces all OOB elements with new ones
and replaces all instances of gives URLs with new URLs, just no actual work is
done yet.
Merge branch 'better-thread-exceptions'

* better-thread-exceptions:
  Terminate on fatal exception
  Import forkXMPP from jingle-xmpp
Terminate on fatal exception

This retry loop is too naive for the current state of Cheogram. It is easy to
create a situation where this gets into a retry spin because some thread is
still holding on to the old connection to prosody but this is trying to restart
said connection.  If it gets so bad that exceptions are out here, just bail out
and let monit restart us.
Import forkXMPP from jingle-xmpp

This is a much safer version that rethrows exceptions to the parent instead of
just printing them and terminating the thread.
Translate Adhoc JID to Real JID in configure-direct-message-route

The adhoc commands that exist in the backend are wrapped and proxied
through cheogram, so it's not that different when the adhoc command is
talking to them vs when the client is talking to them. In both cases the
user is escaped and proxied (test\40example.com@cheogram.com)

But the internal command is different, because when a client is talking
to it directly, it really is direct. Whereas commands from the adhoc bot
appear to come from test\40example.com@cheogram.com, so it sees it as a
different user, which is bad.

So now I look at the JID and if it looks like one of our escaped ones,
then I unescape it when deciding which key to use.
Get "configure-direct-message-route" Working with Adhoc Bot

This command works fine with a client that actually uses commands, but
it wasn't working as well with the bot.

There were two things standing it its way:

First, we built the list of adhoc commands by translating the JIDs of
your chosen backend to look like they're coming from cheogram, and then
adding our internal commands to that list.

But, when we were running the commands with the adhoc bot, we don't want
to convert the destinations, since we want to talk directly to the
backend. This makes sense, but meant we were missing out on internal
comamnds too!

So now I add the internal command to our list of untranslated commands
too (by translating an empty list, and then adding that) so the list of
commands we can run should match the list we show the user.

Second, we have a thread that receives messages, and that spins up a new
thread that looks (among other things) to see if this is for the adhoc
bot, and if so forwards the message on.

But in either case, the main "message received" logic would also look at
the stanza to see what it should do with it. That's not good, because in
this case where cheogram's configure-direct-message-route was talking to
its own adhoc bot, it was triggering some other branch which, triggered
some else case, and returned an error. To itself. But then that error
went through the same flow, which also triggered an error. And so it
would just go around and around logging error after error after error
forever.

So now I just have a case in my stanza handler that says "if this is an
adhoc message, don't do do anything" because I know the other thread's
already got it.
Do not crash when no StatsD listener running

StatsD sends should not block the process from working. Since it's a UDP send
I'm not completely sure how it even can fail, but at least when the target is
localhost it can and indeed did, making dev somewhat annoying.

This just swallows any exceptions produced by the StatsD.push action.
Merge branch 'cv_adhoc_squashed'

* cv_adhoc_squashed:
  Change Case to Select
  Add Thread to Bot Responses
  Add Text-Single Handling
  AdHoc Bot Forms
AdHoc Bot Forms

Before this when a user got back a form it was considered an error. Only
commands that returned a note could be executed.
Now, though, we see the form and try to handle it as a series of chat questions
asked to the people. This is only the first version of the technique, though,
so it has some pretty strong limitations.

First, it only supports lists because that's all the test flow I pulled out of
the spec had in it. There are obviously other field types that this will need
to support to be considered finished.

Second, it only goes forwards. There's no cancel, no returning to previous
questions, etc. It also waits forever (well, until the next restart) for the
user to finish, occupying memory in the session holder until then. We could
also maybe ask confirmation before crossing from one form to another, from the
server's perspective, since there's no guarantee that changes made aren't
immediately applied, rather than waiting for the end. At the very least we
should have timeouts and cancelling though.

Third, there's no error handling at all. It just takes things and assumes
success. That should maybe go along with cancellation, at least, but handling
it with some kind of error message and retry may be nice, if the standard and
the server command accepts it.
Handle Group Jingle Messages

The old jingle handling was constructing a message, and then passing it through
part of the message processing system to try and get a resulting message that
would go out to the backend.

But not all the logic lived in that part of the processing pipeline. The group
logic, in particular, lives on the ingress side where I get a message from the
user, and translate it into a message with multiple receivers.

So, to try and bring these together I've instead pulled the receiver apart from
the XMPP bits a little. So now there's a new thread that just pulls from XMPP
and puts on a channel, and the actual handling logic pulls out of that channel
and processes it.
That logic barely changed at all.

But what that means is that our Jingle code can now produce a message that
looks like the user sent it directly, and then push it in the front of our
pipeline, as though the user sent it directly. Rather than the half-and-half
approach from before.

Hopefully this kind of approach also avoids future issues where we want to
produce something and want it to work in all cases. There's nothing about
Jingle in particular in the fix, really.
Accept an Error to Backend Presence Request

We didn't want the backend servers to be required to support these kinds of
requests, but if we don't handle error on these then the client will never see
numbers as online.
Update Dhall to Newer Version

Some classes changed names, others changed types.
All in all it was a relatively straight-forward port.
Terminate Jingle Sessions After Transfer

The spec for Jingle claims either side can terminate the session, but suggests
that the receiver should, since it knows when it's received things.

The current code expects the sender to do it, and Conversations expects the
receiver to do it, leading to both sides waiting for the other to do something.

So to fix that, Cheogram needs to send a session terminate once the upload is
complete!

At some point this logic, and the optional "received" that's already there,
should live inside the Jingle library, since they're related to the Jingle
session which this code otherwise knows nothing about.

But that day is not today! Today I just want to see this work, and make sure it
doesn't break anything else. Then we can figure out how to move it inside.

Once I had three things there, I put them in do-notation since I felt that was
clearer than what was there, with the ">>) $" thing.
I also considered putting them all in a sub-notation, since they're all being
lifted right now, but decided that would make it harder later, since I'm
planning on pulling this stuff out into the library at some point.
So no need to make things _too_ clean! Gotta feel the hurt!
Ignore message from ourselves

If a message is coming in from our own DID, do not process as that would lead to
a loop.
Better URL block for whispers
Command-only commands work

That is, if the command returns completed immediately with a note, the
note is returned to the user.  Anything else is treated as an error.
Refactor help command to stop using the -and-then resource hack
Only assume nickname for phone number if isE164
Show bot-style help from the ad hoc commands
Start sending some statsd stats
Next