mirror of
https://github.com/perlbot/perlbuut-pastebin
synced 2025-06-07 14:17:26 -04:00
Eval supported, uses memcached
This commit is contained in:
parent
cf450f198c
commit
c1490cd15c
4 changed files with 155 additions and 60 deletions
99
app.pl
99
app.pl
|
@ -9,6 +9,10 @@ use DBI;
|
|||
|
||||
use Mojolicious::Lite;
|
||||
use Mojolicious::Plugin::TtRenderer;
|
||||
use Cache::Memcached::Fast;
|
||||
use POE::Filter::Reference;
|
||||
use IO::Compress::Gzip;
|
||||
use IO::Uncompress::Gunzip;
|
||||
|
||||
plugin 'tt_renderer' => {
|
||||
template_options => {
|
||||
|
@ -21,6 +25,26 @@ plugin 'tt_renderer' => {
|
|||
app->renderer->default_handler( 'tt' );
|
||||
app->renderer->paths( [ './tmpl' ] );
|
||||
|
||||
my $memd = new Cache::Memcached::Fast({
|
||||
servers => [ { address => 'localhost:11211', weight => 2.5 }, ],
|
||||
namespace => 'pastebin:',
|
||||
connect_timeout => 0.2,
|
||||
io_timeout => 0.5,
|
||||
close_on_error => 1,
|
||||
compress_threshold => 1_000,
|
||||
compress_ratio => 0.9,
|
||||
compress_methods => [ \&IO::Compress::Gzip::gzip,
|
||||
\&IO::Uncompress::Gunzip::gunzip ],
|
||||
max_failures => 3,
|
||||
failure_timeout => 2,
|
||||
ketama_points => 150,
|
||||
nowait => 1,
|
||||
hash_namespace => 1,
|
||||
serialize_methods => [ \&Storable::freeze, \&Storable::thaw ],
|
||||
utf8 => 1,
|
||||
max_size => 512 * 1024,
|
||||
});
|
||||
|
||||
my $dbh = DBI->connect("dbi:SQLite:dbname=pastes.db", "", "", {RaiseError => 1});
|
||||
# hardcode some channels first
|
||||
my %channels = (
|
||||
|
@ -28,10 +52,43 @@ my %channels = (
|
|||
"freenode#perl" => "#perl (freenode)",
|
||||
);
|
||||
|
||||
sub insert_pastebin {
|
||||
my ($paste, $who, $what, $where) = @_;
|
||||
|
||||
$dbh->do("INSERT INTO posts (paste, who, 'where', what, 'when') VALUES (?, ?, ?, ?, ?)", {}, $paste, $who, $where, $what, time());
|
||||
my $id = $dbh->last_insert_id('', '', 'posts', 'id');
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
sub get_eval {
|
||||
my ($paste_id, $code) = @_;
|
||||
|
||||
if (my $cached = $memd->get($paste_id)) {
|
||||
return $cached;
|
||||
} else {
|
||||
my $filter = POE::Filter::Reference->new();
|
||||
my $socket = IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => '14400' )
|
||||
or die "error: cannot connect to eval server";
|
||||
|
||||
my $refs = $filter->put( [ { code => "perl $code" } ] );
|
||||
|
||||
print $socket $refs->[0];
|
||||
my $output = do {local $/; <$socket>};
|
||||
close $socket;
|
||||
my $result = $filter->get( [ $output ] );
|
||||
|
||||
$memd->set($paste_id, $result->[0]->[0]);
|
||||
|
||||
return $result->[0]->[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get '/' => sub {
|
||||
my $c = shift;
|
||||
$c->stash({pastedata => q{}, channels => \%channels, viewing => 0});
|
||||
$c->render("editor");
|
||||
$c->stash({pastedata => q{}, channels => \%channels, viewing => 0, page_tmpl => 'editor.html.tt'});
|
||||
$c->render("page");
|
||||
};
|
||||
get '/pastebin' => sub {$_[0]->redirect_to('/')};
|
||||
get '/paste' => sub {$_[0]->redirect_to('/')};
|
||||
|
@ -40,33 +97,59 @@ get '/paste' => sub {$_[0]->redirect_to('/')};
|
|||
post '/paste' => sub {
|
||||
my $c = shift;
|
||||
|
||||
my @args = map {($c->param($_))} qw/paste user chan desc/;
|
||||
my @args = map {($c->param($_))} qw/paste name desc chan/;
|
||||
|
||||
$dbh->do("INSERT INTO posts (paste, who, 'where', what, 'when') VALUES (?, ?, ?, ?, ?)", {}, @args, time());
|
||||
my $id = $dbh->last_insert_id('', '', 'posts', 'id');
|
||||
my $id = insert_pastebin(@args);
|
||||
|
||||
$c->redirect_to('/pastebin/'.$id);
|
||||
#$c->render(text => "post accepted! $id");
|
||||
};
|
||||
|
||||
get '/edit/:pasteid' => sub {
|
||||
my $c = shift;
|
||||
my $pasteid = $c->param('pasteid');
|
||||
|
||||
my $row = $dbh->selectrow_hashref("SELECT * FROM posts WHERE id = ? LIMIT 1", {}, $pasteid);
|
||||
|
||||
if ($row->{when}) {
|
||||
$c->stash({pastedata => $row->{paste}, channels => \%channels, viewing => 0});
|
||||
$c->stash({page_tmpl => 'editor.html.tt'});
|
||||
|
||||
$c->render('page');
|
||||
} else {
|
||||
# 404
|
||||
}
|
||||
};
|
||||
|
||||
get '/pastebin/:pasteid' => sub {
|
||||
my $c = shift;
|
||||
my $pasteid = $c->param('pasteid');
|
||||
|
||||
my $row = $dbh->selectrow_hashref("SELECT * FROM posts WHERE id = ? LIMIT 1", {}, $pasteid);
|
||||
|
||||
print Dumper($row);
|
||||
|
||||
if ($row->{when}) {
|
||||
$c->stash({pastedata => $row->{paste}, channels => \%channels, viewing => 1});
|
||||
$c->stash($row);
|
||||
$c->stash({page_tmpl => 'editor.html.tt'});
|
||||
|
||||
$c->render('editor');
|
||||
$c->render('page');
|
||||
} else {
|
||||
# 404
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
get '/eval/:pasteid' => sub {
|
||||
my ($c) = @_;
|
||||
my $pasteid = $c->param('pasteid');
|
||||
|
||||
my $row = $dbh->selectrow_hashref("SELECT * FROM posts WHERE id = ? LIMIT 1", {}, $pasteid);
|
||||
my $code = $row->{paste} // '';
|
||||
|
||||
my $output = get_eval($pasteid, $code);
|
||||
|
||||
$c->render(json => {evalout => $output});
|
||||
};
|
||||
|
||||
app->start;
|
||||
|
||||
|
|
BIN
pastes.db
BIN
pastes.db
Binary file not shown.
|
@ -1,19 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<script src="https://code.jquery.com/jquery-2.2.4.min.js" ></script>
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||
<!-- Optional theme -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
||||
|
||||
<title>Editor</title>
|
||||
<style type="text/css" media="screen">
|
||||
[% BLOCK body_style %]
|
||||
<style type="text/css" media="screen">
|
||||
#editor {
|
||||
margin: auto;
|
||||
position: relative !important;
|
||||
|
@ -30,44 +16,48 @@
|
|||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
[% END %]
|
||||
|
||||
[% BLOCK page_header %]
|
||||
<div class="row">
|
||||
[% IF viewing %]
|
||||
<div class="col-md-3">
|
||||
<b>Who: </b>[% who %]
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<b>When: </b>[% when %]
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<b>What: </b>[% what %]
|
||||
</div>
|
||||
[% ELSE %]
|
||||
<div class="col-md-3">
|
||||
<label for="name">Who: </label>
|
||||
<input size="20" name="name" placeholder="Anonymous" />
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="chan">Where: </label>
|
||||
<select name="chan" id="chan">
|
||||
<option value="">-- IRC Channel --</option>
|
||||
[% FOREACH channel = channels %]
|
||||
<option value="[% channel.key %]">[% channel.value %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="desc">What: </label>
|
||||
<input size="40" name="desc" placeholder="I broke this" />
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
[% BLOCK body %]
|
||||
<form action="/paste" method="POST" id="form">
|
||||
<div id="content" class="container">
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
<div class="row">
|
||||
[% IF viewing %]
|
||||
<div class="col-md-3">
|
||||
<b>Who: </b>[% who %]
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<b>When: </b>[% when %]
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<b>What: </b>[% what %]
|
||||
</div>
|
||||
[% ELSE %]
|
||||
<div class="col-md-3">
|
||||
<label for="name">Who: </label>
|
||||
<input size="20" name="name" placeholder="Anonymous" />
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="chan">Where: </label>
|
||||
<select name="chan" id="chan">
|
||||
<option value="">-- IRC Channel --</option>
|
||||
[% FOREACH channel = channels %]
|
||||
<option value="[% channel.key %]">[% channel.value %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="desc">What: </label>
|
||||
<input size="40" name="desc" placeholder="I broke this" />
|
||||
</div>
|
||||
[% END %]
|
||||
</div>
|
||||
[% PROCESS page_header %]
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
@ -114,6 +104,4 @@
|
|||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
[% END %]
|
||||
|
|
24
templates/page.html.tt
Executable file
24
templates/page.html.tt
Executable file
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
[% PROCESS "$page_tmpl" %]
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<script src="https://code.jquery.com/jquery-2.2.4.min.js" ></script>
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||
<!-- Optional theme -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
||||
|
||||
<title>Perlbot Pastebin</title>
|
||||
[% PROCESS body_style %]
|
||||
</head>
|
||||
<body>
|
||||
|
||||
[% PROCESS body %]
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue