X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2FModules%2FNews.pl;h=caee5f104751e0fab85324b543997dfecb8f4292;hb=f7cae48a17d6decd0a9bd997188271daa0a885b1;hp=c9d0d580c06cecd7563ab43efb70925548354024;hpb=b6accd0ec31c9e167c396b7d6db73ce9d47815ad;p=infobot.git diff --git a/src/Modules/News.pl b/src/Modules/News.pl index c9d0d58..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! # @@ -15,10 +15,12 @@ # Text - Actual text. ### -use vars qw($who); - package News; +use strict; + +use vars qw($who $chan); + sub Parse { my($what) = @_; $chan = undef; @@ -42,26 +44,26 @@ sub Parse { $chan = lc $1; if (!&::IsNickInChan($who, $chan)) { - &::notice($::who, "sorry but you're not on $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) { - &::notice($::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) { - &::notice($::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]; - &::VERB("Guessed $::who being on chan $chan",2); + &::VERB("Guessed $who being on chan $chan",2); $::chan = $chan; # hack for IsChanConf(). } @@ -102,14 +104,15 @@ sub Parse { } 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!"); + &::msg($who, "newsflush called... check out the logs!"); &::newsFlush(); } elsif ($what =~ /^(un)?notify$/i) { @@ -118,31 +121,31 @@ sub Parse { # 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."); + &::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."); + &::notice($who, "enabled notify."); delete $::newsuser{$chan}{$who}; return; } - &::notice($::who, "already enabled."); + &::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"); + &::notice($who, "notify already disabled"); return; } $::newsuser{$chan}{$who} = -1; - &::notice($::who, "notify is now disabled."); + &::notice($who, "notify is now disabled."); } } else { - &::notice($::who, "unknown command: $what"); + &::notice($who, "unknown command: $what"); } } @@ -192,11 +195,13 @@ sub readNews { close NEWS; my $cn = scalar(keys %::news); - &::status("News: Read ". + return unless ($ci or $cn or $cu); + + &::status("News: read ". $ci. &::fixPlural(" item", $ci). " for ". $cn. &::fixPlural(" chan", $cn). ", ". $cu. &::fixPlural(" user", $cu), " cache" - ) if ($ci or $cn or $cu); + ); } sub writeNews { @@ -205,10 +210,11 @@ sub writeNews { 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; } @@ -221,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} }; @@ -228,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"; } @@ -263,27 +271,27 @@ sub add { } if (length $str > 64) { - &::notice($::who, "That's not really an item (>64chars)"); + &::notice($who, "That's not really an item (>64chars)"); return; } if (exists $::news{$chan}{$str}{Time}) { - &::notice($::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); - &::notice($::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."); - &::notice($::who, "Now do 'news text $item '"); - &::notice($::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(); @@ -301,12 +309,12 @@ sub del { if ($what =~ /^\d+$/) { my $count = scalar keys %{ $::news{$chan} }; if (!$count) { - &::notice($::who, "No news for $chan."); + &::notice($who, "No news for $chan."); return; } if ($what > $count or $what < 0) { - &::notice($::who, "$what is out of range (max $count)"); + &::notice($who, "$what is out of range (max $count)"); return; } @@ -325,12 +333,12 @@ sub del { } if (!scalar @found) { - &::notice($::who, "could not find $what."); + &::notice($who, "could not find $what."); return; } if (scalar @found > 1) { - &::notice($::who, "too many matches for $what."); + &::notice($who, "too many matches for $what."); return; } @@ -346,20 +354,20 @@ sub del { if (!$auth) { # todo: show when it'll expire. - &::notice($::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; } - &::notice($::who, "ok, deleted '$what' from \002$chan\002..."); + &::notice($who, "ok, deleted '$what' from \002$chan\002..."); delete $::news{$chan}{$what}; } else { - &::notice($::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} }) { - &::notice($::who, "No News for \002$chan\002."); + &::notice($who, "No news for \002$chan\002."); return; } @@ -367,10 +375,10 @@ sub list { my $x = $::newsuser{$chan}{$who}; if (defined $x and ($x == 0 or $x == -1)) { - &::DEBUG("news: not updating time for $::who."); + &::DEBUG("news: not updating time for $who."); } else { if (!scalar keys %{ $::news{$chan} }) { - &::DEBUG("news: should not add $chan/$::who to cache!"); + &::DEBUG("news: should not add $chan/$who to cache!"); } $::newsuser{$chan}{$who} = time(); @@ -379,20 +387,33 @@ sub list { # ¬ice() breaks OPN :( - using msg() instead! my $count = scalar keys %{ $::news{$chan} }; - &::msg($::who, "|==== News for \002$chan\002: ($count items)"); + &::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("news: warn: subtopic == undef."); @@ -400,13 +421,20 @@ sub list { } # 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 { @@ -418,22 +446,31 @@ sub read { } if (!scalar keys %{ $::news{$chan} }) { - &::notice($::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} }) { - &::notice($::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}) { - &::notice($::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); @@ -455,16 +492,16 @@ sub read { my $e; if ($_) { $e = sprintf("\037%s\037 [%s from now]", - scalar(localtime($_)), + 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); + &::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(); @@ -494,7 +531,7 @@ sub mod { my ($delim, $op, $np, $flags) = ($1,$2,$3,$4); if ($flags !~ /^(g)?$/) { - &::notice($::who, "error: Invalid flags to regex."); + &::notice($who, "error: Invalid flags to regex."); return; } @@ -505,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) { - &::notice($::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}) { - &::notice($::who, "item '$mod_news' already exists."); + &::notice($who, "item '$mod_news' already exists."); return; } - &::notice($::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}{$_}; @@ -531,7 +568,7 @@ sub mod { } if ($mod_nnews ne $nnews) { # news Text/Description. - &::notice($::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 { @@ -541,23 +578,26 @@ sub mod { return; } else { - &::notice($::who, "error: that regex failed ;("); + &::notice($who, "error: that regex failed ;("); return; } - &::notice($::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) = @_; my($item, $what, $value); + if (!defined $args) { + &::DEBUG("news: set: args == NULL."); + return; + } + $item = $1 if ($args =~ s/^(\S+)\s*//); $what = $1 if ($args =~ s/^(\S+)\s*//); $value = $args; - &::DEBUG("news: set called."); - if ($item eq "") { &::help("news set"); return; @@ -566,13 +606,13 @@ sub set { my $news = &getNewsItem($item); if (!defined $news) { - &::notice($::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 or $what =~ /^\s*$/) { - &::msg($::who, "set: you didn't fill me on the arguments! (what and values)"); + &::msg($who, "set: you didn't fill me on the arguments! (what and values)"); return; } @@ -586,18 +626,18 @@ sub set { } if (!$ok) { - &::notice($::who, "Invalid set. Try: @elements"); + &::notice($who, "Invalid set. Try: @elements"); return; } # show (read) what. if (!defined $value or $value =~ /^\s*$/) { - &::msg($::who, "set: you didn't fill me on the arguments! (value)"); + &::msg($who, "set: you didn't fill me on the arguments! (value)"); return; } if (!exists $::news{$chan}{$news}) { - &::notice($::who, "news '$news' does not exist"); + &::notice($who, "news '$news' does not exist"); return; } @@ -629,18 +669,18 @@ sub set { if (!$time or ($value and $value !~ /^never$/i)) { &::DEBUG("news: set: Expire... need to parse."); - &::msg($::who, "hrm... couldn't parse that."); + &::msg($who, "hrm... couldn't parse that."); return; } if ($time == -1) { - &::notice($::who, "Set never expire for \002$item\002." ); + &::notice($who, "Set never expire for \002$item\002." ); } elsif ($time < -1) { &::DEBUG("news: time should never be negative ($time)."); return; } else { - &::notice($::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("news: hrm... time() > $time, should expire."); @@ -654,7 +694,7 @@ sub set { } my $auth = 0; - &::DEBUG("news: who => '$::who'"); +# &::DEBUG("news: who => '$who'"); my $author = $::news{$chan}{$news}{Author}; $auth++ if ($::who eq $author); $auth++ if (&::IsFlag("o")); @@ -667,7 +707,7 @@ sub set { if (!$auth) { # todo: show when it'll expire. - &::notice($::who, "Sorry, you cannot set items. (author $author owns it)"); + &::notice($who, "Sorry, you cannot set items. (author $author owns it)"); return; } @@ -677,43 +717,49 @@ sub set { &::DEBUG("news: old => $old."); } $::news{$chan}{$news}{$what} = $value; - &::notice($::who, "Setting [$chan]/{$news}/<$what> to '$value'."); + &::notice($who, "Setting [$chan]/{$news}/<$what> to '$value'."); } sub latest { - my($tchan, $flag) = @_; + my ($tchan, $flag) = @_; - # hack hack hack. - $chan ||= $tchan; - $who ||= $::who; + # hack hack hack. fix later. + $chan = $tchan; + $who = $::who; # todo: if chan = undefined, guess. # if (!exists $::news{$chan}) { if (!exists $::channels{$chan}) { - &::notice($::who, "invalid chan $chan") if ($flag); + &::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 /msg $::ident news or /msg $::ident news notify"); + &::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"); + &::DEBUG("news: not displaying any new news for $who"); return; } } $::chan = $chan; my $x = &::IsChanConf("newsNotifyAll"); - if (&::IsChanConf("newsNotifyAll") and !defined $t) { - $t = 1; - } + return if (!$x); + + # I don't understand this code ;) + $t = 1 if (!defined $t); if (!defined $t) { - &::DEBUG("news: something went really wrong."); - &::DEBUG("news: chan => $chan, ::chan => $::chan"); -# &::notice($::who, "something went really wrong."); +# &::msg($who, "News is disabled for $chan"); + &::DEBUG("news: $chan: something went really wrong."); return; } @@ -737,55 +783,76 @@ sub latest { # !scalar @new, $flag if (!scalar @new and $flag) { - &::notice($::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) { 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); + &::notice($who, $reply); return; } # scalar @new, $flag if (scalar @new) { - &::notice($::who, "+==== New news for \002$chan\002 ($unread new; $total total):"); + &::notice($who, "+==== New news for \002$chan\002 ($unread new; $total total):"); my $t = $::newsuser{$chan}{$who}; if (defined $t and $t > 1) { my $timestr = &::Time2String( time() - $t ); - &::notice($::who, "|= Last time read $timestr ago"); + &::notice($who, "|= Last time read $timestr ago"); } + my $i; my @sorted; foreach (@new) { - my $i = &newsS2N($_); + $i = &newsS2N($_); $sorted[$i] = $_; } - for (my $i=0; $i<=scalar(@sorted); $i++) { + for ($i=0; $i<=scalar(@sorted); $i++) { my $news = $sorted[$i]; next unless (defined $news); - my $age = time() - $::news{$chan}{$news}{Time}; - &::notice($::who, sprintf("\002[\002%2d\002]\002 %s", - $i, $news) ); -# $i, $_, &::Time2String($age) ) ); +# 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); + } ); } - &::notice($::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. my $x = $::newsuser{$chan}{$who}; if (defined $x and ($x == 0 or $x == -1)) { - &::DEBUG("news: not updating time for $::who. (2)"); + &::DEBUG("news: not updating time for $who. (2)"); } else { $::newsuser{$chan}{$who} = time(); } @@ -841,6 +908,8 @@ sub getNewsItem { my($what) = @_; my $item = 0; + $what =~ s/^\#//; # '#1' for example. + my %time; foreach (keys %{ $::news{$chan} }) { my $t = $::news{$chan}{$_}{Time}; @@ -885,12 +954,12 @@ sub getNewsItem { if (scalar @items > 1) { &::DEBUG("news: Multiple matches, not guessing."); - &::notice($::who, "Multiple matches, not guessing."); + &::notice($who, "Multiple matches, not guessing."); return; } if (@items) { - &::DEBUG("news: gNI: part_string->full_string: $what->$items[0]"); +# &::DEBUG("news: gNI: part_string->full_string: $what->$items[0]"); return $items[0]; } else { &::DEBUG("news: gNI: No match for '$what'"); @@ -898,7 +967,7 @@ sub getNewsItem { } } - &::ERROR("getNewsItem: Should not happen (what = $what)"); + &::ERROR("news: gNI: should not happen (what = $what)"); return; } @@ -925,7 +994,7 @@ sub do_set { sub stats { &::DEBUG("News: stats called."); - &::msg($::who, "check my logs/console."); + &::msg($who, "check my logs/console."); my($i,$j) = (0,0); # total request count. @@ -957,4 +1026,6 @@ sub stats { $i = $j = 0; } +sub AUTOLOAD { &::AUTOLOAD(@_); } + 1;