X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2FModules%2FNews.pl;h=caee5f104751e0fab85324b543997dfecb8f4292;hb=f7cae48a17d6decd0a9bd997188271daa0a885b1;hp=ab274d32edbb3ac750844963dcd39f0b78de32a1;hpb=6613e021e045081554e304c8e5235d366e207ed6;p=infobot.git diff --git a/src/Modules/News.pl b/src/Modules/News.pl index ab274d3..caee5f1 100644 --- a/src/Modules/News.pl +++ b/src/Modules/News.pl @@ -1,7 +1,7 @@ # # News.pl: Advanced news management # Author: dms -# Version: v0.3 (20014012) +# Version: v0.3 (20010412) # Created: 20010326 # Notes: Testing done by greycat, kudos! # @@ -17,13 +17,18 @@ package News; +use strict; + +use vars qw($who $chan); + sub Parse { my($what) = @_; $chan = undef; + $who = lc $::who; if (!keys %::news) { if (!exists $::cache{newsFirst}) { - &::DEBUG("looks like we enabled news option just then; loading up news file just in case."); + &::DEBUG("news: looks like we enabled news option just then; loading up news file just in case."); $::cache{newsFirst} = 1; } @@ -36,24 +41,30 @@ sub Parse { if (defined $what and $what =~ s/^($::mask{chan})\s*//) { # todo: check if the channel exists aswell. - $chan = $1; + $chan = lc $1; + + if (!&::IsNickInChan($who, $chan)) { + &::notice($who, "sorry but you're not on $chan."); + return; + } } if (!defined $chan) { - my @chans = &::GetNickInChans($::who); + my @chans = &::getNickInChans($who); if (scalar @chans > 1) { - &::msg($::who, "error: I dunno which channel you are referring to since you're on more than one. Try 'news #chan ...' instead"); + &::notice($who, "error: I dunno which channel you are referring to since you're on more than one. Try 'news #chan ...' instead"); return; } if (scalar @chans == 0) { - &::msg($::who, "error: I couldn't find you on any chan. This must be a bug!"); + &::notice($who, "error: I couldn't find you on any chan. This must be a bug!"); return; } - $chan = $chans[0]; - &::DEBUG("Guessed $::who being on chan $chan"); + $chan = $chans[0]; + &::VERB("Guessed $who being on chan $chan",2); + $::chan = $chan; # hack for IsChanConf(). } if (!defined $what or $what =~ /^\s*$/) { @@ -63,39 +74,84 @@ sub Parse { if ($what =~ /^add(\s+(.*))?$/i) { &add($2); + } elsif ($what =~ /^del(\s+(.*))?$/i) { &del($2); + } elsif ($what =~ /^mod(\s+(.*))?$/i) { &mod($2); + } elsif ($what =~ /^set(\s+(.*))?$/i) { &set($2); - } elsif ($what =~ /^(\d)$/i) { - &::DEBUG("read shortcut called."); + + } elsif ($what =~ /^(\d+)$/i) { + &::VERB("News: read shortcut called.",2); &read($1); + } elsif ($what =~ /^read(\s+(.*))?$/i) { &read($2); + } elsif ($what =~ /^(latest|new)(\s+(.*))?$/i) { - &::DEBUG("latest called... hrm"); &latest($3 || $chan, 1); +# $::cmdstats{'News latest'}++; + + } elsif ($what =~ /^stats?$/i) { + &stats(); + } elsif ($what =~ /^list$/i) { - &::DEBUG("list longcut called."); &list(); + } elsif ($what =~ /^(expire|text|desc)(\s+(.*))?$/i) { # shortcut/link. # nice hack. + my $cmd = $1; my($arg1,$arg2) = split(/\s+/, $3, 2); - &set("$arg1 $1 $arg2"); + &set("$arg1 $cmd $arg2"); + } elsif ($what =~ /^help(\s+(.*))?$/i) { - &::help("news$1"); + &::help("news $2"); + + } elsif ($what =~ /^newsflush$/i) { + &::msg($who, "newsflush called... check out the logs!"); + &::newsFlush(); + + } elsif ($what =~ /^(un)?notify$/i) { + my $state = ($1) ? 0 : 1; + + # todo: don't notify even if "news" is called. + if (!&::IsChanConf("newsNotifyAll")) { + &::DEBUG("news: chan => $chan, ::chan => $::chan."); + &::notice($who, "not available for this channel or disabled altogether."); + return; + } + + my $t = $::newsuser{$chan}{$who}; + if ($state) { # state = 1 + if (defined $t and ($t == 0 or $t == -1)) { + &::notice($who, "enabled notify."); + delete $::newsuser{$chan}{$who}; + return; + } + &::notice($who, "already enabled."); + + } else { # state = 0 + my $x = $::newsuser{$chan}{$who}; + if (defined $x and ($x == 0 or $x == -1)) { + &::notice($who, "notify already disabled"); + return; + } + $::newsuser{$chan}{$who} = -1; + &::notice($who, "notify is now disabled."); + } + } else { - &::DEBUG("could not parse '$what'."); - &::msg($::who, "unknown command: $what"); + &::notice($who, "unknown command: $what"); } } sub readNews { my $file = "$::bot_base_dir/blootbot-news.txt"; - if (! -f $file) { + if (! -f $file or -z $file) { return; } @@ -115,7 +171,7 @@ sub readNews { if (/^[\s\t]+(\S+):[\s\t]+(.*)$/) { if (!defined $item) { - &::DEBUG("!defined item, never happen!"); + &::DEBUG("news: !defined item, never happen!"); next; } @@ -138,20 +194,27 @@ sub readNews { } close NEWS; - &::status("News: Read $ci items for ".scalar(keys %::news) - ." chans, $cu users cache"); + my $cn = scalar(keys %::news); + return unless ($ci or $cn or $cu); + + &::status("News: read ". + $ci. &::fixPlural(" item", $ci). " for ". + $cn. &::fixPlural(" chan", $cn). ", ". + $cu. &::fixPlural(" user", $cu), " cache" + ); } sub writeNews { - if (!scalar keys %::news) { - &::DEBUG("wN: nothing to write."); + if (!scalar keys %::news and !scalar keys %::newsuser) { + &::VERB("wN: nothing to write.",2); return; } + # should define this at the top of file. my $file = "$::bot_base_dir/blootbot-news.txt"; if (fileno NEWS) { - &::ERROR("fileno NEWS exists, should never happen."); + &::ERROR("News: write: fileno NEWS exists, should never happen."); return; } @@ -164,6 +227,7 @@ sub writeNews { $c = scalar keys %{ $::news{$chan} }; next unless ($c); $cc++; + my $item; foreach $item (sort keys %{ $::news{$chan} }) { $c = scalar keys %{ $::news{$chan}{$item} }; @@ -171,6 +235,7 @@ sub writeNews { $ci++; print NEWS "$chan $item\n"; + my $what; foreach $what (sort keys %{ $::news{$chan}{$item} }) { print NEWS " $what: $::news{$chan}{$item}{$what}\n"; } @@ -206,27 +271,27 @@ sub add { } if (length $str > 64) { - &::msg($::who, "That's not really an item (>64chars)"); + &::notice($who, "That's not really an item (>64chars)"); return; } if (exists $::news{$chan}{$str}{Time}) { - &::msg($::who, "'$str' for $chan already exists!"); + &::notice($who, "'$str' for $chan already exists!"); return; } $::news{$chan}{$str}{Time} = time(); my $expire = &::getChanConfDefault("newsDefaultExpire",7); $::news{$chan}{$str}{Expire} = time() + $expire*60*60*24; - $::news{$chan}{$str}{Author} = $::who; + $::news{$chan}{$str}{Author} = $::who; # case! my $agestr = &::Time2String($::news{$chan}{$str}{Expire} - time() ); my $item = &newsS2N($str); - &::msg($::who, "Added '\037$str\037' at [".localtime(time). + &::notice($who, "Added '\037$str\037' at [".gmtime(time). "] by \002$::who\002 for item #\002$item\002."); - &::msg($::who, "Now do 'news text $item '"); - &::msg($::who, "This item will expire at \002". - localtime($::news{$chan}{$str}{Expire})."\002 [$agestr from now] " + &::notice($who, "Now do 'news text $item '"); + &::notice($who, "This item will expire at \002". + gmtime($::news{$chan}{$str}{Expire})."\002 [$agestr from now] " ); &writeNews(); @@ -244,12 +309,12 @@ sub del { if ($what =~ /^\d+$/) { my $count = scalar keys %{ $::news{$chan} }; if (!$count) { - &::msg($::who, "No news for $chan."); + &::notice($who, "No news for $chan."); return; } if ($what > $count or $what < 0) { - &::msg($::who, "$what is out of range (max $count)"); + &::notice($who, "$what is out of range (max $count)"); return; } @@ -268,17 +333,17 @@ sub del { } if (!scalar @found) { - &::msg($::who, "could not find $what."); + &::notice($who, "could not find $what."); return; } if (scalar @found > 1) { - &::msg($::who, "too many matches for $what."); + &::notice($who, "too many matches for $what."); return; } $what = $found[0]; - &::DEBUG("del: str: guessed what => $what"); + &::DEBUG("news: del: str: guessed what => $what"); } } @@ -289,55 +354,87 @@ sub del { if (!$auth) { # todo: show when it'll expire. - &::msg($::who, "Sorry, you cannot remove items; just let them expire on their own."); + &::notice($who, "Sorry, you cannot remove items; just let them expire on their own."); return; } - &::msg($::who, "ok, deleted '$what' from \002$chan\002..."); + &::notice($who, "ok, deleted '$what' from \002$chan\002..."); delete $::news{$chan}{$what}; } else { - &::msg($::who, "error: not found $what in news for $chan."); + &::notice($who, "error: not found $what in news for $chan."); } } sub list { if (!scalar keys %{ $::news{$chan} }) { - &::msg($::who, "No News for \002$chan\002."); + &::notice($who, "No news for \002$chan\002."); return; } if (&::IsChanConf("newsKeepRead")) { - $::newsuser{$chan}{$::who} = time(); + my $x = $::newsuser{$chan}{$who}; + + if (defined $x and ($x == 0 or $x == -1)) { + &::DEBUG("news: not updating time for $who."); + } else { + if (!scalar keys %{ $::news{$chan} }) { + &::DEBUG("news: should not add $chan/$who to cache!"); + } + + $::newsuser{$chan}{$who} = time(); + } } - &::msg($::who, "|==== News for \002$chan\002:"); + # ¬ice() breaks OPN :( - using msg() instead! + my $count = scalar keys %{ $::news{$chan} }; + &::msg($who, "|==== News for \002$chan\002: ($count items)"); my $newest = 0; + my $expire = 0; + my $eno = 0; foreach (keys %{ $::news{$chan} }) { my $t = $::news{$chan}{$_}{Time}; + my $e = $::news{$chan}{$_}{Expire}; $newest = $t if ($t > $newest); + if ($e > 1 and $e < $expire) { + $expire = $e; + &::DEBUG("before newsS2N($_)"); + $eno = &newsS2N($_); + &::DEBUG("after newsS2N($_) == $eno"); + } } my $timestr = &::Time2String(time() - $newest); - &::msg($::who, "|= Last updated $timestr ago."); - &::msg($::who, " \037Num\037 \037Item ".(" "x40)." \037"); + &::msg($who, "|= Last updated $timestr ago."); + &::msg($who, " \037Num\037 \037Item ".(" "x40)." \037"); + +# &::DEBUG("news: list: expire = $expire"); +# &::DEBUG("news: list: eno = $eno"); my $i = 1; foreach ( &getNewsAll() ) { my $subtopic = $_; my $setby = $::news{$chan}{$subtopic}{Author}; + my $chr = (exists $::News{$chan}{$subtopic}{Text}) ? "" : "*"; if (!defined $subtopic) { - &::DEBUG("warn: subtopic == undef."); + &::DEBUG("news: warn: subtopic == undef."); next; } # todo: show request stats aswell. - &::msg($::who, sprintf("\002[\002%2d\002]\002 %s", - $i, $subtopic)); + &::msg($who, sprintf("\002[\002%2d\002]\002%s %s", + $i, $chr, $subtopic)); $i++; } - &::msg($::who, "|= End of News."); - &::msg($::who, "use 'news read <#>' or 'news read '"); + my $z = $::newsuser{$who}; + if (defined $z) { + &::DEBUG("cache $who: $z"); + } else { + &::DEBUG("cache: $who doesn't have newscache set."); + } + + &::msg($who, "|= End of News."); + &::msg($who, "use 'news read <#>' or 'news read '"); } sub read { @@ -349,22 +446,31 @@ sub read { } if (!scalar keys %{ $::news{$chan} }) { - &::msg($::who, "No News for \002$chan\002."); + &::notice($who, "No news for \002$chan\002."); return; } my $item = &getNewsItem($str); if (!defined $item or !scalar keys %{ $::news{$chan}{$item} }) { - &::msg($::who, "No news item called '$str'"); + # todo: numerical check. + if ($str =~ /^(\d+)[-, ](\d+)$/ or + $str =~ /^-(\d+)$/ or + $str =~ /^(\d+)-$/ or 0 + ) { + &::notice($who, "We don't support multiple requests of news items yet. Sorry."); + return; + } + + &::notice($who, "No news item called '$str'"); return; } if (!exists $::news{$chan}{$item}{Text}) { - &::msg($::who, "Someone forgot to add info to this news item"); + &::notice($who, "Someone forgot to add info to this news item"); return; } - my $t = localtime( $::news{$chan}{$item}{Time} ); + my $t = gmtime( $::news{$chan}{$item}{Time} ); my $a = $::news{$chan}{$item}{Author}; my $text = $::news{$chan}{$item}{Text}; my $num = &newsS2N($item); @@ -372,20 +478,30 @@ sub read { my $rcount = $::news{$chan}{$item}{Request_Count} || 0; if (length $text < $::param{maxKeySize}) { - &::DEBUG("NEWS: Possible news->factoid redirection."); + &::VERB("NEWS: Possible news->factoid redirection.",2); my $f = &::getFactoid($text); if (defined $f) { - &::DEBUG("NEWS: ok, $text is factoid redirection."); + &::VERB("NEWS: ok, $text is factoid redirection.",2); $f =~ s/^\s*//i; # anything else? $text = $f; } } - &::msg($::who, "+- News \002$chan\002 #$num: \037$item\037"); - &::msg($::who, "| Added by $a at $t"); - &::msg($::who, "| Requested $rcount times, last by $rwho"); - &::msg($::who, $text); + $_ = $::news{$chan}{$item}{'Expire'}; + my $e; + if ($_) { + $e = sprintf("\037%s\037 [%s from now]", + scalar(gmtime($_)), + &::Time2String($_ - time()) + ); + } + + &::notice($who, "+- News \002$chan\002 #$num: $item"); + &::notice($who, "| Added by $a at \037$t\037"); + &::notice($who, "| Expire: $e") if (defined $e); + &::notice($who, $text); + &::notice($who, "| Requested \002$rcount\002 times, last by \002$rwho\002") if ($rcount and $rwho); $::news{$chan}{$item}{'Request_By'} = $::who; $::news{$chan}{$item}{'Request_Time'} = time(); @@ -403,7 +519,7 @@ sub mod { my $news = &getNewsItem($item); if (!defined $news) { - &::DEBUG("error: mod: news == undefined."); + &::DEBUG("news: error: mod: news == undefined."); return; } my $nnews = $::news{$chan}{$news}{Text}; @@ -415,7 +531,7 @@ sub mod { my ($delim, $op, $np, $flags) = ($1,$2,$3,$4); if ($flags !~ /^(g)?$/) { - &::msg($::who, "error: Invalid flags to regex."); + &::notice($who, "error: Invalid flags to regex."); return; } @@ -426,23 +542,23 @@ sub mod { if ($flags eq "") { $done++ if (!$done and $mod_news =~ s/\Q$op\E/$np/); $done++ if (!$done and $mod_nnews =~ s/\Q$op\E/$np/); - } elsif ($flags eq "g") { + } elsif ($flags eq "g") { $done++ if ($mod_news =~ s/\Q$op\E/$np/g); $done++ if ($mod_nnews =~ s/\Q$op\E/$np/g); } if (!$done) { - &::msg($::who, "warning: regex not found in news."); + &::notice($who, "warning: regex not found in news."); return; } if ($mod_news ne $news) { # news item. if (exists $::news{$chan}{$mod_news}) { - &::msg($::who, "item '$mod_news' already exists."); + &::notice($who, "item '$mod_news' already exists."); return; } - &::msg($::who, "Moving item '$news' to '$mod_news' with SAR s/$op/$np/."); + &::notice($who, "Moving item '$news' to '$mod_news' with SAR s/$op/$np/."); foreach (keys %{ $::news{$chan}{$news} }) { $::news{$chan}{$mod_news}{$_} = $::news{$chan}{$news}{$_}; delete $::news{$chan}{$news}{$_}; @@ -452,7 +568,7 @@ sub mod { } if ($mod_nnews ne $nnews) { # news Text/Description. - &::msg($::who, "Changing text for '$news' SAR s/$op/$np/."); + &::notice($who, "Changing text for '$news' SAR s/$op/$np/."); if ($mod_news ne $news) { $::news{$chan}{$mod_news}{Text} = $mod_nnews; } else { @@ -462,37 +578,41 @@ sub mod { return; } else { - &::msg($::who, "error: that regex failed ;("); + &::notice($who, "error: that regex failed ;("); return; } - &::msg($::who, "error: Invalid regex. Try s/1/2/, s#3#4#..."); + &::notice($who, "error: Invalid regex. Try s/1/2/, s#3#4#..."); } sub set { my($args) = @_; - $args =~ /^(\S+)\s+(\S+)\s+(.*)$/; - my($item, $what, $value) = ($1,$2,$3); + my($item, $what, $value); + + if (!defined $args) { + &::DEBUG("news: set: args == NULL."); + return; + } - &::DEBUG("set called."); + $item = $1 if ($args =~ s/^(\S+)\s*//); + $what = $1 if ($args =~ s/^(\S+)\s*//); + $value = $args; if ($item eq "") { &::help("news set"); return; } - &::DEBUG("item => '$item'."); my $news = &getNewsItem($item); - &::DEBUG("news => '$news'"); if (!defined $news) { - &::msg($::who, "Could not find item '$item' substring or # in news list."); + &::notice($who, "Could not find item '$item' substring or # in news list."); return; } # list all values for chan. - if (!defined $what) { - &::DEBUG("set: 1"); + if (!defined $what or $what =~ /^\s*$/) { + &::msg($who, "set: you didn't fill me on the arguments! (what and values)"); return; } @@ -506,18 +626,18 @@ sub set { } if (!$ok) { - &::msg($::who, "Invalid set. Try: @elements"); + &::notice($who, "Invalid set. Try: @elements"); return; } # show (read) what. - if (!defined $value) { - &::DEBUG("set: 2"); + if (!defined $value or $value =~ /^\s*$/) { + &::msg($who, "set: you didn't fill me on the arguments! (value)"); return; } if (!exists $::news{$chan}{$news}) { - &::msg($::who, "news '$news' does not exist"); + &::notice($who, "news '$news' does not exist"); return; } @@ -548,21 +668,22 @@ sub set { } if (!$time or ($value and $value !~ /^never$/i)) { - &::DEBUG("set: Expire... need to parse."); + &::DEBUG("news: set: Expire... need to parse."); + &::msg($who, "hrm... couldn't parse that."); return; } if ($time == -1) { - &::msg($::who, "Set never expire for \002$item\002." ); + &::notice($who, "Set never expire for \002$item\002." ); } elsif ($time < -1) { - &::DEBUG("time should never be negative ($time)."); + &::DEBUG("news: time should never be negative ($time)."); return; } else { - &::msg($::who, "Set expire for \002$item\002, to ". - localtime($time) ." [".&::Time2String($time - time())."]" ); + &::notice($who, "Set expire for \002$item\002, to ". + gmtime($time) ." [".&::Time2String($time - time())."]" ); if (time() > $time) { - &::DEBUG("hrm... time() > $time, should expire."); + &::DEBUG("news: hrm... time() > $time, should expire."); } } @@ -573,12 +694,12 @@ sub set { } my $auth = 0; - &::DEBUG("who => '$::who'"); +# &::DEBUG("news: who => '$who'"); my $author = $::news{$chan}{$news}{Author}; $auth++ if ($::who eq $author); $auth++ if (&::IsFlag("o")); if (!defined $author) { - &::DEBUG("news{$chan}{$news}{Author} is not defined! auth'd anyway"); + &::DEBUG("news: news{$chan}{$news}{Author} is not defined! auth'd anyway"); $::news{$chan}{$news}{Author} = $::who; $author = $::who; $auth++; @@ -586,70 +707,155 @@ sub set { if (!$auth) { # todo: show when it'll expire. - &::msg($::who, "Sorry, you cannot set items. (author $author owns it)"); + &::notice($who, "Sorry, you cannot set items. (author $author owns it)"); return; } # todo: clean this up. my $old = $::news{$chan}{$news}{$what}; if (defined $old) { - &::DEBUG("old => $old."); + &::DEBUG("news: old => $old."); } $::news{$chan}{$news}{$what} = $value; - &::msg($::who, "Setting [$chan]/{$news}/<$what> to '$value'."); + &::notice($who, "Setting [$chan]/{$news}/<$what> to '$value'."); } sub latest { - my($tchan, $flag) = @_; + my ($tchan, $flag) = @_; - $chan ||= $tchan; # hack hack hack. + # hack hack hack. fix later. + $chan = $tchan; + $who = $::who; # todo: if chan = undefined, guess. - if (!exists $::news{$chan}) { - &::msg($::who, "invalid chan $chan"); +# if (!exists $::news{$chan}) { + if (!exists $::channels{$chan}) { + &::notice($who, "invalid chan $chan") if ($flag); + return; + } + + my $t = $::newsuser{$chan}{$who}; +# if (defined $t) { +# &::DEBUG("newsuser: $chan/$who == $t"); +# } else { +# &::DEBUG("newsuser: $chan/$who == undefined"); +# } + + if (defined $t and ($t == 0 or $t == -1)) { + if ($flag) { + &::notice($who, "if you want to read news, try \002/msg $::ident news $chan\002 or \002/msg $::ident news $chan notify\002"); + } else { + &::DEBUG("news: not displaying any new news for $who"); + return; + } + } + + $::chan = $chan; + my $x = &::IsChanConf("newsNotifyAll"); + return if (!$x); + + # I don't understand this code ;) + $t = 1 if (!defined $t); + + if (!defined $t) { +# &::msg($who, "News is disabled for $chan"); + &::DEBUG("news: $chan: something went really wrong."); return; } my @new; foreach (keys %{ $::news{$chan} }) { - my $t = $::newsuser{$chan}{$::who}; next if (!defined $t); next if ($t > $::news{$chan}{$_}{Time}); + # don't list new items if they don't have Text. + if (!exists $::news{$chan}{$_}{Text}) { + if (time() - $::news{$chan}{$_}{Time} > 60*60*24*3) { + &::DEBUG("deleting news{$chan}{$_} because it was too old and had no text info."); + delete $::news{$chan}{$_}; + } + + next; + } + push(@new, $_); } + # !scalar @new, $flag if (!scalar @new and $flag) { - &::msg($::who, "no new news for $chan."); + &::notice($who, "no new news for $chan for $who."); + # valid to set this? + $::newsuser{$chan}{$who} = time(); + return; + } + + # scalar @new, !$flag + my $unread = scalar @new; + my $total = scalar keys %{ $::news{$chan} }; + if (!$flag && !&::IsChanConf("newsTellUnread")) { return; } if (!$flag) { - my $unread = scalar @new; - my $total = scalar keys %{ $::news{$chan} }; - &::msg($::who, "There are unread news in $chan ($unread unread, $total, total). /msg $::ident news latest"); + return unless ($unread); + + # just a temporary measure not to flood ourself off the + # network with news until we get global notice() and msg() + # throttling. + if (time() - ($::cache{newsTime} || 0) < 5) { + &::status("news: not displaying latest notice to $who/$chan."); + return; + } + + $::cache{newsTime} = time(); + my $reply = "There are unread news in $chan ($unread unread, $total total). /msg $::ident news $::chan latest"; + $reply .= " If you don't want further news notification, /msg $::ident news unnotify" if ($unread == $total); + &::notice($who, $reply); + return; } + # scalar @new, $flag if (scalar @new) { - &::msg($::who, "+==== New news for \002$chan\002 (". - scalar(@new)." new items):"); + &::notice($who, "+==== New news for \002$chan\002 ($unread new; $total total):"); - my $timestr = &::Time2String( time() - $::newsuser{$chan}{$::who} ); - &::msg($::who, "|= Last time read $timestr ago"); + my $t = $::newsuser{$chan}{$who}; + if (defined $t and $t > 1) { + my $timestr = &::Time2String( time() - $t ); + &::notice($who, "|= Last time read $timestr ago"); + } + my $i; + my @sorted; foreach (@new) { - my $i = &newsS2N($_); - my $age = time() - $::news{$chan}{$_}{Time}; - &::msg($::who, sprintf("\002[\002%2d\002]\002 %s", - $i, $_) ); -# $i, $_, &::Time2String($age) ) ); + $i = &newsS2N($_); + $sorted[$i] = $_; + } + + for ($i=0; $i<=scalar(@sorted); $i++) { + my $news = $sorted[$i]; + next unless (defined $news); + +# my $age = time() - $::news{$chan}{$news}{Time}; + my $msg = sprintf("\002[\002%2d\002]\002 %s", $i, $news); +### $i, $_, &::Time2String($age) + $::conn->schedule(int((2+$i)/2), sub { + &::notice($who, $msg); + } ); } - &::msg($::who, "|= to read, do 'news read <#>' or 'news read '"); + # todo: implement throttling via schedule into ¬ice() / &msg(). + $::conn->schedule(int((2+$i)/2), sub { + &::notice($who, "|= to read, do \002news $chan read <#>\002 or \002news $chan read \002"); + } ); # lame hack to prevent dupes if we just ignore it. - $::newsuser{$chan}{$::who} = time(); + my $x = $::newsuser{$chan}{$who}; + if (defined $x and ($x == 0 or $x == -1)) { + &::DEBUG("news: not updating time for $who. (2)"); + } else { + $::newsuser{$chan}{$who} = time(); + } } } @@ -673,6 +879,7 @@ sub getNewsAll { sub newsS2N { my($what) = @_; + my $item = 0; my @items; my $no; @@ -681,7 +888,7 @@ sub newsS2N { my $t = $::news{$chan}{$_}{Time}; if (!defined $t or $t !~ /^\d+$/) { - &::DEBUG("warn: t is undefined for news{$chan}{$_}{Time}; removing item."); + &::DEBUG("news: warn: t is undefined for news{$chan}{$_}{Time}; removing item."); delete $::news{$chan}{$_}; next; } @@ -701,12 +908,14 @@ sub getNewsItem { my($what) = @_; my $item = 0; + $what =~ s/^\#//; # '#1' for example. + my %time; foreach (keys %{ $::news{$chan} }) { my $t = $::news{$chan}{$_}{Time}; if (!defined $t or $t !~ /^\d+$/) { - &::DEBUG("warn: t is undefined for news{$chan}{$_}{Time}; removing item."); + &::DEBUG("news: warn: t is undefined for news{$chan}{$_}{Time}; removing item."); delete $::news{$chan}{$_}; next; } @@ -730,36 +939,35 @@ sub getNewsItem { foreach (sort { $a <=> $b } keys %time) { $item++; # $no = $item if ($time{$_} eq $what); - if ($time{$_} eq $what) { - $no = $item; - next; - } +## if ($time{$_} eq $what) { +## $no = $item; +## next; +## } push(@items, $time{$_}) if ($time{$_} =~ /\Q$what\E/i); } - if (defined $no and !@items) { - &::DEBUG("string->number resolution: $what->$no."); - return $no; - } +## if (defined $no and !@items) { +## &::DEBUG("news: string->number resolution: $what->$no."); +## return $no; +## } if (scalar @items > 1) { - &::DEBUG("Multiple matches, not guessing."); - &::msg($::who, "Multiple matches, not guessing."); + &::DEBUG("news: Multiple matches, not guessing."); + &::notice($who, "Multiple matches, not guessing."); return; } - &::DEBUG("gNI: part_string->full_string: $what->$items[0]"); if (@items) { - &::DEBUG("gNI: Guessed '$items[0]'."); +# &::DEBUG("news: gNI: part_string->full_string: $what->$items[0]"); return $items[0]; } else { - &::DEBUG("gNI: No match."); + &::DEBUG("news: gNI: No match for '$what'"); return; } } - &::ERROR("getNewsItem: Should not happen (what = $what)"); + &::ERROR("news: gNI: should not happen (what = $what)"); return; } @@ -767,20 +975,57 @@ sub do_set { my($what,$value) = @_; if (!defined $chan) { - &::DEBUG("do_set: chan not defined."); + &::DEBUG("news: do_set: chan not defined."); return; } if (!defined $what or $what =~ /^\s*$/) { - &::DEBUG("what $what is not defined."); + &::DEBUG("news: what $what is not defined."); return; } + if (!defined $value or $value =~ /^\s*$/) { - &::DEBUG("value $value is not defined."); + &::DEBUG("news: value $value is not defined."); return; } - &::DEBUG("do_set: TODO..."); + &::DEBUG("news: do_set: TODO..."); +} + +sub stats { + &::DEBUG("News: stats called."); + &::msg($who, "check my logs/console."); + my($i,$j) = (0,0); + + # total request count. + foreach $chan (keys %::news) { + foreach (keys %{ $::news{$chan} }) { + $i += $::news{$chan}{$_}{Request_Count}; + } + } + &::DEBUG("news: stats: total request count => $i"); + $i = 0; + + # total user cached. + foreach $chan (keys %::newsuser) { + $i += $::newsuser{$chan}{$_}; + } + &::DEBUG("news: stats: total user cache => $i"); + $i = 0; + + # average latest time read. + my $t = time(); + foreach $chan (keys %::newsuser) { + $i += $t - $::newsuser{$chan}{$_}; + &::DEBUG(" i = $i"); + $j++; + } + &::DEBUG("news: stats: average latest time read: total time: $i"); + &::DEBUG("news: ... count: $j"); + &::DEBUG("news: average: ".sprintf("%.02f", $i/($j||1))." sec/user"); + $i = $j = 0; } +sub AUTOLOAD { &::AUTOLOAD(@_); } + 1;