/* Sunucu ve Kanallara Giriş Çıkışları Mode Topic 
Değişikliklerini Size Bir Monitor Kanalda 
Veren Operleri Bilgilendiren Güzel Bir Modules
Düzenleyen By Romeo
Daha Detayli Bilgi Almak ıcin Ve IRCd Ile Ilgili Bütün 
Sorunlariniz Icin Www.Karayip.Com Forumlarindan
Yardim Alabilirsiniz..
Lütfen Asagidaki Verecegim Codeleri unrealircd.conf
Dosyaniza Ekleyiniz..
chansno
{
    // msgtype privmsg;

    channel "#Bilgi-1" {
        joins; parts; kicks; mode-changes; topics;
    };

    channel "#Bilgi-2" {
        nickchanges; connects; disconnects; server-connects; squits;
    };
};

*/
#include "config.h"
#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include <time.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#endif
#include <fcntl.h>
#include "h.h"
#ifdef STRIPBADWORDS
#include "badwords.h"
#endif
#ifdef _WIN32
#include "version.h"
#endif

typedef struct _conf_operflag OperFlag;
typedef struct _chansnoflag ChanSnoFlag;

struct _conf_operflag
{
	long		flag;
	char		*name;
};

struct _chansnoflag
{
	ChanSnoFlag	*prev, *next;
	char		*channel;
	long		flags;
};

extern ConfigEntry	*config_find_entry(ConfigEntry *, char *);
extern OperFlag		*config_binary_flags_search(OperFlag *table, char *cmd, int size);

#define MSG_CHANSNO	"CHANSNO"
#define TOK_CHANSNO	"CR"
#define MyMod		ModChanSno->handle
#define CHSNO_TABLESIZE	sizeof(_ChanSnoFlags)/sizeof(_ChanSnoFlags[0])
#define MaxSize		(sizeof(msgbuf) - strlen(msgbuf) - 1)

#define ircstrdup(x,y)  if (x) MyFree(x); if (!y) x = NULL; else x = strdup(y)
#define IsParam(x)	(parc > (x) && !BadPtr(parv[(x)]))
#define IsNotParam(x)	(parc <= (x) || BadPtr(parv[(x)]))
#define DelHook(x)	if (x) HookDel(x); x = NULL
#define DelCommand(x)	if (x) CommandDel(x); x = NULL

/* Messages types */

#define MT_PRIVMSG		0x00
#define MT_NOTICE		0x01
#define MsgType			(msgtype == MT_PRIVMSG ? "PRIVMSG" : "NOTICE")

/* Channel server notice masks */

#define CHSNO_CONNECT		0x0001
#define CHSNO_DISCONNECT	0x0002
#define CHSNO_NICKCHANGE	0x0004
#define CHSNO_JOIN		0x0008
#define CHSNO_PART		0x0010
#define CHSNO_KICK		0x0020
#define CHSNO_CHANMODE		0x0040
#define CHSNO_SCONNECT		0x0080
#define CHSNO_SQUIT		0x0100
#define CHSNO_TOPIC		0x0200

/* This MUST be alphabetized */
OperFlag _ChanSnoFlags[] =
{
	{ CHSNO_CONNECT,	"connects"		},
	{ CHSNO_DISCONNECT,	"disconnects"		},
	{ CHSNO_JOIN,		"joins"			},
	{ CHSNO_KICK,		"kicks"			},
	{ CHSNO_CHANMODE,	"mode-changes"		},
	{ CHSNO_NICKCHANGE,	"nickchanges"		},
	{ CHSNO_PART,		"parts"			},
	{ CHSNO_SCONNECT,	"server-connects"	},
	{ CHSNO_SQUIT,		"squits"		},
	{ CHSNO_TOPIC,		"topics"		}
};

static Command		*AddCommand(char *msg, char *token, int (*func)());
DLLFUNC int		m_chansno(aClient *cptr, aClient *sptr, int parc, char *parv[]);
DLLFUNC int		test_chansno(ConfigFile *, ConfigEntry *, int, int *);
DLLFUNC int		conf_chansno(ConfigFile *, ConfigEntry *, int);
DLLFUNC int		rehash_chansno();

DLLFUNC int		cb_mode(aClient *, aClient *, aChannel *, char *, char *, TS, int);
DLLFUNC int		cb_connect(aClient *);
DLLFUNC int		cb_quit(aClient *, char *);
DLLFUNC int		cb_join(aClient *, aClient *, aChannel *, char *[]);
DLLFUNC int		cb_kick(aClient *, aClient *, aClient *, aChannel *, char *);
DLLFUNC int		cb_nickchange(aClient *, char *);
DLLFUNC int		cb_part(aClient *, aClient *, aChannel *, char *);
DLLFUNC int		cb_server_connect(aClient *);
DLLFUNC int		cb_server_quit(aClient *);
DLLFUNC int		cb_topic();

ModuleInfo		*ModChanSno = NULL;
Command			*CmdChanSno = NULL;
ChanSnoFlag		*ConfChanSno;
Hook			*HookConfTest, *HookConfRun, *HookConfRehash;
Hook			*HookMode, *HookConnect, *HookQuit, *HookJoin;
Hook			*HookKick, *HookNickChange, *HookPart, *HookServerConnect;
Hook			*HookServerQuit, *HookTopic;
static char		msgbuf[BUFSIZE+1];
u_int			msgtype = MT_PRIVMSG;

ModuleHeader MOD_HEADER(chansno)
  = {
	"Module",
	"$Id: bilgi.c,v",
	"Sunucuya Giriş Cıkışları Kanal Giriş Çıkış Mode ve topic Değişikliklerini Haber Veren Bir Modules",
	"3.2-b8-1",
	NULL
    };

static Command *AddCommand(char *msg, char *token, int (*func)())
{
	Command *cmd;

	if (CommandExists(msg))
    	{
		config_error("Command %s already exists", msg);
		return NULL;
    	}
    	if (CommandExists(token))
	{
		config_error("Token %s already exists", token);
		return NULL;
    	}

	cmd = CommandAdd(MyMod, msg, token, func, MAXPARA, 0);

#ifndef _WIN32
	if (ModuleGetError(MyMod) != MODERR_NOERROR || !cmd)
#else
	if (!cmd)
#endif
	{
#ifndef _WIN32
		config_error("Error adding command %s: %s", msg,
			ModuleGetErrorStr(MyMod));
#else
		config_error("Error adding command %s", msg);
#endif
		return NULL; /* just to be sure */
	}

	return cmd;
}

// =================================================================
// Functions related to loading/unloading configuration
// =================================================================

static void InitConf()
{
	ConfChanSno	= NULL;
	msgtype		= MT_PRIVMSG;
}

static void FreeConf()
{
	ChanSnoFlag	*c;
	ListStruct 	*next;

	for (c = ConfChanSno; c; c = (ChanSnoFlag *) next)
	{
		next = (ListStruct *) c->next;
		DelListItem(c, ConfChanSno);
		MyFree(c->channel);
		MyFree(c);
	}
}

// =================================================================
// Module functions
// =================================================================

DLLFUNC int MOD_TEST(chansno)(ModuleInfo *modinfo)
{
	ModChanSno	= modinfo;
	HookConfTest	= HookAddEx(MyMod, HOOKTYPE_CONFIGTEST, test_chansno);

	return MOD_SUCCESS;
}

DLLFUNC int MOD_INIT(chansno)(ModuleInfo *modinfo)
{
	ModChanSno	= modinfo;

	InitConf();

	CmdChanSno	= AddCommand(MSG_CHANSNO, TOK_CHANSNO, m_chansno);
	HookConfRun	= HookAddEx(MyMod, HOOKTYPE_CONFIGRUN, conf_chansno);
	HookConfRehash	= HookAddEx(MyMod, HOOKTYPE_REHASH, rehash_chansno);

	if (!CmdChanSno)
		return MOD_FAILED;

	return MOD_SUCCESS;
}

DLLFUNC int MOD_LOAD(userauth)(int module_load)
{
	HookMode = HookAddEx(MyMod, HOOKTYPE_LOCAL_CHANMODE, cb_mode);
	HookConnect = HookAddEx(MyMod, HOOKTYPE_LOCAL_CONNECT, cb_connect);
	HookQuit = HookAddEx(MyMod, HOOKTYPE_LOCAL_QUIT, cb_quit);
	HookJoin = HookAddEx(MyMod, HOOKTYPE_LOCAL_JOIN, cb_join);
	HookKick = HookAddEx(MyMod, HOOKTYPE_LOCAL_KICK, cb_kick);
	HookNickChange = HookAddEx(MyMod, HOOKTYPE_LOCAL_NICKCHANGE, cb_nickchange);
	HookPart = HookAddEx(MyMod, HOOKTYPE_LOCAL_PART, cb_part);
	HookServerConnect = HookAddEx(MyMod, HOOKTYPE_SERVER_CONNECT, cb_server_connect);
	HookServerQuit = HookAddEx(MyMod, HOOKTYPE_SERVER_QUIT, cb_server_quit);
	HookTopic = HookAddEx(MyMod, HOOKTYPE_LOCAL_TOPIC, cb_topic);

	return MOD_SUCCESS;
}

DLLFUNC int MOD_UNLOAD(m_chansno)(int module_unload)
{
	DelHook(HookTopic);
	DelHook(HookServerQuit);
	DelHook(HookServerConnect);
	DelHook(HookPart);
	DelHook(HookNickChange);
	DelHook(HookKick);
	DelHook(HookJoin);
	DelHook(HookQuit);
	DelHook(HookConnect);
	DelHook(HookMode);

	DelHook(HookConfRehash);
	DelHook(HookConfRun);
	DelHook(HookConfTest);
	DelCommand(CmdChanSno);

	FreeConf();
	return MOD_SUCCESS;
}

// =================================================================
// Config file interfacing
// =================================================================

DLLFUNC int rehash_chansno()
{
	FreeConf();
	InitConf();

	return 1;
}

DLLFUNC int test_chansno(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
	ConfigEntry	*cep, *cepp;
	int		errors = 0;

	if (type != CONFIG_MAIN)
		return 0;

	if (!strcmp(ce->ce_varname, "chansno"))
	{
		for (cep = ce->ce_entries; cep; cep = cep->ce_next)
		{
			if (!cep->ce_varname)
			{
				config_error("%s:%i: blank chansno item",
					cep->ce_fileptr->cf_filename,
					cep->ce_varlinenum);
				errors++;
				continue;
			}
			if (!cep->ce_vardata)
			{
				config_error("%s:%i: chansno::%s item without value",
					cep->ce_fileptr->cf_filename,
					cep->ce_varlinenum, cep->ce_varname);
				errors++;
				continue;
			}
			if (!strcmp(cep->ce_varname, "channel"))
			{
				if (!cep->ce_entries)
				{
					config_error("%s:%i: chansno::channel without contents",
						cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
					errors++;
					continue;
				}
				for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
				{
					if (!cepp->ce_varname)
					{
						config_error("%s:%i: chansno::channel item without variable name",
							cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum);
						errors++;
						continue;
					}
					if (!config_binary_flags_search(_ChanSnoFlags, cepp->ce_varname, CHSNO_TABLESIZE))
					{
						config_error("%s:%i: unknown chansno::channel flag '%s'",
							cepp->ce_fileptr->cf_filename, cepp->ce_varlinenum,
							cepp->ce_varname);
						errors++;
					}
				}
			}
			else if (!strcmp(cep->ce_varname, "msgtype"))
			{
				if (!strcmp(cep->ce_vardata, "privmsg"))
					;
				else if (!strcmp(cep->ce_vardata, "notice"))
					;
				else
				{
					config_error("%s:%i: unknown chansno::msgtype '%s'",
						cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
						cep->ce_varname);
					errors++;
				}
			}
			else
			{
				config_error("%s:%i: unknown directive chansno::%s",
					cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
				errors++;
			}
		}
		*errs = errors;
		return errors ? -1 : 1;
	}
	else
		return 0;
}

DLLFUNC int conf_chansno(ConfigFile *cf, ConfigEntry *ce, int type)
{
	ConfigEntry	*cep, *cepp;
	OperFlag	*ofp;
	ChanSnoFlag	*ca;

	if (type != CONFIG_MAIN)
		return 0;

	if (!strcmp(ce->ce_varname, "chansno"))
	{
		for (cep = ce->ce_entries; cep; cep = cep->ce_next)
		{
			if (!strcmp(cep->ce_varname, "channel"))
			{
				ca = MyMallocEx(sizeof(ChanSnoFlag));
				ircstrdup(ca->channel, cep->ce_vardata);

				for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next)
				{
					if ((ofp = config_binary_flags_search(_ChanSnoFlags, cepp->ce_varname, CHSNO_TABLESIZE)))
						ca->flags |= ofp->flag;
				}

				AddListItem(ca, ConfChanSno);
			}
			else if (!strcmp(cep->ce_varname, "msgtype"))
			{
				if (!strcmp(cep->ce_vardata, "privmsg"))
					msgtype = MT_PRIVMSG;
				else if (!strcmp(cep->ce_vardata, "notice"))
					msgtype = MT_NOTICE;
			}
		}

		return 1;
	}

	return 0;
}

// ===============================================================
// Functions used by m_chansno
// ===============================================================

static char *get_flag_names(long flags)
{
	u_int	i, found = 0;

	memset(&msgbuf, 0, sizeof msgbuf);

	for (i = 0; i < CHSNO_TABLESIZE; i++)
        	if (flags & _ChanSnoFlags[i].flag)
		{
			if (found)
				strncat(msgbuf, ", ", MaxSize);
			else
				found = 1;

			strncat(msgbuf, _ChanSnoFlags[i].name, MaxSize);
		}

	if (!strlen(msgbuf))
		strcpy(msgbuf, "<None>");

	return msgbuf;
}

static void stats_chansno_channels(aClient *sptr)
{
	ChanSnoFlag	*c;
	
	for (c = ConfChanSno; c; c = c->next)
		sendto_one(sptr,  "2:%s %i %s :Kanal %s: %s",
			me.name, RPL_TEXT, sptr->name,
			c->channel, get_flag_names(c->flags));

	sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, sptr->name, 'S');
}

static void stats_chansno_config(aClient *sptr)
{
	ChanSnoFlag	*c;
	
	sendto_one(sptr, ":%s %i %s :msgtype: %s",
		me.name, RPL_TEXT, sptr->name, MsgType);
	sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, sptr->name, 'S');
}

// ===============================================================
// m_chansno
//      parv[0]: sender prefix
//      parv[1]: option
//      parv[2]: server name (optional)
// ===============================================================

DLLFUNC int m_chansno(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	if (!IsPerson(sptr))
		return -1;

	if (!IsAnOper(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return -1;
	}

	if (!IsParam(1))
	{
		sendto_one(sptr, ":%s NOTICE %s :Usage:",
			me.name, sptr->name);
		sendto_one(sptr, ":%s NOTICE %s :    /chansno <option> [<servername>]",
			me.name, sptr->name);
		sendto_one(sptr, ":%s NOTICE %s :Options:",
			me.name, sptr->name);
		sendto_one(sptr, ":%s NOTICE %s :    list: displays the chansno::channel block list",
			me.name, sptr->name);
		sendto_one(sptr, ":%s NOTICE %s :    config: shows the rest of chansno configuration",
			me.name, sptr->name);
		return 0;
	}

        if (IsParam(2))
        {
                if (hunt_server_token(cptr, sptr, MSG_CHANSNO, TOK_CHANSNO,
                    "%s", 2, parc, parv) != HUNTED_ISME)
                        return 0;
        }

	if (!strcasecmp(parv[1], "list"))
		stats_chansno_channels(sptr);
	else if (!strcasecmp(parv[1], "config"))
		stats_chansno_config(sptr);
	else
	{
		sendto_one(sptr, ":%s NOTICE %s :Hatali option %s."
			" Valid options are: list | config",
			me.name, sptr->name, parv[1]);
		return -1;
	}

	return 0;
}

// ===============================================================
// Interface for sending notifications
// ===============================================================

#define SendBuf_simple \
	if ((sendto = find_channel(c->channel, NullChn)) != NullChn) \
		sendto_channel_butone(&me, &me, sendto, ":%s %s %s :%s", \
			me.name, MsgType, sendto->chname, msgbuf)

#define SendBuf_channel \
	if (!find_sno_channel(chptr) && (sendto = find_channel(c->channel, NullChn)) != NullChn) \
		sendto_channel_butone(&me, &me, sendto, ":%s %s %s :[%s] %s", \
			me.name, MsgType, sendto->chname, chptr->chname, msgbuf)

static u_int find_sno_channel(aChannel *chptr)
{
	ChanSnoFlag	*c;
	
	for (c = ConfChanSno; c; c = c->next)
		if (!strcasecmp(chptr->chname, c->channel))
			return 1;

	return 0;
}

static void SendNotice_simple(long type)
{
	ChanSnoFlag	*c;
	aChannel	*sendto;

	for (c = ConfChanSno; c; c = c->next)
	{
		if (c->flags & type)
			SendBuf_simple;
	}
}

static void SendNotice_channel(aChannel *chptr, long type)
{
	ChanSnoFlag	*c;
	aChannel	*sendto;

	for (c = ConfChanSno; c; c = c->next)
	{
		if (c->flags & type)
			SendBuf_channel;
	}
}

DLLFUNC int cb_mode(aClient *cptr, aClient *sptr, aChannel *chptr,
  char *modebuf, char *parabuf, TS sendts, int samode)
{
	snprintf(msgbuf, BUFSIZE, "4 %s Nick'i: Mod Degistirdi %s%s%s",
		sptr->name, modebuf,
		BadPtr(parabuf) ? "" : " ",
		BadPtr(parabuf) ? "" : parabuf);

	SendNotice_channel(chptr, CHSNO_CHANMODE);
	return 0;
}

DLLFUNC int cb_connect(aClient *sptr)
{
	snprintf(msgbuf, BUFSIZE, "7Sunucuya Giris Yapildi Portu %d: Nicki %s Ip Nosu (%s) [%s] %s%s%s%s",
		sptr->listener->port, sptr->name, sptr->user->username, sptr->user->realhost,
		    sptr->class ? sptr->class->name : "",
#ifdef USE_SSL
		IsSecure(sptr) ? "[secure " : "",
		IsSecure(sptr) ? SSL_get_cipher((SSL *)sptr->ssl) : "",
		IsSecure(sptr) ? "]" : "");
#else
		"", "", "");
#endif

	SendNotice_simple(CHSNO_CONNECT);
	return 0;
}

DLLFUNC int cb_quit(aClient *sptr, char *comment)
{
	snprintf(msgbuf, BUFSIZE, "5Sunucudan Cikti: %s!%s@%s (%s)",
		sptr->name, sptr->user->username,
		sptr->user->realhost, comment);

	SendNotice_simple(CHSNO_DISCONNECT);
	return 0;
}

DLLFUNC int cb_join(aClient *cptr, aClient *sptr, aChannel *chptr, char *parv[])
{
	snprintf(msgbuf, BUFSIZE, "3 %s [%s@%s] Nicki KanaLa Giris Yapti %s",
		sptr->name, sptr->user->username, sptr->user->realhost,
		chptr->chname);

	SendNotice_channel(chptr, CHSNO_JOIN);
	return 0;
}

DLLFUNC int cb_kick(aClient *cptr, aClient *sptr, aClient *who, aChannel *chptr, char *comment)
{
	snprintf(msgbuf, BUFSIZE, "6Kanalinda By %s Kickledi %s Nickini (By %s)",
		sptr->name, who->name, comment);

	SendNotice_channel(chptr, CHSNO_KICK);
	return 0;
}

DLLFUNC int cb_nickchange(aClient *sptr, char *nick)
{
	snprintf(msgbuf, BUFSIZE, "10 %s (%s@%s) Nick Degistirdi Yeni Nicki: %s",
		sptr->name, sptr->user->username, sptr->user->realhost, nick);

	SendNotice_simple(CHSNO_NICKCHANGE);
	return 0;
}

DLLFUNC int cb_part(aClient *cptr, aClient *sptr, aChannel *chptr, char *comment)
{
	snprintf(msgbuf, BUFSIZE, "3 %s Nick'i (%s@%s) %s 'Den Ayrildi Part Mesaji (%s)",
		sptr->name, sptr->user->username, sptr->user->realhost,
		chptr->chname, comment ? comment : sptr->name);

	SendNotice_channel(chptr, CHSNO_PART);
	return 0;
}

DLLFUNC int cb_server_connect(aClient *sptr)
{
	if (!MyConnect(sptr))
		return 0;

	snprintf(msgbuf, BUFSIZE, "5Sunucuya Giris Yapildi Portu %d: Nicki %s Ip Nosu (%s) [%s] %s%s%s%s",
		sptr->listener->port, sptr->name, sptr->info,
		    sptr->class ? sptr->class->name : "",
#ifdef USE_SSL
		IsSecure(sptr) ? "[secure " : "",
		IsSecure(sptr) ? SSL_get_cipher((SSL *)sptr->ssl) : "",
		IsSecure(sptr) ? "]" : "",
#else
		"", "", "",
#endif

#ifdef ZIP_LINKS
		IsZipped(sptr) ? " [zip]" : "");
#else
		"");
#endif

	SendNotice_simple(CHSNO_SCONNECT);
	return 0;
}

DLLFUNC int cb_server_quit(aClient *sptr)
{
	if (!MyConnect(sptr))
		return 0;

	/* The hook supports no reason :-( */
	snprintf(msgbuf, BUFSIZE, "2Sunucudan Cikti: %s",
		sptr->name);

	SendNotice_simple(CHSNO_SQUIT);
	return 0;
}

DLLFUNC int cb_topic(aClient *cptr, aClient *sptr, aChannel *chptr, char *topic)
{
	snprintf(msgbuf, BUFSIZE, "14Kanalinda By %s Topick Degistirdi. Yeni Topick: %s",
		sptr->name, topic);

	SendNotice_channel(chptr, CHSNO_SQUIT);
	return 0;
}
