chat.pl -- The SWISH collaboration backbone
We have three levels of identity as enumerated below. Note that these form a hierarchy: a particular user may be logged on using multiple browsers which in turn may have multiple SWISH windows opened.
- Any open SWISH window has an associated websocket, represented by the identifier returned by hub_add/3.
- Any browser, possibly having multiple open SWISH windows, is identified by a session cookie.
- The user may be logged in, either based on the cookie or on HTTP authentication.
- start_chat(+Request)[private]
- HTTP handler that establishes a websocket connection where a user gets an avatar and optionally a name.
- check_flooding(+Session)[private]
- See whether the client associated with a session is flooding us and if so, return a resource error.
- accept_chat(+Session, +Options, +WebSocket)[private]
- visitor_session(?WSId, ?Session, ?Token)[private]
- session_user(?Session, ?TmpUser)[private]
- visitor_data(?TmpUser, ?UserData:dict)[private]
- subscription(?Session, ?Channel, ?SubChannel)[private]
- These predicates represent our notion of visitors.
- visitor(?WSID) is nondet[private]
- True when WSID should be considered an active visitor.
- inactive(+WSID, +Timeout) is semidet[private]
- True if WSID is inactive. This means we lost the connection at least Timeout seconds ago.
- visitor_session(?WSID, ?Session) is nondet[private]
- True if websocket WSID is associated with Session.
- wsid_visitor(?WSID, ?Visitor)[private]
- True when WSID is associated with Visitor
- existing_visitor(+WSID, +Session, +Token, -TmpUser, -UserData) is semidet[private]
- True if we are dealing with an existing visitor for which we lost the connection.
- create_visitor(+WSID, +Session, ?Token, -TmpUser, -UserData, +Options)[private]
- Create a new visitor when a new websocket is established.
Options provides information we have about the user:
- current_user_info(+Info)
- Already logged in user with given information
- avatar(Avatar)
- Avatar remembered in the browser for this user.
- nick_name(NickName)
- Nick name remembered in the browser for this user.
- generate_key(-Key) is det[private]
- Generate a random confirmation key
- destroy_visitor(+WSID)[private]
- The web socket WSID has been closed. We should not immediately destroy the temporary user as the browser may soon reconnect due to a page reload or re-establishing the web socket after a temporary network failure. We leave the destruction thereof to the session, but set the session timeout to a fairly short time.
- gc_visitors[private]
- Reclaim all visitors with whom we have lost the connection and the browser did not reclaim the selection within 5 minutes.
- create_session_user(+Session, -User, -UserData, +Options)[private]
- Associate a user with the session. The user id is a UUID that is not associated with any persistent notion of a user. The destruction is left to the destruction of the session.
- update_visitor_data(+TmpUser, +Data, +Reason) is det[private]
- Update the user data for the visitor TmpUser to Data. This is
rather complicates due to all the defaulting rules. Reason is
one of:
- login
- logout
- 'set-nick-name'
- 'profile-edit'
- update_avatar_from_email(+Email, +DataIn, -Data)[private]
- Update the avatar after a change of the known email. If the avatar comes from the profile, no action is needed. If Email has a gravatar, use that. Else use the know or a new generated avatar.
- anonymise_user_data(TmpUser, Data)[private]
- Create anonymous user profile.
- set_visitor_data(+TmpUser, +Data, +Reason) is det[private]
- Update the user data for the session user TmpUser and forward the changes.
- inform_visitor_change(+TmpUser, +Reason) is det[private]
- Inform browsers showing TmpUser that the visitor data has changed. The first clause deals with forwarding from HTTP requests, where we have the session and the second from websocket requests where we have the WSID.
- subscribe(+WSID, +Channel) is det[private]
- sync_gazers(+WSID, +Files:list(atom)) is det[private]
- A browser signals it has Files open. This happens when a SWISH instance is created as well as when a SWISH instance changes state, such as closing a tab, adding a tab, bringing a tab to the foreground, etc.
- add_user_details(+Message, -Enriched) is det[private]
- Add additional information to a message. Message must
contain a
uid
field. - public_user_data(+UID, -Public:dict) is det[private]
- True when Public provides the information we publically share about UID. This is currently the name and avatar.
- get_visitor_data(-Data:dict, +Options) is det[private]
- Optain data for a new visitor. Options include:
- identity(+Identity)
- Identity information provided by authenticate/2. Always present.
- avatar(+URL)
- Avatar provided by the user
- nick_name(+Name)
- Nick name provided by the user.
Data always contains an
avatar
key and optionally contains aname
andemail
key. If the avatar is generated there is also a keyavatar_generated
with the valuetrue
. - reply_avatar(+Request)[private]
- HTTP handler for Noble Avatar images. Using create_avatar/2
re-creates avatars from the file name, so we can safely discard
the avatar file store.
Not really. A new user gets a new avatar and this is based on whether or not the file exists. Probably we should maintain a db of handed out avatars and their last-use time stamp. How to do that? Current swish stats: 400K avatars, 3.2Gb data.
- chat_broadcast(+Message) is det
- chat_broadcast(+Message, +Channel) is det
- Send Message to all known SWISH clients. Message is a valid JSON object, i.e., a dict or option list.
- handle_message(+Message, +Room)[private]
- Handle incoming messages
- json_message(+Message, +WSID) is det[private]
- Process a JSON message translated to a dict. The following
messages are understood:
- subscribe channel [subchannel]
- unsubscribe channel [subchannel] Actively (un)subscribe for specific message channels.
- unload A SWISH instance is cleanly being unloaded.
- has-open-files files Executed after initiating the websocket to indicate loaded files.
- set-nick-name name User set nick name for anonymous identoty
- forbidden(+Message, +DocID, -Why) is semidet[private]
- True if the chat Message about DocID must be forbidden, in which
case Why is unified with a string indicating the reason.
Currently:
- Demands the user to be logged on
- Limits the size of the message and its payloads
- block(+User, +Score, -Cummulative, -Count)[private]
- Keep a count and cummulative score for a user.
- chat_add_user_id(+WSID, +Message0, -Message) is det[private]
- Decorate a message with the user credentials.
- chat_about(+DocID, +Message) is det
- Distribute a chat message about DocID.
- chat_relay(+Message) is det[private]
- Store and relay a chat message.
- chat_enrich(+Message0, -Message) is det[private]
- Add time and identifier to the chat message.
- chat_send(+Message)[private]
- Relay the chat message Message. If the message has a
volatile
property it is broadcasted, but not stored. - chat_event(+Event) is semidet[private]
- Event happened inside SWISH. Currently triggered events:
- updated(+File, +From, +To)
- File was updated from hash From to hash To.
- profile(+ProfileID)
- Session was associated with user with profile ProfileID
- logout(+ProfileID)
- User logged out. If the login was based on HTTP authentication
ProfileID equals
http
.
- propagate_profile_change(+ProfileID, +Attribute, +Value)[private]
- Trap external changes to the profile.
- broadcast_event(+Event) is semidet[private]
- If true, broadcast this event.
- broadcast_event(+Event, +File, +WSID) is det[private]
- Event happened that is related to File in WSID. Broadcast it to subscribed users as a notification. Always succeeds, also if the message cannot be delivered.
- event_file(+Event, -File) is semidet[private]
- True when Event is associated with File.
- chat_to_profile(ProfileID, :HTML) is det
- Send a HTML notification to users logged in using ProfileID.
- notifications(+Options)//
- The chat element is added to the navbar and managed by web/js/chat.js
- broadcast_bell(+Options)//
- Adds a bell to indicate central chat messages
Re-exported predicates
The following predicates are exported from this file while their implementation is defined in imported modules or non-module files loaded by this module.
- chat_broadcast(+Message) is det
- chat_broadcast(+Message, +Channel) is det
- Send Message to all known SWISH clients. Message is a valid JSON object, i.e., a dict or option list.