]> git.donarmstrong.com Git - infobot.git/blobdiff - src/Modules/News.pl
news: can make news compulsory (chanset +newsNotifyAll)
[infobot.git] / src / Modules / News.pl
index b2f8b119780c259430955192753454d0cbd7c98f..6a4d30f0d591a60d64f11493d531250d8a624cc1 100644 (file)
@@ -1,14 +1,14 @@
 #
 # News.pl: Advanced news management
 #   Author: dms
-#  Version: v0.2 (20010326)
+#  Version: v0.3 (20014012)
 #  Created: 20010326
 #    Notes: Testing done by greycat, kudos!
 #
 ### structure:
-# news{ channel }{ string } { items }
+# news{ channel }{ string } { item }
 # newsuser{ channel }{ user } = time()
-### where items is:
+### where item is:
 #      Time    - when it was added (used for sorting)
 #      Author  - Who by.
 #      Expire  - Time to expire.
@@ -22,16 +22,15 @@ sub Parse {
     $chan      = undef;
 
     if (!keys %::news) {
-       if (!exists $cache{newsFirst}) {
+       if (!exists $::cache{newsFirst}) {
            &::DEBUG("looks like we enabled news option just then; loading up news file just in case.");
-           $cache{newsFirst} = 1;
+           $::cache{newsFirst} = 1;
        }
 
        &readNews();
     }
 
-    if ($::msgType eq "private") {
-    } else {
+    if ($::msgType ne "private") {
        $chan = $::chan;
     }
 
@@ -44,7 +43,7 @@ sub Parse {
        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.");
+           &::msg($::who, "error: I dunno which channel you are referring to since you're on more than one. Try 'news #chan ...' instead");
            return;
        }
 
@@ -64,27 +63,68 @@ 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.");
        &read($1);
+
     } elsif ($what =~ /^read(\s+(.*))?$/i) {
        &read($2);
+
+    } elsif ($what =~ /^(latest|new)(\s+(.*))?$/i) {
+       &::DEBUG("latest called... hrm");
+       &latest($3 || $chan, 1);
+
     } elsif ($what =~ /^list$/i) {
        &::DEBUG("list longcut called.");
        &list();
+
     } elsif ($what =~ /^(expire|text|desc)(\s+(.*))?$/i) {
        # shortcut/link.
        # nice hack.
        my($arg1,$arg2) = split(/\s+/, $3, 2);
        &set("$arg1 $1 $arg2");
+
     } elsif ($what =~ /^help(\s+(.*))?$/i) {
        &::help("news$1");
+
+    } elsif ($what =~ /^(un)?notify$/i) {
+       my $state = ($1) ? 0 : 1;
+
+       # todo: don't notify even if "news" is called.
+       if (!&::IsChanConf("newsNotifyAll")) {
+           &::msg($::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)) {
+               &::msg($::who, "enabled notify.");
+               delete $::newsuser{$chan}{$::who};
+               return;
+           }
+           &::msg($::who, "already enabled.");
+
+       } else {                # state = 0
+           my $x = $::newsuser{$chan}{$::who};
+           if (defined $x and ($x == 0 or $x == -1)) {
+               &::msg($::who, "notify already disabled");
+               return;
+           }
+           $::newsuser{$chan}{$::who} = -1;
+           &::msg($::who, "notify is now disabled.");
+       }
+
     } else {
        &::DEBUG("could not parse '$what'.");
        &::msg($::who, "unknown command: $what");
@@ -116,6 +156,7 @@ sub readNews {
                &::DEBUG("!defined item, never happen!");
                next;
            }
+
            $::news{$chan}{$item}{$1} = $2;
            next;
        }
@@ -218,16 +259,15 @@ sub add {
     $::news{$chan}{$str}{Author}       = $::who;
 
     my $agestr = &::Time2String($::news{$chan}{$str}{Expire} - time() );
-    my $item   = &getNewsItem($str);
-    if ($item eq $str) {
-       &::DEBUG("item eq str ($item): should never happen.");
-    }
+    my $item   = &newsS2N($str);
     &::msg($::who, "Added '\037$str\037' at [".localtime(time).
                "] by \002$::who\002 for item #\002$item\002.");
     &::msg($::who, "Now do 'news text $item <your_description>'");
     &::msg($::who, "This item will expire at \002".
        localtime($::news{$chan}{$str}{Expire})."\002 [$agestr from now] "
     );
+
+    &writeNews();
 }
 
 sub del {
@@ -251,9 +291,8 @@ sub del {
            return;
        }
 
-       $item = &getNewsItem($what);
-       &::DEBUG("del: num: item => $item ($what)");
-       $what   = $item;        # hack hack hack.
+       $item   = &getNewsItem($what);
+       $what   = $item;                # hack hack hack.
 
     } else {
        $_      = &getNewsItem($what);  # hack hack hack.
@@ -306,7 +345,13 @@ sub list {
     }
 
     if (&::IsChanConf("newsKeepRead")) {
-       $::newsuser{$chan}{$::who} = time();
+       my $x = $::newsuser{$chan}{$::who};
+
+       if (defined $x and ($x == 0 or $x == -1)) {
+           &::DEBUG("not updating time for $::who.");
+       } else {
+           $::newsuser{$chan}{$::who} = time();
+       }
     }
 
     &::msg($::who, "|==== News for \002$chan\002:");
@@ -352,7 +397,6 @@ sub read {
        return;
     }
 
-#    my $item  = (exists $::news{$chan}{$str}) ? $str : &getNewsItem($str);
     my $item   = &getNewsItem($str);
     if (!defined $item or !scalar keys %{ $::news{$chan}{$item} }) {
        &::msg($::who, "No news item called '$str'");
@@ -364,14 +408,28 @@ sub read {
        return;
     }
 
-    # todo: show item number.
-    # todo: show ago-time aswell?
-    # todo: show request stats aswell.
-    my $t = localtime($::news{$chan}{$item}{Time});
-    my $a = $::news{$chan}{$item}{Author};
-    &::msg($::who, "+- News \002$chan\002 ##, item '\037$item\037':");
+    my $t      = localtime( $::news{$chan}{$item}{Time} );
+    my $a      = $::news{$chan}{$item}{Author};
+    my $text   = $::news{$chan}{$item}{Text};
+    my $num    = &newsS2N($item);
+    my $rwho   = $::news{$chan}{$item}{Request_By} || $::who;
+    my $rcount = $::news{$chan}{$item}{Request_Count} || 0;
+
+    if (length $text < $::param{maxKeySize}) {
+       &::DEBUG("NEWS: Possible news->factoid redirection.");
+       my $f   = &::getFactoid($text);
+
+       if (defined $f) {
+           &::DEBUG("NEWS: ok, $text is factoid redirection.");
+           $f =~ s/^<REPLY>\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, $::news{$chan}{$item}{Text});
+    &::msg($::who, "| Requested $rcount times, last by $rwho");
+    &::msg($::who, $text);
 
     $::news{$chan}{$item}{'Request_By'}   = $::who;
     $::news{$chan}{$item}{'Request_Time'} = time();
@@ -576,6 +634,7 @@ sub set {
        return;
     }
 
+    # todo: clean this up.
     my $old = $::news{$chan}{$news}{$what};
     if (defined $old) {
        &::DEBUG("old => $old.");
@@ -584,6 +643,78 @@ sub set {
     &::msg($::who, "Setting [$chan]/{$news}/<$what> to '$value'.");
 }
 
+sub latest {
+    my($tchan, $flag) = @_;
+
+    $chan ||= $tchan;  # hack hack hack.
+
+    # todo: if chan = undefined, guess.
+    if (!exists $::news{$chan}) {
+       &::msg($::who, "invalid chan $chan");
+       return;
+    }
+
+    my $t = $::newsuser{$chan}{$::who};
+    if (defined $t and ($t == 0 or $t == -1)) {
+       &::DEBUG("not displaying any new news for $::who");
+       return;
+    }
+
+    my @new;
+    foreach (keys %{ $::news{$chan} }) {
+       if (&::IsChanConf("newsNotifyAll") and !defined $t) {
+           &::DEBUG("setting time for $::who to 1...");
+           $::newsuser{$chan}{$::who} = 1;
+           $t = 1;
+       }
+       next if (!defined $t);
+       next if ($t > $::news{$chan}{$_}{Time});
+
+       push(@new, $_);
+    }
+
+    if (!scalar @new and $flag) {
+       &::msg($::who, "no new news for $chan.");
+       return;
+    }
+
+    if (!$flag) {
+       my $unread      = scalar @new;
+       my $total       = scalar keys %{ $::news{$chan} };
+       return unless ($unread);
+
+       &::msg($::who, "There are unread news in $chan ($unread unread, $total total). /msg $::ident news latest.  If you don't want further news notification, /msg $::ident news unnotify");
+
+       return;
+    }
+
+    if (scalar @new) {
+       &::msg($::who, "+==== New news for \002$chan\002 (".
+               scalar(@new)." new items):");
+
+       my $timestr = &::Time2String( time() - $::newsuser{$chan}{$::who} );
+       &::msg($::who, "|= Last time read $timestr ago");
+
+       foreach (@new) {
+           my $i   = &newsS2N($_);
+           my $age = time() - $::news{$chan}{$_}{Time};
+           &::msg($::who, sprintf("\002[\002%2d\002]\002 %s",
+               $i, $_) );
+#              $i, $_, &::Time2String($age) ) );
+       }
+
+       &::msg($::who, "|= to read, do 'news read <#>' or 'news read <keyword>'");
+
+       # 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("not updating time for $::who. (2)");
+       } else {
+           $::newsuser{$chan}{$::who} = time();
+       }
+    }
+}
+
 ###
 ### helpers...
 ###
@@ -602,6 +733,32 @@ sub getNewsAll {
     return @items;
 }
 
+sub newsS2N {
+    my($what)  = @_;
+    my @items;
+    my $no;
+
+    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.");
+           delete $::news{$chan}{$_};
+           next;
+       }
+
+       $time{$t} = $_;
+    }
+
+    foreach (sort { $a <=> $b } keys %time) {
+       $item++;
+       return $item if ($time{$_} eq $what);
+    }
+
+    &::DEBUG("newsS2N($what): failed...");
+}
+
 sub getNewsItem {
     my($what)  = @_;
     my $item   = 0;
@@ -628,22 +785,23 @@ sub getNewsItem {
 
     } else {
        # partial string to full string resolution
+       # in some cases, string->number resolution.
 
        my @items;
        my $no;
        foreach (sort { $a <=> $b } keys %time) {
            $item++;
-           $no = $item if ($time{$_} eq $what);
+#          $no = $item if ($time{$_} eq $what);
+           if ($time{$_} eq $what) {
+               $no = $item;
+               next;
+           }
+
            push(@items, $time{$_}) if ($time{$_} =~ /\Q$what\E/i);
        }
 
-       # since we have so much built into this function, there is so
-       # many guesses we can make.
-       # todo: split this command in the future into:
-       #       full_string->number and number->string
-       #       partial_string->full_string
        if (defined $no and !@items) {
-           &::DEBUG("string->number resolution.");
+           &::DEBUG("string->number resolution: $what->$no.");
            return $no;
        }
 
@@ -653,6 +811,7 @@ sub getNewsItem {
            return;
        }
 
+       &::DEBUG("gNI: part_string->full_string: $what->$items[0]");
        if (@items) {
            &::DEBUG("gNI: Guessed '$items[0]'.");
            return $items[0];