/*

  This module sends a file, line by line, to everyone that joins the specified
channel. Note that this module has NOTHING to do with each registered user's
join message. The file is sent to everyone, and since it's opened in readonly
mode, it can be used in multiple bots.
  To use, put this in the configuration file:

joinmsg <#channel> <filename> <0|1>

where 0|1 is 1 to show the users's host address 0 not to.

*/

#include "mbot.h"

#define DEST s->script.dest
#define BUF s->script.buf

struct joinmsg_type {
  CNetServer *s;
  CString channel;
  CString filename;
  CText text;
  joinmsg_type (CNetServer *server, c_char c, c_char f) : s (server),
    channel (c, CHANNEL_MAX), filename (f, PATH_MAX) {}
};
CList *joinmsg_list;

///////////////
// prototypes
///////////////

static void joinmsg_add (CNetServer *, c_char, c_char);
static joinmsg_type *server2joinmsg (CNetServer *, c_char);
static void joinmsg_event (CNetServer *);
static void joinmsg_conf (CNetServer *, c_char);
static void joinmsg_stop (CModule *);
static void joinmsg_start (CModule *);

////////////////////
// module managing
////////////////////

// add a joinmsg to the list
static void
joinmsg_add (CNetServer *s, c_char name, c_char file)
{
  joinmsg_type *joinmsg;
  joinmsg = new joinmsg_type (s, name, file);
  if (s == NULL)
    s->bot->conf_error ("error initializing joinmsg");
  joinmsg_list->add ((void *)joinmsg);
  if (!joinmsg->text.read_file (file))
    {
      s->write_botlog ("error opening %s: %s", file, strerror (errno));
      mbot_exit ();
    }
}

// return the joinmsg for a given server/channel, NULL if nonexistant
static joinmsg_type *
server2joinmsg (CNetServer *s, c_char chan)
{
  joinmsg_type *joinmsg;
  joinmsg_list->rewind ();
  while ((joinmsg = (joinmsg_type *)joinmsg_list->next ()) != NULL)
    if (joinmsg->s == s && joinmsg->channel == chan)
      return joinmsg;
  return NULL;
}

// check for joins, to send the file
static void
joinmsg_event (CNetServer *s)
{
  if (strcmp (CMD[1], "JOIN") == 0)
    {
      joinmsg_type *c = server2joinmsg (s, CMD[2]);
      if (c == NULL)
        return;
      mask2nick (CMD[0], BUF[0], NICK_SIZE);
      if (strcasecmp (CMD[2], c->channel) == 0
          && strcasecmp (BUF[0], s->nick) != 0 // don't send to the bot
          && (USERS == NULL ? 0 : USERS->match_mask_reallevel (CMD[0])) >= 0)
        {
          c->text.rewind_text ();
          for (int i = c->text.line_num; i > 0; i--)
            s->irc_notice (BUF[0], c->text.get_line ());
        }
    }
}

// configuration file's local parser
static void
joinmsg_conf (CNetServer *s, c_char bufread)
{
  char buf[4][MSG_SIZE+1];

  strsplit (bufread, buf, 3);

  if (strcasecmp (buf[0], "bot") == 0)
    s->script.events.add ((void *)joinmsg_event);

  else if (strcasecmp (buf[0], "joinmsg") == 0)
    {
      if (server2joinmsg (s, buf[1]) == NULL)
        joinmsg_add (s, buf[1], buf[2]);
      else
        s->bot->conf_error ("joinmsg already defined for that channel.");
    }
}

// module termination
static void
joinmsg_stop (CModule *m)
{
  joinmsg_type *joinmsg;
  joinmsg_list->rewind ();
  while ((joinmsg = (joinmsg_type *)joinmsg_list->next ()) != NULL)
    {
      joinmsg->s->script.events.del ((void *)joinmsg_event);
      delete joinmsg;
    }
}

// module initialization
static void
joinmsg_start (CModule *m)
{
  joinmsg_list = new CList;
}

struct CModule::module_type module = {
  MODULE_VERSION,
  "joinmsg",
  joinmsg_start,
  joinmsg_stop,
  joinmsg_conf,
  NULL
};
