/**********************************************************************
* PTlink IRC Services is (C) CopyRight PTlink IRC Software 1999-2005 *
* http://software.pt-link.net *
* This program is distributed under GNU Public License *
* Please read the file COPYING for copyright information. *
**********************************************************************
Description: shows last registered channels
* $Id: cs_ajoin.c,v 1.6 2005/10/29 11:22:29 jpinto Exp $
*/
#include "module.h"
#include "my_sql.h"
#include "chanserv.h"
#include "dbconf.h"
#include "nsmacros.h"
#include "cs_role.h"
/* lang files */
#include "lang/cscommon.lh"
#include "lang/cs_ajoin.lh"
SVS_Module mod_info =
/* module, version, description */
{"cs_ajoin", "1.1", "chanserv ajoin command" };
/* Change Log
1.1 - #46: missing foreign key relations on channels and nicks
#36: CS AJOIN will INVITE the user if he/she has invite perm.
#35: ability to set order on ajoins
Apply cs_ajoin.2.sql for the above changes
1.0 - #1: Replace NS AUTOJOIN with CS AJOIN ADD/DEL
*/
#define DB_VERSION 2
/** functions and events we require **/
static ServiceUser* (*chanserv_suser)(void);
static int e_nick_identify;
MOD_REQUIRES
DBCONF_FUNCTIONS
MOD_FUNC(e_nick_identify)
MOD_FUNC(chanserv_suser)
MOD_FUNC(role_with_permission)
MOD_END
/** Internal functions **/
void ev_cs_ajoin_nick_identify(IRC_User* u, u_int32_t *snid);
static int sql_upgrade(int version, int post);
/* available commands from module */
void cs_ajoin(IRC_User *s, IRC_User *u);
/** Local config **/
static int MaxAjoinsPerUser;
DBCONF_PROVIDES
DBCONF_INT(MaxAjoinsPerUser, "20",
"How many ajoins a user can define?")
DBCONF_END
/** Local variables **/
static ServiceUser* csu;
static int cs_log;
/* this is called before load and at services rehash */
int mod_rehash(void)
{
if(dbconf_get_or_build(mod_info.name, dbconf_provides) < 0 )
{
errlog("Error reading dbconf!");
return -1;
}
return 0;
}
/** load code **/
int mod_load(void)
{
if(sql_check_inst_upgrade(mod_info.name, DB_VERSION, sql_upgrade) < 0 )
return -1;
cs_log = log_handle("chanserv");
csu = chanserv_suser();
suser_add_cmd(csu, "AJOIN", cs_ajoin, CS_AJOIN_SUMMARY, CS_AJOIN_HELP);
suser_add_help(csu, "AJOIN ADD", CS_AJOIN_ADD_SYNTAX);
suser_add_help(csu, "AJOIN DEL", CS_AJOIN_DEL_SYNTAX);
/* Add actions */
mod_add_event_action(e_nick_identify, (ActionHandler) ev_cs_ajoin_nick_identify);
return 0;
}
static int ajoins_count(u_int32_t snid)
{
if(sql_singlequery("SELECT count(*) FROM cs_ajoin WHERE snid=%d", snid))
return sql_field_i(0);
return 0;
}
void cs_ajoin(IRC_User *s, IRC_User *u)
{
u_int32_t source_snid;
char *cmd;
CHECK_IF_IDENTIFIED_NICK
cmd = strtok(NULL, " ");
/* check for required params */
if(!cmd)
send_lang(u, s, CS_AJOIN_HELP);
else
/* check command */
if(strcasecmp(cmd, "ADD") == 0)
{
ChanRecord* cr = NULL;
char *chname = strtok(NULL, " ");
/* check for required params */
if(!chname)
send_lang(u, s, CS_AJOIN_ADD_SYNTAX);
else
/* check MaxAjoinsPerUser */
if(MaxAjoinsPerUser && (ajoins_count(source_snid) >= MaxAjoinsPerUser))
send_lang(u, s, CS_AJOIN_MAX_X_REACHED, MaxAjoinsPerUser);
else
/* check if chan exists */
if((cr = OpenCR(chname)) == NULL)
send_lang(u, s, CHAN_X_NOT_REGISTERED, chname);
else
if(sql_singlequery("SELECT scid FROM cs_ajoin WHERE snid=%d AND scid=%d",
source_snid, cr->scid))
send_lang(u, s, CS_AJOIN_X_ALREADY_IN, chname);
else
{
int order_id = 0;
if(sql_singlequery("SELECT MAX(order_id) FROM cs_ajoin WHERE snid=%d",
source_snid) && sql_field(0))
order_id = sql_field_i(0)+1;
sqlb_init("cs_ajoin");
sqlb_add_int("snid", source_snid);
sqlb_add_int("scid", cr->scid);
sqlb_add_int("order_id", order_id);
if(sql_execute(sqlb_insert()))
send_lang(u, s, CS_AJOIN_ADDED_X, chname);
else
send_lang(u, s, UPDATE_FAIL);
}
CloseCR(cr);
}
else
if(strcasecmp(cmd, "DEL") == 0)
{
int is_all = 0;
char *chname = strtok(NULL, " ");
ChanRecord* cr;
if(chname && (strcasecmp(chname, "ALL") == 0))
is_all = 1;
/* check for required params */
if(!chname)
send_lang(u, s, CS_AJOIN_DEL_SYNTAX);
else
/* check if chan exists */
if(!is_all && (cr = OpenCR(chname)) == NULL)
send_lang(u, s, CHAN_X_NOT_REGISTERED, chname);
else
if(!is_all && sql_singlequery("SELECT scid FROM cs_ajoin WHERE snid=%d AND scid=%d",
source_snid, cr->scid) == 0)
send_lang(u, s, CS_AJOIN_X_NOT_IN, chname);
else
{
if(is_all)
{
sql_execute("DELETE FROM cs_ajoin WHERE snid=%d",
source_snid);
send_lang(u, s, CS_AJOIN_DELETED_ALL, chname);
}
else
{
sql_execute("DELETE FROM cs_ajoin WHERE snid=%d and scid=%d",
source_snid, cr->scid);
send_lang(u, s, CS_AJOIN_DELETED_X, chname);
}
}
}
else
if(strcasecmp(cmd, "LIST") == 0)
{
MYSQL_RES *res;
MYSQL_ROW row;
res = sql_query("SELECT name FROM cs_ajoin a, chanserv c"
" WHERE a.snid=%d AND c.scid=a.scid ORDER BY order_id", source_snid);
send_lang(u, s, CS_AJOIN_LIST_HEADER);
while((row = sql_next_row(res)))
send_lang(u, s, CS_AJOIN_LIST_ITEM_X, row[0]);
send_lang(u, s, CS_AJOIN_LIST_TAIL);
sql_free(res);
}
else
send_lang(u, s, CS_AJOIN_HELP);
}
void ev_cs_ajoin_nick_identify(IRC_User* u, u_int32_t *snid)
{
MYSQL_RES *res;
MYSQL_ROW row;
char ajoin[256];
int i = 0;
IRC_Chan* chan;
ajoin[0] = '\0';
res = sql_query("SELECT name FROM cs_ajoin a, chanserv c"
" WHERE a.snid=%d AND c.scid=a.scid ORDER BY order_id", *snid);
while((row = sql_next_row(res)) && (i + strlen(row[0]) < 255))
{
chan = irc_FindChan(row[0]);
if(chan) /* channel exists */
{
ChanRecord* cr;
IRC_ChanNode* cn;
cr = chan->sdata;
if(!cr) /* channel is not registered ? skip ajoin */
continue;
cn = irc_FindOnChan(chan, u);
if(cn) /* we are already on chan, dont ajoin */
continue;
cr = chan->sdata;
if(cr && irc_IsCMode(chan, (CMODE_i | CMODE_k | CMODE_A | CMODE_O))
&& role_with_permission(cr->scid, *snid, P_INVITE))
irc_ChanInvite(chan, u, csu->u);
}
if(i>0)
ajoin[i++] = ',';
i += sprintf(&ajoin[i], "%s", row[0]);
}
sql_free(res);
if(ajoin[0])
{
send_lang(u, csu->u, CS_AJOIN_IS_X, ajoin);
irc_SvsJoin(u, csu->u, ajoin);
}
}
static int sql_upgrade(int version, int post)
{
MYSQL_RES* res;
MYSQL_ROW row;
switch(version)
{
case 2:
if(!post) /* Upgrading to version 2, need to delete lost snids/scids */
{
int rowc = 0;
res = sql_query("SELECT cs_ajoin.snid FROM cs_ajoin"
" LEFT JOIN nickserv ON (cs_ajoin.snid = nickserv.snid)"
" WHERE cs_ajoin.snid IS NOT NULL AND nickserv.snid IS NULL");
while((row = sql_next_row(res)))
{
log_log(cs_log, mod_info.name,
"Deleting ajoins owned by deleted nick %s", row[0]);
sql_execute("DELETE FROM cs_ajoin WHERE snid=%s", row[0]);
++rowc;
}
if(rowc)
log_log(cs_log, mod_info.name, "Removed %d lost ajoin(s)", rowc);
sql_free(res);
rowc = 0;
res = sql_query("SELECT cs_ajoin.scid FROM cs_ajoin"
" LEFT JOIN chanserv ON (cs_ajoin.scid = chanserv.scid)"
" WHERE cs_ajoin.scid IS NOT NULL AND chanserv.scid IS NULL");
while((row = sql_next_row(res)))
{
log_log(cs_log, mod_info.name,
"Deleting ajoins on deleted chan %s", row[0]);
sql_execute("DELETE FROM cs_ajoin WHERE scid=%s", row[0]);
++rowc;
}
if(rowc)
log_log(cs_log, mod_info.name, "Deleted %d lost ajoins(s)", rowc);
sql_free(res);
}
}
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1