Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implementation of upload API logic #1

Merged
merged 6 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 120 additions & 11 deletions lib/LANraragi/Controller/Api/Archive.pm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ use Storable;
use Mojo::JSON qw(decode_json);
use Scalar::Util qw(looks_like_number);

use LANraragi::Utils::Generic qw(render_api_response);
use File::Temp qw(tempdir);
use File::Basename;
use File::Find;

use LANraragi::Utils::Generic qw(render_api_response is_archive get_bytelength);
use LANraragi::Utils::Database qw(get_archive_json set_isnew);

use LANraragi::Model::Archive;
Expand Down Expand Up @@ -107,18 +111,123 @@ sub serve_file {
$self->render_file( filepath => $file );
}

# TODO
# Upload a file archive along with any metadata.
sub upload_archive {
my $self = shift;
my $create_status = LANraragi::Model::Archive::create_archive();
# Create a file archive along with any metadata.
# adapted from Upload.pm
sub create_archive {
my $self = shift;

$self->render(
json => {
operation => "upload_archive",
success => $create_status eq "0" ? 0 : 1
# receive uploaded file
my $file = $self->req->upload('file');
my $filename = $file->filename;
my $uploadMime = $file->headers->content_type;

# metadata extraction
my $catid = $self->req->param('category_id');
my $tags = $self->req->param('tags');
my $title = $self->req->param('title');
my $summary = $self->req->param('summary');

# return error if archive is not supported.
if ( !is_archive($filename) ) {
return $self->render(
json => {
operation => "upload",
success => 0,
error => "Unsupported File Extension ($filename)"
},
status => 415
);
}

# Move file to a temp folder (not the default LRR one)
my $tempdir = tempdir();

my ( $fn, $path, $ext ) = fileparse( $filename, qr/\.[^.]*/ );
my $byte_limit = LANraragi::Model::Config->enable_cryptofs ? 143 : 255;

$filename = $fn;
while ( get_bytelength( $filename . $ext . ".upload") > $byte_limit ) {
$filename = substr( $filename, 0, -1 );
}
$filename = $filename . $ext;

my $tempfile = $tempdir . '/' . $filename;
if ( !$file->move_to($tempfile) ) {
return $self->render(
json => {
operation => "upload",
success => 0,
error => "Couldn't move uploaded file to $tempfile."
},
status => 500
);
}

# Update $tempfile to the exact reference created by the host filesystem
# This is done by finding the first (and only) file in $tempdir.
find(
sub {
return if -d $_;
$tempfile = $File::Find::name;
$filename = $_;
},
$tempdir
);

# utf downgrade (see LANraragi::Utils::Minion)
unless (utf8::downgrade($filename, 1)) {
return $self->render(
json => {
operation => "upload",
name => $file->filename,
debug_name => $filename,
type => $uploadMime,
success => 0,
error => "Bullshit! File path could not be converted back to a byte sequence!"
},
status => 500
)
};

my ( $success_status, $id, $response_title, $message ) = LANraragi::Model::Upload::handle_incoming_file( $tempfile, $catid, $tags, $title, $summary );
my $status = 200;

# modify status based on handler's return message.
if ( $success_status==0 ) {
$status = 500;
if ( index($message, "Unsupported File Extension") != -1 ) {
$status = 415;
} elsif ( index($message, "Enable replace duplicated archive in config to replace old ones") != -1 ) {
$status = 409;
} elsif ( index($message, "The file couldn't be moved to your content folder") != -1 ) {
$status = 500;
}
)

return $self->render(
json => {
operation => "upload",
name => $file->filename,
debug_name => $filename,
title => $response_title,
success => $success_status,
error => $message
},
status => $status
);
}

# successful response
return $self->render(
json => {
operation => "upload",
name => $file->filename,
debug_name => $filename,
title => $response_title,
success => $success_status,
message => $message
},
status => $status
);
}

# Serve an archive page from the temporary folder, using RenderFile.
Expand Down
6 changes: 0 additions & 6 deletions lib/LANraragi/Model/Archive.pm
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,6 @@ sub update_metadata {
return "";
}

# TODO
sub create_archive() {
my $logger = get_logger( "Archive Create", "lanraragi" );
return "0";
}

# Deletes the archive with the given id from redis, and the matching archive file/thumbnail.
sub delete_archive ($id) {

Expand Down
14 changes: 12 additions & 2 deletions lib/LANraragi/Model/Upload.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use File::Temp qw(tempdir);
use File::Find qw(find);
use File::Copy qw(move);

use LANraragi::Utils::Database qw(invalidate_cache compute_id);
use LANraragi::Utils::Database qw(invalidate_cache compute_id set_title set_summary);
use LANraragi::Utils::Logging qw(get_logger);
use LANraragi::Utils::Database qw(redis_encode);
use LANraragi::Utils::Generic qw(is_archive get_bytelength);
Expand All @@ -32,7 +32,7 @@ use LANraragi::Model::Category;
# Returns a status value, the ID and title of the file, and a status message.
sub handle_incoming_file {

my ( $tempfile, $catid, $tags ) = @_;
my ( $tempfile, $catid, $tags, $title, $summary ) = @_;
my ( $filename, $dirs, $suffix ) = fileparse( $tempfile, qr/\.[^.]*/ );
$filename = $filename . $suffix;
my $logger = get_logger( "File Upload/Download", "lanraragi" );
Expand Down Expand Up @@ -108,6 +108,16 @@ sub handle_incoming_file {
}
}

# Set title
if ($title) {
set_title( $id, $title );
}

# Set summary
if ($summary) {
set_summary( $id, $summary );
}

# Move the file to the content folder.
# Move to a .upload first in case copy to the content folder takes a while...
move( $tempfile, $output_file . ".upload" ) or return ( 0, $id, $name, "The file couldn't be moved to your content folder: $!" );
Expand Down
4 changes: 2 additions & 2 deletions lib/LANraragi/Utils/Minion.pm
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ sub add_tasks {
$logger->info("Processing uploaded file $file...");

# Since we already have a file, this goes straight to handle_incoming_file.
my ( $status, $id, $title, $message ) = LANraragi::Model::Upload::handle_incoming_file( $file, $catid, "" );
my ( $status, $id, $title, $message ) = LANraragi::Model::Upload::handle_incoming_file( $file, $catid, "", "", "" );

$job->finish(
{ success => $status,
Expand Down Expand Up @@ -253,7 +253,7 @@ sub add_tasks {
my $tag = "source:$og_url";

# Hand off the result to handle_incoming_file
my ( $status, $id, $title, $message ) = LANraragi::Model::Upload::handle_incoming_file( $tempfile, $catid, $tag );
my ( $status, $id, $title, $message ) = LANraragi::Model::Upload::handle_incoming_file( $tempfile, $catid, $tag, "", "" );

$job->finish(
{ success => $status,
Expand Down
2 changes: 1 addition & 1 deletion lib/LANraragi/Utils/Routing.pm
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ sub apply_routes {
# Archive API
$public_api->get('/api/archives')->to('api-archive#serve_archivelist');
$public_api->get('/api/archives/untagged')->to('api-archive#serve_untagged_archivelist');
$public_api->put('/api/archives/upload')->to('api-archive#upload_archive'); # TODO
$public_api->put('/api/archives/upload')->to('api-archive#create_archive');
$public_api->get('/api/archives/:id/thumbnail')->to('api-archive#serve_thumbnail');
$public_api->get('/api/archives/:id/download')->to('api-archive#serve_file');
$public_api->get('/api/archives/:id/page')->to('api-archive#serve_page');
Expand Down