137 lines
3.0 KiB
Perl
137 lines
3.0 KiB
Perl
#!/usr/bin/env perl
|
|
|
|
use Mojolicious::Lite;
|
|
use Mojo::Redis;
|
|
use Mojo::JSON 'j';
|
|
|
|
sub handler {
|
|
my $tag = shift;
|
|
return sub {
|
|
my $message = $_[1] || "Closed";
|
|
app->log->debug( "$tag: $message" )
|
|
};
|
|
}
|
|
|
|
app->attr( _redis => sub {
|
|
my $redis = Mojo::Redis->new;
|
|
$redis->on( error => handler("Pub Error") );
|
|
$redis->on( close => handler("Pub") );
|
|
return $redis;
|
|
});
|
|
|
|
helper redis => sub { shift->app->_redis };
|
|
|
|
app->attr( _chat => sub {
|
|
my $redis = shift->redis;
|
|
my $chat = $redis->new($redis); #clone
|
|
$chat->subscribe('chat');
|
|
$chat->on( error => handler("Sub Error") );
|
|
$chat->on( close => handler("Sub") );
|
|
return $chat;
|
|
});
|
|
|
|
helper chat => sub {
|
|
my ($self, $cb) = @_;
|
|
my $chat = $self->app->_chat;
|
|
$chat->on( message => $cb );
|
|
};
|
|
|
|
any '/' => sub {
|
|
my $c = shift;
|
|
|
|
my $name = $c->session('name');
|
|
if ( my $new_name = $c->param('name') ) {
|
|
$c->session( name => $new_name );
|
|
$name = $new_name;
|
|
} elsif ( ! defined $name ) {
|
|
return $c->redirect_to('login');
|
|
}
|
|
|
|
$c->render('chat');
|
|
};
|
|
|
|
any '/login';
|
|
|
|
any '/logout' => sub {
|
|
my $c = shift;
|
|
$c->session( expires => 1 );
|
|
$c->redirect_to('/');
|
|
};
|
|
|
|
websocket '/ws/chat' => sub {
|
|
my $c = shift;
|
|
my $name = $c->session('name');
|
|
|
|
Mojo::IOLoop->stream($c->tx->connection)->timeout(60*60);
|
|
|
|
$c->chat( sub {
|
|
my ($s, $chan, $message) = @_;
|
|
$c->app->log->debug( "Got: $message" );
|
|
$c->send({ text => $message });
|
|
} );
|
|
|
|
$c->on( json => sub {
|
|
my ($ws, $data) = @_;
|
|
$data->{name} = $name;
|
|
my $json = j($data);
|
|
$ws->app->log->debug( "Publishing: $json" );
|
|
$c->redis->publish( chat => $json );
|
|
});
|
|
|
|
#my $r = Mojo::IOLoop->recurring( 1 => sub {
|
|
# state $i = 1;
|
|
# $c->send({ json => { name => 'Joel', message => $i++ }});
|
|
#});
|
|
#$c->on( finish => sub { Mojo::IOLoop->remove($r) } );
|
|
};
|
|
|
|
app->start;
|
|
|
|
__DATA__
|
|
@@ layouts/basic.html.ep
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title><%= title %></title>
|
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
|
|
</head>
|
|
<body>
|
|
%= content
|
|
</body>
|
|
</html>
|
|
@@ login.html.ep
|
|
% layout 'basic';
|
|
% title 'Login';
|
|
%= form_for '/' => method => POST => begin
|
|
%= text_field 'name'
|
|
%= submit_button 'Login'
|
|
% end
|
|
@@ chat.html.ep
|
|
% layout 'basic';
|
|
% title 'Mojo+Redis Chat';
|
|
<input type="text" id="text"><button onclick="send()">Send</button><button onclick="disconnect()">Disconnect</button>
|
|
<div id="log"></div>
|
|
%= javascript begin
|
|
var ws;
|
|
var nows = 0;
|
|
function connect () {
|
|
if (!("WebSocket" in window)) {
|
|
nows = 1;
|
|
alert('Your browser does not support WebSockets!');
|
|
return;
|
|
}
|
|
ws = new WebSocket('<%= url_for('wschat')->to_abs %>');
|
|
ws.onmessage = function (e) {
|
|
console.log(e);
|
|
var data = JSON.parse(e.data);
|
|
$('#log').prepend('<p>' + data.name + ': ' + data.message + '</p>');
|
|
};
|
|
}
|
|
function send () {
|
|
var text = $('#text');
|
|
ws.send(JSON.stringify({ message: text.val() }));
|
|
text.val('');
|
|
}
|
|
function disconnect () { ws.close() }
|
|
$(function(){connect()});
|
|
% end |