/*
 * =================================================================
 * Filename:       randquote.c
 * Description:    Random quotes (based on the code of UltimateIRCd)
 * Requested by:   Sergios Karalis
 * Written by:     AngryWolf <angrywolf@flashmail.com>
 * Documentation:  randquote.txt (comes with the package)
 * =================================================================
 */

#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

extern void			sendto_one(aClient *to, char *pattern, ...);
extern void			sendto_realops(char *pattern, ...);

#define IsSkoAdmin(sptr)	(IsAdmin(sptr) || IsNetAdmin(sptr) || IsSAdmin(sptr) || IsCoAdmin(sptr))
#define QUOTE_FILE		"ircd.quotes"
#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

#define MSG_RANDQUOTE		"RANDQUOTE"	/* Random Quote */
#define TOK_RANDQUOTE		"Q1"
#define MSG_ADDQUOTE		"ADDQUOTE"	/* Add Quote */
#define TOK_ADDQUOTE		"Q2"
#define MSG_ADDGQUOTE		"ADDGQUOTE"	/* Add Global Quote */
#define TOK_ADDGQUOTE		"Q3"

static Command			*AddCommand(Module *module, char *msg, char *token, iFP func, unsigned char params);
static int			m_randquote(aClient *cptr, aClient *sptr, int parc, char *parv[]);
static int			m_addquote(aClient *cptr, aClient *sptr, int parc, char *parv[]);
static int			m_addgquote(aClient *cptr, aClient *sptr, int parc, char *parv[]);
static int			cb_local_connect(aClient *sptr);

Command				*CmdRandquote, *CmdAddquote, *CmdAddgquote;
Hook				*HookConnect = NULL;

ModuleHeader MOD_HEADER(randquote)
  = {
	"randquote",
	"$Id: randquote.c,v 2.5 2004/03/11 20:23:12 angrywolf Exp $",
	"Random quotes (and commands /randquote, /addquote & addgquote)",
	"3.2-b8-1",
	NULL 
    };

DLLFUNC int MOD_INIT(randquote)(ModuleInfo *modinfo)
{
	CmdRandquote	= AddCommand(modinfo->handle, MSG_RANDQUOTE, TOK_RANDQUOTE, m_randquote, MAXPARA);
	CmdAddquote	= AddCommand(modinfo->handle, MSG_ADDQUOTE, TOK_ADDQUOTE, m_addquote, 1);
	CmdAddgquote	= AddCommand(modinfo->handle, MSG_ADDGQUOTE, TOK_ADDGQUOTE, m_addgquote, 1);
	HookConnect	= HookAddEx(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, cb_local_connect);

	if (!CmdRandquote || !CmdAddquote || !CmdAddgquote)
		return MOD_FAILED;

	return MOD_SUCCESS;
}

DLLFUNC int MOD_LOAD(randquote)(int module_load)
{
	return MOD_SUCCESS;
}

DLLFUNC int MOD_UNLOAD(randquote)(int module_unload)
{
	DelHook(HookConnect);
	DelCommand(CmdRandquote);
	DelCommand(CmdAddquote);
	DelCommand(CmdAddgquote);

	return MOD_SUCCESS;
}

static Command *AddCommand(Module *module, char *msg, char *token, iFP func, unsigned char params)
{
	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(module, msg, token, func, params, 0);

#ifndef STATIC_LINKING
	if (ModuleGetError(module) != MODERR_NOERROR || !cmd)
#else
	if (!cmd)
#endif
	{
#ifndef STATIC_LINKING
		config_error("Error adding command %s: %s", msg,
			ModuleGetErrorStr(module));
#else
		config_error("Error adding command %s", msg);
#endif
		return NULL;
	}

	return cmd;
}

static int cb_local_connect(aClient *sptr)
{
	static char *parv[1];

	parv[0] = sptr->name;
	m_randquote(sptr, sptr, 1, parv);
	return 0;
}

/*
 *  UltimateIRCd - an Internet Relay Chat Daemon, src/s_serv.c
 *
 *  Copyright (C) 2002 by the past and present ircd coders, and others.
 *  Refer to the documentation within doc/authors/ for full credits and copyrights.
 *
 *  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
 */

/*
**
** m_randquote - 10th November 1999
** Added from IRIS and adapted to Ultimate by HAMLET
** Added from Ultimate and adapted to Unreal by AngryWolf (with heavy modifications)
**
** parv[0]: sender prefix
**
*/

static int m_randquote(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	int	fd, linenum = 0, randnum;
	char	line[TOPICLEN];
	char	*p;

	srand(time (NULL) + getpid () + rand () % 9999);

	if ((fd = open(QUOTE_FILE, O_RDONLY)) == -1)
		return -1;

	dgets(-1, NULL, 0);
	while (dgets(fd, line, sizeof(line) - 1) > 0)
		linenum++;
	close(fd);

	if (linenum == 0)
		return 0;

	randnum = (rand() % linenum) - 1;
	linenum = 0;

	if ((fd = open(QUOTE_FILE, O_RDONLY)) == -1)
		return -1;

	while (dgets(fd, line, sizeof(line) - 1) > 0)
	{
		if ((p = (char *) index(line, '\n')))
			*p = '\0';
		if ((p = (char *) index(line, '\r')))
			*p = '\0';
		linenum++;
		if (linenum == randnum)
			break;
	}

	if (line[0])
		sendto_one (sptr, ":%s NOTICE %s :\2Quote:\2 %s",
			me.name, sptr->name, line);

	return close(fd);
}

/*
**
** m_addquote - 10th November 1999
** Written by HAMLET
** Added from Ultimate and adapted to Unreal by AngryWolf (with heavy modifications)
**
** Adds a line to the servers ircd.quotes file.
**
** parv[0]: sender prefix
** parv[1]: quote
**
*/

static int m_addquote(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	FILE *fp;

	if (!MyClient(sptr))
		return 0;

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

        if (!IsParam(1))
        {
                sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
            		me.name, sptr->name, MSG_ADDQUOTE);
                return 0;
        }

	if (!(fp = fopen(QUOTE_FILE, "a")))
	{
		sendto_one(sptr, ":%s NOTICE %s :Error opening %s: %s",
			me.name, sptr->name, QUOTE_FILE, strerror(errno));
    		return -1;
	}

	fprintf(fp, "%s\n", parv[1]);
	sendto_one(sptr, ":%s NOTICE %s :Quote added.",
		me.name, sptr->name);
	fclose(fp);

	return 0;
}

/*
**
** m_addgquote - 10th November 1999
** Written by HAMLET
** Added from Ultimate and adapted to Unreal by AngryWolf (with heavy modifications)
**
** Adds a line to the ircd.quotes file of all the servers on the network.
**
** parv[0]: sender prefix
** parv[1]: quote
**
*/

static int m_addgquote(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	FILE *fp;

	if (!IsClient(sptr))
		return 0;

	if (!IsAnOper(sptr) || !IsSkoAdmin(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES),	
			me.name, sptr->name);
		return 0;
	}

        if (!IsParam(1))
        {
                sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
            		me.name, sptr->name, MSG_ADDGQUOTE);
                return 0;
        }

	if (!(fp = fopen(QUOTE_FILE, "a")))
	{
		if (!IsServer(sptr))
			sendto_one(sptr, ":%s NOTICE %s :Error opening %s: %s",
				me.name, sptr->name, QUOTE_FILE, strerror(errno));
		return -1;
	}

	fprintf(fp, "%s\n", parv[1]);
	fclose(fp);

	sendto_realops("%s is adding a global QUOTE. (\2%s\2)",
		sptr->name, parv[1]);
	sendto_serv_butone(cptr, ":%s ADDGQUOTE :%s",
		sptr->name, parv[1]);

	return 0;
}
