]> git.donarmstrong.com Git - infobot.git/commitdiff
hide old cruft in cvs
authortimriker <timriker@c11ca15a-4712-0410-83d8-924469b57eb5>
Wed, 12 Nov 2003 00:15:07 +0000 (00:15 +0000)
committertimriker <timriker@c11ca15a-4712-0410-83d8-924469b57eb5>
Wed, 12 Nov 2003 00:15:07 +0000 (00:15 +0000)
git-svn-id: https://svn.code.sf.net/p/infobot/code/trunk/blootbot@881 c11ca15a-4712-0410-83d8-924469b57eb5

12 files changed:
doc/old/BUGS [deleted file]
doc/old/EXAMPLES [deleted file]
doc/old/FAQ [deleted file]
doc/old/TODO [deleted file]
doc/old/TODO_2000 [deleted file]
doc/old/TODO_2001 [deleted file]
doc/old/USAGE [deleted file]
doc/old/notes.txt [deleted file]
old/Freshmeat_I.pl [deleted file]
old/Freshmeat_II.pl [deleted file]
old/News.pl [deleted file]
old/dbm.pl [deleted file]

diff --git a/doc/old/BUGS b/doc/old/BUGS
deleted file mode 100644 (file)
index 72f3449..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-                       KNOWN PROBLEMS AND BUGS
-
-Problem #1:
-       'topic [#channel] shuffle' will produce 1 in n! (where n
-       is number of subtopics in topic. IS THIS CORRECT PROBABILITY?)
-       chance that it will be the same as before.
-
-       If someone wants to experiment a fix for this, do so.
-       Here is a hint:
-       'while (!defined $newtopic || $topic{$talkchannel} eq $newtopic) {'
-
-Problem #2: [UPDATED 20000224]
-       A race condition is observed if the topic is changed very
-       quickly. If the bot is told to change the topic twice but
-       has not received notification of the new topic before
-       changing to the second modification of the topic, it
-       would use the absolute first (0) topic as a reference,
-       therefore missing out on the first alteration of the
-       topic.
-
-       A very cheap solution exists. Edit IrcHooks.pl, search for
-       'topic', alter '1' to '0'. This will only cache topics made by the
-       bot (I hope). I have a faint feeling that bot-only topics are
-       stored elsewhere (history I think) but I'm not quite sure.
-
-       Yet another (ultimate and preferable) solution would be to have
-       topic queueing, altering the topic once the first alteration has
-       been done, changing the topic until the queue is empty. However,
-       topic floods will eventuate unfortunately. If a queue of 2 or more
-       is detected, no more topic changes are done until a time of
-       5-10seconds (how can this be done?). This is a challenge to
-       implement.
-
-Problem #3: 19991110
-       It appears that if the last string separated by a whitespace
-       of the topic will be chopped off (if it's "()") because the
-       ownership is null. At first I thought it was a bug in the regex
-       but it was okay. I guess it's a minor problem but why should
-       there be a semi-ownerless subtopic :) If it's annoying, please
-       investigate the &topicCipher() function in Topic.pl in relation to
-       &topicDecipher().
-
-Problem #4: 199912xx
-       mysql overload...
-
-       DBD::mysql::st execute failed: Duplicate entry 'xk' for key 1 at
-       ./src/Freshmeat.pl line 85.
-       when freshmeat.pl is building the table and something's said in the
-       channel... seen code tries to update table but fails.
-
-       [UPDATE 20000224]
-       This may be eliminated by reducing 4-5 INSERT/UPDATE requests to
-       just 1 (total of 2), depending on the return of SELECT. If this
-       still persists and memory leaks are happening, first make
-       sure you are not using broken mysql tables, secondly bitch at the
-       mysql-perl author that there is a memory leak when a broken table
-       is in use.
-
-Problem #5:
-       doWarn is called when perl catches a "warning".
-
-       =>
-       [   44] !WARN! PERL: Use of uninitialized value at ./src/Modules.pl line 316.
-       [   45] !WARN! PERL: offending line => '        if ($query eq "") {'.
-       [   46] !DEBUG! test1.
-       [   47] !DEBUG! test2.
-       [   48] !DEBUG! test3.
-
-       ### From 'perlfunc'...
-       Note that this is quite safe and will not produce an endless loop,
-       since __WARN__ hooks are not called from inside one.
-
-       ### From 'perlvar'...
-       Note that __DIE__/__WARN__ handlers are very special in one
-       respect: they may be called to report (probable) errors found by
-       the parser.  In such a case the parser may be in inconsistent
-       state, so any attempt to evaluate Perl code from such a handler
-       will probably result in a segfault.
-
-Problem #6:
-!   14! Debian: 12.87 sec to complete query.
-!   15! </#debian-bots> Debian Search of 'testing' (2 shown): ...
-[   38] disconnect from irc.home.org (Connection reset by peer).
-[   39] reconnection... cleaning out channel cache.
-
-       Solution #6:
-               Edit /usr/lib/perl5/Net/IRC.pm
-               Comment out *->quit() on 'sub DESTROY'
-               Alternatively, bitch at author of Net::IRC.
-
-Problem #7: why...
-       <\ifvoid> apt, cellwave?
-       <apt> i haven't a clue, \ifvoid
-       <tapt> bugger all, i dunno, \ifvoid
-
-Problem #8:
-       <egamI-rorriM> apt: lart
-       * apt/#debian strangles  with a doohicky mouse cord
-
-Problem #9:
-       [Flugh] i say 'rom, rom is a mud server', it says 'ok'. then
-               'rom, rom?' it says 'yes? <nick>'
-
-# info package dist doesn't recognise dist.
diff --git a/doc/old/EXAMPLES b/doc/old/EXAMPLES
deleted file mode 100644 (file)
index ef12862..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-                               EXAMPLES
-                       last updated 16.03.2000
-                             written by xk
-
-<me> blootbot: test is testing
-<blootbot> me: okay
-<me> blootbot: testing?
-<blootbot> testing is testing
-
-<me> blootbot: tests is <REPLY> testing
-<blootbot> me: okay
-<me> blootbot: tests?
-<blootbot> testing
-
-<me> blootbot: cough is <ACTION> coughs
-<blootbot> me: okay
-<me> blootbot: cough
-* blootbot/#blootbot coughs
-
-<me> blootbot: test is <REPLY> What's (one|two|three|four|five|six)
-       times (seven|eight|nine|ten|eleven|twelve)?
-<blootbot> okay, me
-<me> blootbot: test
-<blootbot> What's four times nine?
-<me> blootbot: test?
-<blootbot> What's six times ten?
-
-<me> blootbot: op me is <ACTION> Mode change "+o $nick" on channel
-       $channel by $ident
-<blootbot> me: okay
-<me> blootbot: op me
-* blootbot/#debian-bots Mode change "+o me" on channel #blootbot by
-       blootbot
-
-<me> blootbot: no who am i is <REPLY> You are $nick!$user@$host on
-       $channel.
-<blootbot> okay, me
-<me> blootbot: who am i
-<blootbot> You are me!me@home.org on #blootbot.
-
-<me> blootbot: who last spoke is <REPLY> To my knowledge, $lastspeaker
-       was the last to say something worthwhile.
-<blootbot> me: okay
-<me> blootbot: who last spoke
-<blootbot> To my knowledge, me was the last to say something worthwhile.
-
-<me> blootbot: percentage is <REPLY> you are $randpercentage% lame
-<blootbot> me: okay
-<me> blootbot: percentage
-<blootbot> you are 79% lame
diff --git a/doc/old/FAQ b/doc/old/FAQ
deleted file mode 100644 (file)
index ac1aeef..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Q: The bot exits after I run 'factstats testing' or 'kernel' or anything
-   that uses fork(). Is this a bug in the bot?
-
-A: No, this is not a bug in the bot but rather Net::IRC.  A cheap hack is
-   to edit /usr/lib/perl5/Net/IRC/Connection.pm, search for DESTROY, and
-   comment out '$self->quit();'
-A: Apply the patches in the patches/ directory.
-
-
-Q: I notice that, in the bot logs, the bot attempts to close all current
-   DCC CHAT connections whenever a forked process ends. Why is this?
-
-A: Yet another bug in Net::IRC. Currently, DCC CHAT connections are not
-   closed because there is an endless-loop bug when it is done.
-
-
-Q: I executed 'scripts/setup_user.pl' but it said 'connection refused to
-   localhost'
-
-A: Looks like a bug in the installation of mysqld. You need to reload or
-   restart the daemon.
-       reload => 'mysqladmin -u root -p reload'
-       restart => '/etc/init.d/mysql stop; /etc/init.d/mysql start'
diff --git a/doc/old/TODO b/doc/old/TODO
deleted file mode 100644 (file)
index bc5e23f..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-######### TODO.
-### WISHLIST: SCHEDULER RELATED.
-- if topic -CMD is used, schedule the change for 10seconds later.
-  $schedule{topicchange}{$chan} = SID. use 'dequeue' to delete.
-- if 50% of netsplit victims come back, set a timer for 60seconds to
-  delete those who have not come back from the split.
-- make first run of schedulers skip so they don't run all at once.
-  use 'return' if (ref($_[0]) eq ???); => won't work?
-- use topic-queue for 'topic *'.
-- Add &schedulerAdd() and &schedulerDel();, &scheduleIsInQueue();
-- rename &ScheduleThis() to &scheduleAdd();
-
-### WISHLIST: COMMAND HOOKS.
-- play around with 'hook' idea, see header of CommandStubs.pl.
-- hook for ALL commands through MESSAGES.
-- factoids to take arguments such as $1 $2 ...
-  => check all factoids for hooks then append to hook list.
-
-### WISHLIST: OLDE DBM SUPPORT // PGSQL.
-- Thoroughly test both... core features done though.
-- make a sql_common.pl file for 90% common stuff between mysql/pgsql.
-- pgsql and mysql can be merged but I dunno anything about pgsql :)
-- PGSQL
-       - EVERYTHING
-- DBM
-       --- searchTable can be optimized by determining the correct offset
-           and use that from then on.
-       - Adding factoids [OK]
-       - Deleting factoids [OK]
-       - FactInfo [OK]
-       - Seen [OK]
-       - SearchTable [OK]      -- "%","*" supported?
-       - Countdown [???]
-       - Freshmeat [???]       -- &dbSetRow() should work, but slow.
-       - Factstats unrequested [???]
-
-### WISHLIST: SHOULD BE DONE...
-- Change ""return 'NOREPLY';"" to ""return $noreply;"".
-- make use of &status() in setup_*.pl
-- Add quotes (Finance::Quote) support.
-- Debian module doesn't search non-free or non-us properly.
-- send DCC message when using 'op'.
-- Schedule a 5min(??) interval to display stats in DCC
-  - kill if dcc chat == gone.
-  - add schedule list.
-- if 25lines are logged within 1 second, throttle it (sleep 1)
-- Add &botstatsUpdate() &botstatsGet();
-- Create startCheck(); for once off startup checks.
-- Max size of logs to keep.
-  - use Maxlogsize for both compressed and uncompressed.
-- split Process.pl's FactoidStuph() off to Factoids/FCommands.pl
-- time when last executed commands like fm,/. Useless?
-- if a dunno is issued, add an option to suggest a factiod
-       => IE: fm
-       - $fact =~ / blah|blah / or /\Wblah\W/ ??
-       - debian package. ??
-       - ...
-- add a function to evaluate channels
-  - ie: 'ALL', 'ALL but #blah', '#blah1 #blah2',
-  => Added &makeChanList() but not using it yet.
-- rename performStrictReply to performReplyAsIs() or something?
-- show current stats for top 3 requesters and top 3 requests.
-  => when seen is used, show last factoid/cmd asked
-- understand '\' in infobot.config.
-- Create a script to insert initial factoids like 'status','hello'...
-  like the dbm script in the old days.
-- Add 'heh' count, like on 'dpkg', to &on_public(). create generic table
-  to handle this and karma and probably total msg count. possibly
-  integrate with seen table?
-  .... UPDATE seen SET time=time+1 WHERE nick='xk';
-  .... ERROR 1064: parse error near '+1 WHERE nick='xk'' at line 1
-  => WHY?
-- support for 'find blah 6' for items 6 and more (since the list is
-  ordered). requested by jim.
-- support 'info package [dist] [section]', eg: 'info ssh non-free' or
-  support query for incoming, if dist!=incoming.
-- ...
-
-### WISHLIST: something to be desired...
-- 'tell' (Process.pl) to support commands.
-- reject '<REPLY> see' if redir factoid is too long.
-  need parsing of '||' and '(1|2|...)', too, for all possible
-  combinations (or permutations?).
-- download *.dsc and *.changes file to generate the Incoming Packages
-  file. This will be fun :)
-- Add 'OverwriteFromTxt' and other options for txt2mysql.pl.
-- Set some variable to say "yes, I'm quitting" to prevent log compression
-  since it imposes a perl warning "unreferenced scalar"...
-- Universal FROM<->TO conversion script for factoid table/db.
-### CLEAN UP
-- Split all the functions in Topic.pl to topic <COMMAND>. First chunk of
-  commands should be "Internal", the next chunk "Helpers" and the
-  last one is "Main".
-- Reduce number of global variables used.
-  => convert hash lists to arrays.
-  => convert scalar vars to hash lists.
-
-### CHALLENGE
-- Better method to store topics. Should be very similiar to the
-  joinnextchan code, but a topic queue. _however_, topic may be lost with
-  netsplit + stuff which is another problem, oh well.
-  How do IRC clients do it? set a timer for 0.5s before any changes?
-- Tree to show all variables in use. preliminary stuff there but
-  it's not all that helpful. good oreilly stuff in scripts/
-- Better netjoin detection code.
-- Allow X number of repetition of messages, default cannot be changed due
-  to simplicity of current code.
-
-### EXTERNAL BUGS:
-- Net::IRC doesn't know event 'pong'.
-
-### BROKEN:
-- babelfish
diff --git a/doc/old/TODO_2000 b/doc/old/TODO_2000
deleted file mode 100644 (file)
index bc5e23f..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-######### TODO.
-### WISHLIST: SCHEDULER RELATED.
-- if topic -CMD is used, schedule the change for 10seconds later.
-  $schedule{topicchange}{$chan} = SID. use 'dequeue' to delete.
-- if 50% of netsplit victims come back, set a timer for 60seconds to
-  delete those who have not come back from the split.
-- make first run of schedulers skip so they don't run all at once.
-  use 'return' if (ref($_[0]) eq ???); => won't work?
-- use topic-queue for 'topic *'.
-- Add &schedulerAdd() and &schedulerDel();, &scheduleIsInQueue();
-- rename &ScheduleThis() to &scheduleAdd();
-
-### WISHLIST: COMMAND HOOKS.
-- play around with 'hook' idea, see header of CommandStubs.pl.
-- hook for ALL commands through MESSAGES.
-- factoids to take arguments such as $1 $2 ...
-  => check all factoids for hooks then append to hook list.
-
-### WISHLIST: OLDE DBM SUPPORT // PGSQL.
-- Thoroughly test both... core features done though.
-- make a sql_common.pl file for 90% common stuff between mysql/pgsql.
-- pgsql and mysql can be merged but I dunno anything about pgsql :)
-- PGSQL
-       - EVERYTHING
-- DBM
-       --- searchTable can be optimized by determining the correct offset
-           and use that from then on.
-       - Adding factoids [OK]
-       - Deleting factoids [OK]
-       - FactInfo [OK]
-       - Seen [OK]
-       - SearchTable [OK]      -- "%","*" supported?
-       - Countdown [???]
-       - Freshmeat [???]       -- &dbSetRow() should work, but slow.
-       - Factstats unrequested [???]
-
-### WISHLIST: SHOULD BE DONE...
-- Change ""return 'NOREPLY';"" to ""return $noreply;"".
-- make use of &status() in setup_*.pl
-- Add quotes (Finance::Quote) support.
-- Debian module doesn't search non-free or non-us properly.
-- send DCC message when using 'op'.
-- Schedule a 5min(??) interval to display stats in DCC
-  - kill if dcc chat == gone.
-  - add schedule list.
-- if 25lines are logged within 1 second, throttle it (sleep 1)
-- Add &botstatsUpdate() &botstatsGet();
-- Create startCheck(); for once off startup checks.
-- Max size of logs to keep.
-  - use Maxlogsize for both compressed and uncompressed.
-- split Process.pl's FactoidStuph() off to Factoids/FCommands.pl
-- time when last executed commands like fm,/. Useless?
-- if a dunno is issued, add an option to suggest a factiod
-       => IE: fm
-       - $fact =~ / blah|blah / or /\Wblah\W/ ??
-       - debian package. ??
-       - ...
-- add a function to evaluate channels
-  - ie: 'ALL', 'ALL but #blah', '#blah1 #blah2',
-  => Added &makeChanList() but not using it yet.
-- rename performStrictReply to performReplyAsIs() or something?
-- show current stats for top 3 requesters and top 3 requests.
-  => when seen is used, show last factoid/cmd asked
-- understand '\' in infobot.config.
-- Create a script to insert initial factoids like 'status','hello'...
-  like the dbm script in the old days.
-- Add 'heh' count, like on 'dpkg', to &on_public(). create generic table
-  to handle this and karma and probably total msg count. possibly
-  integrate with seen table?
-  .... UPDATE seen SET time=time+1 WHERE nick='xk';
-  .... ERROR 1064: parse error near '+1 WHERE nick='xk'' at line 1
-  => WHY?
-- support for 'find blah 6' for items 6 and more (since the list is
-  ordered). requested by jim.
-- support 'info package [dist] [section]', eg: 'info ssh non-free' or
-  support query for incoming, if dist!=incoming.
-- ...
-
-### WISHLIST: something to be desired...
-- 'tell' (Process.pl) to support commands.
-- reject '<REPLY> see' if redir factoid is too long.
-  need parsing of '||' and '(1|2|...)', too, for all possible
-  combinations (or permutations?).
-- download *.dsc and *.changes file to generate the Incoming Packages
-  file. This will be fun :)
-- Add 'OverwriteFromTxt' and other options for txt2mysql.pl.
-- Set some variable to say "yes, I'm quitting" to prevent log compression
-  since it imposes a perl warning "unreferenced scalar"...
-- Universal FROM<->TO conversion script for factoid table/db.
-### CLEAN UP
-- Split all the functions in Topic.pl to topic <COMMAND>. First chunk of
-  commands should be "Internal", the next chunk "Helpers" and the
-  last one is "Main".
-- Reduce number of global variables used.
-  => convert hash lists to arrays.
-  => convert scalar vars to hash lists.
-
-### CHALLENGE
-- Better method to store topics. Should be very similiar to the
-  joinnextchan code, but a topic queue. _however_, topic may be lost with
-  netsplit + stuff which is another problem, oh well.
-  How do IRC clients do it? set a timer for 0.5s before any changes?
-- Tree to show all variables in use. preliminary stuff there but
-  it's not all that helpful. good oreilly stuff in scripts/
-- Better netjoin detection code.
-- Allow X number of repetition of messages, default cannot be changed due
-  to simplicity of current code.
-
-### EXTERNAL BUGS:
-- Net::IRC doesn't know event 'pong'.
-
-### BROKEN:
-- babelfish
diff --git a/doc/old/TODO_2001 b/doc/old/TODO_2001
deleted file mode 100644 (file)
index 5bdfc2e..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-CVS COMMIT:
-
-
-
-TODO:
-       - make sure scheduler design is _right_ - it's broken'ish.
-       - debian BTS frontend "bugs"
-       - !country
-       - !dinstall
-       - support DCC SEND of factoid (listkeys/listvals) that matched.
-       - news: show total requested count, users "registered", users
-         "ignored"
-       - add notes about news redesign to accomodate individual items
-         read - need to add id's to each item too.
-       - debian bug lookup.
-       - bind DCC CHAT service to port.
-               - man perlipc, search for service.
-               - do forking aswell.
-       - debian: "find -2.4.1" does not work but 2.4.1 does?
-               - $debug var needed.
-       - check if debian downloading files are proper.
-       - verbose: say why config option was enabled/enabled.
-       - registered flags for users/channels
-               - end of DynaConfig.pl
-               - use in UserDCC.. warn if value is not in list.
-               - add &checkSet() or &_chanset();
-       - update sample.chan and sample.config
-       - attempt to move userDCC to hooks.
-               - need to modify parseCmdHooks for user flags?
-       - make timers below 5 or 10 mins non-random values.
--- EFFORT 1.
-       - make IRC/Schedulers.pl work 100%.
-               - intervals must be multiple of the smallest one
-                       - otherwise auto-fixed.
-               - make intervals chan-specific
-                       - need to store info in $sched{$what}{$chan} =
-                       time(); when last run or next run?
-----------------------------------------------------
------------- FUTURE, NON-IMPORTANT
-       - <greycat> ~country ua
-       - <irq_w> xk: add it :) and my imdb feature :)
-       - <greycat> xk: and ~bugs :)
-       - stats to keep common words.
-               - "heh", "?", "lol", ":)", "hi"
-       - "HACKING" text file, documentation of where things start,
-         what "core" or reuseable functions are used and what for.
-       - web interface... learn php + tables.
-       - on join message - customizeable, option.
-               - addon to UserInfo but for channels?
-       - ^B's are removed (HOW?) from factoids.
-       - asking questions.... make more guesses
-       - throttling of "help topic": push-pull system of &msg().
-       - one key for berk db to show format...
-       - use autoloader properly.
-               - Module::<BLAH>::<CMD>
-               - make a global autoloader.
-       - support notification of author of deleted factoids,
-       - flag to hide owner of factoid.
-       - table data for DCC CHAT or misc table.
-       - DYNAMIC USER//CONFIGURATION FILE UPGRADE:
-               - finer granuality(sp) of userlist/ignore file
-       - <el_gore> apt, find netconfig -- merge similar files.
-               - and same files(1 per package) for multiple packages.
-               - merge partial similar paths together.
-               - do some test cases to confirm code actually works as
-                 proposed.
-
-------------------- useless statistics
-- 20010420:
-[router] [~blootbot/src] # grep DEBUG `find -type f`| wc -l
-    373
-[router] [~blootbot/src] # grep WARN `find -type f` | wc -l
-    129
-[router] [~blootbot/src] # grep FIXME `find -type f` | wc -l
-     35
-[router] [~blootbot/src] # grep status `find -type f` | wc -l
-    386
-[router] [~blootbot/src] # grep ERROR `find -type f` | wc -l
-    145
-
diff --git a/doc/old/USAGE b/doc/old/USAGE
deleted file mode 100644 (file)
index d922ed7..0000000
+++ /dev/null
@@ -1,714 +0,0 @@
-==========================================================================
-=      ===  ========     ====     ===        ==      ====     ===        =
-=  ===  ==  =======  ===  ==  ===  =====  =====  ===  ==  ===  =====  ====
-=      ===  =======  ===  ==  ===  =====  =====      ===  ===  =====  ====
-=  ===  ==  =======  ===  ==  ===  =====  =====  ===  ==  ===  =====  ====
-=      ===       ===     ====     ======  =====      ====     ======  ====
-==========================================================================
-
-                   ======================================
-                               USER COMMANDS
-                   ======================================
-
-Command: 4op
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       4op ...
-
-Example:
-       ...
-
-
-Command: dumpvars
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       dumpvars ...
-
-Example:
-       ...
-
-
-Command: kick
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       kick ...
-
-Example:
-       ...
-
-
-Command: ignore
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       ignore ...
-
-Example:
-       ...
-
-
-Command: ignorelist
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       ignorelist ...
-
-Example:
-       ...
-
-
-Command: unignore
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       unignore ...
-
-Example:
-       ...
-
-
-Command: clear ignorelist
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       clear ignorelist ...
-
-Example:
-       ...
-
-
-Command: lobotomy
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       lobotomy ...
-
-Example:
-       ...
-
-
-Command: unlobotomy
-=============
-Description:
-       ...
-
-Usage:
-       unlobotomy ...
-
-Example:
-       ...
-
-
-Command: op
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       op ...
-
-Example:
-       ...
-
-
-Command: say
-=============
-Description:
-       ...
-
-Usage: REQUIRES +o flag.
-       say ...
-
-Example:
-       ...
-
-
-Command: die
-=============
-Description:
-       ...
-
-Usage: REQUIRES +n flag.
-       die ...
-
-Example:
-       ...
-
-
-Command: jump
-=============
-Description:
-       ...
-
-Usage: REQUIRES +n flag.
-       jump ...
-
-Example:
-       ...
-
-
-Command: rehash
-=============
-Description:
-       ...
-
-Usage: REQUIRES +n flag.
-       rehash ...
-
-Example:
-       ...
-
-
-Command: set
-=============
-Description:
-       ...
-
-Usage: REQUIRES +n flag.
-       set ...
-
-Example:
-       ...
-
-
-Command: unset
-=============
-Description:
-       ...
-
-Usage: REQUIRES +n flag.
-       unset ...
-
-Example:
-       ...
-
-
-Command: chanstats
-=============
-Description:
-       Channel statistics is gathered while the bot is operation in those
-       channels it is located. They include: join, part, kick, ban, and
-       countless others.
-
-Usage:
-       chanstats [#channel]
-
-Example:
-       > blootbot: chanstats
-       <blootbot> i am on 2 channels: #blootbot #debian
-       <blootbot> i've cached 5 users distributed over 2 channels.
-
-       > blootbot: chanstats #blootbot
-       <blootbot> On #blootbot, there have been 1 Join, 1 Op and 20
-               PublicMsgs.
-       <blootbot> At the moment, 3 Opped and 3 Total.
-
-
-Command: cmdstats
-=============
-Description:
-       ...
-
-Usage:
-       cmdstats ...
-
-Example:
-       ...
-
-
-Command: crypt
-=============
-Description:
-       ...
-
-Usage:
-       crypt ...
-
-Example:
-       ...
-
-
-Command: factinfo
-=============
-Description:
-       ...
-
-Usage:
-       factinfo ...
-
-Example:
-       ...
-
-
-Command: factstats
-=============
-Description:
-       ...
-
-Usage:
-       factstats ...
-
-Example:
-       ...
-
-
-Command: karma
-=============
-Description:
-       ...
-
-Usage:
-       karma ...
-
-Example:
-       ...
-
-
-Command: spell
-=============
-Description:
-       ...
-
-Usage:
-       spell ...
-
-Example:
-       ...
-
-
-Command: nslookup
-=============
-Description:
-       ...
-
-Usage:
-       nslookup ...
-
-Example:
-       ...
-
-
-Command: part
-=============
-Description:
-       ...
-
-Usage:
-       part ...
-
-Example:
-       ...
-
-
-Command: rot13
-=============
-Description:
-       ...
-
-Usage:
-       rot13 ...
-
-Example:
-       ...
-
-
-Command: wantNick
-=============
-Description:
-       ...
-
-Usage:
-       wantNick ...
-
-Example:
-       ...
-
-
-Command: join
-=============
-Description:
-       The bot can be commanded to join a channel if it is not already on
-       there in the case of a kick/ban, invite only or invalid key to
-       name a few typical case scenarios.
-
-       The channels which the bot can join is governed by the
-       configuration parameter labelled 'join_channels'. However, this
-       is ignored for those users with the +o flag in the user table.
-
-Usage:
-       join <#channel>[,key]
-
-Example:
-       > blootbot: join #blootbot
-       [blootbot] joining #blootbot
-       *** join/#debian blootbot (bot@router.home.org)
-       > blootbot: join #blootbot
-       [blootbot] I'm already on #blootbot...
-
-
-
-                   ======================================
-                              MODULE COMMANDS
-                   ======================================
-
-Command: babelfish
-=============
-Description:
-       ...
-
-Usage:
-       x from [language]: phrase
-
-Example:
-       ...
-
-
-Command: debian package
-=============
-Description:
-       ...
-
-Usage:
-       [] ...
-
-Example:
-       ...
-
-
-Command: dict
-=============
-Description:
-       ...
-
-Usage:
-       dict ...
-
-Example:
-       ...
-
-
-Command: freshmeat
-=============
-Description:
-       ...
-
-Usage:
-       freshmeat ...
-
-Example:
-       ...
-
-
-Command: google
-=============
-Description:
-       ...
-
-Usage:
-       google ...
-
-Example: DOES NOT WORK YET(??)
-       ...
-
-
-Command: insult
-=============
-Description:
-       ...
-
-Usage:
-       insult ...
-
-Example:
-       ...
-
-
-Command: kernel
-=============
-Description:
-       ...
-
-Usage:
-       kernel ...
-
-Example:
-       ...
-
-
-Command: lart
-=============
-Description:
-       ...
-
-Usage:
-       lart ...
-
-Example:
-       ...
-
-
-Command: list{keys|vals}
-=============
-Description:
-       ...
-
-Usage:
-       list{keys|vals} ...
-
-Example:
-       ...
-
-
-Command: nickometer
-=============
-Description:
-       ...
-
-Usage:
-       nickometer ...
-
-Example:
-       ...
-
-
-Command: quotes
-=============
-Description:
-       ...
-
-Usage:
-       quotes ...
-
-Example:
-       ...
-
-
-Command: rootwarn
-=============
-Description:
-       ...
-
-Usage:
-       rootwarn ...
-
-Example:
-       ...
-
-
-Command: seen
-=============
-Description:
-       ...
-
-Usage:
-       seen ...
-
-Example:
-       ...
-
-
-Command: listauth
-=============
-Description:
-       ...
-
-Usage:
-       listauth ...
-
-Example:
-       ...
-
-
-Command: slashdot
-=============
-Description:
-       ...
-
-Usage:
-       slashdot ...
-
-Example:
-       ...
-
-
-Command: debian contents
-=============
-Description:
-       ...
-
-Usage:
-       debian ...
-
-Example:
-       ...
-
-
-Command: topic
-=============
-Description:
-       ...
-
-Usage:
-       topic ...
-
-Example:
-       ...
-
-
-Command: countdown
-=============
-Description:
-       ...
-
-Usage:
-       countdown ...
-
-Example:
-       ...
-
-
-Command: uptime
-=============
-Description:
-       ...
-
-Usage:
-       uptime ...
-
-Example:
-       ...
-
-
-Command: weather
-=============
-Description:
-       ...
-
-Usage:
-       weather ...
-
-Example: DOES NOT WORK
-       ...
-
-
-Command: whatis
-=============
-Description:
-       ...
-
-Usage:
-       whatis ...
-
-Example: DOES NOT WORK
-       ...
-
-
-
-                   ======================================
-                       MISCELLANEOUS/FACTOID COMMANDS
-                   ======================================
-
-Command: forget
-=============
-Description:
-       ...
-
-Usage:
-       forget ...
-
-Example:
-       ...
-
-
-Command: {un|}lock
-=============
-Description:
-       ...
-
-Usage:
-       {un|}lock ...
-
-Example:
-       ...
-
-
-Command: rename
-=============
-Description:
-       ...
-
-Usage:
-       rename ...
-
-Example:
-       ...
-
-
-Command: substitution
-=============
-Description:
-       ...
-
-Usage:
-       $factoid =~ s/from/to/
-       $factoid =~ s#te/st/#test#g
-
-Example:
-       ...
-
-
-Command: karma set
-=============
-Description:
-       ...
-
-Usage:
-       $nick++
-       $nick--
-
-Example:
-       blootbot++
-       infobot--
-
-
-Command: maths
-=============
-Description:
-       ...
-
-Usage:
-       2 + 2
-
-Example:
-       ...
-
-
-Command: tell
-=============
-Description:
-       ...
-
-Usage:
-       tell <nick> about <factoid>
-
-Example:
-       ...
diff --git a/doc/old/notes.txt b/doc/old/notes.txt
deleted file mode 100644 (file)
index 187ff71..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-##### GLOBAL VARIABLES
-### Scalar variable.
-$who           => Process.pl#7:
-$msgType       => Process.pl#7:
-$message       => Process.pl#7:
-$origWho       => Process.pl#12: untouched $who variable.
-$origMessage   => Process.pl#13: untouched $message variable.
-$origIn                => Question.pl#15: (my) successful (not repeated) asked factoid
-$who           => Process.pl#6:
-$message       => Process.pl#6:
-$nuh           => Irc.pl#279: nick-user-host
-$userHandle    => User.pl: handle which nick is registered under.
-### Array.
-### Hash lists.
-%channels      => $channels{$channel}{$mode}{$nick}
-%chanstats     => $chanstats{$channel}{TYPE}
-%cmdstats      => $cmdstats{TYPE}
-%userList      => $userList{$user}{$type}
-%userList      => $userList{$user}{'mask'}{$what} = 1;
-#####
-
-### Thorough check and cleanup of... (comments need to be read though)
-Process.pl             19991128
-Irc.pl                 19991128
-Misc.pl                        19991128
-
-
-
-### Address testing with the "new" code.
-### nick == $1, text = $'
-blah erp               good
-blah erp erp           good
-blah:erp               good... about time got it to work.
-blah:erp erp           good... ditto
-blah :erp              good
-blah :erp erp          good
-blah : erp             good
-blah : erp erp         good
-blah  : erp            good
-blah  : erp erp                good
-blah  :  erp           good
-blah  :  erp erp       good
-
-unfski erp             good
-unfski erp erp         good
-unfski:erp             hrm... good :)
-unfski:erp erp         hrm... good :)
-unfski :erp            good
-unfski :erp erp                good
-unfski : erp           good
-unfski : erp erp               good
-unfski  : erp          good
-unfski  : erp erp              good
-unfski  :  erp         good
-unfski  :  erp erp     good
-
-### some notes...
-&DoModes($chan,$modes,$targets);
-&DeleteUserInfo($nick,@chans);
-# NOTE: subhash list can only be deleted with "delete" not with "undef".
-foreach $chan (keys %channels) {
-foreach $mode (keys %{$channels{$chan}}) {
-foreach $user (keys %{$channels{$chan}{$mode}}) {
-
-### &DeleteUserInfo().
-# DUI: type    working         fix
-#      part    yes             undef=>delete
-#      sign    yes             fe loops=>DUI($n,%c);
-#      nick    yes             undef=>delete
-#      kill    ...             ...
-###
-
-###
-### Soon to be new format of factoid.db, or at least infobot-extra.db
-###
-[factoid key] -> [created].[modified].[requests].[locked]
-                   |         |           |         |
-               [who by]   [who by]    [who by]  [who by]
-                [time]     [time]     [time]     [time]
-                                      [count]
-
-$db{'key'}    = $created_by    .$;. $created_time      .$;$;.
-               $modified_by    .$;. $modified_time     .$;$;.
-               $request_by     .$;. $request_time      .$;. $request_count .$;$;.
-               $locked_by      .$;. $locked_time;
-
-factoid can only be unlocked by creator. possibly need to be matched
-against nick || user@*.x.org || user@x.y.z.*
-
-#####
-# forget: factoid locking              half-done TODO
-# factoid query                                DONE.
-# factoid update (2 create; 4 modify)  DONE.
-#####
-
-raw: ..... KICK #tnflesh damagick :i can do this too
-940445681 [12632] >>> [1mtoo[0m was kicked off [1m#tnflesh damagick :i \
-       can do this[0m by [1mChimmy[0m ([1mP[0m)
-my ($kicker, $chan, $knick, $why) = @_;
-    $1       $2     $4      $5
-
-("Op",          yes
-"Deop",         yes
-"Ban",          yes
-"Unban",        yes
-"Topic",        yes
-"Kick",         yes
-"PublicMsg"     yes
-"Part",         yes
-"SignOff",      yes
-"Join"          yes
diff --git a/old/Freshmeat_I.pl b/old/Freshmeat_I.pl
deleted file mode 100644 (file)
index 2936b9c..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-#
-# Freshmeat.pl: Frontend to www.freshmeat.net
-#       Author: dms
-#      Version: v0.7d (20000923)
-#      Created: 19990930
-#
-
-package Freshmeat;
-
-use strict;
-
-### download compressed version instead?
-
-my %urls = (
-       'public'  => 'http://www.freshmeat.net/backend/appindex.txt',
-       'private' => 'http://feed.freshmeat.net/appindex/appindex.txt',
-);
-
-####
-# Usage: &Freshmeat($string);
-sub Freshmeat {
-    my $sstr   = lc($_[0]);
-    my $refresh        = &::getChanConfDefault("freshmeatRefreshInterval",
-                       "", 24) * 60 * 60;
-
-    my $last_refresh = &::dbGet("freshmeat", "name","_","stable");
-    my $renewtable   = 0;
-
-    if (defined $last_refresh) {
-       $renewtable++ if (time() - $last_refresh > $refresh);
-    } else {
-       $renewtable++;
-    }
-    $renewtable++ if (&::countKeys("freshmeat") < 10);
-
-    if ($renewtable and $$ == $::bot_pid) {
-       &::Forker("freshmeat", sub {
-               &downloadIndex();
-               &Freshmeat($sstr);
-       } );
-       # both parent/fork runs here, in case the following looks weird.
-       return if ($$ == $::bot_pid);
-    }
-
-    if (!&showPackage($sstr)) {                # no exact match.
-       my $start_time = &::timeget();
-       my %hash;
-
-       # search by key/NAME first.
-       foreach (&::searchTable("freshmeat", "name","name",$sstr)) {
-           $hash{$_} = 1 unless exists $hash{$_};
-       }
-
-       # search by description line.
-       foreach (&::searchTable("freshmeat", "name","oneliner", $sstr)) {
-           $hash{$_} = 1 unless exists $hash{$_};
-           last if (scalar keys %hash > 15);
-       }
-
-       my @list = keys %hash;
-       # search by value, if we have enough room to do it.
-       if (scalar @list == 1) {
-           &::status("only one match found; showing full info.");
-           &showPackage($list[0]);
-           return;
-       }
-
-       # show how long it took.
-       my $delta_time = &::timedelta($start_time);
-       &::status(sprintf("freshmeat: %.02f sec to complete query.", $delta_time)) if ($delta_time > 0);
-
-       for (@list) {
-           tr/A-Z/a-z/;
-           s/([\,\;]+)/\037$1\037/g;
-       }
-
-       &::performStrictReply( &::formListReply(1, "Freshmeat ", @list) );
-    }
-}
-
-sub showPackage {
-    my ($pkg)  = @_;
-    my @fm     = &::dbGet("freshmeat", "name",$pkg,"*");
-
-    if (scalar @fm) {          #1: perfect match of name.
-       my $retval;
-       $retval  = "$fm[0] \002(\002$fm[11]\002)\002, ";
-       $retval .= "section $fm[3], ";
-       $retval .= "is $fm[4]. ";
-       $retval .= "Stable: \002$fm[1]\002, ";
-       $retval .= "Development: \002$fm[2]\002. ";
-       $retval .= $fm[5] || $fm[6];             # fallback to 'download'.
-       $retval .= " deb: ".$fm[8] if ($fm[8] ne ""); # 'deb'.
-       &::performStrictReply($retval);
-       return 1;
-    } else {
-       return 0;
-    }
-}
-
-sub randPackage {
-    my @fm     = &::randKey("freshmeat","*");
-
-    if (scalar @fm) {          #1: perfect match of name.
-       my $retval;
-       $retval  = "$fm[0] \002(\002$fm[11]\002)\002, ";
-       $retval .= "section $fm[3], ";
-       $retval .= "is $fm[4]. ";
-       $retval .= "Stable: \002$fm[1]\002, ";
-       $retval .= "Development: \002$fm[2]\002. ";
-       $retval .= $fm[5] || $fm[6];             # fallback to 'download'.
-       $retval .= " deb: ".$fm[8] if ($fm[8] ne ""); # 'deb'.
-
-       return $retval;
-    } else {
-       return;
-    }
-}
-
-sub downloadIndex {
-    my $start_time     = &::timeget(); # set the start time.
-    my $idx            = "$::param{tempDir}/fm_index.txt";
-
-    &::msg($::who, "Updating freshmeat index... please wait");
-
-    if (&::isStale($idx, 1)) {
-       &::status("Freshmeat: fetching data.");
-       foreach (keys %urls) {
-           my $retval = &::getURLAsFile($urls{$_}, $idx);
-           next if ($retval =~ /^(403|500)$/);
-
-           &::DEBUG("FM: last! retval => '$retval'.");
-           last;
-       }
-    } else {
-       &::status("Freshmeat: local file hack.");
-    }
-
-    if (! -e $idx) {
-       &::msg($::who, "the freshmeat butcher is closed.");
-       return;
-    }
-
-    if ( -s $idx < 100000) {
-       &::DEBUG("FM: index too small?");
-       unlink $idx;
-       &::msg($::who, "internal error?");
-       return;
-    }
-
-    if ($idx =~ /bz2$/) {
-       open(IN, "bzcat $idx |");
-    } elsif ($idx =~ /gz$/) {
-       open(IN, "gzcat $idx |");
-    } else {
-       open(IN, $idx);
-    }
-
-    # delete the table before we redo it.
-    &::deleteTable("freshmeat");
-
-    ### lets get on with business.
-    # set the last refresh time. fixes multiple spawn bug.
-    &::dbSet("freshmeat", "name","_","stable",time());
-
-    my $i = 0;
-    while (my $line = <IN>) {
-       chop $line;
-       $i++ if ($line eq "%%");
-       last if ($i == 2);
-    }
-
-    &::dbRaw("LOCK", "LOCK TABLES freshmeat WRITE");
-    my @data;
-    my @done;
-    while (my $line = <IN>) {
-       chop $line;
-       if ($line ne "%%") {
-           push(@data,$line);
-           next;
-       }
-
-       if ($i % 200 == 0 and $i != 0) {
-           &::DEBUG("FM: unlocking and locking.");
-           &::dbRaw("UNLOCK", "UNLOCK TABLES");
-           ### another lame hack to "prevent" errors.
-           select(undef, undef, undef, 0.2);
-           &::dbRaw("LOCK", "LOCK TABLES freshmeat WRITE");
-       }
-
-       if (grep /^\Q$data[0]\E$/, @done) {
-           &::DEBUG("dupe? $data[0]");
-           @data = ();
-           next;
-       }
-
-       $i++;
-       pop @data;
-       $data[1] ||= "none";
-       $data[2] ||= "none";
-       &::dbSetRow("freshmeat", @data);
-       push(@done,$data[0]);
-       @data = ();
-    }
-    close IN;
-    &::DEBUG("FM: data ".scalar(@data) );
-    &::dbRaw("UNLOCK", "UNLOCK TABLES");
-
-    my $delta_time = &::timedelta($start_time);
-    &::status(sprintf("Freshmeat: %.02f sec to complete.", $delta_time)) if ($delta_time > 0);
-
-    my $count = &::countKeys("freshmeat");
-    &::status("Freshmeat: $count entries loaded.");
-}
-
-sub freshmeatAnnounce {
-    my $file = "$::param{tempDir}/fm_recent.txt";
-    my @old;
-
-    ### if file exists, lets read it.
-    if ( -f $file) {
-       open(IN, $file);
-       while (<IN>) {
-           chop;
-           push(@old,$_);
-       }
-       close IN;
-    }
-
-    my @array = &::getURL("http://core.freshmeat.net/backend/recentnews.txt");
-    my @now;
-
-    while (@array) {
-       my($what,$date,$url) = splice(@array,0,3);
-       push(@now, $what);
-    }
-
-    ### if file does not exist, write new.
-    if (! -f $file) {
-       open(OUT, ">$file");
-       foreach (@now) {
-           print OUT "$_\n";
-       }
-       close OUT;
-
-       return;
-    }
-
-    my @new;
-    for(my $i=0; $i<scalar(@old); $i++) {
-       last if ($now[$i] eq $old[0]);
-       push(@new, $now[$i]);
-    }
-
-    if (!scalar @new) {
-       &::DEBUG("fA: no new items.");
-       return;
-    }
-
-    ### output new file.
-    open(OUT, ">$file");
-    foreach (@now) {
-       print OUT "$_\n";
-    }
-    close OUT;
-
-    return "Freshmeat update: ".join(" \002::\002 ", @new);
-}
-
-1;
diff --git a/old/Freshmeat_II.pl b/old/Freshmeat_II.pl
deleted file mode 100644 (file)
index 470b201..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-#
-# Freshmeat.pl: Frontend to www.freshmeat.net
-#       Author: dms
-#      Version: v0.7d (20000923)
-#      Created: 19990930
-#
-
-package Freshmeat;
-
-use strict;
-use vars qw(@cols @data $string %pkg $i $locktime);
-
-my %urls = (
-       'public'  => 'http://www.freshmeat.net/backend/fm-projects.rdf.bz2',
-#      'private' => 'http://feed.freshmeat.net/appindex/appindex.txt',
-);
-
-####
-# Usage: &Freshmeat($string);
-sub Freshmeat {
-    my $sstr   = lc($_[0]);
-    my $refresh        = &::getChanConfDefault("freshmeatRefreshInterval",
-                       "", 24) * 60 * 60 * 7;
-
-    my $last_refresh = &::dbGet("freshmeat", "latest_version", "projectname_short=".&::dbQuote('_'));
-    my $renewtable   = 0;
-
-    if (defined $last_refresh and $last_refresh =~ /^\d+$/) {
-       $renewtable++ if (time() - $last_refresh > $refresh);
-    } else {
-       $renewtable++;
-    }
-    $renewtable++ if (&::countKeys("freshmeat") < 1000);
-
-    if ($renewtable) {
-       if ($$ == $::bot_pid) {
-           &::Forker("freshmeat", sub {
-               &Freshmeat($sstr) if &downloadIndex();
-           } );
-           # both parent/fork runs here, in case the following looks weird.
-       } else {
-           &downloadIndex();
-       }
-
-       return if ($$ == $::bot_pid);
-    }
-
-    if (!&showPackage($sstr)) {                # no exact match.
-       my $start_time = &::timeget();
-       my %hash;
-
-       # search by key/NAME first.
-       foreach (&::searchTable("freshmeat", "projectname_short", "projectname_short",$sstr)) {
-           $hash{$_} = 1 unless exists $hash{$_};
-       }
-
-       # search by description line.
-       foreach (&::searchTable("freshmeat", "projectname_short", "desc_short", $sstr)) {
-           $hash{$_} = 1 unless exists $hash{$_};
-           last if (scalar keys %hash > 15);
-       }
-
-       my @list = keys %hash;
-       # search by value, if we have enough room to do it.
-       if (scalar @list == 1) {
-           &::status("only one match found; showing full info.");
-           &showPackage($list[0]);
-           return;
-       }
-
-       # show how long it took.
-       my $delta_time = &::timedelta($start_time);
-       &::status(sprintf("freshmeat: %.02f sec to complete query.", $delta_time)) if ($delta_time > 0);
-
-       for (@list) {
-           tr/A-Z/a-z/;
-           s/([\,\;]+)/\037$1\037/g;
-       }
-
-       &::performStrictReply( &::formListReply(1, "Freshmeat ", @list) );
-    }
-}
-
-sub packageText {
-    my ($pkg)  = @_;
-    my %fm     = &::dbGetColNiceHash("freshmeat", "*", "projectname_short=".&::dbQuote($pkg));
-
-    if (scalar keys %fm) {             #1: perfect match of name.
-       my $retval;
-       $retval  = "$fm{'projectname_short'} \002(\002$fm{'desc_short'}\002)\002, ";
-       $retval .= "is $fm{'license'}. ";
-       $retval .= "Version: \002$fm{'latest_version'}\002, $fm{'url_homepage'}";
-       return $retval;
-    } else {
-       return;
-    }
-}
-
-sub showPackage {
-    my ($pkg) = @_;
-    my ($retval);
-    if ($retval = packageText($pkg)) {
-       &::performStrictReply($retval);
-       return 1;
-    } else {
-       return 0;
-    }
-}
-
-sub randPackage {
-    my @fm = &::randKey("freshmeat","*");
-    return &packageText($fm[0]);
-}
-
-sub downloadIndex {
-    my $start_time     = &::timeget(); # set the start time.
-    my $idx            = "$::param{tempDir}/fm-projects.rdf.bz2";
-
-    if (!&::loadPerlModule("XML::Parser")) {
-       &::WARN("don't have xml::parser...");
-       return 0;
-    }
-    my $p = new XML::Parser(Style => 'Objects');
-    my %pkg;
-    my $string;
-
-    $p->setHandlers(
-               Char    => \&xml_text,
-               End     => \&xml_end,
-    );
-
-    &::msg($::who, "Updating freshmeat index... please wait");
-
-    if (&::isStale($idx, 1)) {
-       &::status("Freshmeat: fetching data.");
-
-       foreach (keys %urls) {
-           $urls{$_}   =~ /^.*\/(.*)$/;
-           $idx        = "$::param{tempDir}/$1";
-           my $retval  = &::getURLAsFile($urls{$_}, $idx);
-           next if ($retval =~ /^(403|500)$/);
-
-           &::DEBUG("FM: last! retval => '$retval'.");
-           last;
-       }
-    } else {
-       &::status("Freshmeat: local file hack.");
-    }
-
-    if (! -e $idx) {
-       &::msg($::who, "the freshmeat butcher is closed.");
-       return 0;
-    }
-
-    if ( -s $idx < 100000) {
-       &::DEBUG("FM: index too small?");
-       unlink $idx;
-       &::msg($::who, "internal error?");
-       return 0;
-    }
-
-    if ($idx =~ /bz2$/) {
-       open(IN, "bzcat $idx |");
-    } elsif ($idx =~ /gz$/) {
-       open(IN, "gzcat $idx |");
-    } else {
-       open(IN, $idx);
-    }
-
-    # delete the table before we redo it.
-    &::deleteTable("freshmeat");
-
-    ### lets get on with business.
-    # set the last refresh time. fixes multiple spawn bug.
-    &::dbSet("freshmeat",
-       { "projectname_short"   => "_" },
-       { "latest_version"      => time(),
-         "desc_short"          => "dummy project to track date" }
-    );
-
-#    &::dbRaw("LOCK", "LOCK TABLES freshmeat WRITE");
-    @cols      = &::dbGetColInfo("freshmeat");
-
-    $locktime  = time();
-
-    # this mess is to not dump IN to memory.
-    $_ = <IN>;
-    $_ = <IN>;
-    $_ = <IN>;
-
-    my $str;
-    while (<IN>) {
-       chop;
-
-       $str .= $_;
-
-       next unless (/<\/project>/);
-
-       # XML::Parser's parse() doesn't like the following.
-       # but parsefile() does... why!
-       for ($str) {
-               s/&reg;/_/g;
-               s/&ocirc;//g;
-               s/&quot;//g;
-               s/&eacute;/e/g;
-               s/&agrave;/a/g;
-               s/&iacute;/i/g;
-               s/&shy;/_/g;    # ???
-               s/&acute;/a/g;
-               s/&raquo;/_/g;  # ???
-               s/&laquo;/_/g;  # ???
-               s/&copy;/[C]/g;
-               s/&deg;/deg/g;
-               s/&AElig;/A/g;
-               s/\cN//g;               # fucking openbsd morons.
-               s/&nbsp;/-/g;
-               s/&ouml;/o/g;
-               s/&para;//g;    # ???
-               s/&atilde;//g;
-               s/\cM/ /g;              # stupid windows morons
-               s/&sup2;/square/g;
-               s/&uuml;/?/g;
-               s/&micro;/u/g;
-               s/&aelig;/a/g;
-               s/&oslash;/o/g;
-               s/&eth;/e/g;
-               s/&szlig;//g;
-               s/&middot;//g;
-       }
-
-       if (0 and $str =~ s/\&(\S+?);//g) {
-           &::DEBUG("fm: sarred $1 to ''.");
-       }
-
-       $p->parse($str, ProtocolEncoding => 'ISO-8859-1');
-       $str = "";
-    }
-    close IN;
-
-#    &::dbRaw("UNLOCK", "UNLOCK TABLES");
-
-    my $delta_time = &::timedelta($start_time);
-    &::status(sprintf("Freshmeat: %.02f sec to complete.", $delta_time)) if ($delta_time > 0);
-
-    my $count = &::countKeys("freshmeat");
-    &::status("Freshmeat: $count entries loaded.");
-    return 1;
-}
-
-sub freshmeatAnnounce {
-    my $file = "$::param{tempDir}/fm_recent.txt";
-    my @old;
-
-    ### if file exists, lets read it.
-    if ( -f $file) {
-       open(IN, $file);
-       while (<IN>) {
-           chop;
-           push(@old,$_);
-       }
-       close IN;
-    }
-
-    my @array = &::getURL("http://core.freshmeat.net/backend/recentnews.txt");
-    my @now;
-
-    while (@array) {
-       my($what,$date,$url) = splice(@array,0,3);
-       push(@now, $what);
-    }
-
-    ### if file does not exist, write new.
-    if (! -f $file) {
-       open(OUT, ">$file");
-       foreach (@now) {
-           print OUT "$_\n";
-       }
-       close OUT;
-
-       return;
-    }
-
-    my @new;
-    for(my $i=0; $i<scalar(@old); $i++) {
-       last if ($now[$i] eq $old[0]);
-       push(@new, $now[$i]);
-    }
-
-    if (!scalar @new) {
-       &::DEBUG("fA: no new items.");
-       return;
-    }
-
-    ### output new file.
-    open(OUT, ">$file");
-    foreach (@now) {
-       print OUT "$_\n";
-    }
-    close OUT;
-
-    return "Freshmeat update: ".join(" \002::\002 ", @new);
-}
-
-
-sub xml_text {
-    my ($e,$t) = @_;
-    return if ($t =~ /^\s*$/);
-
-    $string = $t;
-}
-
-sub xml_end {
-    my($expat,$text) = @_;
-
-    $pkg{$text} = $string;
-
-    if ($expat->depth == 0) {
-
-       # old code.
-       if (0) {
-       for (my $j=0; $j<scalar @cols; $j++) {
-           $data[$j] = $pkg{ $cols[$j] };
-       }
-       $i++;
-
-       &::dbSetRow("freshmeat", [@data], "DELAY");
-       undef @data;
-       }
-
-       # new code.
-       $i++;
-       my %data;
-       foreach(@cols) {
-           $data{$_} = $pkg{$_} if ($pkg{$_});
-       }
-       &::dbReplace("freshmeat", "projectname_short", %data);
-       undef %data;
-       # end of new code.
-
-       undef %pkg;
-
-       if ($i % 200 == 0 and $i != 0) {
-           &::showProc();
-           &::status("FM: unlocking and locking ($i): ".
-               &::Time2String( time() - $locktime ) );
-           $locktime = time();
-
-           # I think the following leaks 120k of memory each time it's
-           # called... the wonders of libmysql-perl leaking!
-
-#          &::dbRaw("UNLOCK", "UNLOCK TABLES");
-           ### another lame hack to "prevent" errors.
-#          select(undef, undef, undef, 0.2);
-#          &::dbRaw("LOCK", "LOCK TABLES freshmeat WRITE");
-       }
-    }
-}
-
-1;
diff --git a/old/News.pl b/old/News.pl
deleted file mode 100644 (file)
index e03f9a3..0000000
+++ /dev/null
@@ -1,1031 +0,0 @@
-#
-# News.pl: Advanced news management
-#   Author: dms
-#  Version: v0.3 (20010412)
-#  Created: 20010326
-#    Notes: Testing done by greycat, kudos!
-#
-### structure:
-# news{ channel }{ string } { item }
-# newsuser{ channel }{ user } = time()
-### where item is:
-#      Time    - when it was added (used for sorting)
-#      Author  - Who by.
-#      Expire  - Time to expire.
-#      Text    - Actual text.
-###
-
-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("news: looks like we enabled news option just then; loading up news file just in case.");
-           $::cache{newsFirst} = 1;
-       }
-
-       &readNews();
-    }
-
-    if ($::msgType ne "private") {
-       $chan = $::chan;
-    }
-
-    if (defined $what and $what =~ s/^($::mask{chan})\s*//) {
-       # todo: check if the channel exists aswell.
-       $chan   = lc $1;
-
-       if (!&::IsNickInChan($who, $chan)) {
-           &::notice($who, "sorry but you're not on $chan.");
-           return;
-       }
-    }
-
-    if (!defined $chan) {
-       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");
-           return;
-       }
-
-       if (scalar @chans == 0) {
-           &::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);
-       $::chan = $chan;        # hack for IsChanConf().
-    }
-
-    if (!defined $what or $what =~ /^\s*$/) {
-       &list();
-       return;
-    }
-
-    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) {
-       &::VERB("News: read shortcut called.",2);
-       &read($1);
-
-    } elsif ($what =~ /^read(\s+(.*))?$/i) {
-       &read($2);
-
-    } elsif ($what =~ /^(latest|new)(\s+(.*))?$/i) {
-       &latest($3 || $chan, 1);
-#      $::cmdstats{'News latest'}++;
-
-    } elsif ($what =~ /^stats?$/i) {
-       &stats();
-
-    } elsif ($what =~ /^list$/i) {
-       &list();
-
-    } elsif ($what =~ /^(expire|text|desc)(\s+(.*))?$/i) {
-       # shortcut/link.
-       # nice hack.
-       my $cmd = $1;
-       my($arg1,$arg2) = split(/\s+/, $3, 2);
-       &set("$arg1 $cmd $arg2");
-
-    } elsif ($what =~ /^help(\s+(.*))?$/i) {
-       &::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 {
-       &::notice($who, "unknown command: $what");
-    }
-}
-
-sub readNews {
-    my $file = "$::bot_base_dir/blootbot-news.txt";
-    if (! -f $file or -z $file) {
-       return;
-    }
-
-    if (fileno NEWS) {
-       &::DEBUG("readNews: fileno exists, should never happen.");
-       return;
-    }
-
-    my($item,$chan);
-    my($ci,$cu) = (0,0);
-
-    open(NEWS, $file);
-    while (<NEWS>) {
-       chop;
-
-       # todo: allow commands.
-
-       if (/^[\s\t]+(\S+):[\s\t]+(.*)$/) {
-           if (!defined $item) {
-               &::DEBUG("news: !defined item, never happen!");
-               next;
-           }
-
-           $::news{$chan}{$item}{$1} = $2;
-           next;
-       }
-
-       # U <chan> <nick> <time>
-       if (/^U\s+(\S+)\s+(\S+)\s+(\d+)$/) {
-           $::newsuser{$1}{$2} = $3;
-           $cu++;
-           next;
-       }
-
-       if (/^(\S+)[\s\t]+(.*)$/) {
-           $chan = $1;
-           $item = $2;
-           $ci++;
-       }
-    }
-    close NEWS;
-
-    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 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("News: write: fileno NEWS exists, should never happen.");
-       return;
-    }
-
-    # todo: add commands to output file.
-    my $c = 0;
-    my($cc,$ci,$cu) = (0,0,0);
-
-    open(NEWS, ">$file");
-    foreach $chan (sort keys %::news) {
-       $c = scalar keys %{ $::news{$chan} };
-       next unless ($c);
-       $cc++;
-       my $item;
-
-       foreach $item (sort keys %{ $::news{$chan} }) {
-           $c = scalar keys %{ $::news{$chan}{$item} };
-           next unless ($c);
-           $ci++;
-
-           print NEWS "$chan $item\n";
-           my $what;
-           foreach $what (sort keys %{ $::news{$chan}{$item} }) {
-               print NEWS "    $what: $::news{$chan}{$item}{$what}\n";
-           }
-           print NEWS "\n";
-       }
-    }
-
-    # todo: show how many users we wrote down.
-    if (&::getChanConfList("newsKeepRead")) {
-       # old users are removed in newsFlush(), perhaps it should be
-       # done here.
-
-       foreach $chan (sort keys %::newsuser) {
-
-           foreach (sort keys %{ $::newsuser{$chan} }) {
-               print NEWS "U $chan $_ $::newsuser{$chan}{$_}\n";
-               $cu++;
-           }
-       }
-    }
-
-    close NEWS;
-
-    &::status("News: Wrote $ci items for $cc chans, $cu user cache.");
-}
-
-sub add {
-    my($str) = @_;
-
-    if (!defined $chan or !defined $str or $str =~ /^\s*$/) {
-       &::help("news add");
-       return;
-    }
-
-    if (length $str > 64) {
-       &::notice($who, "That's not really an item (>64chars)");
-       return;
-    }
-
-    if (exists $::news{$chan}{$str}{Time}) {
-       &::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;       # case!
-
-    my $agestr = &::Time2String($::news{$chan}{$str}{Expire} - time() );
-    my $item   = &newsS2N($str);
-    &::notice($who, "Added '\037$str\037' at [".localtime(time).
-               "] by \002$::who\002 for item #\002$item\002.");
-    &::notice($who, "Now do 'news text $item <your_description>'");
-    &::notice($who, "This item will expire at \002".
-       localtime($::news{$chan}{$str}{Expire})."\002 [$agestr from now] "
-    );
-
-    &writeNews();
-}
-
-sub del {
-    my($what)  = @_;
-    my $item   = 0;
-
-    if (!defined $what) {
-       &::help("news del");
-       return;
-    }
-
-    if ($what =~ /^\d+$/) {
-       my $count = scalar keys %{ $::news{$chan} };
-       if (!$count) {
-           &::notice($who, "No news for $chan.");
-           return;
-       }
-
-       if ($what > $count or $what < 0) {
-           &::notice($who, "$what is out of range (max $count)");
-           return;
-       }
-
-       $item   = &getNewsItem($what);
-       $what   = $item;                # hack hack hack.
-
-    } else {
-       $_      = &getNewsItem($what);  # hack hack hack.
-       $what   = $_ if (defined $_);
-
-       if (!exists $::news{$chan}{$what}) {
-           my @found;
-           foreach (keys %{ $::news{$chan} }) {
-               next unless (/\Q$what\E/);
-               push(@found, $_);
-           }
-
-           if (!scalar @found) {
-               &::notice($who, "could not find $what.");
-               return;
-           }
-
-           if (scalar @found > 1) {
-               &::notice($who, "too many matches for $what.");
-               return;
-           }
-
-           $what       = $found[0];
-           &::DEBUG("news: del: str: guessed what => $what");
-       }
-    }
-
-    if (exists $::news{$chan}{$what}) {
-       my $auth = 0;
-       $auth++ if ($::who eq $::news{$chan}{$what}{Author});
-       $auth++ if (&::IsFlag("o"));
-
-       if (!$auth) {
-           # todo: show when it'll expire.
-           &::notice($who, "Sorry, you cannot remove items; just let them expire on their own.");
-           return;
-       }
-
-       &::notice($who, "ok, deleted '$what' from \002$chan\002...");
-       delete $::news{$chan}{$what};
-    } else {
-       &::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.");
-       return;
-    }
-
-    if (&::IsChanConf("newsKeepRead")) {
-       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();
-       }
-    }
-
-    # &notice() 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");
-
-#    &::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.");
-           next;
-       }
-
-       # todo: show request stats aswell.
-       &::msg($who, sprintf("\002[\002%2d\002]\002%s %s",
-                               $i, $chr, $subtopic));
-       $i++;
-    }
-
-    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 <keyword>'");
-}
-
-sub read {
-    my($str) = @_;
-
-    if (!defined $chan or !defined $str or $str =~ /^\s*$/) {
-       &::help("news read");
-       return;
-    }
-
-    if (!scalar keys %{ $::news{$chan} }) {
-       &::notice($who, "No News for \002$chan\002.");
-       return;
-    }
-
-    my $item   = &getNewsItem($str);
-    if (!defined $item or !scalar keys %{ $::news{$chan}{$item} }) {
-       # 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");
-       return;
-    }
-
-    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}) {
-       &::VERB("NEWS: Possible news->factoid redirection.",2);
-       my $f   = &::getFactoid($text);
-
-       if (defined $f) {
-           &::VERB("NEWS: ok, $text is factoid redirection.",2);
-           $f =~ s/^<REPLY>\s*//i;     # anything else?
-           $text = $f;
-       }
-    }
-
-    $_ = $::news{$chan}{$item}{'Expire'};
-    my $e;
-    if ($_) {
-       $e = sprintf("\037%s\037  [%s from now]",
-               scalar(localtime($_)),
-               &::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();
-    $::news{$chan}{$item}{'Request_Count'}++;
-}
-
-sub mod {
-    my($item, $str) = split /\s+/, $_[0], 2;
-
-    if (!defined $item or $item eq "" or $str =~ /^\s*$/) {
-       &::help("news mod");
-       return;
-    }
-
-    my $news = &getNewsItem($item);
-
-    if (!defined $news) {
-       &::DEBUG("news: error: mod: news == undefined.");
-       return;
-    }
-    my $nnews = $::news{$chan}{$news}{Text};
-    my $mod_news  = $news;
-    my $mod_nnews = $nnews;
-
-    # SAR patch. mu++
-    if ($str =~ m|^\s*s([/,#\|])(.+?)\1(.*?)\1([a-z]*);?\s*$|) {
-       my ($delim, $op, $np, $flags) = ($1,$2,$3,$4);
-
-       if ($flags !~ /^(g)?$/) {
-           &::notice($who, "error: Invalid flags to regex.");
-           return;
-       }
-
-       ### TODO: use m### to make code safe!
-       # todo: make code safer.
-       my $done = 0;
-       # todo: use eval to deal with flags easily.
-       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") {
-           $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.");
-           return;
-       }
-
-       if ($mod_news ne $news) { # news item.
-           if (exists $::news{$chan}{$mod_news}) {
-               &::notice($who, "item '$mod_news' already exists.");
-               return;
-           }
-
-           &::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}{$_};
-           }
-           # needed?
-           delete $::news{$chan}{$news};
-       }
-
-       if ($mod_nnews ne $nnews) { # news Text/Description.
-           &::notice($who, "Changing text for '$news' SAR s/$op/$np/.");
-           if ($mod_news ne $news) {
-               $::news{$chan}{$mod_news}{Text} = $mod_nnews;
-           } else {
-               $::news{$chan}{$news}{Text}     = $mod_nnews;
-           }
-       }
-
-       return;
-    } else {
-       &::notice($who, "error: that regex failed ;(");
-       return;
-    }
-
-    &::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;
-
-    if ($item eq "") {
-       &::help("news set");
-       return;
-    }
-
-    my $news = &getNewsItem($item);
-
-    if (!defined $news) {
-       &::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)");
-       return;
-    }
-
-    my $ok = 0;
-    my @elements = ("Expire","Text");
-    foreach (@elements) {
-       next unless ($what =~ /^$_$/i);
-       $what = $_;
-       $ok++;
-       last;
-    }
-
-    if (!$ok) {
-       &::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)");
-       return;
-    }
-
-    if (!exists $::news{$chan}{$news}) {
-       &::notice($who, "news '$news' does not exist");
-       return;
-    }
-
-    if ($what eq "Expire") {
-       # todo: use do_set().
-
-       my $time = 0;
-       my $plus = ($value =~ s/^\+//g);
-       while ($value =~ s/^(\d+)(\S*)\s*//) {
-           my($int,$unit) = ($1,$2);
-           $time += $int       if ($unit =~ /^s(ecs?)?$/i);
-           $time += $int*60    if ($unit =~ /^m(in(utes?)?)?$/i);
-           $time += $int*60*60 if ($unit =~ /^h(ours?)?$/i);
-           $time += $int*60*60*24 if (!$unit or $unit =~ /^d(ays?)?$/i);
-           $time += $int*60*60*24*7 if ($unit =~ /^w(eeks?)?$/i);
-           $time += $int*60*60*24*30 if ($unit =~ /^mon(th)?$/i);
-       }
-
-       if ($value =~ s/^never$//i) {
-           # never.
-           $time = -1;
-       } elsif ($plus) {
-           # from now.
-           $time += time();
-       } else {
-           # from creation of item.
-           $time += $::news{$chan}{$news}{Time};
-       }
-
-       if (!$time or ($value and $value !~ /^never$/i)) {
-           &::DEBUG("news: set: Expire... need to parse.");
-           &::msg($who, "hrm... couldn't parse that.");
-           return;
-       }
-
-       if ($time == -1) {
-           &::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())."]" );
-
-           if (time() > $time) {
-               &::DEBUG("news: hrm... time() > $time, should expire.");
-           }
-       }
-
-
-       $::news{$chan}{$news}{Expire} = $time;
-
-       return;
-    }
-
-    my $auth = 0;
-#    &::DEBUG("news: who => '$who'");
-    my $author = $::news{$chan}{$news}{Author};
-    $auth++ if ($::who eq $author);
-    $auth++ if (&::IsFlag("o"));
-    if (!defined $author) {
-       &::DEBUG("news: news{$chan}{$news}{Author} is not defined! auth'd anyway");
-       $::news{$chan}{$news}{Author} = $::who;
-       $author = $::who;
-       $auth++;
-    }
-
-    if (!$auth) {
-       # todo: show when it'll expire.
-       &::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("news: old => $old.");
-    }
-    $::news{$chan}{$news}{$what} = $value;
-    &::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 &notice() / &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();
-       }
-    }
-}
-
-###
-### helpers...
-###
-
-sub getNewsAll {
-    my %time;
-    foreach (keys %{ $::news{$chan} }) {
-       $time{ $::news{$chan}{$_}{Time} } = $_;
-    }
-
-    my @items;
-    foreach (sort { $a <=> $b } keys %time) {
-       push(@items, $time{$_});
-    }
-
-    return @items;
-}
-
-sub newsS2N {
-    my($what)  = @_;
-    my $item   = 0;
-    my @items;
-    my $no;
-
-    my %time;
-    foreach (keys %{ $::news{$chan} }) {
-       my $t = $::news{$chan}{$_}{Time};
-
-       if (!defined $t or $t !~ /^\d+$/) {
-           &::DEBUG("news: 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;
-
-    $what =~ s/^\#//;  # '#1' for example.
-
-    my %time;
-    foreach (keys %{ $::news{$chan} }) {
-       my $t = $::news{$chan}{$_}{Time};
-
-       if (!defined $t or $t !~ /^\d+$/) {
-           &::DEBUG("news: warn: t is undefined for news{$chan}{$_}{Time}; removing item.");
-           delete $::news{$chan}{$_};
-           next;
-       }
-
-       $time{$t} = $_;
-    }
-
-    # number to string resolution.
-    if ($what =~ /^\d+$/) {
-       foreach (sort { $a <=> $b } keys %time) {
-           $item++;
-           return $time{$_} if ($item == $what);
-       }
-
-    } 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);
-##         if ($time{$_} eq $what) {
-##             $no = $item;
-##             next;
-##         }
-
-           push(@items, $time{$_}) if ($time{$_} =~ /\Q$what\E/i);
-       }
-
-##     if (defined $no and !@items) {
-##         &::DEBUG("news: string->number resolution: $what->$no.");
-##         return $no;
-##     }
-
-       if (scalar @items > 1) {
-           &::DEBUG("news: Multiple matches, not guessing.");
-           &::notice($who, "Multiple matches, not guessing.");
-           return;
-       }
-
-       if (@items) {
-#          &::DEBUG("news: gNI: part_string->full_string: $what->$items[0]");
-           return $items[0];
-       } else {
-           &::DEBUG("news: gNI: No match for '$what'");
-           return;
-       }
-    }
-
-    &::ERROR("news: gNI: should not happen (what = $what)");
-    return;
-}
-
-sub do_set {
-    my($what,$value) = @_;
-
-    if (!defined $chan) {
-       &::DEBUG("news: do_set: chan not defined.");
-       return;
-    }
-
-    if (!defined $what or $what =~ /^\s*$/) {
-       &::DEBUG("news: what $what is not defined.");
-       return;
-    }
-
-    if (!defined $value or $value =~ /^\s*$/) {
-       &::DEBUG("news: value $value is not defined.");
-       return;
-    }
-
-    &::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;
diff --git a/old/dbm.pl b/old/dbm.pl
deleted file mode 100644 (file)
index 8dc5d4b..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-#
-#      dbm.pl: Extension on the factoid database.
-#  OrigAuthor: Kevin Lenzo  (c) 1997
-#  CurrAuthor: dms <dms@users.sourceforge.net>
-#     Version: v0.6 (20000707)
-#   FModified: 19991020
-#
-
-use strict;
-no strict 'refs';
-
-package main;
-
-use vars qw(%factoids %param);
-
-{
-    # FIXME we don't handle multiply indexes tables
-    # perhaps we should combine the keys with a ':' or something?
-    # the spaces below separate the keys from the rest
-    # of the fields.
-    # Tim Riker thinks that freshmeat below should be a single index
-    my %formats = (
-       'factoids', [
-           'factoid_key',
-
-           'requested_by',
-           'requested_time',
-           'requested_count',
-           'created_by',
-           'created_time',
-           'modified_by',
-           'modified_time',
-           'locked_by',
-           'locked_time',
-           'factoid_value'
-       ],
-       'freshmeat', [
-           'projectname_short',
-           'latest_version',
-
-           'license',
-           'url_homepage',
-           'desc_short'
-       ],
-       'rootwarn', [
-           'nick',
-
-           'attempt',
-           'time',
-           'host',
-           'channel'
-       ],
-       'seen', [
-           'nick',
-
-           'time',
-           'channel',
-           'host',
-           'message'
-       ],
-       'stats', [
-           'nick',
-           'type',
-           'channel',
-
-           'time',
-           'counter'
-       ],
-       'botmail', [
-           'srcwho',
-           'dstwho',
-
-           'srcuh',
-           'time',
-           'msg'
-       ]
-    );
-
-    sub openDB {
-       use DB_File;
-       foreach my $table (keys %formats) {
-           next unless (&IsParam($table));
-
-           my $file = "$param{'DBName'}-$table";
-
-           if (dbmopen(%{"$table"}, $file, 0666)) {
-               &status("Opened DBM $table ($file).");
-           } else {
-               &ERROR("Failed open to DBM $table ($file).");
-               &shutdown();
-               exit 1;
-           }
-       }
-    }
-
-    sub closeDB {
-       foreach my $table (keys %formats) {
-           next unless (&IsParam($table));
-
-           if (dbmclose(%{ $table })) {
-               &status("Closed DBM $table successfully.");
-               next;
-           }
-           &ERROR("Failed closing DBM $table.");
-       }
-    }
-
-    #####
-    # Usage: &dbGetColInfo($table);
-    sub dbGetColInfo {
-       my ($table) = @_;
-
-       if (scalar @{$formats{$table}}) {
-           return @{$formats{$table}};
-       } else {
-           &ERROR("dbGCI: no format for table ($table).");
-           return;
-       }
-    }
-}
-
-#####
-# Usage: &dbQuote($str);
-sub dbQuote {
-    return $_[0];
-}
-
-#####
-# Usage: &dbGet($table, $select, $where);
-sub dbGet {
-    my ($table, $select, $where) = @_;
-    my ($key, $val) = split('=',$where) if $where =~ /=/;
-    my $found = 0;
-    my @retval;
-    my $i;
-    &DEBUG("dbGet($table, $select, $where);");
-    return unless $key;
-
-    my @format = &dbGetColInfo($table);
-    if (!scalar @format) {
-       return;
-    }
-
-    if (!defined ${ "$table" }{lc $val}) {     # dbm hash exception.
-       &DEBUG("dbGet: '$val' does not exist in $table.");
-       return;
-    }
-
-    # return the whole row.
-    if ($select eq "*") {
-       @retval = split $;, ${"$table"}{lc $val};
-       unshift(@retval,$key);
-       return(@retval);
-    }
-
-    # FIXME this should be in $select order
-    # and it's now in field order
-    &DEBUG("dbGet: select=>'$select'.");
-    my @array = split "$;", ${"$table"}{lc $val};
-    unshift(@array,$val);
-    for (0 .. $#format) {
-       my $str = $format[$_];
-       next unless (grep /^$str$/, split(/\,/, $select));
-       $array[$_] ||= '';
-       &DEBUG("dG: '$format[$_]'=>'$array[$_]'.");
-       push(@retval, $array[$_]);
-    }
-
-    if (scalar @retval > 1) {
-       return @retval;
-    } elsif (scalar @retval == 1) {
-       return $retval[0];
-    } else {
-       return;
-    }
-}
-
-#####
-# Usage: &dbGetCol();
-# Usage: &dbGetCol($table, $select, $where, [$type]);
-sub dbGetCol {
-    my ($table, $select, $where, $type) = @_;
-    &FIXME("STUB: &dbGetCol($table, $select, $where, $type);");
-}
-
-#####
-# Usage: &dbGetColNiceHash($table, $select, $where);
-sub dbGetColNiceHash {
-    my ($table, $select, $where) = @_;
-    &DEBUG("dbGetColNiceHash($table, $select, $where);");
-    my ($key, $val) = split('=',$where) if $where =~ /=/;
-    return unless ${$table}{lc $val};
-    my (%hash) = ();
-    $hash{lc $key} = $val;
-    my (@format) = &dbGetColInfo($table);
-    shift @format;
-    @hash{@format} = split $;, ${$table}{lc $val};
-    return %hash;
-}
-
-#####
-# Usage: &dbInsert($table, $primkey, %hash);
-#  Note: dbInsert should do dbQuote.
-sub dbInsert {
-    my ($table, $primkey, %hash) = @_;
-    my $found = 0;
-    &DEBUG("dbInsert($table, $primkey, ...)");
-
-    my $info = ${$table}{lc $primkey} || '';   # primkey or primval?
-
-    my @format = &dbGetColInfo($table);
-    if (!scalar @format) {
-       return 0;
-    }
-
-    my $i;
-    my @array = split $;, $info;
-    delete $hash{$format[0]};
-    for $i (1 .. $#format) {
-       my $col = $format[$i];
-       $array[$i - 1]=$hash{$col};
-       $array[$i - 1]='' unless $array[$i - 1];
-       delete $hash{$col};
-       &DEBUG("dbI: '$col'=>'$array[$i - 1]'");
-    }
-
-    if (scalar keys %hash) {
-       &ERROR("dbI: not added...");
-       foreach (keys %hash) {
-           &ERROR("dbI: '$_'=>'$hash{$_}'");
-       }
-       return 0;
-    }
-
-    ${$table}{lc $primkey}     = join $;, @array;
-
-    return 1;
-}
-
-sub dbUpdate {
-    &FIXME("STUB: &dbUpdate(@_);=>somehow use dbInsert!");
-}
-
-#####
-# Usage: &dbSetRow($table, @values);
-sub dbSetRow {
-    &FIXME("STUB: &dbSetRow(@_)");
-}
-
-#####
-# Usage: &dbDel($table, $primhash_ref);
-#  Note: dbDel does dbQuote
-sub dbDel {
-    my ($table, $phref) = @_;
-    # FIXME does not really handle more than one key!
-    my $primval = join(':', values %{$phref});
-
-    if (!defined ${$table}{lc $primval}) {
-       &DEBUG("dbDel: lc $primval does not exist in $table.");
-    } else {
-       delete ${$table}{lc $primval};
-    }
-
-    return '';
-}
-
-#####
-# Usage: &dbReplace($table, $key, %hash);
-#  Note: dbReplace does optional dbQuote.
-sub dbReplace {
-    my ($table, $key, %hash) = @_;
-    &DEBUG("dbReplace($table, $key, %hash);");
-
-    &dbDel($table, {$key=>$hash{$key}});
-    &dbInsert($table, $hash{$key}, %hash);
-    return 1;
-}
-
-#####
-# Usage: &dbSet($table, $primhash_ref, $hash_ref);
-sub dbSet {
-    my ($table, $phref, $href) = @_;
-    &DEBUG("dbSet(@_)");
-    my ($key) = keys %{$phref};
-    my $where = $key . "=" . $phref->{$key};
-
-    my %hash = &dbGetColNiceHash($table, "*", $where);
-    $hash{$key}=$phref->{$key};
-    foreach (keys %{$href}) {
-       &DEBUG("dbSet: setting $_=${$href}{$_}");
-       $hash{$_} = ${$href}{$_};
-    }
-    &dbReplace($table, $key, %hash);
-    return 1;
-}
-
-sub dbRaw {
-    &FIXME("STUB: &dbRaw(@_);");
-}
-
-sub dbRawReturn {
-    &FIXME("STUB: &dbRawReturn(@_);");
-}
-
-
-
-####################################################################
-##### Factoid related stuff...
-#####
-
-sub countKeys {
-    return scalar keys %{$_[0]};
-}
-
-sub getKeys {
-    &FIXME("STUB: &getKeys(@_); -- REDUNDANT");
-}
-
-sub randKey {
-    &DEBUG("STUB: &randKey(@_);");
-    my ($table, $select) = @_;
-    my @format = &dbGetColInfo($table);
-    if (!scalar @format) {
-       return;
-    }
-
-    my $rand = int(rand(&countKeys($table) - 1));
-    my @keys = keys %{$table};
-    &dbGet($table, '$select', "$format[0]=$keys[$rand]");
-}
-
-#####
-# Usage: &deleteTable($table);
-sub deleteTable {
-    my ($table) = @_;
-    &FIXME("STUB: deleteTable($table)");
-}
-
-##### $select is misleading???
-# Usage: &searchTable($table, $returnkey, $primkey, $str);
-sub searchTable {
-    my ($table, $primkey, $key, $str) = @_;
-    &FIXME("STUB: searchTable($table, $primkey, $key, $str)");
-    return;
-    &DEBUG("searchTable($table, $primkey, $key, $str)");
-
-    if (!scalar &dbGetColInfo($table)) {
-       return;
-    }
-
-    my @results;
-    foreach (keys %{$table}) {
-       my $val = &dbGet($table, "NULL", $_, $key) || '';
-       next unless ($val =~ /\Q$str\E/);
-       push(@results, $_);
-    }
-
-    &DEBUG("sT: ".scalar(@results) );
-
-    @results;
-}
-
-#####
-# Usage: &getFactInfo($faqtoid, $type);
-sub getFactInfo {
-    my ($faqtoid, $type) = @_;
-
-    my @format = &dbGetColInfo("factoids");
-    if (!scalar @format) {
-       return;
-    }
-
-    if (!defined $factoids{$faqtoid}) {        # dbm hash exception.
-       return;
-    }
-
-    if ($type eq "*") {                # all.
-       return split /$;/, $factoids{$faqtoid};
-    }
-
-    # specific.
-    if (!grep /^$type$/, @format) {
-       &ERROR("gFI: type '$type' not valid for factoids.");
-       return;
-    }
-
-    my @array  = split /$;/, $factoids{$faqtoid};
-    for (0 .. $#format) {
-       next unless ($type eq $format[$_]);
-       return $array[$_];
-    }
-
-    &ERROR("gFI: should never happen.");
-}
-
-#####
-# Usage: &getFactoid($faqtoid);
-sub getFactoid {
-    my ($faqtoid) = @_;
-
-    if (!defined $faqtoid or $faqtoid =~ /^\s*$/) {
-       &WARN("getF: faqtoid == NULL.");
-       return;
-    }
-
-    if (defined $factoids{$faqtoid}) { # dbm hash exception.
-       # we assume 1 unfortunately.
-       ### TODO: use &getFactInfo() instead?
-       my $retval = (split $;, $factoids{$faqtoid})[1];
-
-       if (defined $retval) {
-           &DEBUG("getF: returning '$retval' for '$faqtoid'.");
-       } else {
-           &DEBUG("getF: returning NULL for '$faqtoid'.");
-       }
-       return $retval;
-    } else {
-       return;
-    }
-}
-
-#####
-# Usage: &delFactoid($faqtoid);
-sub delFactoid {
-    my ($faqtoid) = @_;
-
-    if (!defined $faqtoid or $faqtoid =~ /^\s*$/) {
-       &WARN("delF: faqtoid == NULL.");
-       return;
-    }
-
-    if (defined $factoids{$faqtoid}) { # dbm hash exception.
-       delete $factoids{$faqtoid};
-       &status("DELETED $faqtoid");
-    } else {
-       &WARN("delF: nothing to deleted? ($faqtoid)");
-       return;
-    }
-}
-
-sub checkTables {
-# nothing - DB_FIle will create them on openDB()
-}
-
-1;