diff options
author | Yorhel <git@yorhel.nl> | 2011-02-16 19:24:13 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2011-02-16 19:24:13 +0100 |
commit | 49a2516e6b076667e163aaff2ae2e94ed52fa083 (patch) | |
tree | 46d864db6670f8304353027ad2ea6eec36cff23a | |
parent | cd7b3f34173dfeceec03691957c95f4d4ab9cf47 (diff) |
chardb: Added image to character entries
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | data/global.pl | 1 | ||||
-rw-r--r-- | data/lang.txt | 77 | ||||
-rw-r--r-- | data/style.css | 5 | ||||
-rw-r--r-- | lib/Multi/Feed.pm | 5 | ||||
-rw-r--r-- | lib/Multi/Image.pm | 40 | ||||
-rw-r--r-- | lib/VNDB/DB/Chars.pm | 12 | ||||
-rw-r--r-- | lib/VNDB/Handler/Chars.pm | 69 | ||||
-rw-r--r-- | util/sql/func.sql | 7 | ||||
-rw-r--r-- | util/updates/update_2.19.sql | 3 |
11 files changed, 205 insertions, 21 deletions
@@ -6,6 +6,7 @@ /static/feeds/ /static/s/*/style.css /static/s/*/boxbg.png +/static/ch/ /static/cv/ /static/sf/ /static/st/ @@ -43,7 +43,7 @@ all: dirs js skins robots data/config.pl -dirs: static/f/js static/cv static/sf static/st data/log www www/feeds +dirs: static/f/js static/ch static/cv static/sf static/st data/log www www/feeds js: static/f/js/en.js @@ -51,7 +51,7 @@ skins: static/s/*/style.css robots: dirs www/robots.txt static/robots.txt -static/cv static/sf static/st: +static/ch static/cv static/sf static/st: mkdir $@; for i in $$(seq -w 0 1 99); do mkdir "$@/$$i"; done @@ -70,7 +70,7 @@ static/s/%/style.css: static/s/%/conf util/skingen.pl data/style.css chmod: all chmod a+xrw static/f/js - chmod -R a-x+rwX static/{cv,sf,st} + chmod -R a-x+rwX static/{ch,cv,sf,st} chmod a-x+rw static/s/*/{style.css,boxbg.png} chmod-tladmin: diff --git a/data/global.pl b/data/global.pl index 0e4b02e8..e6f935ec 100644 --- a/data/global.pl +++ b/data/global.pl @@ -29,6 +29,7 @@ our %S = (%S, source_url => 'http://git.blicky.net/vndb.git/?h=master', admin_email => 'contact@vndb.org', scr_size => [ 136, 102 ], # w*h of screenshot thumbnails + ch_size => [ 256, 300 ], # max. w*h of char images cv_size => [ 256, 400 ], # max. w*h of cover images user_ranks => [ # allowed actions # DB number diff --git a/data/lang.txt b/data/lang.txt index ae605d3a..b0f899d1 100644 --- a/data/lang.txt +++ b/data/lang.txt @@ -4784,6 +4784,27 @@ cs*: hu*: nl : Omschrijving +:_revfield_c_image +en : Image +ru*: +cs*: +hu*: +nl : Plaatje + +:_chdiff_image_proc +en : ~[processing~] +ru : ~[обработка~] +cs : ~[zpracovává se~] +hu : ~[feldolgozás~] +nl : ~[bewerken...~] + +:_chdiff_image_none +en : No image +ru : Нет изображения +cs : Obrázek není +hu : Nincs kép +nl : Geen plaatje + # Add/edit character @@ -4843,6 +4864,55 @@ cs*: hu*: nl : (In)officiele aliassen, elke alias op een aparte regel. +:_chare_image +en : Image +ru : Изображение +cs : Obrázek +hu : Kép +nl : Plaatje + +:_chare_image_none +en : No image uploaded yet +ru : Изображения пока нет +cs : Obrázek ještě nebyl nahrán +hu : Még nincs kép feltöltve +nl : Nog geen plaatje geupload + +:_chare_image_processing +en : ~[processing image, please return in a few minutes~] +ru : ~[обработка изображения, пожалуйста подождите несколько минут~] +cs : ~[obrázek se zpracovává, vraťte se prosím za několik minut~] +hu : ~[a kép feldolgozás alatt van, gyere vissza pár perc múlva~] +nl : ~[bezig met het verwerken van het plaatje, kom a.u.b. terug in een paar minuten~] + +:_chare_image_id +en : Image ID +ru*: +cs*: +hu*: +nl : Plaatje ID + +:_chare_image_id_msg +en : Use a character image that is already on the server. Set to '0' to remove the current image. +ru : +cs : +hu : +nl : Gebruik een karakterplaatje dat al op de server staat. Gebruik '0' om een huidig plaatje te verwijderen. + +:_chare_image_upload +en : Upload new image +ru : Загрузить новое изображение +cs : Nahrát nový obrázek +hu : Tölts fel egy új képet +nl : Upload nieuw plaatje + +:_chare_image_upload_msg +en : Image must be in JPEG or PNG format and at most 1MiB. Images larger than 256x300 will automatically be resized. Image must be safe for work! +ru*: +cs*: +hu*: +nl : Plaatje moet in het JPEG of PNG formaat zijn, en moet kleiner zijn dan 1MiB. Plaatjes groter dan 256x300 worden automatisch verkleind. Het plaatje moet veilig zijn in een werkomgeving! + @@ -6671,6 +6741,13 @@ nl : Spatiegescheiden lijst van [url,http://anidb.net/,AniDB] anime IDs. en [url,http://anidb.net/a3348,Fate/stay night] toe als gerelateerde anime.[br] Houd er rekening mee dat het een aantal minuten kan duren voordat de animetitels zichtbaar worden op de VN pagina. +:_chare_form_desc +en : Description +ru : Описание +cs : Popis +hu : Leírás +nl : Omschrijving + :_vnedit_image en : Image ru : Изображение diff --git a/data/style.css b/data/style.css index 99b0f9e6..d4437491 100644 --- a/data/style.css +++ b/data/style.css @@ -852,6 +852,11 @@ div.scr_uploader { visibility: hidden; overflow: hidden; width: 1px; height: 1px .relbrowse .tc3 { width: 85px; text-align: right; padding: 0; } +/***** Char edit *****/ +#jt_box_chare_img div.img { float: left; height: 400px; padding-right: 20px; } +#jt_box_chare_img h2 { margin: 0; } + + /***** Documentation pages *****/ diff --git a/lib/Multi/Feed.pm b/lib/Multi/Feed.pm index 12631497..483089bd 100644 --- a/lib/Multi/Feed.pm +++ b/lib/Multi/Feed.pm @@ -64,13 +64,14 @@ sub generate { # changes $_[KERNEL]->post(pg => query => q{ - SELECT '/'||c.type||COALESCE(vr.vid, rr.rid, pr.pid)||'.'||c.rev AS id, - COALESCE(vr.title, rr.title, pr.name) AS title, extract('epoch' from c.added) AS updated, + SELECT '/'||c.type||COALESCE(vr.vid, rr.rid, pr.pid, cr.cid)||'.'||c.rev AS id, + COALESCE(vr.title, rr.title, pr.name, cr.name) AS title, extract('epoch' from c.added) AS updated, u.username, u.id AS uid, c.comments AS summary FROM changes c LEFT JOIN vn_rev vr ON c.type = 'v' AND c.id = vr.id LEFT JOIN releases_rev rr ON c.type = 'r' AND c.id = rr.id LEFT JOIN producers_rev pr ON c.type = 'p' AND c.id = pr.id + LEFT JOIN chars_rev cr ON c.type = 'c' AND c.id = cr.id JOIN users u ON u.id = c.requester WHERE c.requester <> 1 ORDER BY c.id DESC diff --git a/lib/Multi/Image.pm b/lib/Multi/Image.pm index ad1d436c..3f8bb1a9 100644 --- a/lib/Multi/Image.pm +++ b/lib/Multi/Image.pm @@ -18,10 +18,11 @@ sub spawn { POE::Session->create( package_states => [ $p => [qw| _start - _start shutdown cv_check cv_process scr_check scr_process + _start shutdown ch_check ch_process cv_check cv_process scr_check scr_process |], ], heap => { + chpath => $VNDB::ROOT.'/static/ch', cvpath => $VNDB::ROOT.'/static/cv', sfpath => $VNDB::ROOT.'/static/sf', stpath => $VNDB::ROOT.'/static/st', @@ -35,20 +36,53 @@ sub spawn { sub _start { $_[KERNEL]->alias_set('image'); $_[KERNEL]->sig(shutdown => 'shutdown'); - $_[KERNEL]->post(pg => listen => coverimage => 'cv_check', screenshot => 'scr_check'); + $_[KERNEL]->post(pg => listen => charimage => 'ch_check', coverimage => 'cv_check', screenshot => 'scr_check'); + $_[KERNEL]->yield('ch_check'); $_[KERNEL]->yield('cv_check'); $_[KERNEL]->yield('scr_check'); } sub shutdown { - $_[KERNEL]->post(pg => unlisten => 'coverimage', 'screenshot'); + $_[KERNEL]->post(pg => unlisten => 'charimage', 'coverimage', 'screenshot'); + $_[KERNEL]->delay('ch_check'); $_[KERNEL]->delay('cv_check'); $_[KERNEL]->delay('scr_check'); $_[KERNEL]->alias_remove('image'); } +sub ch_check { + $_[KERNEL]->delay('ch_check'); + $_[KERNEL]->post(pg => query => 'SELECT image FROM chars_rev WHERE image < 0 LIMIT 1', undef, 'ch_process'); +} + + +sub ch_process { # num, res + return $_[KERNEL]->delay(ch_check => $_[HEAP]{check_delay}) if $_[ARG0] == 0; + + my $id = -1*$_[ARG1][0]{image}; + my $start = time; + my $img = sprintf '%s/%02d/%d.jpg', $_[HEAP]{chpath}, $id%100, $id; + my $os = -s $img; + + my $im = Image::Magick->new; + $im->Read($img); + $im->Set(magick => 'JPEG'); + my($ow, $oh) = ($im->Get('width'), $im->Get('height')); + my($nw, $nh) = imgsize($ow, $oh, @{$VNDB::S{ch_size}}); + $im->Thumbnail(width => $nw, height => $nh); + $im->Set(quality => 80); + $im->Write($img); + + $_[KERNEL]->post(pg => do => 'UPDATE chars_rev SET image = image*-1 WHERE image = ?', [ -1*$id ]); + $_[KERNEL]->call(core => log => 'Processed character image %d in %.2fs: %.2fkB (%dx%d) -> %.2fkB (%dx%d)', + $id, time-$start, $os/1024, $ow, $oh, (-s $img)/1024, $nw, $nh); + + $_[KERNEL]->yield('ch_check'); +} + + sub cv_check { $_[KERNEL]->delay('cv_check'); $_[KERNEL]->post(pg => query => 'SELECT image FROM vn_rev WHERE image < 0 LIMIT 1', undef, 'cv_process'); diff --git a/lib/VNDB/DB/Chars.pm b/lib/VNDB/DB/Chars.pm index b12c4425..3f744239 100644 --- a/lib/VNDB/DB/Chars.pm +++ b/lib/VNDB/DB/Chars.pm @@ -5,7 +5,7 @@ use strict; use warnings; use Exporter 'import'; -our @EXPORT = qw|dbCharGet dbCharRevisionInsert|; +our @EXPORT = qw|dbCharGet dbCharRevisionInsert dbCharImageId|; # options: id rev what results page @@ -26,7 +26,7 @@ sub dbCharGet { ); my @select = qw|c.id cr.name cr.original|; - push @select, qw|c.hidden c.locked cr.alias cr.desc| if $o{what} =~ /extended/; + push @select, qw|c.hidden c.locked cr.alias cr.desc cr.image| if $o{what} =~ /extended/; push @select, qw|h.requester h.comments c.latest u.username h.rev h.ihid h.ilock|, "extract('epoch' from h.added) as added", 'cr.id AS cid' if $o{what} =~ /changes/; my @join; @@ -51,10 +51,16 @@ sub dbCharRevisionInsert { my($self, $o) = @_; my %set = map exists($o->{$_}) ? (qq|"$_" = ?|, $o->{$_}) : (), - qw|name original alias desc|; + qw|name original alias desc image|; $self->dbExec('UPDATE edit_char !H', \%set) if keys %set; } +# fetches an ID for a new image +sub dbCharImageId { + return shift->dbRow("SELECT nextval('charimg_seq') AS ni")->{ni}; +} + + 1; diff --git a/lib/VNDB/Handler/Chars.pm b/lib/VNDB/Handler/Chars.pm index f593077f..1c0643fd 100644 --- a/lib/VNDB/Handler/Chars.pm +++ b/lib/VNDB/Handler/Chars.pm @@ -35,6 +35,10 @@ sub page { [ original => diff => 1 ], [ alias => diff => qr/[ ,\n\.]/ ], [ desc => diff => qr/[ ,\n\.]/ ], + [ image => htmlize => sub { + return $_[0] > 0 ? sprintf '<img src="%s/ch/%02d/%d.jpg" />', $self->{url_static}, $_[0]%100, $_[0] + : mt $_[0] < 0 ? '_chdiff_image_proc' : '_chdiff_image_none'; + }], ); } @@ -42,6 +46,7 @@ sub page { $self->htmlItemMessage('c', $r); h1 $r->{name}; h2 class => 'alttitle', $r->{original} if $r->{original}; + img src => sprintf('%s/ch/%02d/%d.jpg', $self->{url_static}, $r->{image}%100, $r->{image}), alt => $r->{name} if $r->{image}; if($r->{desc}) { p class => 'description'; lit bb2html($r->{desc}); @@ -64,7 +69,7 @@ sub edit { || $id && ($r->{locked} && !$self->authCan('lock') || $r->{hidden} && !$self->authCan('del')); my %b4 = !$id ? () : ( - (map { $_ => $r->{$_} } qw|name original alias desc ihid ilock|), + (map { $_ => $r->{$_} } qw|name original alias desc image ihid ilock|), ); my $frm; @@ -75,11 +80,16 @@ sub edit { { post => 'original', required => 0, maxlength => 200, default => '' }, { post => 'alias', required => 0, maxlength => 500, default => '' }, { post => 'desc', required => 0, maxlength => 5000, default => '' }, + { post => 'image', required => 0, default => 0, template => 'int' }, { post => 'editsum', required => 0, maxlength => 5000 }, { post => 'ihid', required => 0 }, { post => 'ilock', required => 0 }, ); push @{$frm->{_err}}, 'badeditsum' if !$frm->{editsum} || lc($frm->{editsum}) eq lc($frm->{desc}); + + # handle image upload + $frm->{image} = _uploadimage($self, $r, $frm); + if(!$frm->{_err}) { $frm->{ihid} = $frm->{ihid} ?1:0; $frm->{ilock} = $frm->{ilock}?1:0; @@ -99,18 +109,57 @@ sub edit { $self->htmlHeader(title => $title, noindex => 1); $self->htmlMainTabs('c', $r, 'edit') if $r; $self->htmlEditMessage('c', $r, $title); - $self->htmlForm({ frm => $frm, action => $r ? "/c$id/edit" : '/c/new', editsum => 1 }, - 'chare_geninfo' => [ mt('_chare_form_generalinfo'), - [ input => name => mt('_pedit_form_name'), short => 'name' ], - [ input => name => mt('_pedit_form_original'), short => 'original' ], - [ static => content => mt('_pedit_form_original_note') ], - [ text => name => mt('_pedit_form_alias'), short => 'alias', rows => 3 ], - [ static => content => mt('_pedit_form_alias_note') ], - [ text => name => mt('_pedit_form_desc').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 6 ], - ]); + $self->htmlForm({ frm => $frm, action => $r ? "/c$id/edit" : '/c/new', editsum => 1, upload => 1 }, + chare_geninfo => [ mt('_chare_form_generalinfo'), + [ input => name => mt('_chare_form_name'), short => 'name' ], + [ input => name => mt('_chare_form_original'), short => 'original' ], + [ static => content => mt('_chare_form_original_note') ], + [ text => name => mt('_chare_form_alias'), short => 'alias', rows => 3 ], + [ static => content => mt('_chare_form_alias_note') ], + [ text => name => mt('_chare_form_desc').'<br /><b class="standout">'.mt('_inenglish').'</b>', short => 'desc', rows => 6 ], + ], + + chare_img => [ mt('_chare_image'), [ static => nolabel => 1, content => sub { + div class => 'img'; + p mt '_chare_image_none' if !$frm->{image}; + p mt '_chare_image_processing' if $frm->{image} && $frm->{image} < 0; + img src => sprintf("%s/ch/%02d/%d.jpg", $self->{url_static}, $frm->{image}%100, $frm->{image}) if $frm->{image} && $frm->{image} > 0; + end; + + div; + h2 mt '_chare_image_id'; + input type => 'text', class => 'text', name => 'image', id => 'image', value => $frm->{image}; + p mt '_chare_image_id_msg'; + br; br; + + h2 mt '_chare_image_upload'; + input type => 'file', class => 'text', name => 'img', id => 'img'; + p mt('_chare_image_upload_msg'); + end; + }]]); $self->htmlFooter; } +sub _uploadimage { + my($self, $c, $frm) = @_; + return $c ? $frm->{image} : 0 if $frm->{_err} || !$self->reqPost('img'); + + # perform some elementary checks + my $imgdata = $self->reqUploadRaw('img'); + $frm->{_err} = [ 'noimage' ] if $imgdata !~ /^(\xff\xd8|\x89\x50)/; # JPG or PNG headers + $frm->{_err} = [ 'toolarge' ] if length($imgdata) > 1024*1024; + return undef if $frm->{_err}; + + # get image ID and save it, to be processed by Multi + my $imgid = $self->dbCharImageId; + my $fn = sprintf '%s/static/ch/%02d/%d.jpg', $VNDB::ROOT, $imgid%100, $imgid; + $self->reqSaveUpload('img', $fn); + chmod 0666, $fn; + + return -1*$imgid; +} + + 1; diff --git a/util/sql/func.sql b/util/sql/func.sql index 23ae0fb2..2b204902 100644 --- a/util/sql/func.sql +++ b/util/sql/func.sql @@ -560,6 +560,13 @@ $$ LANGUAGE plpgsql; +-- Send a notify when a new character image is uploaded +CREATE OR REPLACE FUNCTION chars_rev_image_notify() RETURNS trigger AS $$ + BEGIN NOTIFY charimage; RETURN NULL; END; +$$ LANGUAGE plpgsql; + + + -- Send a notify when a screenshot needs to be processed CREATE OR REPLACE FUNCTION screenshot_process_notify() RETURNS trigger AS $$ BEGIN NOTIFY screenshot; RETURN NULL; END; diff --git a/util/updates/update_2.19.sql b/util/updates/update_2.19.sql index 0360feda..462e4eed 100644 --- a/util/updates/update_2.19.sql +++ b/util/updates/update_2.19.sql @@ -75,6 +75,8 @@ CREATE TABLE chars_vns ( PRIMARY KEY(cid, vid, rid) ); +CREATE SEQUENCE charimg_seq; + -- allow characters to be versioned using the changes table @@ -86,6 +88,7 @@ DROP TYPE dbentry_type; ALTER TYPE dbentry_type_tmp RENAME TO dbentry_type; CREATE TRIGGER hidlock_update BEFORE UPDATE ON chars FOR EACH ROW WHEN (OLD.latest IS DISTINCT FROM NEW.latest) EXECUTE PROCEDURE update_hidlock(); +CREATE TRIGGER chars_rev_image_notify AFTER INSERT OR UPDATE ON chars_rev FOR EACH ROW WHEN (NEW.image < 0) EXECUTE PROCEDURE chars_rev_image_notify(); -- load the updated functions |