144 lines
3.5 KiB
Text
144 lines
3.5 KiB
Text
(:~
|
|
: Simple WebSocket chat. RESTXQ functions.
|
|
: @author BaseX Team, BSD License
|
|
:)
|
|
module namespace chat = 'chat';
|
|
|
|
import module namespace chat-util = 'chat/util' at 'lsp-util.xqm';
|
|
|
|
(:~
|
|
: Login or main page.
|
|
: @return HTML page
|
|
:)
|
|
declare
|
|
%rest:path('/lsp')
|
|
%output:method('html')
|
|
function chat:chat() as element() {
|
|
if(session:get($chat-util:id)) then (
|
|
chat:main()
|
|
) else (
|
|
chat:login()
|
|
)
|
|
};
|
|
|
|
(:~
|
|
: Checks the user input, registers the user and reloads the chat.
|
|
: @param $name username
|
|
: @param $pass password
|
|
: @return redirection
|
|
:)
|
|
declare
|
|
%rest:POST
|
|
%rest:path('/lsp/login-check')
|
|
%rest:form-param('name', '{$name}')
|
|
%rest:form-param('pass', '{$pass}')
|
|
function chat:login-check(
|
|
$name as xs:string,
|
|
$pass as xs:string
|
|
) as element(rest:response) {
|
|
try {
|
|
user:check($name, $pass),
|
|
session:set($chat-util:id, $name)
|
|
} catch user:* {
|
|
(: login fails: no session info is set :)
|
|
},
|
|
web:redirect('/chat')
|
|
};
|
|
|
|
(:~
|
|
: Logs out the current user, notifies all WebSocket clients, and redirects to the login page.
|
|
: @return redirection
|
|
:)
|
|
declare
|
|
%rest:path('/lsp/logout')
|
|
function chat:logout() as element(rest:response) {
|
|
session:get($chat-util:id) ! chat-util:close(.),
|
|
session:delete($chat-util:id),
|
|
web:redirect('/chat')
|
|
};
|
|
|
|
(:~
|
|
: Returns the HTML login page.
|
|
: @return HTML page
|
|
:)
|
|
declare %private function chat:login() as element(html) {
|
|
chat:wrap((
|
|
<div class='warning'>Please enter your credentials:</div>,
|
|
<form action='/chat/login-check' method='post'>
|
|
<div class='small'/>
|
|
<table>
|
|
<tr>
|
|
<td><b>Name:</b></td>
|
|
<td>
|
|
<input size='30' name='name' id='user' autofocus=''/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td><b>Password:</b></td>
|
|
<td>{
|
|
<input size='30' type='password' name='pass'/>,
|
|
<button type='submit'>Login</button>
|
|
}</td>
|
|
</tr>
|
|
</table>
|
|
</form>
|
|
), ())
|
|
};
|
|
|
|
(:~
|
|
: Returns the HTML main page.
|
|
: @return HTML page
|
|
:)
|
|
declare %private function chat:main() as element(html) {
|
|
chat:wrap((
|
|
<p>
|
|
<input type='text' size='60' autofocus='true' placeholder='Message to all users…'
|
|
id='input' onkeydown='keyDown(event)' autocomplete='off'/>
|
|
</p>,
|
|
<table width='100%'>
|
|
<tr>
|
|
<td width='100'>
|
|
<div class='note'>USERS (<b>online</b>)</div>
|
|
<div id='users'/>
|
|
</td>
|
|
<td class='vertical'/>
|
|
<td>
|
|
<div class='note'>CHAT MESSAGES</div>
|
|
<div id='messages'/>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
), <script type='text/javascript' src='/static/chat.js'/>)
|
|
};
|
|
|
|
(:~
|
|
: Returns an HTML page.
|
|
: @param $contents page contents
|
|
: @param $login login page
|
|
: @return HTML page
|
|
:)
|
|
declare %private function chat:wrap(
|
|
$contents as item()*,
|
|
$headers as element()*
|
|
) as element(html) {
|
|
<html>
|
|
<head>
|
|
<meta charset='utf-8'/>
|
|
<title>BaseX WebSocket Chat</title>
|
|
<meta name='author' content='BaseX Team, BSD License'/>
|
|
<link rel='stylesheet' type='text/css' href='/static/style.css'/>
|
|
{ $headers }
|
|
</head>
|
|
<body>
|
|
<span class='right'>
|
|
{
|
|
for $id in session:get($chat-util:id)
|
|
return <span><b>{ $id }</b> (<a href='/chat/logout'>logout</a>)</span>
|
|
}
|
|
  <a href='/'><img src='static/basex.svg' class='img'/></a>
|
|
</span>
|
|
<h1>BaseX WebSocket Chat</h1>
|
|
{ $contents }
|
|
</body>
|
|
</html>
|
|
};
|