#!/usr/bin/env perl
use FindBin;
use Cwd;
use lib "$FindBin::Bin/lib";
use Mojolicious::Lite;
use Mojo::Util qw(md5_sum spurt);
use Mojo::Loader qw(data_section);
use Bootylicious;
use Bootylicious::Timestamp;
app->home->parse($ENV{BOOTYLICIOUS_HOME} || getcwd());
unshift @{app->plugins->namespaces}, 'Bootylicious::Plugin';
plugin 'booty_config' => {file => app->home->rel_file('bootylicious.conf')};
plugin 'markdown_parser';
plugin 'model';
my $ALIAS_RE = qr/[a-zA-Z0-9-_]+/;
my $TAG_RE = qr/[\w\s-]+/;
if (@ARGV && $ARGV[0] eq '--create-config') {
if (-e 'bootylicious.conf') {
die "bootylicious.conf already exists\n";
}
spurt(data_section(__PACKAGE__, 'bootylicious.conf'), 'bootylicious.conf');
exit;
}
get '/' => \&index => 'root';
get '/index' => \&index => 'index';
sub index {
my $self = shift;
my $timestamp = $self->param('timestamp');
my $pager = $self->get_articles(timestamp => $timestamp);
$self->stash(articles => $pager->articles, pager => $pager);
$self->render_smart('index');
}
get '/articles/:year/:month' => [year => qr/\d+/, month => qr/\d+/] =>
{year => undef, month => undef} => sub {
my $self = shift;
my $year = $self->stash('year');
my $month = $self->stash('month');
my $archive = $self->get_archive(year => $year, month => $month);
$self->stash(archive => $archive);
$self->render_smart;
} => 'articles';
get '/articles/:year/:month/:alias' =>
[year => qr/\d+/, month => qr/\d+/, alias => $ALIAS_RE] => sub {
my $self = shift;
my $article = $self->get_article(@{$self->stash}{qw/year month alias/});
return $self->reply->not_found unless $article;
$self->stash(article => $article);
$self->render_smart;
} => 'article';
post '/articles/:year/:month/:alias/comment' => sub {
my $self = shift;
return $self->reply->not_found unless $self->comments_enabled;
my $article = $self->get_article(@{$self->stash}{qw/year month alias/});
return $self->reply->not_found unless $article && $article->comments_enabled;
my $validator = $self->create_validator;
my $comment_name = md5_sum($article->created->year, $article->created->month, $article->name);
$validator->field('author')->required(1);
$validator->field('email')->email(1);
$validator->field('content')->length(0); # bot protection
$validator->field($comment_name)->required(1);
return $self->render('article', article => $article)
unless $self->validate($validator);
my $comment_params = $validator->values;
$comment_params->{content} = delete $comment_params->{$comment_name};
my $comment = $article->comment(%$comment_params);
return $self->redirect_to($self->href_to_article($article)
->fragment('comment-' . $comment->number));
} => 'comment';
get '/comments' => sub {
my $self = shift;
return $self->reply->not_found unless $self->comments_enabled;
$self->render_smart;
} => 'comments';
get '/tags/:tag' => [tag => $TAG_RE] => sub {
my $self = shift;
my $tag = $self->stash('tag');
my $timestamp = $self->param('timestamp');
my $pager = $self->get_articles_by_tag($tag, timestamp => $timestamp);
return $self->reply->not_found unless $pager->articles->size;
$self->stash(articles => $pager->articles, pager => $pager);
$self->render_smart;
} => 'tag';
get '/tags' => sub {
my $self = shift;
my $cloud = $self->get_tag_cloud;
$self->stash(tags => $cloud);
$self->render_smart;
} => 'tags';
get '/pages/:name' => [name => $ALIAS_RE] => sub {
my $self = shift;
my $name = $self->stash('name');
my $page = $self->get_page($name);
return $self->reply->not_found unless $page;
$self->stash(page => $page);
$self->render_smart;
} => 'page';
get '/drafts/:name' => [name => $ALIAS_RE] => sub {
my $self = shift;
my $name = $self->stash('name');
my $draft = $self->get_draft($name);
return $self->reply->not_found unless $draft;
$self->stash(draft => $draft);
$self->render_smart;
} => 'draft';
app->start;
__DATA__
@@ index.html.ep
% stash description => config('descr');
% if ($articles->size == 0) {
Nothing here yet :(
% }
% while (my $article = $articles->next) {
%= include 'index-item', article => $article;
% }
%= include 'index-pager', pager => $pager;
@@ index-item.html.ep
<%= link_to_article $article %>
<%= include 'article-meta', article => $article %>
<%= render_article_or_preview $article %>
% if (comments_enabled) {
% }
@@ index-pager.html.ep
@@ articles.html.ep
% stash title => strings('archive'), description => strings('archive-description');
<%= strings 'archive' %>
% if ($archive->is_yearly) {
%= include 'archive-yearly', archive => $archive;
% }
% else {
%= include 'archive-monthly', articles => $archive->articles;
% }
@@ archive-yearly.html.ep
% while (my $year = $archive->next) {
<%= $year->year %>
% while (my $article = $year->articles->next) {
<%= link_to_article $article %>
<%= include 'article-meta', article => $article %>
% }
% }
@@ archive-monthly.html.ep
% while (my $article = $articles->next) {
<%= link_to_article $article %>
<%= include 'article-meta', article => $article; %>
% }
@@ article-meta.html.ep
% my $author = article_author $article;
<%= date $article->created %> <%= $author ? 'by '.$author : '' %>
<%= tags_links $article %>
@@ index.rss.ep
<%= config 'title' %>
<%= href_to_rss->to_abs %>
<%= config 'description' %>
% my $first = $pager->articles->first;
% my $first_created = $first ? $first->created
% : Bootylicious::Timestamp->new(epoch => 0);
<%= date_rss $first_created %>
<%= generator %>
% while (my $article = $pager->articles->next) {
-
<%= $article->title %>
<%= href_to_article($article)->to_abs %>
% if ($article->link) {
<%= permalink_to($article->link) if $article->link %>
% }
]]>
% foreach my $tag (@{$article->tags}) {
<%= $tag %>
% }
% if (comments_enabled) {
<%= href_to_comments($article)->to_abs %>
% }
<%= date_rss $article->created %>
<%= href_to_article($article)->to_abs %>
% }
@@ comments.rss.ep
% my $comments = get_recent_comments(10);
<%= config 'title' %>
<%= href_to_comments_rss->to_abs %>
<%= config 'description' %>
% my $first = $comments->first;
% my $first_created = $first ? $first->created
% : Bootylicious::Timestamp->new(epoch => 0);
<%= date_rss $first_created %>
<%= generator %>
% while (my $comment = $comments->next) {
-
<%= $comment->author %> on <%= $comment->article->title %>
<%= href_to_comment($comment)->to_abs %>
]]>
<%= date_rss $comment->created %>
<%= href_to_comment($comment)->to_abs %>
% }
@@ layouts/wrapper.rss.ep
% die('RSS disabled') unless config 'rss_enabled';
<%= content %>
@@ tags.html.ep
% stash title => strings('tags'), description => strings('tags-description');
<%= strings 'tags' %>
% while (my $tag = $tags->next) {
<%= link_to_tag $tag %>
(<%= $tag->count %>)
% }
@@ tag.html.ep
% stash title => $tag, description => strings('tag-description', $tag);
<%= strings 'tag' %> <%= $tag %>
% if (config 'rss_enabled') {
<%= link_to_tag $tag => { format => 'rss'} => begin %> <% end %>
% }
% while (my $article = $articles->next) {
<%= link_to_article $article %>
%= include 'article-meta', article => $article;
% }
%= include 'tag-pager', pager => $pager, tag => $tag;
@@ tag-pager.html.ep
@@ tag.rss.ep
%= include 'index', format => 'rss';
@@ article.html.ep
% stash title => $article->title, description => $article->description;
<%= link_to_article $article %>
<%= include 'article-meta', article => $article %>
<%= render_article $article %>
%= include 'article-pingbacks', pingbacks => $article->pingbacks if $article->pingbacks->size;
%= include 'article-comments', comments => $article->comments if comments_enabled && $article->comments->size;
%= include 'article-comment-form' if comments_enabled;
%= include 'article-pager', next => $article->next, prev => $article->prev;
@@ article-pingbacks.html.ep
Pingbacks
% while (my $pingback = $pingbacks->next) {
<%= date $pingback->created %> <%= link_to $pingback->source_uri %>
% }
@@ article-comments.html.ep
@@ article-comment-form.html.ep
@@ article-pager.html.ep
@@ page.html.ep
% stash title => $page->title, description => $page->description;
<%= $page->title %>
<%== render_page $page %>
@@ draft.html.ep
% stash title => $draft->{title}, description => strings('draft');
<%= $draft->title %>
<%= tags_links $draft %>
<%== render_article $draft %>
@@ not_found.html.ep
% stash title => 'Not found', description => 'Not found';
404
<%= strings 'not-found' %>
@@ exception.html.ep
% stash title => 'Error', description => 'Error';
500
<%= strings 'error' %>
@@ layouts/wrapper.html.ep
<%= $title ? "$title / " : '' %><%= config 'title' %>
<%= stylesheet '/styles.css' %>
% if (config 'rss_enabled') {
% }
% if (comments_enabled && config 'rss_enabled') {
% }
<%= meta %>
<%= js %>
<%= css %>