Before this, if a request was not coming from an existing user (no token
in the request or no user with the given token), then and only then
would we send the access captcha. This meant that if a user left a chat
message and became absent, they wouldn't be prompted to do the access
captcha again until their message was eventuallly rotated. (While
messages exist we don't delete the users who posted them.)
This commit makes it so if user['verified'] is None, the user is kicked
and prompted with the access captcha. This is automatically done for
absent users by a background task.
We now time the interval between consecutive tasks. This is more precise
than using the constant interval the task is supposed to run at since
there is some drift on each run (~0.004s).
Also implements stack/queue behaviour where if the eyes limit would be
exceeded, either the new eyes cause the oldest eyes to be deleted OR
the new eyes aren't created at all. The default is the first option.
Client and server both close the connection if they don't hear from the
other party after a timeout period. This is a failsafe and should
improve reliability.
This adds a field 'watching' in `user_for_websocket` that's True iff WATCHING,
False iff NOTWATCHING, and None otherwise (since clients don't need to know if
a user is tentative or absent). When the value of this field changes for any
user, they get added to the update buffer (like with any other change).
Removed race condition in `t_sunset_users`: `broadcast_users_update` was being
called *after* a user was removed from memory (and for each user being removed,
which was redundant). In that scenario if there's a user in the update buffer
and `t_sunset_users` wins the race between it and `t_broadcast_users_update`,
then when `t_sunset_users` calls `broadcast_users_update` a KeyError would be
raised since the user's already been removed.
Fixed unintended behaviour of `t_sunset_users`: it was removing users based on
the result of `is_visible`, so users who were actually tenative (as opposed to
absent) were being removed.
By default the buffer is exhausted every 4 seconds. This should defend against
a potential DoS against clients with JavaScript enabled. Before this, any
request with no token would generate a new user and immediately broadcast the
new user to all the websockets. It's best to lock down as much as possible the
number of places a client can cause the server to broadcasts to all the
websockets.