### NEWS:
if (&IsChanConf("news") && &IsChanConf("newsKeepRead")) {
- my @new;
- foreach (keys %{ $::news{$chan} }) {
- my $t = $::newsuser{$chan}{$who};
- next if (!defined $t);
- next if ($t > $::news{$chan}{$_}{Time});
-
- push(@new, $_);
- }
-
- if (scalar @new) {
- &msg($who, "+==== New news for $chan (".scalar(@new)."):");
- # todo: show how many sec/min/etc ago?
- my $timestr = &Time2String( time() - $::newsuser{$chan}{$who} );
- &msg($who, "|= Last time read $timestr ago");
-
- foreach (@new) {
- my $i = &News::getNewsItem($_);
- my $age = time() - $::news{$chan}{$_}{Time};
- &msg($who, sprintf("\002[\002%2d\002]\002 %s (%s)",
- $i, $_, &Time2String($age) ) );
- }
- &msg($who, "to read, do 'news read <#>' or 'news read <keyword>'");
-
- # lame hack to prevent dupes if we just ignore it.
- $::newsuser{$chan}{$who} = time();
- }
+ # todo: what if it hasn't been loaded?
+ &News::latest($chan);
}
### chanlimit check.
if ($nick eq $ident) { # hopefully ourselves.
if ($msg eq "TEST") {
- &status("Local: Yes, we're alive.");
+ &status("IRCTEST: Yes, we're alive.");
delete $cache{connect};
return;
}
while (1) {
($key,$val) = &randKey("factoids","factoid_key,factoid_value");
### $val =~ tr/^[A-Z]/[a-z]/; # blah is Good => blah is good.
- last if ($val !~ /^</);
+ last if (defined $val and $val !~ /^</);
+
$error++;
if ($error == 5) {
&ERROR("rF: tried 5 times but failed.");
foreach $item (keys %{ $::news{$chan} }) {
my $t = $::news{$chan}{$item}{Expire};
+ my $tadd = $::news{$chan}{$item}{Time};
+ $oldest = $tadd if ($oldest > $tadd);
+
next if ($t == 0 or $t == -1);
if ($t < 1000) {
&status("newsFlush: Fixed Expire time for $chan/$item, should not happen anyway.");
next;
}
- $oldest = $t if ($t < $oldest);
-
next unless (time() > $t);
# todo: show how old it was.
delete $::news{$chan}{$item};
if ($param{'DBType'} =~ /^mysql|pg|postgres/i) {
foreach $nick (keys %seencache) {
+ if (0) {
+ my $retval = &dbReplace("seen", $nick, (
+ "nick" => $seencache{$nick}{'nick'},
+ "time" => $seencache{$nick}{'time'},
+ "host" => $seencache{$nick}{'host'},
+ "channel" => $seencache{$nick}{'chan'},
+ "message" => $seencache{$nick}{'msg'},
+ ) );
+ &DEBUG("retval => $retval.");
+ delete $seencache{$nick};
+ $flushed++;
+
+ next;
+ }
+ ### OLD CODE...
+
my $exists = &dbGet("seen","nick", $nick, "nick");
if (defined $exists and $exists) {
&ircloop();
delete $cache{connect};
} else {
- &DEBUG("possible lost in space; checking.");
+ &status("IRCTEST: possible lost in space; checking. ".
+ scalar(localtime) );
&msg($ident, "TEST");
$cache{connect} = time();
}
next if (time() - $time < 60*60);
} else {
- &DEBUG("shm: $shmid is not ours or old blootbot => ($z)");
+# &DEBUG("shm: $shmid is not ours or old blootbot => ($z)");
# next;
}
if ( -e "$file~" ) {
$backup++ if ( -s $file > -s "$file~");
- $backup++ if ( (stat $file)[9] - (stat "$file~")[9] > $time);
+ $backup++ if ((stat $file)[9] - (stat "$file~")[9] > $time);
} else {
$backup++;
}
### TODO: do internal copying.
&status("Backup: $file to $file~");
CORE::system("/bin/cp $file $file~");
+ CORE::system("/bin/touch $file~"); # needed!
}
1;
$pkg{'info'} = "\002(\002". $pkg{'desc'} ."\002)\002";
$pkg{'info'} .= ", section ".$pkg{'section'};
$pkg{'info'} .= ", is ".$pkg{'priority'};
- $pkg{'info'} .= ". Version: \002$pkg{'version'}\002";
+# $pkg{'info'} .= ". Version: \002$pkg{'version'}\002";
+ $pkg{'info'} .= ". Version: \002$pkg{'version'}\002 ($dist)";
$pkg{'info'} .= ", Packaged size: \002". int($pkg{'size'}/1024) ."\002 kB";
$pkg{'info'} .= ", Installed size: \002$pkg{'installed'}\002 kB";
&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();
$::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 {
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.
&::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 @new;
+ foreach (keys %{ $::news{$chan} }) {
+ my $t = $::newsuser{$chan}{$::who};
+ 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 (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($_);
+ &::DEBUG("i = $i, _ => $_");
+ 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.
+ $::newsuser{$chan}{$::who} = time();
+ }
+}
+
###
### helpers...
###
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;
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);
}
# todo: split this command in the future into:
# full_string->number and number->string
# partial_string->full_string
+ &::DEBUG("no => $no, items => @items.");
if (defined $no and !@items) {
&::DEBUG("string->number resolution.");
return $no;
return;
}
+ &::DEBUG("gNI: string->number(??): $what->$items[0]");
if (@items) {
&::DEBUG("gNI: Guessed '$items[0]'.");
return $items[0];
}
}
+ # override msgType.
+ if ($msgType =~ /public/ and $message =~ s/^\+//) {
+ &status("found '+' flag; setting msgType to public.");
+ $force_public_reply++;
+ $msgType = 'public';
+ $who = $chan; # major hack to fix &msg().
+ &DEBUG("addressed => $addressed.");
+ }
+
# User Processing, for all users.
if ($addressed) {
my $retval;
### bot commands...
###
- # override msgType.
- if ($msgType =~ /public/ and $message =~ s/^\+//) {
- &status("found '+' flag; setting msgType to public.");
- $force_public_reply++;
- $msgType = 'public';
- }
-
if ($message =~ s/^literal\s+//i) {
&status("literal ask of '$message'.");
$literal = 1;
Help => 'nslookup', Identifier => 'allowDNS',
Forker => "NULL", ) );
&addCmdHook("main", 'tell|explain', ('CODEREF' => 'tell',
- Help => 'tell', Identifier => 'allowTelling', ) );
+ Help => 'tell', Identifier => 'allowTelling',
+ Cmdstats => 'Tell') );
&addCmdHook("main", 'news', ('CODEREF' => 'News::Parse',
Module => 'news', Identifier => 'news') );
return 1;
}
+#####
+# Usage: &dbReplace($table, $primkey, %hash);
+sub dbReplace {
+ my ($table, $primkey, %hash) = @_;
+ my (@keys, @vals);
+
+ foreach (keys %hash) {
+ &DEBUG("hash{$_} => $hash{$_}");
+ push(@keys, $_);
+ push(@vals, &dbQuote($hash{$_}));
+ }
+
+ &dbRaw("Replace($table)", "REPLACE INTO $table (".join(',',@keys).
+ ") VALUES (".join(',',@vals).")"
+ );
+
+ return 1;
+}
+
#####
# Usage: &dbSetRow($table, @values);
sub dbSetRow {
return;
}
- my $age = (stat $file)[9];
- return if ($age == $moduleAge{$file});
-
- if ($age < $moduleAge{$file}) {
- &WARN("rM: we're not gonna downgrade the file. use 'touch'.");
- return;
- }
-
if (grep /$mod/, @myModulesReloadNot) {
&DEBUG("rM: SHOULD NOT RELOAD $mod!!!");
return;
}
- my $dc = &Time2String($age - $moduleAge{$file});
- my $ago = &Time2String(time() - $moduleAge{$file});
+ my $age = (stat $file)[9];
+
+ if (!exists $moduleAge{$file}) {
+ &DEBUG("Looks like $file was not loaded; fixing.");
+ } else {
+ return if ($age == $moduleAge{$file});
+
+ if ($age < $moduleAge{$file}) {
+ &WARN("rM: we're not gonna downgrade the file. use 'touch'.");
+ return;
+ }
+
+ my $dc = &Time2String($age - $moduleAge{$file});
+ my $ago = &Time2String(time() - $moduleAge{$file});
+
+ &VERB("Module: delta change: $dc",2);
+ &VERB("Module: ago: $ago",2);
+ }
&status("Module: Loading $mod...");
- &VERB("Module: delta change: $dc",2);
- &VERB("Module: ago: $ago",2);
delete $INC{$file};
eval "require \"$file\""; # require or use?