summary refs log blame commit diff stats
path: root/server/service.raku
blob: f209a6764e1d4df25a88402b754cff1a07a426b6 (plain) (tree)
1
2
3
4
5
6
7
8







                                             



                                          
                         
                      
                                  




                                                                       
                                       


                                                                   
 
                                                        


         


                                                               
 
                    
                              




                                                             
                    
                                      






                                             



















                                                                        
                                                       















                                                                                   

     




                                                           

















                                                           
                            

                             



                                                          



                                                              




                                                           

  
                     




















                                                                      
use Cro::HTTP::Server;
use Cro::HTTP::Router;
use Cro::HTTP::Log::File;

unit sub MAIN(
    Bool :$debug = True, #= enable debug mode
);

my IO() $store = "store";
mkdir $store;
die "Store doesn't exist" unless $store.d;

my $application = route {
    post -> 'create' {
        request-body -> (:$name) {
            my Str $id = ('a'...'z', 'A'...'Z', 0...9).roll(32).join;
            my Str $auth = ('a'...'z', 'A'...'Z', 0...9).roll(32).join;

            my IO() $user-store = "%s/%s".sprintf: $store, $id;
            mkdir $user-store;
            mkdir "$user-store/images";
            die "Failed to create user store" unless $user-store.d;
            spurt "$user-store/name", "$name";
            spurt "$user-store/auth", "$auth";

            content 'application/json', %(:$id, :$auth);
        }
    }

    post -> 'verify' {
        request-body -> (:$id, :$auth) {
            my IO() $user-store = "%s/%s".sprintf: $store, $id;

            my %res;
            if $user-store.d {
                if "$user-store/auth".IO.slurp ne $auth {
                    response.status = 401;
                } else {
                    %res<name> = "$user-store/name".IO.slurp;
                }
            } else {
                response.status = 404;
            }

            content 'application/json', %res;
        }
    }

    post -> 'upload' {
        request-body -> (:$id is copy, :$auth is copy, :$images) {
            $id .= body-text;
            $auth .= body-text;

            my Bool $skip-loop;
            my IO() $user-store = "%s/%s".sprintf: $store, $id;
            if "$user-store/auth".IO.slurp ne $auth {
                response.status = 401;
                $skip-loop = True;
            }

            my @res;
            IMAGE: for @($images) -> $img {
                last IMAGE if $skip-loop;

                my Bool $stored = True;

                my Str @messages;
                @messages.push("Max file size exceeded")
                    if $img.body-blob.bytes > 2097152; # 1024 * 1024 * 2
                @messages.push("Only png/jpeg allowed")
                    if $img.content-type ne "image/png"|"image/jpeg";

                $stored = False if @messages.elems;
                if $stored {
                    my Str $filename = ('a'...'z', 'A'...'Z', 0...9).roll(16).join;
                    spurt "$user-store/images/$filename", $img.body-blob;
                }

                push @res, %(
                    filename => $img.filename,
                    :@messages, :$stored
                );
            }

            content 'application/json', @res;
        }
    }

    get -> 'smile', $id {
        my IO() $user-store = "%s/%s".sprintf: $store, $id;

        my $img;
        if "$user-store/images".IO.d {
            my @imgs = dir("$user-store/images").grep(*.f);
            if @imgs.elems {
                $img = @imgs.pick(1).first;
            } else {
                response.status = 406;
            }
        } else {
            response.status = 404;
        }

        if $img {
            static $img;
            $img.unlink;
        } else {
            content 'text/plain', '';
        }
    }

    # Serving static assets.

    # Quick fix for an issue.
    get -> 'js', *@path { static 'dist/js', @path; }
    get -> 'css', *@path { static 'dist/css', @path; }
    get -> 'img', *@path { static 'dist/img', @path; }
    get -> 'fonts', *@path { static 'dist/fonts', @path; }
    get -> $x, 'js', *@path { static 'dist/js', @path; }
    get -> $x, 'css', *@path { static 'dist/css', @path; }
    get -> $x, 'img', *@path { static 'dist/img', @path; }
    get -> $x, 'fonts', *@path { static 'dist/fonts', @path; }

    # Serve the app on all paths, it'll handle the routing.
    get -> *@path {
        static 'dist/index.html';
    }
};

my $host = "0.0.0.0";
my $port = 9090;

my Cro::Service $http = Cro::HTTP::Server.new(
    http => <1.1>,
    host => $host,
    port => $port,
    :$application,
    after => [
              Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
          ]
);
$http.start;
put "Listening at http://{$host}:{$port}";

react {
    whenever signal(SIGINT) {
        say "Shutting down...";
        $http.stop;
        done;
    }
}