diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ChangeLog | 14 | ||||
-rw-r--r-- | lib/Multi/Anime.pm | 303 | ||||
-rw-r--r-- | lib/Multi/Core.pm | 2 | ||||
-rw-r--r-- | lib/Multi/Maintenance.pm | 43 | ||||
-rw-r--r-- | lib/VNDB/Util/DB.pm | 36 | ||||
-rw-r--r-- | lib/VNDB/Util/Tools.pm | 4 | ||||
-rw-r--r-- | lib/VNDB/VN.pm | 23 | ||||
-rw-r--r-- | lib/global.pl | 27 |
8 files changed, 433 insertions, 19 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog index 2568880b..3e325ccd 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -5,7 +5,19 @@ TODO: + Remove all references to an item when it's hidden (preferably with the option to re-add them when unhiding) + Add a link for the hidden 'h' option at /hist - + The delete option should be removed + + The delete option should be removed + + AJAXified image upload system to avoid confusion about whether an image is + uploaded or not + + Use AniDB's daily title dump and implement a search feature to add + anime relations without having to visit AniDB. + +1.15 - ? + - Relation graph now also updated on VN title change + - Anime relations + - [js] Position of the dropdown box is now relative to the link element, not + the cursor + - Used inline-block instead of block for icon image sprites (to avoid stupid + float hacks) 1.14 - 2008-04-26 - Removed the ID gap prevention method diff --git a/lib/Multi/Anime.pm b/lib/Multi/Anime.pm new file mode 100644 index 00000000..44fafb92 --- /dev/null +++ b/lib/Multi/Anime.pm @@ -0,0 +1,303 @@ + +# +# Multi::Anime - Fetches anime info from AniDB +# + +package Multi::Anime; + +use strict; +use warnings; +use POE 'Wheel::UDP'; +use Tie::ShareLite ':lock'; +use Socket 'inet_ntoa'; +use Time::HiRes 'time'; + + +sub TIMEOUT () { 100 } # not part of the API +sub LOGIN_ACCEPTED () { 200 } +sub LOGIN_ACCEPTED_NEW_VER () { 201 } +sub ANIME () { 230 } +sub NO_SUCH_ANIME () { 330 } +sub NOT_LOGGED_IN () { 403 } +sub LOGIN_FIRST () { 501 } +sub CLIENT_BANNED () { 504 } +sub INVALID_SESSION () { 506 } +sub BANNED () { 555 } +sub ANIDB_OUT_OF_SERVICE () { 601 } +sub SERVER_BUSY () { 602 } + +my @expected_codes = ( TIMEOUT, LOGIN_ACCEPTED, LOGIN_ACCEPTED_NEW_VER, ANIME, NO_SUCH_ANIME, NOT_LOGGED_IN, LOGIN_FIRST, INVALID_SESSION ); + + +sub spawn { + # The 'anime' command doesn't actually do anything, it just + # adds IDs to process to the internal queue, which is seperate + # from the global processing queue. + # This module -only- fetches anime information in daemon mode! + # Calling the anime command with an ID as argument will force + # the information to be refreshed. This is not recommended, + # just use 'anime check' for normal usage. + + my $p = shift; + POE::Session->create( + package_states => [ + $p => [qw| _start shutdown cmd_anime nextcmd receivepacket updateanime |], + ], + heap => { + # POE::Wheels::UDP options + LocalAddr => '0.0.0.0', + LocalPort => 9000, + PeerAddr => do { + if(!$Multi::DAEMONIZE) { + my $a = gethostbyname('api.anidb.info'); + die "ERROR: Couldn't resolve domain" if !defined $a; + inet_ntoa($a); + } else { + 0; + } + }, + PeerPort => 9000, + # AniDB UDP API options + user => 'vnmulti', + pass => '', + client => 'multi', + clientver => 1, + # Misc settings + msgdelay => 10, + timeout => 30, + timeoutdelay => 0.4, # $delay = $msgdelay ^ (1 + $tm*$timeoutdelay) + maxtimeoutdelay => 2*3600, # two hours + cachetime => 30*24*3600, # one month + + @_, + w => undef, + s => '', # session key, '' = not logged in + tm => 0, # number of repeated timeouts + lm => 0, # timestamp of last outgoing message, 0=no running msg + aid => 0, # anime ID of the last sent ANIME command + tag => int(rand()*50000), + }, + ); +} + + +sub _start { + $_[KERNEL]->alias_set('anime'); + $_[KERNEL]->call(core => register => qr/^anime ([0-9]+|check)$/, 'cmd_anime'); + + # check for anime twice a day + $_[KERNEL]->post(core => addcron => '0 0,12 * * *', 'anime check'); + $_[KERNEL]->sig('shutdown' => 'shutdown'); + + if(!$Multi::DAEMONIZE) { + # init the UDP 'connection' + $_[HEAP]{w} = POE::Wheel::UDP->new( + (map { $_ => $_[HEAP]{$_} } qw| LocalAddr LocalPort PeerAddr PeerPort |), + InputEvent => 'receivepacket', + Filter => POE::Filter::Stream->new(), + ); + + # start executing commands + $_[KERNEL]->delay(nextcmd => 0); #$_[HEAP]{msgdelay}); + } +} + + +sub shutdown { + undef $_[HEAP]{w}; + $_[KERNEL]->delay('nextcmd'); + $_[KERNEL]->delay('receivepacket'); +} + + +sub cmd_anime { # cmd, arg + my @push; + if($_[ARG1] eq 'check') { + # only animes we have never fetched, or haven't been updated for a month + my $q = $Multi::SQL->prepare(q| + SELECT id + FROM anime + WHERE lastfetch < ? + AND lastfetch <> -1|); + $q->execute(int(time-$_[HEAP]{cachetime})); + push @push, map $_->[0], @{$q->fetchall_arrayref([])}; + $_[KERNEL]->call(core => log => 2, 'All anime info is up-to-date!') if !@push; + } else { + push @push, $_[ARG1]; + } + + if(@push) { + my $s = tie my %s, 'Tie::ShareLite', @VNDB::SHMOPTS; + $s->lock(LOCK_EX); + my @q = $s{anime} ? @{$s{anime}} : (); + push @q, grep { + my $ia = $_; + !(scalar grep $ia == $_, @q) + } @push; + $s{anime} = \@q; + $s->unlock(); + } + + $_[KERNEL]->post(core => finish => $_[ARG0]); +} + + +sub nextcmd { + return if $_[HEAP]{lm}; + + my $s = tie my %s, 'Tie::ShareLite', @VNDB::SHMOPTS; + my @q = $s{anime} ? @{$s{anime}} : (); + undef $s; + + if(!@q) { # nothing to do... + $_[KERNEL]->delay(nextcmd => $_[HEAP]{msgdelay}); + return; + } + my %cmd; + + # not logged in, get a session + if(!$_[HEAP]{s}) { + %cmd = ( + command => 'AUTH', + user => $_[HEAP]{user}, + pass => $_[HEAP]{pass}, + protover => 3, + client => $_[HEAP]{client}, + clientver => $_[HEAP]{clientver}, + enc => 'UTF-8', + ); + $_[KERNEL]->call(core => log => 3, 'Authenticating with AniDB...'); + } + + # logged in, get anime + else { + $_[HEAP]{aid} = $q[0]; + %cmd = ( + command => 'ANIME', + aid => $q[0], + acode => 3973121, # aid, ANN id, NFO id, year, type, romaji, kanji + ); + $_[KERNEL]->call(core => log => 3, 'Fetching info for a%d', $q[0]); + } + + # send command + my $cmd = delete $cmd{command}; + $cmd{tag} = ++$_[HEAP]{tag}; + $cmd{s} = $_[HEAP]{s} if $_[HEAP]{s}; + $cmd .= ' '.join('&', map { + $cmd{$_} =~ s/&/&/g; + $cmd{$_} =~ s/\r?\n/<br \/>/g; + $_.'='.$cmd{$_} + } keys %cmd); + $_[HEAP]{w}->put({ payload => [ $cmd ]}); + $VNDB::DEBUG && printf " > %s\n", $cmd; + + $_[KERNEL]->delay(receivepacket => $_[HEAP]{timeout}, { payload => [ $_[HEAP]{tag}.' 100 TIMEOUT' ] }); + $_[HEAP]{lm} = time; +} + + +sub receivepacket { # input, wheelid + $_[KERNEL]->delay('receivepacket'); # disable the timeout + my @r = split /\n/, $_[ARG0]{payload}[0]; + my $delay = $_[HEAP]{msgdelay}; + + my($tag, $code, $msg) = ($1, $2, $3) if $r[0] =~ /^([0-9]+) ([0-9]+) (.+)$/; + + if(!grep $_ == $code, @expected_codes) { + $_[KERNEL]->call(core => log => 1, "Received an unexpected reply after %.2fs!\n < %s", + time-$_[HEAP]{lm}, join("\n < ", @r)); + } else { + $_[KERNEL]->call(core => log => 3, 'Received from AniDB after %.2fs: %d %s', + time-$_[HEAP]{lm}, $code, $msg); + $VNDB::DEBUG && print ' < '.join("\n < ", @r)."\n"; + } + + # just handle anime data, even if the tag is not correct + if($code == ANIME) { + $_[KERNEL]->yield(updateanime => $_[HEAP]{aid}, $r[1]); + } + + # tag incorrect, ignore message + if($tag != $_[HEAP]{tag}) { + $_[KERNEL]->call(core => log => 3, 'Ignoring incorrect tag') if $code != ANIME; + return; + } + + # try again later + if($code == TIMEOUT || $code == CLIENT_BANNED || $code == BANNED || $code == ANIDB_OUT_OF_SERVICE || $code == SERVER_BUSY) { + $_[HEAP]{tm}++; + $delay = $_[HEAP]{msgdelay}**(1 + $_[HEAP]{tm}*$_[HEAP]{timeoutdelay}); + $delay = $_[HEAP]{maxtimeoutdelay} if $delay > $_[HEAP]{maxtimeoutdelay}; + $_[KERNEL]->call(core => log => 1, 'Delaying %.0fs.', $delay); + } + + # oops, wrong id + if($code == NO_SUCH_ANIME) { + $_[KERNEL]->yield(updateanime => $_[HEAP]{aid}, 'notfound'); + } + + # ok, we have a session now + if($code == LOGIN_ACCEPTED || $code == LOGIN_ACCEPTED_NEW_VER) { + $_[HEAP]{s} = $1 if $msg =~ /^\s*([a-zA-Z0-9]{4,8}) /; + } + + # oops, we should've logged in, get a new session + if($code == NOT_LOGGED_IN || $code == LOGIN_FIRST || $code == INVALID_SESSION) { + $_[HEAP]{s} = ''; + } + + $_[HEAP]{lm} = $_[HEAP]{aid} = 0; + $_[HEAP]{tm} = 0 if $delay == $_[HEAP]{msgdelay}; + $_[KERNEL]->delay(nextcmd => $delay); +} + + +sub updateanime { # aid, data|'notfound' + # aid, ANN id, NFO id, year, type, romaji, kanji, lastfetch + my @col = $_[ARG1] eq 'notfound' + ? ($_[ARG0], 0, 0, 0, 0, '', '', -1) + : (split(/\|/, $_[ARG1]), int time); + + if($col[7] > 0) { + for (@col) { + $_ =~ s/<br \/>/\n/g; + $_ =~ s/`/'/g; + } + $col[3] = $1 if $col[3] =~ /^([0-9]+)/; # remove multi-year stuff + for(0..$#$VNDB::ANITYPE) { + $col[4] = $_ if lc($VNDB::ANITYPE->[$_][1]) eq lc($col[4]); + } + $col[4] = 0 if $col[4] !~ /^[0-9]+$/; + } + + # try to UPDATE first + my $r = $Multi::SQL->do(q| + UPDATE anime + SET id = ?, ann_id = ?, nfo_id = ?, year = ?, type = ?, + title_romaji = ?, title_kanji = ?, lastfetch = ? + WHERE id = ?|, + undef, @col, $col[0]); + + # fall back to INSERT when nothing was updated + $Multi::SQL->do(q| + INSERT INTO anime + (id, ann_id, nfo_id, year, type, title_romaji, title_kanji, lastfetch) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)|, + undef, @col) if $r < 1; + + # remove from queue + my $s = tie my %s, 'Tie::ShareLite', @VNDB::SHMOPTS; + $s->lock(LOCK_EX); + my @q = grep $_ != $_[ARG0], ($s{anime} ? @{$s{anime}} : ()); + $s{anime} = \@q; + $s->unlock(); + + $col[7] > 0 + ? $_[KERNEL]->post(core => log => 2, 'Updated anime info for a%d', $col[0]) + : $_[KERNEL]->post(core => log => 1, 'Anime a%d not found!', $col[0]); +} + + +1; + diff --git a/lib/Multi/Core.pm b/lib/Multi/Core.pm index 6f94f860..2d9ea85f 100644 --- a/lib/Multi/Core.pm +++ b/lib/Multi/Core.pm @@ -123,7 +123,7 @@ sub log { # level, msg close $F; # (debug) log to stdout as well... - #printf "[%s] %s\n", scalar localtime, $msg; + $VNDB::DEBUG && printf "[%s] %s\n", scalar localtime, $msg; } diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm index fb74e192..51fff936 100644 --- a/lib/Multi/Maintenance.pm +++ b/lib/Multi/Maintenance.pm @@ -11,10 +11,12 @@ use POE; sub spawn { + # WARNING: these maintenance tasks can block the process for a few seconds + my $p = shift; POE::Session->create( package_states => [ - $p => [qw| _start cmd_maintenance vncache ratings prevcache integrity |], + $p => [qw| _start cmd_maintenance vncache ratings prevcache integrity unkanime |], ], ); } @@ -22,7 +24,7 @@ sub spawn { sub _start { $_[KERNEL]->alias_set('maintenance'); - $_[KERNEL]->call(core => register => qr/^maintenance((?: (?:all|vncache|ratings|prevcache|integrity))+)$/, 'cmd_maintenance'); + $_[KERNEL]->call(core => register => qr/^maintenance((?: (?:all|vncache|ratings|prevcache|integrity|unkanime))+)$/, 'cmd_maintenance'); # Perform all maintenance functions every day on 0:00 $_[KERNEL]->post(core => addcron => '0 0 * * *', 'maintenance all'); @@ -32,10 +34,11 @@ sub _start { sub cmd_maintenance { local $_ = $_[ARG1]; - $_[KERNEL]->yield('vncache') if /(vncache|all)/; - $_[KERNEL]->yield('ratings') if /(ratings|all)/; - $_[KERNEL]->yield('prevcache') if /(prevcache|all)/; - $_[KERNEL]->yield('integrity') if /(integrity|all)/; + $_[KERNEL]->yield('vncache') if /(?:vncache|all)/; + $_[KERNEL]->yield('ratings') if /(?:ratings|all)/; + $_[KERNEL]->yield('prevcache') if /(?:prevcache|all)/; + $_[KERNEL]->yield('integrity') if /(?:integrity|all)/; + $_[KERNEL]->yield('unkanime') if /(?:unkanime|all)/; $_[KERNEL]->post(core => finish => $_[ARG0]); } @@ -55,6 +58,7 @@ sub ratings { sub prevcache { $_[KERNEL]->call(core => log => 3 => 'Updating prev column in the changes table...'); + # this can take a while, maybe split these up in 3 queries? $Multi::SQL->do(q|SELECT update_prev('vn', ''), update_prev('releases', ''), update_prev('producers', '')|); } @@ -79,6 +83,33 @@ sub integrity { } +sub unkanime { + # warn for VNs with a non-existing anidb id + # (maybe do an automated edit or something in the future) + + my $q = $Multi::SQL->prepare(q| + SELECT v.id, va.aid + FROM vn_anime va + JOIN vn v ON va.vid = v.latest + JOIN anime a ON va.aid = a.id + WHERE a.lastfetch < 0|); + $q->execute(); + my $r = $q->fetchall_arrayref([]); + my %aid = map { + my $a=$_; + $a->[1] => join(',', map { $a->[1] == $_->[1] ? $_->[0] : () } @$r) + } @$r; + + if(keys %aid) { + $_[KERNEL]->call(core => log => 1, '!NON-EXISTING RELATED ANIME FOUND!: %s', + join('; ', map { 'a'.$_.':v'.$aid{$_} } keys %aid) + ); + } else { + $_[KERNEL]->call(core => log => 3, 'No problems found with the related anime'); + } +} + + 1; diff --git a/lib/VNDB/Util/DB.pm b/lib/VNDB/Util/DB.pm index 3f99aff8..f10f7b67 100644 --- a/lib/VNDB/Util/DB.pm +++ b/lib/VNDB/Util/DB.pm @@ -630,10 +630,11 @@ sub DBGetVN { # %options->{ id rev char search order results page what cati cate ); $_->{c_released} = sprintf '%08d', $_->{c_released} for @$r; - if($o{what} =~ /(relations|categories)/ && $#$r >= 0) { + if($o{what} =~ /(?:relations|categories|anime)/ && $#$r >= 0) { my %r = map { $r->[$_]{relations} = []; $r->[$_]{categories} = []; + $r->[$_]{anime} = []; ($r->[$_]{cid}, $_) } 0..$#$r; @@ -646,6 +647,16 @@ sub DBGetVN { # %options->{ id rev char search order results page what cati cate )}); } + if($o{what} =~ /anime/) { + push(@{$r->[$r{$_->{vid}}]{anime}}, $_) && delete $_->{vid} for (@{$s->DBAll(q| + SELECT va.vid, a.* + FROM vn_anime va + JOIN anime a ON va.aid = a.id + WHERE va.vid IN(!l)|, + [ keys %r ] + )}); + } + if($o{what} =~ /relations/) { my $rel = $s->DBAll(q| SELECT rel.vid1, rel.vid2, rel.relation, vr.title @@ -669,7 +680,7 @@ sub DBGetVN { # %options->{ id rev char search order results page what cati cate } -sub DBAddVN { # %options->{ columns in vn_rev + comm + relations } +sub DBAddVN { # %options->{ columns in vn_rev + comm + relations + categories + anime } my($s, %o) = @_; $s->DBExec(q| @@ -690,7 +701,7 @@ sub DBAddVN { # %options->{ columns in vn_rev + comm + relations } } -sub DBEditVN { # id, %options->( columns in vn_rev + comm + relations + categories + uid + causedby } +sub DBEditVN { # id, %options->( columns in vn_rev + comm + relations + categories + anime + uid + causedby } my($s, $vid, %o) = @_; $s->DBExec(q| @@ -733,6 +744,25 @@ sub _insert_vn_rev { VALUES (%d, %d, %d)|, $cid, $_->[1], $_->[0] ) for (@{$o->{relations}}); + + if(@{$o->{anime}}) { + $s->DBExec(q| + INSERT INTO vn_anime (vid, aid) + VALUES (%d, %d)|, + $cid, $_ + ) for (@{$o->{anime}}); + + # insert unknown anime + my $a = $s->DBAll(q| + SELECT id FROM anime WHERE id IN(!l)|, + $o->{anime}); + $s->DBExec(q| + INSERT INTO anime (id) VALUES (%d)|, $_ + ) for (grep { + my $ia = $_; + !(scalar grep $ia == $_->{id}, @$a) + } @{$o->{anime}}); + } } diff --git a/lib/VNDB/Util/Tools.pm b/lib/VNDB/Util/Tools.pm index c2d9268b..f338ad7c 100644 --- a/lib/VNDB/Util/Tools.pm +++ b/lib/VNDB/Util/Tools.pm @@ -132,8 +132,8 @@ sub AddDefaultStuff { sub RunCmd { # cmd my $s = tie my %s, 'Tie::ShareLite', @VNDB::SHMOPTS; $s->lock(LOCK_EX); - $s{queue} = [] if !$s{queue}; - push(@{$s{queue}}, grep !/^-/, $_[1]); + my @q = ( ($s{queue} ? @{$s{queue}} : ()), $_[1] ); + $s{queue} = \@q; $s->unlock(); } diff --git a/lib/VNDB/VN.pm b/lib/VNDB/VN.pm index ea13445b..4732e278 100644 --- a/lib/VNDB/VN.pm +++ b/lib/VNDB/VN.pm @@ -24,13 +24,13 @@ sub VNPage { my $v = $self->DBGetVN( id => $id, - what => 'extended relations categories'.($r->{rev} ? ' changes' : ''), + what => 'extended relations categories anime'.($r->{rev} ? ' changes' : ''), $r->{rev} ? ( rev => $r->{rev} ) : () )->[0]; return $self->ResNotFound if !$v->{id}; $r->{diff} ||= $v->{prev} if $r->{rev}; - my $c = $r->{diff} && $self->DBGetVN(id => $id, rev => $r->{diff}, what => 'extended changes relations categories')->[0]; + my $c = $r->{diff} && $self->DBGetVN(id => $id, rev => $r->{diff}, what => 'extended changes relations categories anime')->[0]; $v->{next} = $self->DBGetHist(type => 'v', id => $id, next => $v->{cid}, showhid => 1)->[0]{id} if $r->{rev}; if($page eq 'rg' && $v->{rgraph}) { @@ -67,7 +67,7 @@ sub VNEdit { my $rev = $self->FormCheck({ name => 'rev', required => 0, default => 0, template => 'int' })->{rev}; - my $v = $self->DBGetVN(id => $id, what => 'extended changes relations categories', $rev ? ( rev => $rev ) : ())->[0] if $id; + my $v = $self->DBGetVN(id => $id, what => 'extended changes relations categories anime', $rev ? ( rev => $rev ) : ())->[0] if $id; return $self->ResNotFound() if $id && !$v; return $self->ResDenied if !$self->AuthCan('edit') || ($v->{locked} && !$self->AuthCan('lock')); @@ -76,6 +76,7 @@ sub VNEdit { ( map { $_ => $v->{$_} } qw| title desc alias img_nsfw length l_wp l_cisv l_vnn | ), relations => join('|||', map { $_->{relation}.','.$_->{id}.','.$_->{title} } @{$v->{relations}}), categories => join(',', map { $_->[0].$_->[1] } sort { $a->[0] cmp $b->[0] } @{$v->{categories}}), + anime => join(' ', sort { $a <=> $b } map $_->{id}, @{$v->{anime}}), ) : (); my $frm = {}; @@ -88,18 +89,21 @@ sub VNEdit { { name => 'l_wp', required => 0, default => '', maxlength => 150 }, { name => 'l_cisv', required => 0, default => 0, template => 'int' }, { name => 'l_vnn', required => 0, default => 0, template => 'int' }, + { name => 'anime', required => 0, default => '' }, { name => 'img_nsfw', required => 0 }, { name => 'categories', required => 0, default => '' }, { name => 'relations', required => 0, default => 0 }, { name => 'comm', required => 0, default => '' }, ); $frm->{img_nsfw} = $frm->{img_nsfw} ? 1 : 0; + $frm->{anime} = join(' ', sort { $a <=> $b } grep /^[0-9]+$/, split(/\s+/, $frm->{anime})); # re-sort return $self->ResRedirect('/v'.$id, 'post') - if $id && !$self->ReqParam('img') && 10 == scalar grep { $b4{$_} eq $frm->{$_} } keys %b4; + if $id && !$self->ReqParam('img') && 11 == scalar grep { $b4{$_} eq $frm->{$_} } keys %b4; my $relations = [ map { /^([0-9]+),([0-9]+)/ && $2 != $id ? ( [ $1, $2 ] ) : () } split /\|\|\|/, $frm->{relations} ]; my $cat = [ map { [ substr($_,0,3), substr($_,3,1) ] } split /,/, $frm->{categories} ]; + my $anime = [ split / /, $frm->{anime} ]; # upload image my $imgid = ''; @@ -134,6 +138,7 @@ sub VNEdit { my %args = ( ( map { $_ => $frm->{$_} } qw| title desc alias comm length l_wp l_cisv l_vnn img_nsfw| ), image => $imgid, + anime => $anime, relations => $relations, categories => $cat, ); @@ -149,6 +154,13 @@ sub VNEdit { my %new = map { $_->[1] => $_->[0] } @$relations; $self->VNUpdReverse(\%old, \%new, $id, $cid); } + # also regenerate relation graph if the title changes + elsif($frm->{title} ne $b4{title}) { + $self->RunCmd('relraph '.$id); + } + + # check for new anime data + $self->RunCmd('anime check') if $frm->{anime} ne $b4{anime}; return $self->ResRedirect('/v'.$id.'?rev='.$cid, 'post'); } @@ -302,7 +314,7 @@ sub VNUpdReverse { # old, new, id, cid } for my $i (keys %upd) { - my $r = $self->DBGetVN(id => $i, what => 'extended relations categories')->[0]; + my $r = $self->DBGetVN(id => $i, what => 'extended relations categories anime')->[0]; my @newrel; $_->{id} != $id && push @newrel, [ $_->{relation}, $_->{id} ] for (@{$r->{relations}}); @@ -312,6 +324,7 @@ sub VNUpdReverse { # old, new, id, cid comm => 'Reverse relation update caused by revision '.$cid.' of v'.$id, causedby => $cid, uid => 1, # Multi - hardcoded + anime => [ map $_->{id}, @{$r->{anime}} ], ( map { $_ => $r->{$_} } qw| title desc alias categories img_nsfw length l_wp l_cisv l_vnn image | ) ); } diff --git a/lib/global.pl b/lib/global.pl index 74c3c070..890046b2 100644 --- a/lib/global.pl +++ b/lib/global.pl @@ -10,7 +10,7 @@ our $PLAT = { lin => 'Linux', mac => 'Mac OS', dvd => 'DVD Player', - gba => 'Game Boy Advanced', + gba => 'Game Boy Advance', nds => 'Nintendo DS', psp => 'Playstation Portable', ps => 'Playstation', @@ -21,6 +21,7 @@ our $PLAT = { oth => 'Other' }; + # NOTE: don't forget to update dyna.js our $MED = { cd => 'CD', @@ -32,18 +33,21 @@ our $MED = { otc => 'Other (console)', }; + our $PROT = { co => 'Company', in => 'Individual', ng => 'Amateur group', }; + our $RTYP = [ 'Complete', 'Partial', 'Trial' ]; + # Yes, this is the category list. No, changing something here may # not change it on the entire site - many things are still hardcoded our $CAT = { @@ -104,6 +108,7 @@ our $LSTAT = [ 'Other', # XXX: hardcoded at 6 ]; + our $VREL = [ 'Sequel', 'Prequel', # 1 @@ -146,6 +151,26 @@ our $VRAGES = { }; +our $ANITYPE = [ + # VNDB AniDB + [ 'unknown', 'unknown', ], + [ 'TV', 'TV Series' ], + [ 'OVA', 'OVA' ], + [ 'Movie', 'Movie' ], + [ 'unknown', 'Other' ], + [ 'unknown', 'Web' ], + [ 'TV Special', 'TV Special' ], + [ 'unknown', 'Music Video' ], +]; +# AniDB defines: +# id="1", name="unknown +# id="2", name="TV Series +# id="3", name="OVA +# id="4", name="Movie +# id="5", name="Other +# id="6", name="Web +# id="7", name="TV Special +# id="8", name="Music Video |