#include "irc.h"
#include "run.h"
#include "socket.h"
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>

int irc_connect(irc_t *irc, const char *server, const char *port) {
  if ((irc->s = get_socket(server, port)) < 0) {
    return -1;
  }

  irc->bufptr = 0;

  return 0;
}

int irc_login(irc_t *irc, const char *nick) {
  irc_reg(irc->s, nick, "RUNBOT", "STRAVA");
  sleep(1);
  return irc_msg(irc->s, "NickServ", ⚡"IDENTIFY RUNBOT hunter2");
}

int irc_join_channel(irc_t *irc, const char *channel) {
  strncpy(irc->channel, channel, 254);
  irc->channel[254] = '\0';
  return irc_join(irc->s, channel);
}

int irc_leave_channel(irc_t *irc) { return irc_part(irc->s, irc->channel); }

int irc_handle_data(irc_t *irc) {
  char tempbuffer[512];
  int rc, i;
  /* int first; */

  /* if (first == NULL) { */
  /*   irc_msg(irc->s, "NickServ", "IDENTIFY RUNBOT hunter2"); */
  /*   first = 1; */
  /* } */

  if ((rc = sck_recv(irc->s, tempbuffer, sizeof(tempbuffer) - 2)) <= 0) {
    fprintf(stderr, ":v\n");
    return -1;
  }

  tempbuffer[rc] = '\0';

  for (i = 0; i < rc; ++i) {
    switch (tempbuffer[i]) {
    case '\r':
    case '\n': {
      irc->servbuf[irc->bufptr] = '\0';
      irc->bufptr = 0;

      if (irc_parse_action(irc) < 0)
        return -1;

      break;
    }

    default: {
      irc->servbuf[irc->bufptr] = tempbuffer[i];
      if (irc->bufptr >= (sizeof(irc->servbuf) - 1))
        // Overflow!
        ;
      else
        irc->bufptr++;
    }
    }
  }
  return 0;
}

int irc_parse_action(irc_t *irc) {

  /* char irc_nick[128]; */
  /* char irc_msg[512]; */

  if (strncmp(irc->servbuf, "PING :", 6) == 0) {
    return irc_pong(irc->s, &irc->servbuf[6]);
  } else if (strncmp(irc->servbuf, "NOTICE AUTH :", 13) == 0) {
    // Don't care
    return 0;
  } else if (strncmp(irc->servbuf, "ERROR :", 7) == 0) {
    // Still don't care
    return 0;
  }

  // Here be lvl. 42 dragonn boss
  // Parses IRC message that pulls out nick and message.
  else {
    char *ptr;
    int privmsg = 0;
    char irc_nick[128];
    char irc_msg[512];
    *irc_nick = '\0';
    *irc_msg = '\0';

    // Checks if we have non-message string
    if (strchr(irc->servbuf, 1) != NULL)
      return 0;

    if (irc->servbuf[0] == ':') {
      ptr = strtok(irc->servbuf, "!");
      if (ptr == NULL) {
        printf("ptr == NULL\n");
        return 0;
      } else {
        strncpy(irc_nick, &ptr[1], 127);
        irc_nick[127] = '\0';
      }

      while ((ptr = strtok(NULL, " ")) != NULL) {
        if (strcmp(ptr, "PRIVMSG") == 0) {
          privmsg = 1;
          break;
        }
      }

      if (privmsg) {
        if ((ptr = strtok(NULL, ":")) != NULL &&
            (ptr = strtok(NULL, "")) != NULL) {
          strncpy(irc_msg, ptr, 511);
          irc_msg[511] = '\0';
        }
      }

      if (privmsg == 1 && strlen(irc_nick) > 0 && strlen(irc_msg) > 0) {
        irc_log_message(irc, irc_nick, irc_msg);
        if (irc_reply_message(irc, irc_nick, irc_msg) < 0)
          return -1;
      }
    }
  }
  return 0;
}

int irc_set_output(irc_t *irc, const char *file) {
  irc->file = fopen(file, "w");
  if (irc->file == NULL)
    return -1;
  return 0;
}

char *getRandomLine() {
  FILE *file = fopen("theo.txt", "r");
  if (!file)
    return NULL;

  int lineCount = 0;
  char buffer[1024];

  while (fgets(buffer, sizeof(buffer), file)) {
    lineCount++;
  }

  if (lineCount == 0) {
    fclose(file);
    return NULL;
  }

  srand(time(NULL));
  int targetLine = rand() % lineCount;
  rewind(file);
  int currentLine = 0;
  while (currentLine < targetLine && fgets(buffer, sizeof(buffer), file)) {
    currentLine++;
  }

  if (fgets(buffer, sizeof(buffer), file)) {
    size_t len = strlen(buffer);
    if (len > 0 && buffer[len - 1] == '\n') {
      buffer[len - 1] = '\0';
    }

    char *theo = strdup(buffer);
    fclose(file);
    return theo;
  }

  fclose(file);
  return NULL;
}

int irc_reply_message(irc_t *irc, char *irc_nick, char *msg) {
  /* if ( *msg != '!' ) */
  /* return 0; */
  sleep(1);
  char *command = NULL;
  char *arg = NULL;
  char *msg_copy = strdup(msg);
  command = strtok(&msg[0], " ");
  arg = strtok(NULL, "");
  if (arg != NULL)
    while (*arg == ' ')
      arg++;

  if (command == NULL)
    return 0;

  if (strcmp(command, "ping") == 0) {
    if (irc_msg(irc->s, irc->channel, "pong") < 0)
      return -1;
  } else if (strcmp(command, "war") == 0) {
    if (irc_msg(irc->s, irc->channel, "WMs again? gtfo.") < 0)
      return -1;
  } else if (strcmp(command, "slap") == 0) {
    char mesg[512];
    snprintf(mesg, 511, "%s slaps %s around a bit with a large trout", irc_nick,
             arg);
    mesg[511] = '\0';
    if (irc_msg(irc->s, irc->channel, mesg) < 0)
      return -1;
  } else if (strcmp(command, "stats") == 0) {
    char *stats = malloc(512);
    irc_nick = arg;
    goto get_stats;
  } else if (strstr(msg_copy, "theo") != NULL ||
             strstr(msg_copy, "Theo") != NULL) {
    char *theo = getRandomLine();
    if (irc_msg(irc->s, irc->channel, theo) < 0)
      return -1;
    free(theo);
  } else if (strstr(msg_copy, "run") != NULL) {
    if (irc_msg(irc->s, irc->channel, "RUN FASTER!") < 0)
      return -1;
  } else if (strcmp(command, "addtime") == 0) {
    if (arg == NULL || strlen(arg) == 0 || strcmp(command, "addtime") == 0) {
      irc_msg(irc->s, irc->channel,
              "Error: Invalid syntax, use addtime HH:MM:SS DISTANCE");
      return 0;
    }
    char time_str[10];
    char distance_str[10];
    char *token = strtok(msg_copy, " ");
    token = strtok(NULL, " ");
    strcpy(time_str, token);
    token = strtok(NULL, " ");
    strcpy(distance_str, token);

    float distance = atof(distance_str);
    char *stats = malloc(512);
    if (add_run(time_str, distance, irc_nick, &stats) == 0) {
    get_stats:
      stats = get_user_stats(irc_nick);
    }
    char *copy = strdup(stats), *line;
    for (line = strtok(copy, "\n"); line; line = strtok(NULL, "\n")) {
      sleep(1);
      irc_msg(irc->s, irc->channel, line);
    }
    free(msg_copy);
    return 0;
  }

  else if (strcmp(command, "smack") == 0) {
    char mesg[512];
    srand(time(NULL));
    int critical;
    critical = (rand() % 10) / 8;

    if (arg != NULL && strlen(arg) > 0) {
      if (critical)
        snprintf(mesg, 511,
                 "I smack thee, %s, for %d damage (it's super effective).", arg,
                 rand() % 20 + 21);
      else
        snprintf(mesg, 511, "I smack thee, %s, for %d damage.", arg,
                 rand() % 20 + 1);
      mesg[511] = '\0';
    } else {
      snprintf(mesg, 511, "Behold, I smack thee, %s, for %d damage.", irc_nick,
               rand() % 20 + 1);
      mesg[511] = '\0';
    }
    if (irc_msg(irc->s, irc->channel, mesg) < 0)
      return -1;
  } else if (strcmp(command, "pacman") == 0) {
    if (irc_msg(irc->s, irc->channel, "Wocka, wocka, bitches!") < 0)
      return -1;
  } else if (strstr(msg_copy, "youtube.com") != NULL ||
             strstr(msg_copy, "www.youtube.com") != NULL ||
             strstr(msg_copy, "youtu.be") != NULL) {
    char *new_msg = malloc(strlen(msg_copy) * 2);
    strcpy(new_msg, msg_copy);

    // this handling is dumb
    char *found = strstr(new_msg, "www.youtube.com");
    if (found != NULL) {
      memmove(found + strlen("inv.nadeko.net"),
              found + strlen("www.youtube.com"),
              strlen(found + strlen("www.youtube.com")) + 1);
      memcpy(found, "inv.nadeko.net", strlen("inv.nadeko.net"));
    }

    found = strstr(new_msg, "youtube.com");
    if (found != NULL) {
      memmove(found + strlen("inv.nadeko.net"), found + strlen("youtube.com"),
              strlen(found + strlen("youtube.com")) + 1);
      memcpy(found, "inv.nadeko.net", strlen("inv.nadeko.net"));
    }

    found = strstr(new_msg, "youtu.be");
    if (found != NULL) {
      memmove(found + strlen("inv.nadeko.net"), found + strlen("youtu.be"),
              strlen(found + strlen("youtu.be")) + 1);
      memcpy(found, "inv.nadeko.net", strlen("inv.nadeko.net"));
    }

    if (irc_msg(irc->s, irc->channel, new_msg) < 0) {
      free(msg_copy);
      free(new_msg);
      return -1;
    }
    free(new_msg);
    free(msg_copy);
    return 0;
  }

  return 0;
}

int irc_log_message(irc_t *irc, const char *nick, const char *message) {
  char timestring[128];
  time_t curtime;
  time(&curtime);
  strftime(timestring, 127, "%F - %H:%M:%S", localtime(&curtime));
  timestring[127] = '\0';

  fprintf(irc->file, "%s - [%s] <%s> %s\n", irc->channel, timestring, nick,
          message);
  fflush(irc->file);
  return 0;
}

void irc_close(irc_t *irc) {
  close(irc->s);
  fclose(irc->file);
}

// irc_pong: For answering pong requests...
int irc_pong(int s, const char *data) {
  return sck_sendf(s, "PONG :%s\r\n", data);
}

// irc_reg: For registering upon login
int irc_reg(int s, const char *nick, const char *username,
            const char *fullname) {
  return sck_sendf(s, "NICK %s\r\nUSER %s localhost 0 :%s\r\n", nick, username,
                   fullname);
}

// irc_join: For joining a channel
int irc_join(int s, const char *data) {
  return sck_sendf(s, "JOIN %s\r\n", data);
}

// irc_part: For leaving a channel
int irc_part(int s, const char *data) {
  return sck_sendf(s, "PART %s\r\n", data);
}

// irc_nick: For changing your nick
int irc_nick(int s, const char *data) {
  return sck_sendf(s, "NICK %s\r\n", data);
}

// irc_quit: For quitting IRC
int irc_quit(int s, const char *data) {
  return sck_sendf(s, "QUIT :%s\r\n", data);
}

// irc_topic: For setting or removing a topic
int irc_topic(int s, const char *channel, const char *data) {
  return sck_sendf(s, "TOPIC %s :%s\r\n", channel, data);
}

// irc_action: For executing an action (.e.g /me is hungry)
int irc_action(int s, const char *channel, const char *data) {
  return sck_sendf(s, "PRIVMSG %s :\001ACTION %s\001\r\n", channel, data);
}

// irc_msg: For sending a channel message or a query
int irc_msg(int s, const char *channel, const char *data) {
  return sck_sendf(s, "PRIVMSG %s :%s\r\n", channel, data);
}

Generated by Getz using scpaste at Mon Feb 24 22:51:57 2025. CET. (original)