This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats-logserv/logserv.c

749 lines
21 KiB
C
Executable file

/* NeoStats - IRC Statistical Services
** Copyright (c) 1999-2004 Justin Hammond
** http://www.neostats.net/
**
** This program 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.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** 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, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
** USA
**
** NeoStats CVS Identification
** $Id$
*/
/** template.c
* You can copy this file as a template for writing your own modules
*/
#include <stdio.h>
#include "modconfig.h"
#include "logserv.h"
/* forward decl */
static int lgs_about(User * u, char **av, int ac);
static int lgs_version(User * u, char **av, int ac);
static int lgs_chans(User * u, char **av, int ac);
static int lgs_stats(User * u, char **av, int ac);
static int lgs_send_to_logproc( logmsgtype msgtype, ChannelLog *lgschan, char **av, int ac);
static void lgs_save_channels_data(ChannelLog *cl);
ChannelLog *lgs_newchanlog(User *u, char **av, int ac);
ChannelLog *lgs_findactchanlog(Chans *c);
logtype_proc logging_funcs[] = {
{logserv_joinproc, logserv_partproc, logserv_msgproc, logserv_quitproc, logserv_topicproc, logserv_kickproc, logserv_nickproc, logserv_modeproc},
{egg_joinproc, egg_partproc, egg_msgproc, egg_quitproc, egg_topicproc, egg_kickproc, egg_nickproc, egg_modeproc},
{mirc_joinproc, mirc_partproc, mirc_msgproc, mirc_quitproc, mirc_topicproc, mirc_kickproc, mirc_nickproc, mirc_modeproc},
{xchat_joinproc, xchat_partproc, xchat_msgproc, xchat_quitproc, xchat_topicproc, xchat_kickproc, xchat_nickproc, xchat_modeproc},
};
/** Module Info definition
* version information about our module
* This structure is required for your module to load and run on NeoStats
*/
ModuleInfo __module_info = {
"LogServ",
"Channel Logging Bot",
MODULE_VERSION,
__DATE__,
__TIME__
};
bot_cmd lgs_commands[]=
{
{"ABOUT", lgs_about, 0, 0, lgs_help_about, lgs_help_about_oneline},
{"VERSION", lgs_version, 0, 0, lgs_help_version, lgs_help_version_oneline},
{"CHANS", lgs_chans, 1, NS_ULEVEL_OPER, lgs_help_chan, lgs_help_chan_oneline},
{"STATS", lgs_stats, 0, 0, lgs_help_stats, lgs_help_stats_oneline},
{NULL, NULL, 0, 0, NULL, NULL}
};
bot_setting lgs_settings[]=
{
{"NICK", &s_LogServ, SET_TYPE_NICK, 0, MAXNICK, NS_ULEVEL_ADMIN, "Nick", NULL, ns_help_set_nick },
{"USER", &LogServ.user, SET_TYPE_USER, 0, MAXUSER, NS_ULEVEL_ADMIN, "User", NULL, ns_help_set_user },
{"HOST", &LogServ.host, SET_TYPE_HOST, 0, MAXHOST, NS_ULEVEL_ADMIN, "Host", NULL, ns_help_set_host },
{"REALNAME",&LogServ.realname, SET_TYPE_REALNAME, 0, MAXREALNAME, NS_ULEVEL_ADMIN, "RealName",NULL, ns_help_set_realname },
{"LOGTYPE",
&LogServ.logtype,
SET_TYPE_INT,
1,
3,
NS_ULEVEL_ADMIN,
"LogType",
"Log Type",
lgs_help_set_logtype },
{"LOGSIZE",
&LogServ.maxlogsize,
SET_TYPE_INT,
0,
10000000,
NS_ULEVEL_ADMIN,
"LogSwitchSize",
"Bytes",
lgs_help_set_logsize },
{"LOGAGE",
&LogServ.maxopentime,
SET_TYPE_INT,
0,
86400,
NS_ULEVEL_ADMIN,
"LogSwitchTime",
"Seconds",
lgs_help_set_logtime },
{NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL },
};
/** Module function list
* A list of IRCd (server) commands that we will respond to
* e.g. VERSION
* This table is required for your module to load and run on NeoStats
* but you do not have to have any functions in it
*/
Functions __module_functions[] = {
{NULL, NULL, 0}
};
/** Channel message processing
* What do we do with messages in channes
* This is required if you want your module to respond to channel messages
*/
int __ChanMessage(char *origin, char **argv, int argc)
{
char *chan = argv[0];
Chans *c;
ChannelLog *cl;
char **data;
int datasize = 0;
char *buf;
SET_SEGV_INMODULE(__module_info.module_name);
if (argc <= 1) {
return NS_FAILURE;
}
c = findchan(chan);
if (c && c->moddata[LogServ.modnum]) {
cl = c->moddata[LogServ.modnum];
AddStringToList(&data, origin, &datasize);
if (argv[1][0] == '\1') {
AddStringToList(&data, argv[1], &datasize);
buf = joinbuf(argv, argc, 2);
} else {
buf = joinbuf(argv, argc, 1);
}
strip_mirc_codes(buf);
AddStringToList(&data, buf, &datasize);
lgs_send_to_logproc(LGSMSG_MSG, cl, data, datasize);
free(data);
}
return 1;
}
static int lgs_PartChan(char **av, int ac)
{
ChannelLog *cl;
Chans *c;
/* this function is called recursively, so ignore parts by LogServ */
if (!strcasecmp(av[1], s_LogServ)) {
return NS_FAILURE;
}
c = findchan(av[0]);
if ((cl = lgs_findactchanlog(c)) != NULL) {
/* process the part message now */
lgs_send_to_logproc(LGSMSG_PART, cl, av, ac);
if (c->cur_users == 2) {
/* last user just parted, so we leave as well */
nlog(LOG_DEBUG1, LOG_MOD, "Parting Channel %s as there are no more members", c->name);
/*close/switch the logfile*/
lgs_switch_file(cl);
spart_cmd(s_LogServ, c->name);
c->moddata[LogServ.modnum] = NULL;
cl->c = NULL;
cl->flags &= ~LGSACTIVE;
}
return NS_SUCCESS;
}
return NS_SUCCESS;
}
static int lgs_JoinChan(char **av, int ac) {
ChannelLog *cl;
if (!strcasecmp(av[1], s_LogServ)) {
/* its me, so ignore */
return NS_FAILURE;
}
if ((cl = lgs_findactchanlog(findchan(av[0]))) != NULL) {
lgs_send_to_logproc(LGSMSG_JOIN, cl, av, ac);
return NS_SUCCESS;
}
return NS_SUCCESS;
}
static int lgs_NewChan(char **av, int ac)
{
ChannelLog *cl;
hnode_t *cn;
Chans *c;
c = findchan(av[0]);
cn = hash_lookup(lgschans, av[0]);
if (!cn)
return NS_FAILURE;
cl = hnode_get(cn);
if (c && cl) {
if (join_bot_to_chan(s_LogServ, cl->channame, 0) == NS_SUCCESS) {
SET_SEGV_INMODULE(__module_info.module_name);
cl->flags |= LGSACTIVE;
nlog(LOG_NOTICE, LOG_MOD, "Actived Logging on channel %s", cl->channame);
if (cl->statsurl[0] != '\0') {
prefmsg(cl->channame, s_LogServ, "Stats will be avaiable at %s when Logs are processed next", cl->statsurl);
}
}
c->moddata[LogServ.modnum] = cl;
cl->c = c;
}
return NS_SUCCESS;
}
/** Online event processing
* What we do when we first come online
*/
static int lgs_Online(char **av, int ac)
{
ChannelLog *cl;
hnode_t *cn;
char **row;
int count;
Chans *c;
char *tmp;
/* Introduce a bot onto the network */
lgs_bot = init_mod_bot(s_LogServ, LogServ.user, LogServ.host, LogServ.realname, services_bot_modes,
BOT_FLAG_ONLY_OPERS, lgs_commands, lgs_settings, __module_info.module_name);
/* load Channels and join them */
if (GetTableData("Chans", &row) > 0) {
for (count = 0; row[count] != NULL; count++) {
nlog(LOG_DEBUG1, LOG_MOD, "Loading Channel %s", row[count]);
cl = malloc(sizeof(ChannelLog));
bzero(cl, sizeof(ChannelLog));
strlcpy(cl->channame, row[count], CHANLEN);
if (GetData((void *)&cl->flags, CFGINT, "Chans", cl->channame, "Flags") > 0) {
cl->flags &= ~LGSACTIVE;
cl->flags &= ~LGSFDNEEDFLUSH;
cl->flags &= ~LGSFDOPENED;
}
if (GetData((void *)&tmp, CFGSTR, "Chans", cl->channame, "URL") < 0) {
cl->statsurl[0] = '\0';
} else {
strlcpy(cl->statsurl, tmp, MAXPATH);
}
c = findchan(cl->channame);
if (c) {
if (join_bot_to_chan(s_LogServ, cl->channame, 0) == NS_SUCCESS) {
SET_SEGV_INMODULE(__module_info.module_name);
cl->flags |= LGSACTIVE;
nlog(LOG_NOTICE, LOG_MOD, "Actived Logging on channel %s", cl->channame);
if (cl->statsurl[0] != '\0') {
prefmsg(cl->channame, s_LogServ, "Stats will be avaiable at %s when Logs are processed next", cl->statsurl);
}
}
c->moddata[LogServ.modnum] = cl;
cl->c = c;
}
cn = hnode_create(cl);
hash_insert(lgschans, cn, cl->channame);
}
}
/* start a timer to scan the logs for rotation */
add_mod_timer("lgs_RotateLogs", "Rotate_LogServ_Logs", __module_info.module_name, 300);
return 1;
};
static int lgs_Signoff(char **av, int ac) {
/* This function is kinda useless, because,
* partchan will be called for each channel the user is a member off
* before this function is called. - Damn
*/
#if 0
ChannelLog *cl;
if (!strcasecmp(av[0], s_LogServ)) {
/* its me, so ignore */
return NS_FAILURE;
}
if ((cl = lgs_findactchanlog(findchan(av[0]))) != NULL) {
lgs_send_to_logproc(LGSMSG_QUIT, cl, av, ac);
return NS_SUCCESS;
}
#endif
return NS_SUCCESS;
}
static int lgs_KickChan(char **av, int ac) {
ChannelLog *cl;
if (!strcasecmp(av[1], s_LogServ)) {
/* its me, so ignore */
return NS_FAILURE;
}
if ((cl = lgs_findactchanlog(findchan(av[0]))) != NULL) {
lgs_send_to_logproc(LGSMSG_KICK, cl, av, ac);
if (cl->c->cur_users == 2) {
/* last user just parted, so we leave as well */
nlog(LOG_DEBUG1, LOG_MOD, "Parting Channel %s as there are no more members", cl->channame);
lgs_switch_file(cl);
spart_cmd(s_LogServ, cl->channame);
cl->c->moddata[LogServ.modnum] = NULL;
cl->c = NULL;
cl->flags &= ~LGSACTIVE;
}
return NS_SUCCESS;
}
return NS_SUCCESS;
}
static int lgs_TopicChan(char **av, int ac) {
ChannelLog *cl;
if (!strcasecmp(av[1], s_LogServ)) {
/* its me, so ignore */
return NS_FAILURE;
}
if ((cl = lgs_findactchanlog(findchan(av[0]))) != NULL) {
lgs_send_to_logproc(LGSMSG_TOPIC, cl, av, ac);
return NS_SUCCESS;
}
return NS_SUCCESS;
}
static int lgs_NickChange(char **av, int ac) {
ChannelLog *cl;
User *u;
lnode_t *cm;
if (!strcasecmp(av[1], s_LogServ)) {
/* its me, so ignore */
return NS_FAILURE;
}
u = finduser(av[1]);
if (!u) {
return NS_FAILURE;
}
/* ok, move through each of the channels */
cm = list_first (u->chans);
while (cm) {
if ((cl = lgs_findactchanlog(findchan (lnode_get (cm)))) != NULL) {
lgs_send_to_logproc(LGSMSG_NICK, cl, av, ac);
}
cm = list_next (u->chans, cm);
}
return NS_SUCCESS;
}
/* damn, 2.5.11 doesn't have a chan mode event. Duh! */
#ifdef EVENT_CHANMODE
static int lgs_ChanMode(char **av, int ac) {
ChannelLog *cl;
if (!strcasecmp(av[0], s_LogServ)) {
/* its me, so ignore */
return NS_FAILURE;
}
if ((cl = lgs_findactchanlog(findchan(av[1]))) != NULL) {
lgs_send_to_logproc(LGSMSG_CHANMODE, cl, av, ac);
return NS_SUCCESS;
}
return NS_SUCCESS;
}
#endif
/** Module event list
* What events we will act on
* This is required if you want your module to respond to events on IRC
* see modules.txt for a list of all events available
*/
EventFnList __module_events[] = {
{EVENT_ONLINE, lgs_Online},
{EVENT_NEWCHAN, lgs_NewChan},
{EVENT_JOINCHAN, lgs_JoinChan},
{EVENT_PARTCHAN, lgs_PartChan},
{EVENT_SIGNOFF, lgs_Signoff},
{EVENT_KICK, lgs_KickChan},
{EVENT_TOPICCHANGE, lgs_TopicChan},
{EVENT_NICKCHANGE, lgs_NickChange},
#ifdef EVENT_CHANMODE
{EVENT_CHANMODE, lgs_ChanMode},
#endif
{NULL, NULL}
};
/** Init module
* This is required if you need to do initialisation of your module when
* first loaded
*/
int __ModInit(int modnum, int apiver)
{
char *tmp;
#ifdef NS_ERR_VERSION /* Forward port version checks */
/* Check that our compiled version if compatible with the calling version of NeoStats */
if( ircstrncasecmp (me.version, NEOSTATS_VERSION, VERSIONSIZE) !=0) {
return NS_ERR_VERSION;
}
#endif
strlcpy(s_LogServ, "LogServ", MAXNICK);
lgschans = hash_create(-1, 0,0);
if (GetConf((void *) &tmp, CFGSTR, "Nick") < 0) {
strlcpy(s_LogServ, "LogServ", MAXNICK);
} else {
strlcpy(s_LogServ, tmp, MAXNICK);
free(tmp);
}
if (GetConf((void *) &tmp, CFGSTR, "User") < 0) {
strlcpy(LogServ.user, "LogBot", MAXUSER);
} else {
strlcpy(LogServ.user, tmp, MAXUSER);
free(tmp);
}
if (GetConf((void *) &tmp, CFGSTR, "Host") < 0) {
strlcpy(LogServ.host, me.name, MAXHOST);
} else {
strlcpy(LogServ.host, tmp, MAXHOST);
free(tmp);
}
if (GetConf((void *) &tmp, CFGSTR, "RealName") < 0) {
ircsnprintf(LogServ.realname, MAXREALNAME, "Channel Logging Bot");
} else {
strlcpy(LogServ.realname, tmp, MAXREALNAME);
free(tmp);
}
/* get the logtype */
if (GetConf((void *)&LogServ.logtype, CFGINT, "LogType") < 0) {
LogServ.logtype = 1;
}
/* get the logsize switch */
if (GetConf((void *)&LogServ.maxlogsize, CFGINT, "LogSwitchSize") < 0) {
/* 1Mb, or there abouts is default */
LogServ.maxlogsize = 1000000;
}
/* get the logage time */
if (GetConf((void *)&LogServ.maxopentime, CFGINT, "LogSwitchTime") < 0) {
/* switch every 1 hour */
LogServ.maxopentime = 3600;
}
/*XXX TODO */
ircsnprintf(LogServ.logdir, MAXPATH, "logs/chanlogs");
ircsnprintf(LogServ.savedir, MAXPATH, "ChanLogs");
LogServ.modnum = modnum;
return 1;
}
/** Init module
* This is required if you need to do cleanup of your module when it ends
*/
void __ModFini()
{
/* close the log files */
lgs_close_logs();
/* delete the hash */
hash_destroy(lgschans);
};
/* ok, now here are logservs functions */
/* @brief Send Description of Module to user
*
* @param u The user requesting help
* @param av the text sent
* @param ac the number of words in av
* @returns NS_SUCCESS or NS_FAILURE
*/
static int lgs_about(User * u, char **av, int ac) {
privmsg_list(u->nick, s_LogServ, lgs_help_about);
return 1;
}
/* @brief Send version of Module to user
*
* @param u The user requesting version
* @param av the text sent
* @param ac the number of words in av
* @returns NS_SUCCESS or NS_FAILURE
*/
static int lgs_version(User * u, char **av, int ac) {
SET_SEGV_LOCATION();
prefmsg(u->nick, s_LogServ, "\2%s Version Information\2", s_LogServ);
prefmsg(u->nick, s_LogServ, "%s Version: %s Compiled %s at %s", s_LogServ, __module_info.module_version, __module_info.module_build_date, __module_info.module_build_time);
return 1;
}
/* @brief manipulate the logged channels
*
* @param u The user requesting channel data
* @param av the text sent
* @param ac the number of words in av
* @returns NS_SUCCESS or NS_FAILURE
*/
static int lgs_chans(User * u, char **av, int ac) {
hscan_t hs;
hnode_t *hn;
ChannelLog *cl;
if (!strcasecmp(av[2], "LIST")) {
prefmsg(u->nick, s_LogServ, "Monitored Channel List:");
hash_scan_begin(&hs, lgschans);
while ((hn = hash_scan_next(&hs)) != NULL) {
cl = hnode_get(hn);
if ((cl->flags & LGSPUBSTATS) || (UserLevel(u) >= NS_ULEVEL_LOCOPER)) {
/* its a priv channel, only show to opers */
prefmsg(u->nick, s_LogServ, "%s (%c) URL: %s", cl->channame, (cl->flags & LGSACTIVE) ? '*' : '-', (cl->statsurl[0] != 0) ? cl->statsurl : "None");
}
}
prefmsg(u->nick, s_LogServ, "End Of List.");
return NS_SUCCESS;
} else if (!strcasecmp(av[2], "DEL")) {
if (ac < 4) {
prefmsg(u->nick, s_LogServ, "Syntax error: insufficient parameters");
prefmsg(u->nick, s_LogServ, "/msg %s HELP CHANS for more information", s_LogServ);
return NS_FAILURE;
}
hn = hash_lookup(lgschans, av[3]);
if (hn) {
cl = hnode_get(hn);
} else {
prefmsg(u->nick, s_LogServ, "Can not find channel %s in Logging System", av[3]);
return NS_FAILURE;
}
if (!cl) {
prefmsg(u->nick, s_LogServ, "Can not find Channel %s in Logging System", av[3]);
return NS_FAILURE;
}
/* rotate out the file */
if (cl->flags & LGSACTIVE) {
lgs_switch_file(cl);
}
if (cl->c) {
cl->c->moddata[LogServ.modnum] = NULL;
}
hash_delete(lgschans, hn);
hnode_destroy(hn);
spart_cmd(s_LogServ, cl->channame);
SET_SEGV_INMODULE(__module_info.module_name);
free(cl);
DelRow("Chans", av[3]);
prefmsg(u->nick, s_LogServ, "Deleted Channel %s", av[3]);
chanalert(s_LogServ, "%s deleted %s from Channel Logging", u->nick, av[3]);
return NS_SUCCESS;
} else if (!strcasecmp(av[2], "ADD")) {
if (ac < 6) {
prefmsg(u->nick, s_LogServ, "Syntax error: insufficient parameters");
prefmsg(u->nick, s_LogServ, "/msg %s HELP CHANS for more information", s_LogServ);
return NS_FAILURE;
}
lgs_newchanlog(u, av, ac);
return NS_SUCCESS;
} else if (!strcasecmp(av[2], "SET")) {
if (ac < 6) {
prefmsg(u->nick, s_LogServ, "Syntax error: insufficient parameters");
prefmsg(u->nick, s_LogServ, "/msg %s HELP CHANS for more information", s_LogServ);
return NS_FAILURE;
}
hn = hash_lookup(lgschans, av[3]);
if (hn) {
cl = hnode_get(hn);
} else {
prefmsg(u->nick, s_LogServ, "Can not find channel %s in Logging System", av[3]);
return NS_FAILURE;
}
if (!cl) {
prefmsg(u->nick, s_LogServ, "Can not find Channel %s in Logging System", av[3]);
return NS_FAILURE;
}
if (!strcasecmp(av[4], "URL")) {
ircsnprintf(cl->statsurl, MAXPATH, "%s", av[5]);
prefmsg(u->nick, s_LogServ, "Changed URL for %s to: %s", cl->channame, cl->statsurl);
chanalert(s_LogServ, "%s changed the URL for %s to: %s", u->nick, cl->channame, cl->statsurl);
lgs_save_channels_data(cl);
} else {
prefmsg(u->nick, s_LogServ, "Unknown Set Option");
}
return NS_SUCCESS;
} else {
prefmsg(u->nick, s_LogServ, "Syntax error: Unknown Command %s", av[2]);
prefmsg(u->nick, s_LogServ, "/msg %s HELP CHANS for more information", s_LogServ);
return NS_FAILURE;
}
return NS_FAILURE;
}
/* @brief Send some very simple stats to the user
*
* @param u The user requesting stats data
* @param av the text sent
* @param ac the number of words in av
* @returns NS_SUCCESS or NS_FAILURE
*/
static int lgs_stats(User * u, char **av, int ac) {
prefmsg(u->nick, s_LogServ, "LogServ Stats:");
prefmsg(u->nick, s_LogServ, "Monitoring %d channels", (int)hash_count(lgschans));
return NS_SUCCESS;
}
/* @breif Send the Log Message to the relevent Log Processor
*
* @param msgtype the type of message (join, part etc)
* @param av contents of the message
* @param ac message size
* @returns NS_SUCCESS or NS_FAILURE
*/
static int lgs_send_to_logproc( logmsgtype msgtype, ChannelLog *lgschan, char **av, int ac) {
switch (msgtype) {
case 0:
return logging_funcs[LogServ.logtype].joinproc(lgschan, av, ac);
break;
case 1:
return logging_funcs[LogServ.logtype].partproc(lgschan, av, ac);
break;
case 2:
return logging_funcs[LogServ.logtype].msgproc(lgschan, av, ac);
break;
case 3:
return logging_funcs[LogServ.logtype].quitproc(lgschan, av, ac);
break;
case 4:
return logging_funcs[LogServ.logtype].topicproc(lgschan, av, ac);
break;
case 5:
return logging_funcs[LogServ.logtype].kickproc(lgschan, av, ac);
break;
case 6:
return logging_funcs[LogServ.logtype].nickproc(lgschan, av, ac);
break;
case 7:
return logging_funcs[LogServ.logtype].modeproc(lgschan, av, ac);
break;
default:
nlog(LOG_WARNING, LOG_MOD, "Unknown msgtype %d", msgtype);
return NS_FAILURE;
break;
}
return NS_FAILURE;
}
ChannelLog *lgs_newchanlog(User *u, char **av, int ac) {
Chans *c;
ChannelLog *cl;
hnode_t *cn;
c = findchan(av[3]);
if (!c) {
prefmsg(u->nick, s_LogServ, "Error, Channel %s is not Online at the moment", av[3]);
return NULL;
}
if ((cn = hash_lookup(lgschans, av[3])) != NULL) {
prefmsg(u->nick, s_LogServ, "Already Logging %s.", av[3]);
return hnode_get(cn);
}
cl = malloc(sizeof(ChannelLog));
bzero(cl, sizeof(ChannelLog));
strlcpy(cl->channame, av[3], CHANLEN);
cl->c = c;
c->moddata[LogServ.modnum] = cl;
if (!strcasecmp(av[4], "Public")) {
cl->flags |= LGSPUBSTATS;
} else if (!strcasecmp(av[4], "Private")) {
cl->flags &= ~LGSPUBSTATS;
} else {
prefmsg(u->nick, s_LogServ, "Unknown Public Type %s. Setting to Public", av[4]);
cl->flags |= LGSPUBSTATS;
}
if (ac == 6) {
/* we have a URL */
strlcpy(cl->statsurl, av[5], MAXPATH);
prefmsg(u->nick, s_LogServ, "Stats URL is set to %s", cl->statsurl);
} else {
prefmsg(u->nick, s_LogServ, "No Stats URL is Set");
}
cn = hnode_create(cl);
hash_insert(lgschans, cn, cl->channame);
lgs_save_channels_data(cl);
if (join_bot_to_chan(s_LogServ, cl->channame, 0) == NS_SUCCESS) {
cl->flags |= LGSACTIVE;
nlog(LOG_NOTICE, LOG_MOD, "%s actived Logging on channel %s", u->nick, cl->channame);
prefmsg(cl->channame, s_LogServ, "%s Actived Channel Logging on %s", u->nick, cl->channame);
if (cl->statsurl[0] != '\0') {
prefmsg(cl->channame, s_LogServ, "Stats will be avaiable at %s when Logs are processed next", cl->statsurl);
}
}
prefmsg(u->nick, s_LogServ, "Now Logging %s", cl->channame);
chanalert(s_LogServ, "%s Activated Logging on %s", u->nick, cl->channame);
return cl;
}
static void lgs_save_channels_data(ChannelLog *cl) {
nlog(LOG_DEBUG1, LOG_MOD, "Saving Channel Data for %s", cl->channame);
SetData((void *)cl->flags, CFGINT, "Chans", cl->channame, "Flags");
SetData((void *)cl->statsurl, CFGSTR, "Chans", cl->channame, "URL");
}
/* @brief find a active Channel Log record
*
* @params c - Chans Struct of the channel we are looking for
*
* @returns A ChannelLog Struct on success, or NULL on failure
*/
ChannelLog *lgs_findactchanlog(Chans *c) {
ChannelLog *cl;
if (c && c->moddata[LogServ.modnum]) {
cl = c->moddata[LogServ.modnum];
#ifdef DEBUG
/* paranoid checking this is */
if (!(cl->c == c)) {
nlog(LOG_WARNING, LOG_MOD, "Channel Log Channel doesn't match channel.");
return NULL;
}
#endif
return cl;
} else {
return NULL;
}
}