#ifdef RCS
static char rcsid[]="$Id: tell.c,v 1.1.1.1 2000/11/13 02:42:49 holsta Exp $";
#endif
/******************************************************************************
 *                    Internetting Cooperating Programmers
 * ----------------------------------------------------------------------------
 *
 *  ____    PROJECT
 * |  _ \  __ _ _ __   ___ ___ _ __ 
 * | | | |/ _` | '_ \ / __/ _ \ '__|
 * | |_| | (_| | | | | (_|  __/ |   
 * |____/ \__,_|_| |_|\___\___|_|   the IRC bot
 *
 * All files in this archive are subject to the GNU General Public License.
 *
 * $Source: /cvsroot/dancer/dancer/src/tell.c,v $
 * $Revision: 1.1.1.1 $
 * $Date: 2000/11/13 02:42:49 $
 * $Author: holsta $
 * $State: Exp $
 * $Locker:  $
 *
 * ---------------------------------------------------------------------------
 *****************************************************************************/

#include "dancer.h"
#include "trio.h"
#include "strio.h"
#include "function.h"
#include "user.h"
#include "transfer.h"
#include "tell.h"
#include "list.h"
#include "news.h"

/* --- Global ----------------------------------------------------- */

extern time_t now;

extern char nickname[];
extern char tellfile[];
extern int tellmonths;
extern itemident *current;

int numTell = 0;
itemtell *tellHead = NULL;


static int tellId = 0;

/* --- AddTell ---------------------------------------------------- */

itemtell *AddTell(char *sender, char *receiver, char *msg, time_t when)
{
  char *ptr;
  itemtell *t;

  snapshot;
  ptr = StrIndexLast(receiver, '!');
  if (ptr) {
    /*
     * In case we have a nick-part in the receiver-pattern, we scan for the
     * '!' and points to the rest of the string instead
     */
    receiver = ++ptr;
  }

  if (NULL == StrIndex(receiver, '@')) /* illegal pattern, we can't use this one */
    return NULL;

  if (IsPrefix(receiver)) /* Skip prefix */
    ++receiver;

  t = NewEntry(itemtell);
  if (t) {
    InsertLast(tellHead, t);
    t->sender    = StrDuplicate(sender);
    t->receiver  = StrDuplicate(receiver);
    t->rcvdomain = Userdomain(receiver);
    t->message   = StrDuplicate(msg);
    t->when      = when;
    t->id        = ++tellId;
    numTell++;
  }
  return t;
}

/* --- FreeTell --------------------------------------------------- */

void FreeTell(void *v)
{
  itemtell *t;

  snapshot;
  t = (itemtell *)v;
  if (t) {
    if (t->sender)
      StrFree(t->sender);
    if (t->receiver)
      StrFree(t->receiver);
    if (t->rcvdomain)
      StrFree(t->rcvdomain);
    if (t->message)
      StrFree(t->message);
    numTell--;
  }
}

/* --- ReportTell ------------------------------------------------- */

inline void ReportTell(char *from, itemtell *t)
{
  snapshot;
  Sendf(from, "%s %s \"%s\" %s %s", t->sender, GetText(msg_said),
        t->message, TimeAgo(t->when), GetText(msg_ago));
}

/* --- TellNotify ------------------------------------------------- */

void TellNotify(itemguest *g)
{
  extern bool chat;
  extern itemclient *client;
  char msgstr[MINIBUFFER], newstr[MINIBUFFER];
  long news = 0;
  int mcnt = 0;
  itemuser *u;
  itemtell *t, *tt;
  itemnews *n;
  itemlist *l;

  snapshot;
  chat = FALSE;
  client = NULL;

  for (t = First(tellHead); t; t = Next(t)) {
    if (Match(t->receiver, g->ident->userdomain)) {
      tt = t;
      mcnt++;
    }
    else {
      u = g->ident->user;
      if (u) {
        for (l = First(u->domainhead); l; l = Next(l)) {
          if (Match(l->pointer, t->receiver)) {
            tt = t;
            mcnt++;
            break;
          }
        }
      }
    }
  }
  g->msgs = mcnt;

  if (g->ident->user) {
    current = g->ident; /* silly fix */
    news = NewsRead(g->ident->user->newsid, &n);
  }

  /* News and Tells combined: */
  switch (mcnt + news) {

    case 0: /* none */
      break;

    case 1: /* tell immediately */
      if (mcnt) {
        ReportTell(g->ident->nick, tt);
        DeleteEntry(tellHead, tt, FreeTell);
        g->msgs = 0;
      }
      else {
        NewsReport(g->ident);
      }
      break;

    default: /* TELLME to tell you */
      if (mcnt) {
        StrFormatMax(msgstr, sizeof(msgstr), "%d %s ", mcnt,
                     (mcnt > 1) ? GetText(msg_msgs) : GetText(msg_msg));
      }
      if (news) {
        StrFormatMax(newstr, sizeof(newstr), " %d %s ",
                     (int)news, GetText(msg_news_items));

      }
      SendNickf(g->ident->nick, GetText(msg_i_have_tells),
                mcnt ? msgstr : "",
                (news && mcnt) ? GetText(msg_and) : "",
                news ? newstr : "",
                nickname);
      break;

  }
}

/* --- TellNext --------------------------------------------------- */

void TellNext(char *from, itemguest *g, itemtell *t, bool all)
{
  snapshot;
  ReportTell(from, t);
  g->msgs--;
  if (!all && (g->msgs > 0)) {
    Sendf(from, GetText(msg_you_have_more), g->msgs,
          (g->msgs > 1) ? GetText(msg_msgs) : GetText(msg_msg));
  }

  DeleteEntry(tellHead, t, FreeTell);
}

/* --- TellMe ----------------------------------------------------- */

void TellMe(char *from, char *host, bool all)
{
  int count = 0;
  itemlist *l;
  itemtell *t, *next;
  itemguest *g;

  snapshot;
  g = current->guest;
  if (g) {
    for (t = First(tellHead); t; t = next) {
      next = Next(t);
      if (Match(t->receiver, host)) {
        TellNext(from, g, t, all);
        if (!all)
          return;
        count++;
      }
      else if (g->ident->user) {
        for (l = First(g->ident->user->domainhead); l; l = Next(l)) {
          if (Match(t->receiver, l->pointer)) {
            TellNext(from, g, t, all);
            if (!all)
              return;
            count++;
            break;
          }
        }
      }
    }

    if (0 == count) {
      if (current->user && NewsRead(current->user->newsid, NULL))
        NewsReport(current);
      else
        Send(from, GetText(msg_no_msgs_or_news));
    }
  }
  else
    Send(from, GetText(msg_please_join_channel));
}

/* --- TellAdd ---------------------------------------------------- */

void TellAdd(char *from, char *sender, char *receiver, char *msg)
{
  itemtell *t;

  snapshot;
  if (receiver && (t = AddTell(sender, receiver, msg, now))) {
    TellSave();
    Sendf(from, GetText(msg_message_stored), t->rcvdomain, t->id);
  }
  else {
    if (NULL == receiver)
      receiver = "<empty>";
    Sendf(from, GetText(msg_error_message_pattern), receiver);
  }
}

/* --- TellDel ---------------------------------------------------- */

void TellDel(char *from, char *uhost, char *which)
{
  char buf[MIDBUFFER];
  char *ptr;
  bool deleted = FALSE;
  long id;
  itemtell *t;

  snapshot;
  id = StrToLong(which, &ptr, 10);

  if (which != ptr) {  /* Find number */
    for (t = First(tellHead); t; t = Next(t)) {
      /* Not t->sender, but Userdomain of host part */
      if (t->id == id) {
        if (1 == StrScan(t->sender, "%*[^!]!%"MIDBUFFERTXT"[^\n]", buf)) {
          ptr = Userdomain(buf);
          if (ptr) {
            if (Match(uhost, ptr)) {
              deleted = TRUE;
              Sendf(from, GetText(msg_had_been_removed), t->id);
              DeleteEntry(tellHead, t, FreeTell);
            }
            else {
              Sendf(from, GetText(msg_not_your_messageid), t->id);
            }
            StrFree(ptr);
          }
          break;
        }
      }
    }

    if ((NULL == t) && !deleted)
      Send(from, GetText(msg_no_such_id));
  }
}

/* --- TellList --------------------------------------------------- */

void TellList(char *from, char *uhost)
{
  char *ptr;
  int count = 0;
  itemtell *t;

  snapshot;
  for (t = First(tellHead); t; t = Next(t)) {
    ptr = StrIndex(t->sender, '!');
    if (ptr) {
      if (Match(uhost, ptr + 1)) {
        if (0 == count)
          Send(from, GetText(msg_you_have_stored_these));
        Sendf(from, "%d: %s %s %s", t->id, t->receiver,
              TimeAgo(t->when), GetText(msg_ago));
        count++;
      }
    }
  }
  if (0 == count)
    Send(from, GetText(msg_tell_list_empty));
}

/* --- TellInit --------------------------------------------------- */

void TellInit(void)
{
  char buffer[MAXLINE], sender[MINIBUFFER], receiver[MINIBUFFER], msg[BIGBUFFER];
  time_t when;
  FILE *f;

  snapshot;
  tellHead = NewList(itemtell);

  if (tellfile[0] && (f = fopen(tellfile, "r"))) {
    if (fgets(buffer, sizeof(buffer), f)) {
      tellId = atoi(buffer);

      while (fgets(buffer, sizeof(buffer), f)) {
        if (4 == StrScan(buffer, "%"MINIBUFFERTXT"s %"MINIBUFFERTXT"s %d %"BIGBUFFERTXT"[^\n]",
                         sender, receiver, &when, msg))
          AddTell(sender, receiver, msg, when);
      }
    }
    fclose(f);
  }
}

/* --- TellSave --------------------------------------------------- */

void TellSave(void)
{
  char tempfile[MIDBUFFER];
  bool ok = TRUE;
  itemtell *t;
  FILE *f;

  snapshot;
  if ((char)0 == tellfile[0])
    return;

  StrFormatMax(tempfile, sizeof(tempfile), "%s~", tellfile);

  f = fopen(tempfile, "w");
  if (f) {
    if (0 > fprintf(f, "%d\n", tellId)) {
      ok = FALSE;
    }
    else {
      for (t = First(tellHead); t; t = Next(t)) {
        /* Ignore messages older than two months */
        if ((now - t->when) < tellmonths*SECINMONTH) {
          if (0 > fprintf(f, "%s %s %d %s\n", t->sender, t->receiver,
                          t->when, t->message)) {
            ok = FALSE;
            break;
          }
        }
      }
    }
    fclose(f);

    if (ok)
      rename(tempfile, tellfile);
  }
}

/* --- TellCleanup ------------------------------------------------ */

void TellCleanup(void)
{
  snapshot;
  TellSave();
  DeleteList(tellHead, FreeTell);
}


syntax highlighted by Code2HTML, v. 0.9.1