#!perl -w # # xNN is a CGI newest nodes client that sorts nodes by date, author, category, and threads. # Displays nodes from n days in the past, or fractions of the current day. # Saves node data to disk, uses cookies to remember sort mode, and can undo a refresh. # Requires XML::Simple # # Note: Threaded mode can get dramatically slower as the number of nodes increases, # so be prepared to wait to thread more than a few days worth (1000+). # # usage: # Make sure the first 3 variables and the #! line are correct and load in a browser. # First run involves your first download of new nodes so be online. # # coded by epoptai - http://perlmonks.org/index.pl?node=epoptai # Updated: 5.23.2002 use strict; use CGI::Carp 'fatalsToBrowser'; use CGI::Cookie; use CGI qw(param header url); use LWP::Simple 'get'; use Data::Dumper; eval("use XML::Simple 'XMLin'"); # required xml parser $@ && install_xml_simple(); # check the values of these 3 variables my$perlmonks = 'www.perlmonks.org'; # your usual perlmonks domain my$temp = './'; # where to write data and undo files my$trgt = ' target="_self"'; # link target window my@days = qw(0.1 0.5 1 2 3 4 5 6 7); # day values for the select menu, can customize but max = 8 days my$pmurl = "http://$perlmonks/index.pl"; my$nnxml = "$pmurl?node_id=30175"; # new nodes xml ticker my$method = 'post'; # 'get' may cause a re-refresh when using the back button after refresh my$done = 0; use vars qw( @kids @cache @sorted %nodes %nodetype %nodetypes %whom %roots $total $lastcheck $data $data1 $b1 $b2 $numdays $nd ); my%types = ( 'bookreview' => 'Book Reviews', 'categorized answer' => 'Categorized Answers', 'categorized question' => 'Categorized Questions', 'CUFP' => 'Cool Uses for Perl', 'modulereview' => 'Reviews', 'monkdiscuss' => 'Perlmonks Discussion', 'note' => 'Reply', 'obfuscated' => 'Obfuscated Code', 'perlcraft' => 'Perl Craft', 'perlmeditation' => 'Meditations', 'perlnews' => 'Perl News', 'perltutorial' => 'Tutorials', 'perlquestion' => 'Seekers of Perl Wisdom', 'poem' => 'Poems', 'review' => 'Reviews', 'snippet' => 'Snippets Section', 'sourcecode' => 'Code Catacombs', 'tutorial' => 'Tutorials', 'user' => 'Users', ); my%stypes = ( 'bookreview' => 'Book', 'categorized answer' => 'Answers', 'categorized question' => 'Questions', 'CUFP' => 'Cool Uses', 'monkdiscuss' => 'Discussion', 'obfuscated' => 'Obfuscated', 'perlquestion' => 'Seekers', 'snippet' => 'Snippets', 'sourcecode' => 'Code', ); my$file = $temp.'xnn.dat'; my$undo = $file.'.undo'; my$uri = url(); my$handle = select(); my%i = map {$_ => param($_)} param; my%cookies = CGI::Cookie->fetch(); my$start = (times)[0]; copy($undo,$file) if (($i{'m'} && $i{'m'} eq 'undo') && -e $undo); if( (($i{'m'}) && ($i{'m'} eq 'refresh')) || (!-e $file) ){ if($i{'numdays'} && $i{'pageloadtime'}){ $numdays = $i{'numdays'}; my$sut = ( $i{'pageloadtime'} - (86400*$numdays) ); $nnxml = $nnxml."&sinceunixtime=$sut"; } my$nn = get "$nnxml"; unless($nn=~/\S/){ print header; print qq~Download failed! Return~; exit } $nn = fixxml($nn); $data = XMLin($nn, forcearray => 1); copy($file,$undo) if -e $file; open(DAT,"> $file") or die "$!"; $Data::Dumper::Indent = 0; $Data::Dumper::Varname = 'data'; print DAT Dumper($data); if($i{'numdays'}){ print DAT qq~\$nd = $i{'numdays'};~; } close DAT or die "$!"; } else{ if(eval "require '$file'"){ $data = $data1; $numdays = $nd; } } my($c1,$c2,$c3,$c4,$cookie,$mode) = ('') x 6; if( ($i{'n'}) || ($i{'m'}) || ($cookies{'nn_mode'}) ){ # determine mode, set cookies, execute subs unless($i{'n'}){ $mode = $cookies{'nn_mode'}->value if $cookies{'nn_mode'}; } if(($i{'n'} && $i{'n'} eq 'categorized') || $mode eq 'ca'){ if($i{'n'} && $i{'n'} eq 'categorized'){ $cookie = CGI::Cookie->new(-name=>'nn_mode',-value=>'ca',-expires=>'+1y'); } $c1 = ' checked'; initdat(); stance('ca'); types(); # categorized } if(($i{'n'} && $i{'n'} eq 'chronological') || $mode eq 'ch'){ if($i{'n'} && $i{'n'} eq 'chronological'){ $cookie = CGI::Cookie->new(-name=>'nn_mode',-value=>'ch',-expires=>'+1y'); } $c2 = ' checked'; initdat(); stance('ch'); cron(); # chronological } if(($i{'n'} && $i{'n'} eq 'threaded') || $mode eq 'th'){ if($i{'n'} && $i{'n'} eq 'threaded'){ $cookie = CGI::Cookie->new(-name=>'nn_mode',-value=>'th',-expires=>'+1y'); } $c3 = ' checked'; initdat('th'); stance('th'); threaded(); # threaded } if(($i{'n'} && $i{'n'} eq 'byauthor') || $mode eq 'au'){ if($i{'n'} && $i{'n'} eq 'byauthor'){ $cookie = CGI::Cookie->new(-name=>'nn_mode',-value=>'au',-expires=>'+1y'); } $c4 = ' checked'; initdat(); stance('au'); cron('au'); # by author } } else{ $c2 = ' checked'; initdat(); stance('ch'); } my$end = (times)[0]; my$sprnt = sprintf "That took %.2F CPU seconds.", $end - $start; my$prnt = qq~
$sprnt | top | xNN by epoptai |