package WWW::Hashbang::Pastebin;
use strict;
use warnings;
use 5.014000;
use Dancer ':syntax';
use Dancer::Plugin::DBIC qw(schema);
use Dancer::Plugin::EscapeHTML qw(escape_html);
use Integer::Tiny;
use Try::Tiny;
use DateTime;

# ABSTRACT: command line pastebin
our $VERSION = '0.004'; # VERSION

my $mapper = do {
    my $key = config->{key} || join '', ('a'..'z', 0..9);
    $key =~ tr/+//d;

get '/' => sub {
    return template 'index';

post '/' => sub {
    my $paste_content = param('p') || param('sprunge');
    my $lang = param('lang');

    unless ($paste_content) {
        status 'bad_request';
        return 'No paste content received';

    my $now = DateTime->now( time_zone => 'UTC' );
    my $row = schema->resultset('Paste')->create({
        paste_content => $paste_content,
        paste_date    => $now,

    my $ext_id  = $mapper->encrypt($row->id);
    my $ext_url = uri_for("/$ext_id");
    $ext_url = "$ext_url?$lang" if $lang;
    debug "Created paste $ext_id: $ext_url";
        'X-Pastebin-ID'     => $ext_id,
        'X-Pastebin-URL'    => $ext_url;
    return "$ext_url\n";

get '/:id' => sub {
    my $ext_id = param('id');
    my $line_nos = ($ext_id =~ s{\+$}{});

    my $int_id = try { $mapper->decrypt( $ext_id ) } || do {
        status 'bad_request';
        return "'$ext_id' is not a valid paste ID";
    debug "paste ID requested: $int_id";

    my $paste = schema->resultset('Paste')->find( $int_id );

    unless ($paste) {
        my $msg = "No such paste as '$ext_id'";
        warning $msg;
        status 'not_found';
        return $msg;
    elsif ($paste->deleted) {
        warning "Request was for deleted paste '$ext_id'->'$int_id'";
        status 'gone';
        return "No such paste as '$ext_id'";

    headers 'X-Pastebin-ID' => $ext_id;
    if ($line_nos) {
        open my $in, '<', \$paste->content;
        1 while (<$in>);
        my $lines = $.;
        close $in;
        return template paste => { content => $paste->content, lines => [1..$lines] };
    else {
        return $paste->content;



=encoding utf-8

=head1 NAME

WWW::Hashbang::Pastebin - command line pastebin

=head1 VERSION

version 0.004


    $ (hostname ; uptime) | curl -F 'p=<-'
    $ chromium-browser


This pastebin has no user interface - use C<curl> or L<WWW::Hashbang::Pastebin::Client>'s
C<p> command to POST paste content. Your paste's ID is returned in the
C<X-Pastebin-ID> header; the URL in the C<X-Pastebin-URL>, as well as the response

Append a plus sign to the URL to get line numbers. Add an anchor like C<#l1> to
jump to the given line number, or click the line number you want. The line number
for the selected line will be highlighted.

=for test_synopsis 1;

=head1 SEE ALSO

=over 4

=item * L<>

=item * L<>



The project homepage is L<>.

The latest version of this module is available from the Comprehensive Perl
Archive Network (CPAN). Visit L<> to find a CPAN
site near you, or see L<>.

=head1 SOURCE

The development version is on github at L<>
and may be cloned from L<git://>


You can make new bug reports, and view existing ones, through the
web interface at L<>.

=head1 AUTHOR

Mike Doherty <>


This software is copyright (c) 2012 by Mike Doherty.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.