/**
* This handler will do any mud base manipulations of the twiki
* database.
* @author Pinkfish
* @started Wed May 24 17:19:06 PDT 2000
*/
#include <board.h>
void do_check_changes();
#define SAVE_FILE "/save/twiki"
#define CHECK_TIME (7 * 24 * 60 * 60)
#define TWIKI_CHANGE_FILE "/.changes"
#define TWIKI_DATA_DIRECTORY "/twiki/data/"
private nosave string* _databases;
private int _last_check;
private mapping _last_change;
void create() {
_databases = ({ "Main", "Am", "Ram", "Cwc", "Sur", "Klatch",
"Forn", "Underworld", "Other", "Playtesters" });
seteuid(getuid());
restore_object(SAVE_FILE);
if (_last_check + CHECK_TIME < time()) {
do_check_changes();
}
call_out("do_check_changes", _last_check + CHECK_TIME - time());
if (!_last_change) {
_last_change = ([ ]);
}
call_out("do_change_inform", 60 * 5);
} /* setup() */
/**
* This method finds the pages that have changed since the specified time.
* @param limit the time after which to find the changes
* @return the mapping of pages to who changed them
*/
mapping find_changed_pages(int limit, string database) {
string* lines;
int i;
int tim;
string page;
string author;
mixed* bits;
mapping changes_pages;
lines = explode(read_file(TWIKI_DATA_DIRECTORY + database + TWIKI_CHANGE_FILE), "\n");
changes_pages = ([ ]);
for (i = 1; i < sizeof(lines); i++) {
bits = reg_assoc(lines[<i], ({ "([a-zA-Z][a-zA-Z0-9]+)", "[0-9]+" }), ({ 1, 2 }) );
if (sizeof(bits[0]) == 9 || sizeof(bits[0]) == 7) {
page = bits[0][1];
author = bits[0][3];
sscanf(bits[0][5], "%d", tim);
if (tim > limit) {
//
// Ignore all the user page changes...
//
if (page[0..4] != "TWiki" &&
page[0..9] != "Underworld" &&
author != "PeterThoeny" &&
page != author &&
page != "WebPreferences") {
//
// Read the page and determine from that.
//
if (file_size("/twiki/data/" + database + "/" + page + ".txt") > 0 &&
strsrch(read_file("/twiki/data/" + database + "/" + page + ".txt"),
"\t* Login Name:") == -1) {
if (!changes_pages[page]) {
changes_pages[page] = ({ });
}
if (member_array(author, changes_pages[page]) == -1) {
changes_pages[page] += ({ author });
}
}
}
} else {
break;
}
} else {
break;
}
}
return changes_pages;
} /* find_changed_pages() */
/**
* This method prints out any changes since the specified limit.
* @param limit the time after which to show any changes
* @return the changes since that time
*/
string find_changes(int limit) {
mapping changes_pages;
string ret;
string page;
string database;
ret = "Changes since " + ctime(limit) + " in\n"
"http://discworld.imaginary.com/twiki/bin/view/Main/WebHome\n\n";
foreach (database in _databases) {
changes_pages = find_changed_pages(limit, database);
foreach (page in sort_array(keys(changes_pages), 1)) {
ret += sprintf("%-30s changed by %s\n", database + "." + page,
query_multiple_short(changes_pages[page]));
}
}
return ret;
} /* find_changes() */
/**
* This method prints out any changes since the specified limit.
* @param database the database to find the changes in
* @param limit the time after which to show any changes
* @return the changes since that time
*/
string find_changes_in_database(string database, int limit) {
mapping changes_pages;
string ret;
string page;
if (database == "Playtesters") {
ret = "Changes since " + ctime(limit) + " in\n"
"http://discworld.imaginary.com/twiki/pt/bin/view/Playtesters/WebHome\n\n";
} else {
ret = "Changes since " + ctime(limit) + " in\n"
"http://discworld.imaginary.com/twiki/bin/view/Main/WebHome\n\n";
}
changes_pages = find_changed_pages(limit, database);
foreach (page in sort_array(keys(changes_pages), 1)) {
ret += sprintf("%-30s changed by %s\n", database + "." + page,
query_multiple_short(changes_pages[page]));
}
return ret;
} /* find_changes() */
/**
* This method finds the specified file and shows it to us.
* @param fname the file name to find
* @return the text of the file, 0 if the file is not found
*/
string query_file(string fname) {
if (strsrch(fname, ".") > 0) {
fname = "/twiki/data/" + replace_string(fname, ".", "/") + ".txt";
} else {
fname = "/twiki/data/Main/" + fname + ".txt";
}
if (sizeof(stat(fname))) {
return read_file(fname);
}
return 0;
} /* query_file() */
/** @ignore yes */
void do_check_changes() {
string changes;
changes = find_changes(_last_check);
BOARD_HAND->add_message("commonroom", "Twiki Database",
"Changes in the Twiki database",
changes);
_last_check = time();
save_object(SAVE_FILE);
call_out("do_check_changes", _last_check + CHECK_TIME - time());
} /* do_changes() */
/** @ignore yes */
void do_change_inform() {
int changed;
mapping changed_pages;
string page;
string* changers;
int dosave;
string database;
//
// See if the file has changed.
//
if (!mapp(_last_change)) {
_last_change = ([ ]);
}
foreach (database in _databases) {
if (!_last_change[database]) {
_last_change[database] = time();
dosave = 1;
} else {
changed = stat(TWIKI_DATA_DIRECTORY + database + TWIKI_CHANGE_FILE)[1];
if (changed != _last_change[database]) {
//
// Do an inform about it...
//
changed_pages = find_changed_pages(_last_change[database], database);
_last_change[database] = changed;
dosave = 1;
foreach (page, changers in changed_pages) {
user_event( "inform",
sprintf( "%s changes the twiki page %s.%s",
query_multiple_short(changers), database,
page),
"message",
this_player() );
}
}
}
}
if (dosave) {
save_object(SAVE_FILE);
}
call_out("do_change_inform", 60 * 5);
} /* do_change_inform() */