-/* helpserv.c - Support Helper assistant service
+/* mod-helpserv.c - Support Helper assistant service
* Copyright 2002-2003 srvx Development Team
*
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of srvx.
+ *
+ * srvx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version. Important limitations are
- * listed in the COPYING file that accompanies this software.
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, email srvx-maintainers@srvx.net.
+ * along with srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
/* Wishlist for helpserv.c
{ "HSMSG_STATS_TIME", "$uTime spent helping in %s:$u" },
{ "HSMSG_STATS_REQS", "$uRequest activity statistics:$u" },
+/* Status report headers */
+ { "HSMSG_STATS_REPORT_0", "Stats report for current week" },
+ { "HSMSG_STATS_REPORT_1", "Stats report for one week ago" },
+ { "HSMSG_STATS_REPORT_2", "Stats report for two weeks ago" },
+ { "HSMSG_STATS_REPORT_3", "Stats report for three weeks ago" },
+
/* Responses to user commands */
{ "HSMSG_YOU_BEING_HELPED", "You are already being helped." },
{ "HSMSG_YOU_BEING_HELPED_BY", "You are already being helped by $b%s$b." },
};
static const char *statsreport_week[] = {
- "Stats report for current week",
- "Stats report for one week ago",
- "Stats report for two weeks ago",
- "Stats report for three weeks ago"
+ "HSMSG_STATS_REPORT_0",
+ "HSMSG_STATS_REPORT_1",
+ "HSMSG_STATS_REPORT_2",
+ "HSMSG_STATS_REPORT_3"
};
static struct {
static time_t last_stats_update;
static int shutting_down;
static FILE *reqlog_f;
-static struct saxdb_context *reqlog_ctx;
static struct log_type *HS_LOG;
#define CMD_NEED_BOT 0x001
static void helpserv_log_request(struct helpserv_request *req, const char *reason) {
char key[27+NICKLEN];
char userhost[USERLEN+HOSTLEN+2];
+ struct saxdb_context *ctx;
+ int res;
- if (!reqlog_ctx || !req)
+ assert(req != NULL);
+ assert(reason != NULL);
+ if (!(ctx = saxdb_open_context(reqlog_f)))
return;
- if (!reason)
- reason = "";
-
sprintf(key, "%s-" FMT_TIME_T "-%lu", req->hs->helpserv->nick, req->opened, req->id);
- saxdb_start_record(reqlog_ctx, key, 1);
- if (req->helper) {
- saxdb_write_string(reqlog_ctx, KEY_REQUEST_HELPER, req->helper->handle->handle);
- saxdb_write_int(reqlog_ctx, KEY_REQUEST_ASSIGNED, req->assigned);
- }
- if (req->handle) {
- saxdb_write_string(reqlog_ctx, KEY_REQUEST_HANDLE, req->handle->handle);
- }
- if (req->user) {
- saxdb_write_string(reqlog_ctx, KEY_REQUEST_NICK, req->user->nick);
- sprintf(userhost, "%s@%s", req->user->ident, req->user->hostname);
- saxdb_write_string(reqlog_ctx, KEY_REQUEST_USERHOST, userhost);
+ if ((res = setjmp(ctx->jbuf)) != 0) {
+ log_module(HS_LOG, LOG_ERROR, "Unable to log helpserv request: %s.", strerror(res));
+ } else {
+ saxdb_start_record(ctx, key, 1);
+ if (req->helper) {
+ saxdb_write_string(ctx, KEY_REQUEST_HELPER, req->helper->handle->handle);
+ saxdb_write_int(ctx, KEY_REQUEST_ASSIGNED, req->assigned);
+ }
+ if (req->handle) {
+ saxdb_write_string(ctx, KEY_REQUEST_HANDLE, req->handle->handle);
+ }
+ if (req->user) {
+ saxdb_write_string(ctx, KEY_REQUEST_NICK, req->user->nick);
+ sprintf(userhost, "%s@%s", req->user->ident, req->user->hostname);
+ saxdb_write_string(ctx, KEY_REQUEST_USERHOST, userhost);
+ }
+ saxdb_write_int(ctx, KEY_REQUEST_OPENED, req->opened);
+ saxdb_write_int(ctx, KEY_REQUEST_CLOSED, now);
+ saxdb_write_string(ctx, KEY_REQUEST_CLOSEREASON, reason);
+ saxdb_write_string_list(ctx, KEY_REQUEST_TEXT, req->text);
+ saxdb_end_record(ctx);
+ saxdb_close_context(ctx);
+ fflush(reqlog_f);
}
- saxdb_write_int(reqlog_ctx, KEY_REQUEST_OPENED, req->opened);
- saxdb_write_int(reqlog_ctx, KEY_REQUEST_CLOSED, now);
- saxdb_write_string(reqlog_ctx, KEY_REQUEST_CLOSEREASON, reason);
- saxdb_write_string_list(reqlog_ctx, KEY_REQUEST_TEXT, req->text);
- saxdb_end_record(reqlog_ctx);
-
- fflush(reqlog_f);
}
/* Searches for a request by number, nick, or account (num|nick|*account).
sprintf(lbuf[0], fmt, req->id);
}
if (req != hs->unhandled) {
- intervalString(unh, now - hs->unhandled->opened);
+ intervalString(unh, now - hs->unhandled->opened, user->handle_info);
fmt = user_find_message(user, "HSMSG_REQ_UNHANDLED_TIME");
sprintf(lbuf[1], fmt, unh);
} else {
char buf[MAX_LINE_SIZE], updatestr[INTERVALLEN], timestr[MAX_LINE_SIZE];
strftime(timestr, MAX_LINE_SIZE, HSFMT_TIME, localtime(&req->opened));
- intervalString(updatestr, now - req->updated);
+ intervalString(updatestr, now - req->updated, user->handle_info);
if (req->helper && (hs->notify >= NOTIFY_USER))
if (user->handle_info)
helpserv_notify(req->helper, "HSMSG_PAGE_UPD_REQUEST_AUTHED", req->id, user->nick, user->handle_info->handle, timestr, updatestr);
pos = count;
}
assert(pos >= 0);
- intervalString(buf, now - req->hs->unhandled->opened);
+ intervalString(buf, now - req->hs->unhandled->opened, req->user->handle_info);
helpserv_user_reply("HSMSG_WAIT_STATUS", pos+1, count, buf);
}
struct modeNode *mn = GetUserMode(hs->helpchan, req_user);
if ((!newest || !newest->helper) && mn && (mn->modes & MODE_VOICE)) {
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_REMOVE | MODE_VOICE;
change.args[0].member = mn;
}
tbl.contents[line][1] = strdup(username);
tbl.contents[line][2] = req->helper ? req->helper->handle->handle : "(Unassigned)";
- intervalString(opentime, now - req->opened);
+ intervalString(opentime, now - req->opened, user->handle_info);
tbl.contents[line][3] = strdup(opentime);
tbl.contents[line][4] = ((req->user || req->handle->users) ? "Online" : "Offline");
}
else
helpserv_notice(user, "HSMSG_REQ_INFO_2e");
strftime(buf, MAX_LINE_SIZE, HSFMT_TIME, localtime(&req->opened));
- intervalString(buf2, now - req->opened);
+ intervalString(buf2, now - req->opened, user->handle_info);
helpserv_notice(user, "HSMSG_REQ_INFO_3", buf, buf2);
helpserv_notice(user, "HSMSG_REQ_INFO_4");
for (nn=0; nn < req->text->used; nn++)
if (req->user && hs->auto_voice) {
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_VOICE;
if ((change.args[0].member = GetUserMode(hs->helpchan, req->user)))
AddChannelUser(hs->helpserv, hs->helpchan)->modes |= MODE_CHANOP;
} else if (!helpserv_in_channel(hs, old_helpchan)) {
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = AddChannelUser(hs->helpserv, hs->helpchan);
tbl.contents[i][1] = bot->helpchan->name;
tbl.contents[i][2] = owner ? owner->handle->handle : "None";
tbl.contents[i][3] = alloca(INTERVALLEN);
- intervalString((char*)tbl.contents[i][3], now - bot->last_active);
+ intervalString((char*)tbl.contents[i][3], now - bot->last_active, user->handle_info);
}
table_send((from_opserv ? opserv : hs->helpserv), user->nick, 0, NULL, tbl);
helpserv_msguser(req->user, "HSMSG_REQ_UNASSIGNED", req->id, reason);
if (hs->auto_devoice && mn && (mn->modes & MODE_VOICE)) {
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_REMOVE | MODE_VOICE;
change.args[0].member = mn;
if (reqlist.used) {
char strwhinedelay[INTERVALLEN];
- intervalString(strwhinedelay, (time_t)hs->intervals[INTERVAL_WHINE_DELAY]);
+ intervalString(strwhinedelay, (time_t)hs->intervals[INTERVAL_WHINE_DELAY], NULL);
#if ANNOYING_ALERT_PAGES
tbl.length = reqlist.used + 1;
tbl.width = 4;
tbl.contents[i][0] = strdup(reqid);
tbl.contents[i][1] = unh->user ? unh->user->nick : "Not online";
tbl.contents[i][2] = unh->handle ? unh->handle->handle : "Not authed";
- intervalString(unh_time, now - unh->opened);
+ intervalString(unh_time, now - unh->opened, NULL);
tbl.contents[i][3] = strdup(unh_time);
}
}
tbl.contents[i][2] = strdup(reqid);
- intervalString(idle_time, now - mn->idle_since);
+ intervalString(idle_time, now - mn->idle_since, NULL);
tbl.contents[i][3] = strdup(idle_time);
}
- intervalString(stridledelay, (time_t)hs->intervals[INTERVAL_IDLE_DELAY]);
+ intervalString(stridledelay, (time_t)hs->intervals[INTERVAL_IDLE_DELAY], NULL);
helpserv_page(PGSRC_STATUS, "HSMSG_PAGE_IDLE_HEADER", mode_list.used, hs->helpchan->name, stridledelay);
table_send(hs->helpserv, hs->page_targets[PGSRC_STATUS]->name, 0, page_types[hs->page_types[PGSRC_STATUS]].func, tbl);
* it's a harmless default */
hs = calloc(1, sizeof(struct helpserv_bot));
- if (!(hs->helpserv = AddService(nick, helpserv_conf.description))) {
+ if (!(hs->helpserv = AddService(nick, helpserv_conf.description, NULL))) {
free(hs);
return NULL;
}
AddChannelUser(hs->helpserv, hs->helpchan)->modes |= MODE_CHANOP;
} else {
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = AddChannelUser(hs->helpserv, hs->helpchan);
DelChannelUser(hs->helpserv, old_target, "Changing page target.", 0);
if (new_target && !helpserv_in_channel(hs, new_target)) {
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = AddChannelUser(hs->helpserv, new_target);
return 0;
}
if (new_int && new_int < min) {
- intervalString(buf, min);
+ intervalString(buf, min, user->handle_info);
helpserv_notice(user, "HSMSG_INVALID_INTERVAL", user_find_message(user, interval_types[idx].print_name), buf);
return 0;
}
changed = 1;
}
if (hs->intervals[idx]) {
- intervalString(buf, hs->intervals[idx]);
+ intervalString(buf, hs->intervals[idx], user->handle_info);
helpserv_notice(user, interval_types[idx].print_name, buf);
} else
helpserv_notice(user, interval_types[idx].print_name, user_find_message(user, "HSMSG_0_DISABLED"));
str = database_get_data(conf_node, "user_escape", RECDB_QSTRING);
helpserv_conf.user_escape = str ? str[0] : '@';
- if (reqlog_ctx) {
- saxdb_close_context(reqlog_ctx);
- reqlog_ctx = NULL;
- }
if (reqlog_f) {
fclose(reqlog_f);
reqlog_f = NULL;
}
- if (helpserv_conf.reqlogfile) {
- if (!(reqlog_f = fopen(helpserv_conf.reqlogfile, "a"))) {
- log_module(HS_LOG, LOG_ERROR, "Unable to open request logfile (%s): %s", helpserv_conf.reqlogfile, strerror(errno));
- } else {
- reqlog_ctx = saxdb_open_context(reqlog_f);
- }
+ if (helpserv_conf.reqlogfile
+ && !(reqlog_f = fopen(helpserv_conf.reqlogfile, "a"))) {
+ log_module(HS_LOG, LOG_ERROR, "Unable to open request logfile (%s): %s", helpserv_conf.reqlogfile, strerror(errno));
}
}
if (hs->auto_voice && req->helper)
{
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_VOICE;
if ((change.args[0].member = GetUserMode(hs->helpchan, user)))
dict_delete(helpserv_reqs_byhand_dict);
dict_delete(helpserv_users_byhand_dict);
- if (reqlog_ctx)
- saxdb_close_context(reqlog_ctx);
if (reqlog_f)
fclose(reqlog_f);
}