summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryorhel <yorhel@1fe2e327-d9db-4752-bcf7-ef0cb4a1748b>2008-05-19 07:01:24 +0000
committeryorhel <yorhel@1fe2e327-d9db-4752-bcf7-ef0cb4a1748b>2008-05-19 07:01:24 +0000
commit2ce770e7e5817f8838fdaf7bc7eda2a8da972962 (patch)
tree4aa6306599d38b6af01c8495d6731a838944602e
parent8b72b6535a553f8751842369a3abc0016d18611e (diff)
Too many changes to keep track of. See ChangeLog. (I should commit more often -.-)
git-svn-id: svn://vndb.org/vndb@13 1fe2e327-d9db-4752-bcf7-ef0cb4a1748b
-rw-r--r--data/tpl/defs.pl26
-rw-r--r--data/tpl/home10
-rw-r--r--data/tpl/main5
-rw-r--r--data/tpl/pbrowse16
-rw-r--r--data/tpl/redit2
-rw-r--r--data/tpl/vnbrowse110
-rw-r--r--data/tpl/vnedit2
-rw-r--r--data/tpl/vnpage37
-rw-r--r--data/tpl/vnpage_rel6
-rw-r--r--data/tpl/vnpage_stats6
-rw-r--r--lib/ChangeLog12
-rw-r--r--lib/Multi/Anime.pm3
-rw-r--r--lib/Multi/IRC.pm60
-rw-r--r--lib/Multi/Maintenance.pm20
-rw-r--r--lib/Multi/RG.pm2
-rw-r--r--lib/VNDB.pm7
-rw-r--r--lib/VNDB/Releases.pm2
-rw-r--r--lib/VNDB/Util/DB.pm18
-rw-r--r--lib/VNDB/VN.pm72
-rw-r--r--lib/global.pl15
-rw-r--r--static/files/16x14.pngbin2397 -> 0 bytes
-rw-r--r--static/files/def.js152
-rw-r--r--static/files/icons.pngbin0 -> 2816 bytes
-rw-r--r--static/files/style.css177
-rw-r--r--util/multi.pl2
-rw-r--r--util/updates/update_1.16.sql74
26 files changed, 519 insertions, 317 deletions
diff --git a/data/tpl/defs.pl b/data/tpl/defs.pl
index 6c70a68b..405cc2a5 100644
--- a/data/tpl/defs.pl
+++ b/data/tpl/defs.pl
@@ -19,14 +19,14 @@ sub shorten {local$_=shift||return'';return length>$_[0]?substr($_,0,$_[0]-3)
# Date string format: yyyy-mm-dd
# y = 0 -> Unknown
# y = 9999 -> TBA (To Be Announced)
-# m = 0 -> Month + day unknown, year known
-# d = 0 -> Day unknown, month + year known
+# m = 99 -> Month + day unknown, year known
+# d = 99 -> Day unknown, month + year known
sub datestr {
- my $d = $_[0]||'00000000';
- my @d = map { int } $1, $2, $3 if $d =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/;
+ my $d = sprintf '%08d', $_[0]||0;
+ my $b = $d > Time::CTime::strftime("%Y%m%d", gmtime());
+ my @d = map int, $1, $2, $3 if $d =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/;
return 'unknown' if $d[0] == 0;
- my $r = sprintf !$d[1] ? '%04d' : !$d[2] ? '%04d-%02d' : '%04d-%02d-%02d', @d;
- my $b = $r gt Time::CTime::strftime("%Y-%m-%d", gmtime());
+ my $r = sprintf $d[1] == 99 ? '%04d' : $d[2] == 99 ? '%04d-%02d' : '%04d-%02d-%02d', @d;
$r = 'TBA' if $d[0] == 9999;
return ($b?'<b class="future">':'').$r.($b?'</b>':'');
}
@@ -134,7 +134,8 @@ sub summary { # cmd, len, def
my $res = '';
my $len = 0;
my $as = 0;
- for (split / /, $_[0]) {
+ (my $txt = $_[0]) =~ s/\r?\n/\n /g;
+ for (split / /, $txt) {
next if !defined $_ || $_ eq '';
my $l = length;
s/\&/&amp;/g;
@@ -146,7 +147,7 @@ sub summary { # cmd, len, def
}
if(!$as && s/(http|https):\/\/(.+[0-9a-zA-Z=\/])/<a href="$1:\/\/$2" rel="nofollow">link<\/a>/) {
$l = 4;
- } elsif(!$as) {
+ } elsif($as) {
s/^([duvpr][0-9]+)[^\w]*$/<a href="\/$1">$1<\/a>/;
}
while(s/\[\/url\]/<\/a>/) {
@@ -157,8 +158,8 @@ sub summary { # cmd, len, def
last if $_[1] && $len > $_[1];
$res .= "$_ ";
}
- $res =~ y/\r\n/ / if $_[1];
- $res =~ s/\r?\n/<br \/>/g if !$_[1];
+ $res =~ y/\n/ / if $_[1];
+ $res =~ s/\n/<br \/>/g if !$_[1];
$res =~ s/ +$//;
$res .= '</a>' x $as if $as;
$res .= '...' if $_[1] && $len > $_[1];
@@ -179,7 +180,7 @@ sub ttabs { # [vrp], obj, sel
'<a href="/%s/del" id="idel">del</a>',
sprintf('<a href="/%%s/hide"%s>%s</a>', $t eq 'v' ? ' id="vhide"' : '', $$o{hidden} ? 'unhide' : 'hide')
) : (),
- !$$o{locked} || ($p{Authedit} && $p{Authlock}) ?
+ (!$$o{locked} && !$$o{hidden}) || ($p{Authedit} && $p{Authlock}) ?
($s eq 'edit' ? 'edit' : '<a href="'.($p{Authedit}?'/%s/edit':'/u/register?n=1').'" '.($t eq 'v' || $t eq 'r' ? 'class="dropdown" rel="nofollow editDD"':'').'>edit</a>') : (),
$p{Authhist} ?
@@ -247,8 +248,7 @@ my %pagetitles = (
vnrg => sub { return 'Relations for '.$p{vnrg}{vn}{title} },
vnstats => sub { return 'User statistics for '.$p{vnstats}{vn}{title} },
vnbrowse => sub {
- return $p{vnbrowse}{chr} eq 'search' ? sprintf 'Search results for "%s"', $p{searchquery} :
- $p{vnbrowse}{chr} eq 'cat' ? 'Browse categories' :
+ return $p{vnbrowse}{chr} eq 'search' ? 'Visual novel search' :
$p{vnbrowse}{chr} eq 'mod' ? 'Visual Novels awaiting moderation' :
$p{vnbrowse}{chr} eq 'all' ? 'Browse all visual novels' :
$p{vnbrowse}{chr} eq '0' ? 'Browse by char: Other' :
diff --git a/data/tpl/home b/data/tpl/home
index 37ada1d8..e8e9158d 100644
--- a/data/tpl/home
+++ b/data/tpl/home
@@ -13,13 +13,13 @@
or to discuss about the database at our <a href="http://forum.vndb.org/">forums</a>.
</p>
-<h3 class="home">VNDB 1.14!</h3>
+<h3 class="home">VNDB 1.15!</h3>
<p class="desc">
- A large update technical-wise, but no major noticable changes: Large cover images will now automatically
- get resized, all static content has been moved to a separate domain, the Nintento Wii has been
- added to the platform list, and various other small changes and bug fixes.
+ This update finally implements a new feature I've been wanting to see for a
+ while now: anime relations! Other than that, it also includes the usual bug
+ fixes and some other improvements.
<br />
- <a href="http://forum.vndb.org/index.php?topic=49.0">Read more...</a> - <a href="http://forum.vndb.org/index.php?board=7.0">news archive</a>.
+ <a href="http://forum.vndb.org/index.php?topic=50.0">Read more...</a> - <a href="http://forum.vndb.org/index.php?board=7.0">news archive</a>.
</p>
<ul class="home">
diff --git a/data/tpl/main b/data/tpl/main
index cbac2729..5c009297 100644
--- a/data/tpl/main
+++ b/data/tpl/main
@@ -32,7 +32,7 @@
<form id="search" method="get" action="/v/search">
<fieldset>
<legend>Search</legend>
- <input id="searchfield" type="text" name="q" value="[[: $p{searchquery} || 'search' ]]"[[= !$p{searchquery} ? ' style="color: #999"': '' ]]- />
+ <input id="searchfield" type="text" name="sq" value="search" style="color: #999" />
<input id="searchsubmit" type="submit" value="Search" />
</fieldset>
</form>
@@ -75,7 +75,7 @@
<li><a href="/">Home</a></li>
<li><a href="/v">Visual Novels</a></li>
<li><a href="/p">Producers</a></li>
- <li><a href="/v/cat">Categories</a></li>
+ <li><a href="/v/search">Search</a></li>
<li><a href="/u/list">Users</a></li>
<li><a href="/hist">Recent changes</a></li>
<li><a href="/d6">FAQ</a></li>
@@ -134,6 +134,7 @@
<div id="footer">
<p>
vndb v[[: $VNDB::VERSION ]]- |
+ <a href="/d7">about us</a> |
<a href="mailto:contact@vndb.org">contact@vndb.org</a> |
designed by <a href="http://www.freecsstemplates.org/">free css templates</a>.
</p>
diff --git a/data/tpl/pbrowse b/data/tpl/pbrowse
index 71b40c82..8d2604c3 100644
--- a/data/tpl/pbrowse
+++ b/data/tpl/pbrowse
@@ -6,8 +6,8 @@
[[ } ]]-
<form id="psearch" method="get" action="/p" accept-charset="UTF-8">
<fieldset>
- <input type="text" name="q" id="q" value="[[: $d{query} ]]" class="text" />
- <input type="submit" value="Search!" />
+ <input type="text" name="q" id="q" value="[[: $d{query} ]]" class="text"
+ /><input type="submit" value="Search!" />
</fieldset>
</form>
</p>
@@ -25,17 +25,17 @@
<thead><tr>
<td class="tc1">Name</td>
<td class="tc2">Type</td>
- <td class="tc3">Main language</td>
- <td class="tc4">Website</td>
+ <td class="tc3">Website</td>
</tr></thead>
[[ for (@{$d{prods}}) { ]]-
<tr>
- <td class="tc1"><a href="/p[[= $_->{id} ]]">[[: $_->{name} ]]</a></td>
+ <td class="tc1">
+ <acronym class="icons lang -[[= $_->{lang} ]]" title="[[: $VNDB::LANG->{$_->{lang}} ]]">&nbsp;</acronym><a
+ href="/p[[= $_->{id} ]]" title="[[: $_->{original}||$_->{name} ]]">[[: $_->{name} ]]</a></td>
<td class="tc2">[[: $VNDB::PROT->{$_->{type}} ]]</td>
- <td class="tc3">[[: $VNDB::LANG->{$_->{lang}} ]]</td>
- <td class="tc4">
+ <td class="tc3">
[[ if($_->{website}) { ]]
- <a href="[[: $_->{website} ]]">[[: length($_->{website}) > 30 ? substr($_->{website}, 0, 27).'...' : $_->{website} ]]
+ <a href="[[: $_->{website} ]]">[[: shorten $_->{website}, 50 ]]
[[ } else { ]]---[[ } ]]
</td>
</tr>
diff --git a/data/tpl/redit b/data/tpl/redit
index 9567cce0..4bac5e24 100644
--- a/data/tpl/redit
+++ b/data/tpl/redit
@@ -42,7 +42,7 @@
{ type => 'static', raw => 1, text => '<label>Platforms</label><ul class="platforms">'.join('', map { my $p = $_;
'<li><input type="checkbox" name="platforms" value="'.$_.'" id="'.$_.'" '.
(($d{form}{platforms} && grep { $p eq $_ } @{$d{form}{platforms}}) ? 'checked="checked" ':'').'/>'.
- '<label for="'.$_.'"><acronym class="plat '.$_.'" title="'.$VNDB::PLAT->{$_}.'">&nbsp;</acronym>'.$VNDB::PLAT->{$_}.'</label></li>'
+ '<label for="'.$_.'"><acronym class="icons '.$_.'" title="'.$VNDB::PLAT->{$_}.'">&nbsp;</acronym>'.$VNDB::PLAT->{$_}.'</label></li>'
} sort { $VNDB::PLAT->{$a} cmp $VNDB::PLAT->{$b} } keys %$VNDB::PLAT).'</ul>' },
{ type => 'static', text => '<br />' },
diff --git a/data/tpl/vnbrowse b/data/tpl/vnbrowse
index 27aa78b7..fef795a3 100644
--- a/data/tpl/vnbrowse
+++ b/data/tpl/vnbrowse
@@ -1,31 +1,56 @@
<h2>[[: $p{PageTitle} ]]</h2>
-[[ if($d{chr} eq 'cat') { ]]-
-<ul id="cat">
-[[ for my $c (qw| e g p t l s |) { ]]-
- -[[= $c ne 'l' && $c ne 'p' ? '<li>' : '<br />' ]][[: $VNDB::CAT->{$c}[0] ]]-
- <ul>
- [[ for (sort keys %{$VNDB::CAT->{$c}[1]}) { ]]-
- <li class="cat_[[= $c.$_ ]][[= $d{incl} =~ /$c$_/ ? ' inc' : $d{excl} =~ /$c$_/ ? ' exc' : '' ]]">
- [[: $VNDB::CAT->{$c}[1]{$_} ]]- ([[= $d{cat}{$c.$_} || 0 ]])</li>
- [[ } ]]
- </ul>[[= $c ne 't' && $c ne 'g' ? '</li>' : '' ]]-
-[[ } ]]-
-</ul>
-<div id="lfilter">
- <b>Languages</b> (none selected means all)<br />
-[[ for (sort keys %{$d{lang}}) { next if !$d{lang}{$_}; ]]-
- <input type="checkbox" name="lang_[[= $_ ]]" id="lang_[[= $_ ]]" value="1" -[[= $d{slang}=~/$_/?'checked="checked"':'' ]] />
- <label for="lang_[[= $_ ]]">[[: $VNDB::LANG->{$_} ]]- ([[= $d{lang}{$_} ]])</label>
-[[ } ]]-
-</div>
-<br style="clear: left" />
-<input type="button" class="right" id="catsearch" name="catsearch" value="Search!" />
-<br style="clear: left" />
-<br />
-<br />
-[[ } elsif($d{chr} ne 'search') { ]]-
+[[ if($d{chr} eq 'search') { ]]
+ <form id="vsearch" method="get" action="/v/search" accept-charset="UTF-8">
+ <fieldset>
+ <input type="text" name="q" id="q" value="[[: $p{searchquery} ]]" class="text"
+ /><input type="submit" value="Search!" />
+ <br />
+ <b id="adsearchclick">[[= !$p{searchquery} ? '&#9662;' : '&#9656;' ]]- advanced options</b>
+ </fieldset>
+ </form>
+
+ <div id="adsearch" [[= !$p{searchquery} ? '' : ' style="display: none"' ]]>
+ <b>Categories</b> (inclusive, selecting more gives less results)
+ <ul id="cat">
+ [[ for my $c (qw| e g p t l s |) { ]]-
+ -[[= $c ne 'l' && $c ne 'p' ? '<li>' : '<br />' ]][[: $VNDB::CAT->{$c}[0] ]]-
+ <ul>
+ [[ for (sort keys %{$VNDB::CAT->{$c}[1]}) { my $ca = $c.$_; ]]-
+ <li[[= (grep /$ca/, @{$d{incl}}) ? ' class="inc"' : (grep /$ca/, @{$d{excl}}) ? ' class="exc"' : '' ]]- id="cat_[[= $ca ]]">
+ [[: $VNDB::CAT->{$c}[1]{$_} ]]- ([[= $d{cat}{$ca} || 0 ]])</li>
+ [[ } ]]
+ </ul>[[= $c ne 't' && $c ne 'g' ? '</li>' : '' ]]-
+ [[ } ]]-
+ </ul>
+ <br style="clear: both" />
+ <br />
+
+ <b>Languages</b> (exclusive, selecting more gives more results)<br />
+ <ul class="filter" id="lfilter">
+ [[ for (sort keys %{$d{langc}}) { next if !$d{langc}{$_}; my $l=$_; ]]-
+ <li><input type="checkbox" name="lang_[[= $l ]]" id="lang_[[= $l ]]" value="[[: $VNDB::LANG->{$l} ]]" [[= (grep /$l/, @{$d{lang}}) ? ' checked="checked"' : '' ]]- />
+ <label for="lang_[[= $l ]]"><acronym class="icons lang -[[= $l ]]" title="[[: $VNDB::LANG->{$l} ]]">&nbsp;</acronym>([[= $d{langc}{$l} ]])</label></li>
+ [[ } ]]-
+ </ul>
+ <br style="clear: both" />
+ <br />
+
+ <b>Platforms</b> (exclusive, selecting more gives more results)<br />
+ <ul class="filter" id="pfilter">
+ [[ for (sort keys %$VNDB::PLAT) { next if /oth/; my $l=$_; ]]-
+ <li><input type="checkbox" name="plat_[[= $l ]]" id="plat_[[= $l ]]" value="[[: $VNDB::PLAT->{$l} ]]" [[= (grep /$l/, @{$d{plat}}) ? ' checked="checked"' : '' ]]- />
+ <label for="plat_[[= $l ]]"><acronym class="icons -[[= $l ]]" title="[[: $VNDB::PLAT->{$l} ]]">&nbsp;</acronym></label></li>
+ [[ } ]]-
+ </ul>
+ <br style="clear: both" />
+ <input type="button" class="right" id="vsearch_sub" name="vsearch_sub" value="Search!" />
+ <br style="clear: left" />
+ <br /><br />
+ </div>
+
+[[ } else { ]]-
<p class="chr">
-[[= $d{chr} ne 'all' ? '<a href="/v/all">all</a>' : 'all' ]]- |
[[ for('a'..'z', 0) { ]]-
@@ -35,23 +60,16 @@
</p>
[[ } ]]-
+
-[[ if($#{$d{vn}} < 0) { ]]
+ -[[ if($d{chr} eq 'search' && $p{searchquery} || $d{chr} ne 'search') { ]]
<p>
- -[[ if($d{chr} eq 'cat' && !$d{scat}[0][0] && !$d{scat}[0][1]) { ]]
- Select some categories and hit the "Search" button to get a list of visual novels. Click on a
- category again to exclude it.<br />
- Please keep in mind that not all visual novels have the correct categories set, so you
- may not always find what you are looking for.
- [[ } else { ]]
No results again, life sucks... :'(
- [[ } ]]-
</p>
+ [[ } ]]
[[ } else {
my %url = (
$p{searchquery} ? ( q => $p{searchquery} ) : (),
- $d{incl} ? ( i => $d{incl} ) : (),
- $d{excl} ? ( e => $d{excl} ) : (),
- $d{slang} ? ( l => $d{slang} ) : (),
);
my %urls = ( %url,
$d{order}[0] ne 'title' ? ( s => $d{order}[0] ) : (),
@@ -67,19 +85,25 @@
<table id="tbv">
<thead><tr>
<td class="tc1">Title [[= sortbut($url, 'title') ]]</td>
- <td class="tc2">Released [[= sortbut($url, 'released') ]]</td>
- <td class="tc3">Languages</td>
- <td class="tc4">Rating [[= sortbut($url, 'votes') ]]</td>
+ <td class="tc2">&nbsp;</td>
+ <td class="tc3">&nbsp;</td>
+ <td class="tc4">Released [[= sortbut($url, 'released') ]]</td>
+ <td class="tc5">Rating [[= sortbut($url, 'votes') ]]</td>
</tr></thead>
[[ for (@{$d{vn}}) {
$_->{c_votes} =~ s#^([0-9]{2}.[0-9]{2})\|([0-9]{4})$#$1 == 0 ? sprintf '- (%d)', $2 : sprintf '%.2f (%d)', $1, $2#e;
- $_->{c_released} =~ s#^([0-9]{4})([0-9]{2}).+#$1==0?'N/A':$1==9999?'TBA':(($2&&$2>0?($Time::CTime::MoY[$2-1].' '):'').$1)#e;
+ $_->{c_released} =~ s#^([0-9]{4})([0-9]{2}).+#$1==0?'N/A':$1==9999?'TBA':(($2&&$2<13?($Time::CTime::MoY[$2-1].' '):'').$1)#e;
+ $_->{c_platforms} = join '', map {
+ $_ ne 'oth' ? '<acronym class="icons '.$_.'" title="'._hchar($VNDB::PLAT->{$_}).'">&nbsp;</acronym>' : ()
+ } split /\//, $_->{c_platforms};
+ $_->{c_languages} = join '', map qq|<acronym class="icons lang $_" title="$$VNDB::LANG{$_}">&nbsp;</acronym>|, reverse sort split /\//, $_->{c_languages};
]]-
<tr>
- <td class="tc1"><a href="/v[[= $_->{id} ]]">[[: $_->{title} ]]</a></td>
- <td class="tc2">[[: $_->{c_released} ]]</td>
- <td class="tc3">[[: $_->{c_languages} || 'N/A' ]]</td>
- <td class="tc4">[[: $_->{c_votes} ]]</td>
+ <td class="tc1"><a href="/v[[= $_->{id} ]]" title="[[: $_->{title} ]]">[[: shorten $_->{title}, 50 ]]</a></td>
+ <td class="tc2">[[= $_->{c_platforms} ]]</td>
+ <td class="tc3">[[= $_->{c_languages} ]]</td>
+ <td class="tc4">[[: $_->{c_released} ]]</td>
+ <td class="tc5">[[: $_->{c_votes} ]]</td>
</tr>
[[ } ]]-
</table>
diff --git a/data/tpl/vnedit b/data/tpl/vnedit
index 0e46ba47..b0869b45 100644
--- a/data/tpl/vnedit
+++ b/data/tpl/vnedit
@@ -45,7 +45,7 @@
{ type => 'static', text => '<br />' },
{ type => 'input', name => 'External links', short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' },
{ type => 'input', name => '&nbsp;', short => 'l_vnn', pre => 'http://visual-novels.net/vn/index.php?option=com_content&amp;task=view&amp;id=', class => 'shortopts' },
- { type => 'input', name => '&nbsp;', short => 'l_cisv', pre => 'http://cisvisual.net/title/', class => 'shortopts' },
+# { type => 'input', name => '&nbsp;', short => 'l_cisv', pre => 'http://cisvisual.net/title/', class => 'shortopts' },
{ type => 'static', text => '<br />' },
{ type => 'input', name => 'Related anime', short => 'anime' },
diff --git a/data/tpl/vnpage b/data/tpl/vnpage
index 1388fd03..84c00fc2 100644
--- a/data/tpl/vnpage
+++ b/data/tpl/vnpage
@@ -69,18 +69,32 @@
my @links = (
$d{vn}{l_wp} ? [ 'Wikipedia', 'http://en.wikipedia.org/wiki/%s', $d{vn}{l_wp} ] : (),
$d{vn}{l_vnn} ? [ 'V-N.net', 'http://visual-novels.net/vn/index.php?option=com_content&amp;task=view&amp;id=%d', $d{vn}{l_vnn} ] : (),
- $d{vn}{l_cisv} ? [ 'CISVisual', 'http://cisvisual.net/title/%d', $d{vn}{l_cisv} ] : (),
+# $d{vn}{l_cisv} ? [ 'CISVisual', 'http://cisvisual.net/title/%d', $d{vn}{l_cisv} ] : (),
);
-if($d{vn}{length} || $d{vn}{alias} || @links) { ]]
+ my $prod = @lang && grep { @{$_->{producers}} } @{$d{rel}};
+
+if($d{vn}{length} || $d{vn}{alias} || @links || $prod) { ]]
<h3>General info</h3>
<dl>
[[ if($d{vn}{length}) { ]]-
<dt>Length</dt><dd>[[: $VNDB::VNLEN->[$d{vn}{length}][0] ]]- ([[: $VNDB::VNLEN->[$d{vn}{length}][1] ]])</dd>[[ } ]]-
[[ if($d{vn}{alias}) { ]]-
<dt>Aliases</dt><dd>[[: $d{vn}{alias} ]]</dd>[[ } ]]-
+ [[ if($prod) { ]]-
+ <dt>Producers</dt><dd>
+ [[ for my $l (@lang) { my %l;
+ $_->{language} eq $l && (%l = ( %l, map {
+ sprintf('<a href="/p%d" title="%s">%s</a>',
+ $_->{id}, _hchar($_->{name}), _hchar shorten $_->{name}, 30) => 1
+ } @{$_->{producers}} )) for (@{$d{rel}});
+ if(keys %l) { ]]-
+ <acronym class="icons lang -[[= $l ]]" title="[[: $VNDB::LANG->{$l} ]]">&nbsp;</acronym>[[= join(' &amp; ', keys %l) ]]<br />
+ [[ } } ]]
+ </dd>[[ } ]]-
[[ if(@links > 0) { ]]-
<dt>Links</dt><dd>[[= join(', ', map { '<a href="'.sprintf($_->[1],$_->[2]).'">'.$_->[0].'</a>' } @links) ]]</dd>[[ } ]]-
+ <dt>Rating</dt><dd>[[: $d{vn}{c_votes} ]]</dd>
</dl>
[[ } ]]-
@@ -129,25 +143,6 @@ if($d{vn}{length} || $d{vn}{alias} || @links) { ]]
[[ } ]]
</ul>
[[ } ]]-
-
- [[ if(@lang && grep { @{$_->{producers}} } @{$d{rel}}) { ]]-
- <h3>Producers</h3>
- <dl>
- [[ for my $l (@lang) { my %l;
- $_->{language} eq $l && (%l = ( %l, map {
- sprintf('<a href="/p%d" title="%s">%s</a>',
- $_->{id}, _hchar($_->{name}), _hchar shorten $_->{name}, 30) => 1
- } @{$_->{producers}} )) for (@{$d{rel}});
- if(keys %l) { ]]-
- <dt>[[: $VNDB::LANG->{$l} ]]</dt><dd>[[= join(' &amp; ', keys %l) ]]</dd>
- [[ } } ]]
- </dl>
- [[ } ]]-
-
- <h3>[[= $d{page} eq 'stats' ? 'User stats' : '<a href="/v'.$d{vn}{id}.'/stats">User stats</a>' ]]</h3>
- <dl>
- <dt>Rating</dt><dd>[[: $d{vn}{c_votes} ]]</dd>
- </dl>
</div>
-[[
diff --git a/data/tpl/vnpage_rel b/data/tpl/vnpage_rel
index ea5c5235..e213c12f 100644
--- a/data/tpl/vnpage_rel
+++ b/data/tpl/vnpage_rel
@@ -30,11 +30,11 @@
<td class="tc1">[[= datestr($_->{released}) ]]</td>
<td class="tc2">[[= $_->{minage}<0 ? '' : $VNDB::VRAGES->{$_->{minage}} ]]</td>
<td class="tc3">
- [[= join('', map { $_ ne 'oth' ? '<acronym class="plat '.$_.'" title="'._hchar($VNDB::PLAT->{$_}).'">&nbsp;</acronym>' : () } sort @{$_->{platforms}}) ]]
- <acronym title="[[= $VNDB::RTYP->[$_->{type}] ]]- release" class="plat -[[= lc substr($VNDB::RTYP->[$_->{type}],0,3) ]]">&nbsp;</acronym>
+ [[= join('', map { $_ ne 'oth' ? '<acronym class="icons '.$_.'" title="'._hchar($VNDB::PLAT->{$_}).'">&nbsp;</acronym>' : () } sort @{$_->{platforms}}) ]]
+ <acronym title="[[= $VNDB::RTYP->[$_->{type}] ]]- release" class="icons -[[= lc substr($VNDB::RTYP->[$_->{type}],0,3) ]]">&nbsp;</acronym>
</td>
<td class="tc4"><a href="/r[[= $_->{id} ]]" title="[[: $_->{original} || $_->{title} ]]">[[: shorten $_->{title},60 ]]</a></td>
- <td class="tc5">[[ if($_->{website}) { ]]<a href="[[: $_->{website} ]]" class="plat ext" title="WWW">&nbsp;</a>[[ } ]]</td>
+ <td class="tc5">[[ if($_->{website}) { ]]<a href="[[: $_->{website} ]]" class="icons ext" title="WWW">&nbsp;</a>[[ } ]]</td>
</tr>
[[ } ]]-
[[ } ]]-
diff --git a/data/tpl/vnpage_stats b/data/tpl/vnpage_stats
index dde9aed3..7108486e 100644
--- a/data/tpl/vnpage_stats
+++ b/data/tpl/vnpage_stats
@@ -8,8 +8,8 @@
}
]]
[[ if(!$d{user} || ($d{pv} && $d{user}{votes})) { ]]-
-<li><h3>Vote graph <b class="actions">[[= $total ]]- vote[[= $total==1?'':'s' ]]- total
- [[= $total ? sprintf(', average: %.1f.', $sum/$total) : '' ]]</b></h3>
+<li><h3>Vote graph <p class="actions">[[= $total ]]- vote[[= $total==1?'':'s' ]]- total
+ [[= $total ? sprintf(', average: %.1f.', $sum/$total) : '' ]]</p></h3>
<table id="tvg">
[[ for (0..$#{$d{votes}{graph}}) { ]]-
<tr>
@@ -39,7 +39,7 @@
-[[ $max = 1; $total = 0;
for (@{$d{lists}{graph}}) { $total += $_; $max = $_ if $_ > $max; } ]]
[[ if(!$d{user} || ($d{pl} && $d{user}{vnlist})) { ]]-
-<li class="break"><h3>VN List stats <b class="actions">[[= $total ]]- -[[= $d{user}?'visual novel':'user' ]][[= $total==1?'':'s' ]]- total</b></h3>
+<li class="break"><h3>VN List stats <p class="actions">[[= $total ]]- -[[= $d{user}?'visual novel':'user' ]][[= $total==1?'':'s' ]]- total</p></h3>
<table id="tus">
[[ for (0..$#$VNDB::LSTAT) { ]]-
<tr>
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 3f01492f..a9969ac5 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -10,9 +10,17 @@ TODO:
uploaded or not
+ Use AniDB's daily title dump and implement a search feature to add
anime relations without having to visit AniDB.
- + Clear up style.css (or wait until the new layout is ready...)
-1.15 - ?
+1.16 - ?
+ - Release dates in the current year or month without a specified day will
+ be considered as not yet released
+ - Added platform and language icons to the VN browser
+ - Grouped producers, user stats and general information on the VN page
+ - Added language icons to producer browser
+ - A little CSS cleanup
+ - Grouped category browser into one advanced search
+
+1.15 - 2008-05-04
- Relation graph now also updated on VN title change
- Anime relations
- [js] Position of the dropdown box is now relative to the link element
diff --git a/lib/Multi/Anime.pm b/lib/Multi/Anime.pm
index 44fafb92..0da54e2e 100644
--- a/lib/Multi/Anime.pm
+++ b/lib/Multi/Anime.pm
@@ -257,7 +257,7 @@ 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);
+ : (split(/\|/, $_[ARG1], 7), int time);
if($col[7] > 0) {
for (@col) {
@@ -269,6 +269,7 @@ sub updateanime { # aid, data|'notfound'
$col[4] = $_ if lc($VNDB::ANITYPE->[$_][1]) eq lc($col[4]);
}
$col[4] = 0 if $col[4] !~ /^[0-9]+$/;
+ $col[2] = '' if $col[2] =~ /^0,/;
}
# try to UPDATE first
diff --git a/lib/Multi/IRC.pm b/lib/Multi/IRC.pm
index 984d5d5d..58789675 100644
--- a/lib/Multi/IRC.pm
+++ b/lib/Multi/IRC.pm
@@ -27,7 +27,7 @@ sub spawn {
);
POE::Session->create(
package_states => [
- $p => [qw| _start irc_001 irc_public irc_ctcp_action irc_msg vndbid shutdown |],
+ $p => [qw| _start irc_001 irc_public irc_ctcp_action irc_msg irccmd vndbid shutdown |],
],
heap => { irc => $irc,
o => {
@@ -36,7 +36,8 @@ sub spawn {
ircname => 'VNDB.org Multi',
channel => '#vndb',
@_
- }
+ },
+ log => {},
}
);
}
@@ -83,9 +84,10 @@ sub irc_001 {
sub irc_public {
- if($_[ARG2] =~ /^!info/) {
- $_[KERNEL]->post(circ => privmsg => $_[ARG1][0],
- 'Hello, I am HMX-12 Multi v'.$VNDB::VERSION.' made by the great Yorhel! (Please ask Ayo for more info)');
+ if($_[ARG2] =~ /^!/) {
+ (my $cmd = $_[ARG2]) =~ s/^!//;
+ my $nick = (split /!/, $_[ARG0])[0];
+ $_[KERNEL]->call(irc => irccmd => $_[ARG1][0], $cmd, $nick, $nick.', ');
} else {
$_[KERNEL]->call(irc => vndbid => $_[ARG1][0], $_[ARG2]);
}
@@ -99,26 +101,39 @@ sub irc_ctcp_action {
sub irc_msg {
my $nick = ( split /!/, $_[ARG0] )[0];
+ $_[KERNEL]->call(irc => irccmd => $nick => $_[ARG2]);
+}
- if(!$_[HEAP]{irc}->is_channel_operator($_[HEAP]{o}{channel}, $nick)
- && !$_[HEAP]{irc}->is_channel_owner($_[HEAP]{o}{channel}, $nick)
- && !$_[HEAP]{irc}->is_channel_admin($_[HEAP]{o}{channel}, $nick)) {
- $_[KERNEL]->post(circ => privmsg => $nick, 'You are not my master');
- return;
- }
- my $m = $_[ARG2];
- if($m =~ /^say (.+)$/) {
+sub irccmd { # dest, cmd, [nick], [prep]
+ my($dest, $cmd, $nick, $prep) = @_[ARG0..$#_];
+ $nick ||= $_[ARG0];
+ $prep ||= '';
+
+ if($cmd =~ /^info/) {
+ return $_[KERNEL]->post(circ => privmsg => $dest,
+ 'Hello, I am HMX-12 Multi v'.$VNDB::VERSION.' made by the great Yorhel!');
+ }
+
+ return $_[KERNEL]->post(circ => privmsg => $dest,
+ $prep.'You are not my master!')
+ if !$_[HEAP]{irc}->is_channel_operator($_[HEAP]{o}{channel}, $nick)
+ && !$_[HEAP]{irc}->is_channel_owner($_[HEAP]{o}{channel}, $nick)
+ && !$_[HEAP]{irc}->is_channel_admin($_[HEAP]{o}{channel}, $nick);
+
+ if($cmd =~ /^say (.+)$/) {
$_[KERNEL]->post(circ => privmsg => $_[HEAP]{o}{channel}, $1);
- } elsif($m =~ /^me (.+)$/) {
+ } elsif($cmd =~ /^me (.+)$/) {
$_[KERNEL]->post(circ => ctcp => $_[HEAP]{o}{channel}, "ACTION $1");
- } elsif($m =~ /^cmd (.+)$/) {
+ } elsif($cmd =~ /^cmd (.+)$/) {
$_[KERNEL]->post(core => queue => $1);
- } elsif($m =~ /^eval (.+)$/) {
- $_[KERNEL]->post(circ => privmsg => $nick, 'eval: '.$_)
+ $_[KERNEL]->post(circ => privmsg => $dest => sprintf "%sExecuting command '%s'", $prep, $1);
+ } elsif($cmd =~ /^eval (.+)$/) {
+ $_[KERNEL]->post(circ => privmsg => $dest, $prep.'eval: '.$_)
for (split /\r?\n/, eval($1)||$@);
} else {
- $_[KERNEL]->post(circ => privmsg => $nick, 'Unkown command'); }
+ $_[KERNEL]->post(circ => privmsg => $dest, $prep.'Unkown command');
+ }
# TODO: add command to view the current queue, and a method to send log messages
}
@@ -126,12 +141,19 @@ sub irc_msg {
sub vndbid { # dest, msg
my $m = $_[ARG1];
+
+ $_[HEAP]{log}{$_} < time-60 and delete $_[HEAP]{log}{$_}
+ for (keys %{$_[HEAP]{log}});
+
my @id;
push @id, [$1,$2,$3,$4] while $m =~ s/^(.*)([duvpr])([0-9]+)(.*)$/ $1 $4 /i;
for (reverse @id) {
- next if $$_[0] =~ /(\.org\/|[a-z])$/i || $$_[3] =~ /^[a-z]/i;
+ next if $$_[0] =~ /[a-z0-9%/]$/i || $$_[3] =~ /^[a-z]/i;
my($t, $id, $ext) = (lc($$_[1]), $$_[2], $$_[3]);
+ next if $_[HEAP]{log}{$t.$id};
+ $_[HEAP]{log}{$t.$id} = time;
+
if($t ne 'd') {
my $s = $Multi::SQL->prepare(
$t eq 'v' ? 'SELECT vr.title FROM vn_rev vr JOIN vn v ON v.latest = vr.id WHERE v.id = ?' :
diff --git a/lib/Multi/Maintenance.pm b/lib/Multi/Maintenance.pm
index 1f1a337e..d0aa4dbc 100644
--- a/lib/Multi/Maintenance.pm
+++ b/lib/Multi/Maintenance.pm
@@ -26,24 +26,18 @@ sub spawn {
sub _start {
$_[KERNEL]->alias_set('maintenance');
- $_[KERNEL]->call(core => register => qr/^maintenance((?: (?:all|vncache|ratings|prevcache|integrity|unkanime|logrotate))+)$/, 'cmd_maintenance');
+ $_[KERNEL]->call(core => register => qr/^maintenance((?: (?:vncache|ratings|prevcache|integrity|unkanime|logrotate))+)$/, 'cmd_maintenance');
- # Perform all maintenance functions every day on 0:00
- $_[KERNEL]->post(core => addcron => '0 0 * * *', 'maintenance all');
- # rotate logs every 1st day of the month at 0:05
- $_[KERNEL]->post(core => addcron => '5 0 1 * *' => 'maintenance logrotate');
+ # Perform some maintenance functions every day on 0:00
+ $_[KERNEL]->post(core => addcron => '0 0 * * *', 'maintenance ratings integrity unkanime');
+ # update caches and rotate logs every 1st day of the month at 0:05
+ $_[KERNEL]->post(core => addcron => '5 0 1 * *' => 'maintenance vncache prevcache logrotate');
}
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('unkanime') if /(?:unkanime|all)/;
- $_[KERNEL]->yield('logrotate') if /logrotate/;
+ $_[KERNEL]->yield($_)
+ for (split /\s+/, $_[ARG1]);
$_[KERNEL]->post(core => finish => $_[ARG0]);
}
diff --git a/lib/Multi/RG.pm b/lib/Multi/RG.pm
index b32fedba..ebb93013 100644
--- a/lib/Multi/RG.pm
+++ b/lib/Multi/RG.pm
@@ -130,7 +130,7 @@ sub relscomplete { # heap->nodes and heap->rels are now assumed to contain all n
# insert all nodes, ordered by release date
for (sort { $a->[2] <=> $b->[2] } values %{$_[HEAP]{nodes}}) {
my $date = sprintf '%08d', $_->[2];
- $date =~ s#^([0-9]{4})([0-9]{2}).+#$1==0?'N/A':$1==9999?'TBA':(($2&&$2>0?($_[HEAP]{moy}[$2-1].' '):'').$1)#e;
+ $date =~ s#^([0-9]{4})([0-9]{2}).+#$1==0?'N/A':$1==9999?'TBA':(($2&&$2<13?($_[HEAP]{moy}[$2-1].' '):'').$1)#e;
my $title = unidecode($_->[1]);
$title = substr($title, 0, 27).'...' if length($title) > 30;
diff --git a/lib/VNDB.pm b/lib/VNDB.pm
index 2632a358..93f9e190 100644
--- a/lib/VNDB.pm
+++ b/lib/VNDB.pm
@@ -79,7 +79,8 @@ my %VNDBuris = ( # wildcards: * -> (.+), + -> ([0-9]+)
v => {
'/' => sub { shift->VNBrowse },
new => sub { shift->VNEdit(0); },
- '*' => sub { $_[2] =~ /^([a-z0]|all|search|cat)$/ ? shift->VNBrowse($_[1]) : shift->ResNotFound; },
+ #search => sub { shift->VNSearch },
+ '*' => sub { $_[2] =~ /^([a-z0]|all|search)$/ ? shift->VNBrowse($_[1]) : shift->ResNotFound; },
},
'v+' => {
'/' => sub { shift->VNPage(shift) },
@@ -128,10 +129,14 @@ my %VNDBuris = ( # wildcards: * -> (.+), + -> ([0-9]+)
# provide redirects for old URIs
my %OLDuris = (
faq => sub { shift->ResRedirect('/d6', 'perm') },
+ notes => sub { shift->ResRedirect('/d8', 'perm') },
vn => {
rss => sub { shift->ResRedirect('/hist/rss?t=v&e=1', 'perm') },
'*' => sub { shift->ResRedirect('/v/'.$_[1], 'perm') },
},
+ v => {
+ cat => sub { },
+ },
'v+' => {
votes => sub { shift->ResRedirect('/v'.(shift).'/stats', 'perm') },
},
diff --git a/lib/VNDB/Releases.pm b/lib/VNDB/Releases.pm
index 6f642cba..abf3a786 100644
--- a/lib/VNDB/Releases.pm
+++ b/lib/VNDB/Releases.pm
@@ -87,7 +87,7 @@ sub REdit {
my $released = !$frm->{released}[0] ? 0 :
$frm->{released}[0] == 9999 ? 99999999 :
- sprintf '%04d%02d%02d', $frm->{released}[0]||0, $frm->{released}[1]||0, $frm->{released}[2]||0;
+ sprintf '%04d%02d%02d', $frm->{released}[0], $frm->{released}[1]||99, $frm->{released}[2]||99;
my $media = [ map { /_/ ? [ split /_/ ] : [ $_, 0 ] } split /,/, $frm->{media} ];
my $producers = [ map { /^([0-9]+)/ ? $1 : () } split /\|\|\|/, $frm->{producers} ];
my $new_vn = [ map { /^([0-9]+)/ ? $1 : () } split /\|\|\|/, $frm->{vn} ];
diff --git a/lib/VNDB/Util/DB.pm b/lib/VNDB/Util/DB.pm
index e5eba14f..a2b4a035 100644
--- a/lib/VNDB/Util/DB.pm
+++ b/lib/VNDB/Util/DB.pm
@@ -538,7 +538,7 @@ sub DBDelVNList { # uid, @vid # uid = 0 to delete all
#-----------------------------------------------------------------------------#
-sub DBGetVN { # %options->{ id rev char search order results page what cati cate lang }
+sub DBGetVN { # %options->{ id rev char search order results page what cati cate lang platform }
my $s = shift;
my %o = (
page => 1,
@@ -573,14 +573,10 @@ sub DBGetVN { # %options->{ id rev char search order results page what cati cate
JOIN vn iv ON iv.latest = ivc.vid
WHERE cat IN(!L)
GROUP BY iv.id)| => $o{cate} ) : (),
- $o{lang} && @{$o{lang}} ? ( q|
- v.id IN(SELECT irv.vid
- FROM releases_rev irr
- JOIN releases ir ON irr.id = ir.latest
- JOIN releases_vn irv ON irv.rid = irr.id
- WHERE irr.language IN(!L)
- AND irr.type <> 2
- AND irr.released <= TO_CHAR('today'::timestamp, 'YYYYMMDD')::integer)| => $o{lang} ) : (),
+ $o{lang} && @{$o{lang}} ? (
+ '('.join(' OR ', map "v.c_languages ILIKE '%%$_%%'", @{$o{lang}}).')' => 1 ) : (),
+ $o{platform} && @{$o{platform}} ? (
+ '('.join(' OR ', map "v.c_platforms ILIKE '%%$_%%'", @{$o{platform}}).')' => 1 ) : (),
);
if($o{search}) {
@@ -613,7 +609,7 @@ sub DBGetVN { # %options->{ id rev char search order results page what cati cate
'JOIN users u ON u.id = c.requester' ) : (),
);
- my $sel = 'v.id, v.locked, v.hidden, v.c_released, v.c_languages, v.c_votes, vr.title, vr.id AS cid, v.rgraph';
+ my $sel = 'v.id, v.locked, v.hidden, v.c_released, v.c_languages, v.c_votes, v.c_platforms, vr.title, vr.id AS cid, v.rgraph';
$sel .= ', vr.alias, vr.image AS image, vr.img_nsfw, vr.length, vr.desc, vr.l_wp, vr.l_cisv, vr.l_vnn' if $o{what} =~ /extended/;
$sel .= ', c.added, c.requester, c.comments, v.latest, u.username, c.prev, c.causedby' if $o{what} =~ /changes/;
@@ -909,7 +905,7 @@ sub DBGetRelease { # %options->{ id vid results page rev }
)});
}
if($o{what} =~ /platforms/) {
- ($_->{platform}=~s/\s+//||1)&&push(@{$r->[$r{$_->{rid}}]{platforms}}, $_->{platform}) for (@{$s->DBAll(q|
+ push(@{$r->[$r{$_->{rid}}]{platforms}}, $_->{platform}) for (@{$s->DBAll(q|
SELECT rid, platform
FROM releases_platforms
WHERE rid IN(!l)|,
diff --git a/lib/VNDB/VN.pm b/lib/VNDB/VN.pm
index 4732e278..fd46672c 100644
--- a/lib/VNDB/VN.pm
+++ b/lib/VNDB/VN.pm
@@ -92,7 +92,7 @@ sub VNEdit {
{ name => 'anime', required => 0, default => '' },
{ name => 'img_nsfw', required => 0 },
{ name => 'categories', required => 0, default => '' },
- { name => 'relations', required => 0, default => 0 },
+ { name => 'relations', required => 0, default => '' },
{ name => 'comm', required => 0, default => '' },
);
$frm->{img_nsfw} = $frm->{img_nsfw} ? 1 : 0;
@@ -155,8 +155,8 @@ sub VNEdit {
$self->VNUpdReverse(\%old, \%new, $id, $cid);
}
# also regenerate relation graph if the title changes
- elsif($frm->{title} ne $b4{title}) {
- $self->RunCmd('relraph '.$id);
+ elsif(@$relations && $frm->{title} ne $b4{title}) {
+ $self->RunCmd('relgraph '.$id);
}
# check for new anime data
@@ -230,25 +230,49 @@ sub VNBrowse {
my $f = $self->FormCheck(
{ name => 's', required => 0, default => 'title', enum => [ qw|title released votes| ] },
{ name => 'o', required => 0, default => 'a', enum => [ 'a','d' ] },
- { name => 'i', required => 0, default => '' },
- { name => 'e', required => 0, default => '' },
- { name => 'l', required => 0, default => '' },
- { name => 'q', required => 0},
+ { name => 'q', required => 0, default => '' },
+ { name => 'sq', required => 0, default => '' },
{ name => 'p', required => 0, template => 'int', default => 1},
);
- my($r, $np) = $chr ne 'cat' || $f->{e} || $f->{i} || $f->{l} ? ($self->DBGetVN(
- $chr =~ /^[a-z0]$/ ? (
- char => $chr ) : (),
- $chr eq 'search' && $f->{q} ? (
- search => $f->{q} ) : (),
- page => $f->{p},
- $chr eq 'cat' ? (
- cati => [ split /,/, $f->{i} ],
- cate => [ split /,/, $f->{e} ],
- lang => [ grep { $VNDB::LANG->{$_} } split /,/, $f->{l} ],
- ) : (),
+ $f->{q} ||= $f->{sq};
+
+ my(@cati, @cate, @plat, @lang);
+ my $q = $f->{q};
+ if($chr eq 'search') {
+ # VNDBID
+ return $self->ResRedirect('/'.$1, 'temp')
+ if $q =~ /^([vrpud][0-9]+)$/;
+
+ if(!($q =~ s/^title://)) {
+ # categories
+ my %catl = map {
+ my $ic = $_;
+ map { $ic.$_ => $VNDB::CAT->{$ic}[1]{$_} } keys %{$VNDB::CAT->{$ic}[1]}
+ } keys %$VNDB::CAT;
+
+ $q =~ s/-(?:$catl{$_}|c:$_)//ig && push @cate, $_ for keys %catl;
+ $q =~ s/(?:$catl{$_}|c:$_)//ig && push @cati, $_ for keys %catl;
+
+ # platforms
+ $_ ne 'oth' && $q =~ s/(?:$VNDB::PLAT->{$_}|p:$_)//ig && push @plat, $_ for keys %$VNDB::PLAT;
+
+ # languages
+ $q =~ s/($VNDB::LANG->{$_}|l:$_)//ig && push @lang, $_ for keys %$VNDB::LANG;
+ }
+ }
+ $q =~ s/ +$//;
+ $q =~ s/^ +//;
+
+ my($r, $np) = $chr ne 'search' || $q || @lang || @plat || @cati || @cate ? ($self->DBGetVN(
+ $chr =~ /^[a-z0]$/ ? ( char => $chr ) : (),
+ $q ? ( search => $q ) : (),
+ @cati ? ( cati => \@cati ) : (),
+ @cate ? ( cate => \@cate ) : (),
+ @lang ? ( lang => \@lang ) : (),
+ @plat ? ( platform => \@plat ) : (),
results => 50,
+ page => $f->{p},
order => {title => 'vr.title', released => 'v.c_released', votes => 'v.c_votes'
}->{$f->{s}}.{a=>' ASC',d=>' DESC'}->{$f->{o}},
)) : ([], 0);
@@ -261,12 +285,13 @@ sub VNBrowse {
npage => $np,
page => $f->{p},
chr => $chr,
- $chr eq 'cat' ? (
- incl => $f->{i},
- excl => $f->{e},
+ $chr eq 'search' ? (
+ incl => \@cati,
+ excl => \@cate,
cat => $self->DBCategoryCount,
- lang => $self->DBLanguageCount,
- slang => $f->{l},
+ langc => $self->DBLanguageCount,
+ lang => \@lang,
+ plat => \@plat,
) : (),
order => [ $f->{s}, $f->{o} ],
},
@@ -336,4 +361,3 @@ sub VNUpdReverse { # old, new, id, cid
1;
-
diff --git a/lib/global.pl b/lib/global.pl
index 890046b2..cf8d02db 100644
--- a/lib/global.pl
+++ b/lib/global.pl
@@ -3,7 +3,7 @@ package VNDB;
our @DBLOGIN = ( 'dbi:Pg:dbname=vndb', 'vndb', 'passwd' );
our @SHMOPTS = ( -key => 'VNDB', -create => 'yes', -destroy => 'no', -mode => 0666);
our $DEBUG = 1;
-our $VERSION = '1.15';
+our $VERSION = '1.16';
our $PLAT = {
win => 'Windows',
@@ -13,9 +13,9 @@ our $PLAT = {
gba => 'Game Boy Advance',
nds => 'Nintendo DS',
psp => 'Playstation Portable',
- ps => 'Playstation',
+ ps1 => 'Playstation 1',
ps2 => 'Playstation 2',
- dc => 'Dreamcast',
+ drc => 'Dreamcast',
sfc => 'Super Nintendo',
wii => 'Nintendo Wii',
oth => 'Other'
@@ -54,7 +54,7 @@ our $CAT = {
g => [ 'Gameplay', {
aa => 'Visual Novel', # 0..1
ab => 'Adventure', # 0..1
- ac => 'Action',
+ ac => "Act\x{200B}ion", # Ugliest. Hack. Ever.
rp => 'RPG',
st => 'Strategy',
si => 'Simulation',
@@ -64,7 +64,7 @@ our $CAT = {
br => 'Branching', # 0..1
} ],
e => [ 'Elements', {
- ac => 'Action',
+ ac => 'Action',
co => 'Comedy',
dr => 'Drama',
fa => 'Fantasy',
@@ -82,7 +82,7 @@ our $CAT = {
} ],
l => [ 'Place', {
ea => 'Earth',
- fa => 'Fantasy World',
+ fa => "Fant\x{200B}asy world",
sp => 'Space',
} ],
s => [ 'Sexual content', {
@@ -102,7 +102,6 @@ our $LSTAT = [
'Wishlist',
'Blacklist',
'Playing',
- 'Finished',
'Stalled',
'Dropped',
'Other', # XXX: hardcoded at 6
@@ -291,7 +290,7 @@ our $LANG = {
'fr' => q|French|,
# 'fur' => q|Friulian|,
# 'fy' => q|Frisian|,
- 'ga' => q|Irish|,
+# 'ga' => q|Irish|,
# 'gaa' => q|Ga|,
# 'gay' => q|Gayo|,
# 'gba' => q|Gbaya|,
diff --git a/static/files/16x14.png b/static/files/16x14.png
deleted file mode 100644
index 1cf35c08..00000000
--- a/static/files/16x14.png
+++ /dev/null
Binary files differ
diff --git a/static/files/def.js b/static/files/def.js
index 72b5cd80..ed7e1f41 100644
--- a/static/files/def.js
+++ b/static/files/def.js
@@ -75,7 +75,6 @@ function formtoggle(n) {
/* D R O P D O W N M E N U S */
-
var ddx;var ddy;var dds=null;
function dropDown(e) {
e = e || window.event;
@@ -119,6 +118,92 @@ function dropDown(e) {
+/* A D V A N C E D S E A R C H */
+
+var ad_cats = {};
+var ad_lang = {};
+var ad_plat = {};
+
+function adsearch() {
+ x('vsearch').onsubmit = ad_dosearch;
+ x('vsearch_sub').onclick = ad_dosearch;
+ x('q').onkeyup = ad_update;
+
+ x('adsearchclick').onclick = function() {
+ if(x('adsearch').style.display == 'none') {
+ x('adsearch').style.display = 'block';
+ x('adsearchclick').innerHTML = '&#9662; advanced options';
+ } else {
+ x('adsearch').style.display = 'none';
+ x('adsearchclick').innerHTML = '&#9656; advanced options';
+ }
+ };
+
+ var l = x('cat').getElementsByTagName('li');
+ for(i=0;i<l.length;i++)
+ if(l[i].id.indexOf('cat_') != -1) {
+ ad_cats[ l[i].id.substr(l[i].id.indexOf('cat_')+4, 3) ] = l[i].innerHTML.substring(0, l[i].innerHTML.indexOf('(')-1).toLowerCase();
+ l[i].onclick = function () {
+ try { document.selection.empty() } catch(e) { try { window.getSelection().collapse(this, 0) } catch(e) {} };
+ ad_update(1, this.innerHTML.substring(0, this.innerHTML.indexOf('(')-1));
+ };
+ }
+
+ l = x('lfilter').getElementsByTagName('input');
+ for(i=0;i<l.length;i++) {
+ ad_lang[ l[i].name.substring(5) ] = l[i].value.toLowerCase();
+ l[i].onclick = function() { ad_update(0, this.value) };
+ }
+
+ l = x('pfilter').getElementsByTagName('input');
+ for(i=0;i<l.length;i++) {
+ ad_plat[ l[i].name.substring(5) ] = l[i].value.toLowerCase();
+ l[i].onclick = function() { ad_update(0, this.value) };
+ }
+}
+
+function ad_update(add, term) {
+ var q = x('q').value;
+ var i;
+
+ if(add == 0 || add === 1) {
+ var qn = q;
+ if(!add)
+ eval('qn = qn.replace(/'+term+'/gi, "")');
+ else {
+ eval('qn = qn.replace(/(^|[^-])'+term+'/gi, "$1-'+term+'")');
+ if(qn == q)
+ eval('qn = qn.replace(/-'+term+'/gi, "")');
+ }
+ if(qn == q)
+ q += ' '+term;
+ else
+ q = qn;
+
+ q = q.replace(/^ +/, "");
+ q = q.replace(/ +$/, "");
+ q = q.replace(/ +/g, " ");
+
+ x('q').value = q;
+ }
+
+ q = q.toLowerCase();
+ for (i in ad_lang)
+ x('lang_'+i).checked = q.indexOf(ad_lang[i]) >= 0 || q.indexOf('l:'+i) >= 0 ? true : false;
+ for (i in ad_plat)
+ x('plat_'+i).checked = q.indexOf(ad_plat[i]) >= 0 || q.indexOf('p:'+i) >= 0 ? true : false;
+ for (i in ad_cats)
+ x('cat_'+i).className = q.indexOf('-'+ad_cats[i]) >= 0 || q.indexOf('-c:'+i) >= 0 ? 'exc' : q.indexOf(ad_cats[i]) >= 0 || q.indexOf('c:'+i) >= 0 ? 'inc' : '';
+}
+
+function ad_dosearch() {
+ location.href = '?q='+x('q').value;
+ return false;
+}
+
+
+
+
/* O N L O A D */
DOMLoad(function() {
@@ -134,41 +219,10 @@ DOMLoad(function() {
if(this.value.length < 1) {
this.value = 'search';
this.style.color = '#999';} };
-
- // browse categories
- if(x('catsearch')) {
- x('catsearch').onclick = function () {
- var u = { i:'',e:'',l:'' };
- var l = x('cat').getElementsByTagName('li');
- var y;var j;
- for(y=0;y<l.length;y++)
- if((j = l[y].className.indexOf('cat_')) != -1) {
- var k = l[y].className.substr(j+4, 3);
- if(l[y].className.indexOf(' inc') != -1)
- u.i += (u.i?',':'')+k;
- if(l[y].className.indexOf(' exc') != -1)
- u.e += (u.e?',':'')+k;
- }
- l = x('lfilter').getElementsByTagName('input');
- for(y=0;y<l.length;y++)
- if(l[y].checked)
- u.l+=(u.l!=''?',':'')+l[y].name.substr(5);
- var url = '/v/cat';
- for (y in u)
- if(u[y])
- url+=(url.indexOf('?')<0?'?':';')+y+'='+u[y];
- location.href=url;
- return false;
- };
- var l = x('cat').getElementsByTagName('li');
- for(i=0;i<l.length;i++)
- if(l[i].className.indexOf('cat_') != -1)
- l[i].onclick = function () {
- try { document.selection.empty() } catch(e) { try { window.getSelection().collapse(this, 0) } catch(e) {} };
- var sel = this.className.substr(this.className.indexOf('cat_'), 7);
- this.className = this.className.indexOf(' inc') != -1 ? (sel+' exc') : this.className.indexOf(' exc') != -1 ? sel : (sel + ' inc');
- };
- }
+
+ // advanced search
+ if(x('adsearch'))
+ adsearch();
// vnlist
cl('askcomment', function() {
@@ -197,22 +251,9 @@ DOMLoad(function() {
}
}
- // autocheck
- cl('checkall', function () {
- var l = document.getElementsByTagName('input');
- var y;
- for(y=0;y<l.length;y++)
- if(l[y].type == 'checkbox' && l[y].name == this.name)
- l[y].checked = this.checked;
- });
-
- // a few confirm popups
+ // confirm popup
cl('idel', function () {
return confirm('Are you sure you want to delete this item?\n\nAll previous edits will be deleted, this action can not be reverted!') });
-// cl('vhide', function () {
-// return confirm('!WARNING!\nHiding a visual novel also DELETES the following information:\n - VN Relations of ALL revisions\n - VN lists\n - Votes\nThis is NOT recoverable!'); });
- cl('massdel', function () {
- return confirm('Are you sure you want to mass-delete all the selected changes?\n\nThis action can not be reverted!') });
// NSFW
cl('nsfw', function () {
@@ -238,7 +279,6 @@ DOMLoad(function() {
formhid();
// init dyna
-// if(x('vn_select') || x('md_select') || x('pd_select') || x('rl_select'))
if(window.dInit)
dInit();
@@ -247,3 +287,13 @@ DOMLoad(function() {
for(i=1; i<sub.length; i+=2)
sub[i].style.backgroundColor = '#f5f5f5';
});
+
+
+
+
+// small hack because the mozilla -moz-inline-stack display hack sucks
+// (so we're counter-hacking a CSS hack using JS... right)
+if(navigator.userAgent.indexOf('Gecko') >= 0 && navigator.userAgent.indexOf('like Gecko') < 0 && navigator.userAgent.indexOf('fox/3') < 0)
+ document.write('<style type="text/css">.icons.lang { width: 15px; height: 13px; }</style>');
+
+
diff --git a/static/files/icons.png b/static/files/icons.png
new file mode 100644
index 00000000..f9cad068
--- /dev/null
+++ b/static/files/icons.png
Binary files differ
diff --git a/static/files/style.css b/static/files/style.css
index 5d1996c6..980e0861 100644
--- a/static/files/style.css
+++ b/static/files/style.css
@@ -54,12 +54,7 @@ h3 {
p, ul, ol {
margin: 0;
}
-
-blockquote {
- font-style: italic;
-}
a {
-/* color: #7AB9AB;*/
color: #69A89A;
}
a:hover {
@@ -367,6 +362,7 @@ span.warning ul, span.msg ul {
padding: 0 0 0 15px;
}
+/* VN page header, general dl and list markup */
dt {
float: left;
font-style: italic;
@@ -383,25 +379,13 @@ ul.vnani acronym { border: 0 }
ul {
padding: 0 0 0 17px;
}
-p.actions, #vnheader p.actions, b.actions {
+p.actions {
display: inline;
margin: 0 0 0 5px;
font-weight: normal;
font-size: 12px;
color: #999;
}
-a.relch {
- color: #900;
-}
-a.rss {
- display: block;
- height: 16px;
- width: 16px;
- background: url(/files/rss.png) no-repeat;
- text-indent: -9999px;
- overflow: hidden;
- float: right;
-}
#vnheader div {
width: 256px;
float: left;
@@ -413,15 +397,6 @@ a.rss {
#vnheader #nsfw {
cursor: pointer;
}
-img.left {
- float: left;
- margin: 0 15px 0 0;
-}
-
-img.right {
- float: left;
- margin: 0 0 0 15px;
-}
#vnheader dl, #vnheader ul {
margin: 0 0 0 270px;
padding: 0;
@@ -431,21 +406,6 @@ img.right {
margin: 5px 0 0 260px;
font-size: 13px;
}
-#vnheader p {
- margin: 0 0 0 270px;
-}
-#vnheader select {
- width: 60px;
- height: 16px;
- display: inline;
- float: none;
- text-align: center;
-}
-#vnheader #vnlist {
- width: 150px;
- text-align: left;
-}
-
#vnheader p.mod {
margin: 0;
}
@@ -453,11 +413,12 @@ img.right {
/* producer search */
-form#psearch {
+form#psearch fieldset {
display: block;
- margin: 10px 0 20px 210px;
+ width: 700px;
+ text-align: center;
}
-* html form#psearch { margin-left: 105px; }
+form#psearch input { margin: 0 auto; float: none; position: relative; display: inline }
ul.home {
@@ -540,10 +501,28 @@ b.mod, a.mod {
}
+/* vn search */
+
+form#vsearch fieldset {
+ display: block;
+ width: 700px;
+ text-align: center;
+}
+form#vsearch input { margin: 0 auto; float: none; position: relative; display: inline }
+form#vsearch input.text { width: 400px; }
+b#adsearchclick { cursor: pointer }
+
+ul.filter { margin: 0 0 0 15px; padding: 0; list-style-type: none }
+ul.filter li { float: left; padding: 4px 10px 0 0; }
+ul.filter label { width: auto; color: #666; font-size: 11px; margin: 0; padding: 0 0 0 1px;}
+ul.filter input { border: 0; margin: 0; }
+
+
+
/* categories */
ul#cat {
- margin: 0;
+ margin: 0 0 0 15px;
padding: 0;
}
ul#cat ul {
@@ -589,20 +568,6 @@ i.crgn2 { font-style: normal; }
i.crgn3 { font-style: normal; font-weight: bold; }
-/* language filter */
-
-div#lfilter {
- clear: left;
- padding: 10px 0 0 0;
-}
-div#lfilter input {
- float: left; margin: 3px 3px 0 10px;
-}
-div#lfilter label {
- float: left; margin-top: 3px;
- width: 90px;
-}
-
/* DOCUMENTATION PAGES */
#dpage h3 { margin-top: 25px; }
@@ -654,10 +619,19 @@ acronym.date {
b.future { font-weight: normal; color: #900; }
-/* 16x14 image sprites */
+/* icon image sprites */
-.plat {
- background: url(/files/16x14.png) no-repeat;
+a.rss {
+ display: block;
+ height: 16px;
+ width: 16px;
+ background: url(/files/rss.png) no-repeat;
+ text-indent: -9999px;
+ overflow: hidden;
+ float: right;
+}
+.icons {
+ background: url(/files/icons.png) no-repeat;
width: 16px;
height: 14px;
margin: 0 2px 0 0;
@@ -668,25 +642,49 @@ b.future { font-weight: normal; color: #900; }
border: 0;
text-decoration: none;
}
-acronym.plat { cursor: default; }
-.plat.oth { background: none; }
-.plat.dc { background-position: 0px 0px; }
-.plat.lin { background-position: 0px -14px; }
-.plat.nds { background-position: 0px -28px; }
-.plat.ps2 { background-position: 0px -42px; }
-.plat.sfc { background-position: 0px -56px; }
-.plat.gba { background-position: 0px -70px; }
-.plat.ext { background-position: 0px -84px; }
-.plat.par { background-position: 0px -98px; }
-.plat.dvd { background-position: -16px 0px; }
-.plat.mac { background-position: -16px -14px; }
-.plat.ps { background-position: -16px -28px; }
-.plat.psp { background-position: -16px -42px; }
-.plat.win { background-position: -16px -56px; }
-.plat.wii { background-position: -16px -70px; }
-.plat.tri { background-position: -16px -84px; }
-.plat.com { background-position: -16px -98px; }
-.plat.par, .plat.tri, .plat.com { width: 11px; }
+.icons.lang {
+ width: 13px;
+ height: 11px;
+ border: 1px solid #999;
+ /* see def.js for an ugly FF hack */
+}
+.icons.par, .icons.tri, .icons.com { width: 11px; }
+acronym.icons { cursor: default; }
+.icons.oth { background: none; }
+.icons.drc { background-position: 0px 0px; }
+.icons.lin { background-position: 0px -14px; }
+.icons.nds { background-position: 0px -28px; }
+.icons.ps2 { background-position: 0px -42px; }
+.icons.sfc { background-position: 0px -56px; }
+.icons.gba { background-position: 0px -70px; }
+.icons.ext { background-position: 0px -84px; }
+.icons.par { background-position: 0px -98px; }
+.icons.dvd { background-position: -16px 0px; }
+.icons.mac { background-position: -16px -14px; }
+.icons.ps1 { background-position: -16px -28px; }
+.icons.psp { background-position: -16px -42px; }
+.icons.win { background-position: -16px -56px; }
+.icons.wii { background-position: -16px -70px; }
+.icons.tri { background-position: -16px -84px; }
+.icons.com { background-position: -16px -98px; }
+.icons.cs { background-position: -32px 0px; }
+.icons.da { background-position: -32px -11px; }
+.icons.de { background-position: -32px -22px; }
+.icons.en { background-position: -32px -33px; }
+.icons.es { background-position: -32px -44px; }
+.icons.fi { background-position: -32px -55px; }
+.icons.fr { background-position: -32px -66px; }
+.icons.it { background-position: -32px -77px; }
+.icons.ja { background-position: -32px -88px; }
+.icons.ko { background-position: -32px -99px; }
+.icons.nl { background-position: -45px 0px; }
+.icons.no { background-position: -45px -11px; }
+.icons.pl { background-position: -45px -22px; }
+.icons.pt { background-position: -45px -33px; }
+.icons.ru { background-position: -45px -44px; }
+.icons.sv { background-position: -45px -55px; }
+.icons.tr { background-position: -45px -66px; }
+.icons.zh { background-position: -45px -77px; }
/* tables */
@@ -733,9 +731,20 @@ b.diff_del { font-weight: normal; background-color: #fcc; }
#tre tr.lang { background-color: #f5f5f5!important; font-style: italic; }
#tre .tc1 { width: 75px; padding-left: 10px; }
-#tre .tc2 { width: 60px; text-align: center; }
+#tre .tc2 { width: 50px; text-align: center; white-space: nowrap; }
#tre .tc3, #tre .tc5 { width: 16px; margin: 0; padding: 0; white-space: nowrap; text-align: right }
-#tre .tc3 { width: 60px; }
+#tre .tc3 { width: 70px; }
+
+#tbv .tc2 acronym, #tbv .tc3 acronym {
+ zoom: 1;
+ opacity: 0.7;
+ filter:alpha(opacity=70);
+ -moz-opacity: 0.7;
+}
+#tbv .tc2, #tbv .tc3 { margin: 0; padding: 0; white-space: nowrap }
+#tbv .tc2 { text-align: right; padding-right: 3px; }
+
+#tpd .tc1 { margin: 0; padding: 0; }
#debug {
border-top: 1px solid #ffb4b4;
diff --git a/util/multi.pl b/util/multi.pl
index 3e6e07a7..93c4fe44 100644
--- a/util/multi.pl
+++ b/util/multi.pl
@@ -80,7 +80,7 @@ Multi::Image->spawn();
Multi::Sitemap->spawn();
Multi::Anime->spawn();
Multi::Maintenance->spawn();
-Multi::IRC->spawn() if !$VNDB::DEBUG;
+Multi::IRC->spawn(user => 'Multi_test', channel => '#vndb_test') if !$VNDB::DEBUG;
$SIG{__WARN__} = sub {(local$_=shift)=~s/\r?\n//;$poe_kernel->call(core=>log=>1,'__WARN__: '.$_)};
diff --git a/util/updates/update_1.16.sql b/util/updates/update_1.16.sql
new file mode 100644
index 00000000..c64e1d49
--- /dev/null
+++ b/util/updates/update_1.16.sql
@@ -0,0 +1,74 @@
+
+-- empty nfo_id
+UPDATE anime SET nfo_id = '' WHERE nfo_id = '0,';
+
+
+-- future release dates
+UPDATE releases_rev
+ SET released = (SUBSTRING(released::text, 1, 4)||'9999')::integer
+ WHERE SUBSTRING(released::text, 5, 4) = '0000';
+
+UPDATE releases_rev
+ SET released = (SUBSTRING(released::text, 1, 6)||'99')::integer
+ WHERE SUBSTRING(released::text, 7, 4) = '00';
+
+
+
+-- all platforms are three-letters now
+UPDATE releases_platforms SET platform = 'ps1' WHERE platform = 'ps ';
+UPDATE releases_platforms SET platform = 'drc' WHERE platform = 'dc ';
+
+
+
+-- cache platforms
+ALTER TABLE vn ADD COLUMN c_platforms varchar(32) NOT NULL DEFAULT '';
+
+CREATE OR REPLACE FUNCTION update_vncache(id integer) RETURNS void AS $$
+DECLARE
+ w text := '';
+BEGIN
+ IF id > 0 THEN
+ w := ' WHERE id = '||id;
+ END IF;
+ EXECUTE 'UPDATE vn SET
+ c_released = COALESCE((SELECT
+ MIN(rr1.released)
+ FROM releases_rev rr1
+ JOIN releases r1 ON rr1.id = r1.latest
+ JOIN releases_vn rv1 ON rr1.id = rv1.rid
+ WHERE rv1.vid = vn.id
+ AND rr1.type <> 2
+ AND r1.hidden = 0
+ AND rr1.released <> 0
+ GROUP BY rv1.vid
+ ), 0),
+ c_languages = COALESCE(ARRAY_TO_STRING(ARRAY(
+ SELECT language
+ FROM releases_rev rr2
+ JOIN releases r2 ON rr2.id = r2.latest
+ JOIN releases_vn rv2 ON rr2.id = rv2.rid
+ WHERE rv2.vid = vn.id
+ AND rr2.type <> 2
+ AND rr2.released <= TO_CHAR(''today''::timestamp, ''YYYYMMDD'')::integer
+ AND r2.hidden = 0
+ GROUP BY rr2.language
+ ORDER BY rr2.language
+ ), ''/''), ''''),
+ c_platforms = COALESCE(ARRAY_TO_STRING(ARRAY(
+ SELECT rp3.platform
+ FROM releases_platforms rp3
+ JOIN releases_rev rr3 ON rp3.rid = rr3.id
+ JOIN releases r3 ON rp3.rid = r3.latest
+ JOIN releases_vn rv3 ON rp3.rid = rv3.rid
+ WHERE rv3.vid = vn.id
+ AND rr3.type <> 2
+ AND rr3.released <= TO_CHAR(''today''::timestamp, ''YYYYMMDD'')::integer
+ AND r3.hidden = 0
+ GROUP BY rp3.platform
+ ORDER BY rp3.platform
+ ), ''/''), '''')
+ '||w;
+END;
+$$ LANGUAGE plpgsql;
+
+SELECT update_vncache(0);