+ &::notice($who, "Setting [$chan]/{$news}/<$what> to '$value'.");
+}
+
+sub latest {
+ my($tchan, $flag) = @_;
+
+ # hack hack hack.
+ $chan ||= $tchan;
+ $who = $::who;
+
+ # todo: if chan = undefined, guess.
+# 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");
+ if (&::IsChanConf("newsNotifyAll") and !defined $t) {
+ $t = 1;
+ }
+
+ if (!defined $t) {
+# &::msg($who, "News is disabled for $chan");
+ &::DEBUG("news: something went really wrong.");
+ &::DEBUG("news: chan => $chan.");
+ return;
+ }
+
+ my @new;
+ foreach (keys %{ $::news{$chan} }) {
+ 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) {
+ &::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);
+
+ return;
+ }
+
+ # scalar @new, $flag
+ if (scalar @new) {
+ &::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");
+ }
+
+ my $i;
+ my @sorted;
+ foreach (@new) {
+ $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);
+ } );
+ }
+
+ # 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 <keyword>\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)");
+ } else {
+ $::newsuser{$chan}{$who} = time();
+ }
+ }