void IRC_Loop(void) { /*Most of the action is triggered here.*/ char MessageBuf[2048]; while (1) { if (!Net_Read(SocketDescriptor, MessageBuf, sizeof MessageBuf, true)) { /*No command should ever call Net_Read() besides us and the connecting stuff that comes before us.*/ puts("\033[31mCONNECTION LOST\033[0m"); close(SocketDescriptor); exit(1); } if (!strncmp(MessageBuf, "PING ", strlen("PING "))) IRC_Pong(MessageBuf); /*Respond to pings.*/ switch (IRC_GetMessageType(MessageBuf)) { char Nick[1024], Ident[1024], Mask[1024]; case IMSG_PRIVMSG: { char MessageData[2048], *TC = NULL, Channel[1024]; unsigned long Inc = 0; if (!IRC_BreakdownNick(MessageBuf, Nick, Ident, Mask)) continue; IRC_GetMessageData(MessageBuf, MessageData); if (Auth_IsBlacklisted(Nick, Ident, Mask)) continue; /*Says "you are not going to be listened to bud.*/ if (strcmp(Nick, ServerInfo.Nick) != 0) Log_WriteMsg(MessageBuf, IMSG_PRIVMSG); for (; MessageData[Inc] != ' ' && MessageData[Inc] && Inc < sizeof Channel - 1; ++Inc) { Channel[Inc] = MessageData[Inc]; } Channel[Inc] = '\0'; TC = strchr(MessageData, ' ') + 1; if (*TC == ':') ++TC; if (*TC == 0x01) { /*IRC escape code thingy...*/ if (!strcmp(TC, "\01VERSION\01")) { IRC_Notice(Nick, "\01VERSION aqu4bot " BOT_VERSION "\01"); } else if (!strncmp(TC, "\01PING", strlen("\01PING"))) { IRC_Notice(Nick, TC); } } else { /*I don't feel like including time.h*/ time_t time(time_t*); CMD_ProcessCommand(MessageBuf); if (strcmp(Nick, ServerInfo.Nick) != 0) { CMD_UpdateSeenDB(time(NULL), Nick, Channel, TC); } } break; } case IMSG_NOTICE: if (!IRC_BreakdownNick(MessageBuf, Nick, Ident, Mask)) continue; if (Auth_IsBlacklisted(Nick, Ident, Mask)) continue; if (strcmp(Nick, ServerInfo.Nick) != 0) Log_WriteMsg(MessageBuf, IMSG_NOTICE); break; case IMSG_INVITE: { if (!IRC_BreakdownNick(MessageBuf, Nick, Ident, Mask)) continue; if (Auth_IsBlacklisted(Nick, Ident, Mask)) continue; if (Auth_IsAdmin(Nick, Ident, Mask, NULL)) { const char *TWorker = MessageBuf; TWorker = strchr(TWorker, '#'); if (!TWorker) { IRC_Message(Nick, "There is something wrong, and although you are an admin," "your invite request is either malformed or it's my fault."); break; } IRC_Message(Nick, "Coming."); if (IRC_JoinChannel(TWorker)) IRC_AddChannelToTree(TWorker); } else { IRC_Message(Nick, "I'm sorry, I can only accept invite requests from my admins."); } break; } case IMSG_KICK: { char InBuf[2048], *Worker = InBuf; IRC_GetMessageData(MessageBuf, InBuf); Log_WriteMsg(MessageBuf, IMSG_KICK); if (!(Worker = strchr(InBuf, ' '))) break; *Worker = '\0'; IRC_DelChannelFromTree(*InBuf == ':' ? InBuf + 1 : InBuf); break; } case IMSG_QUIT: { if (!IRC_BreakdownNick(MessageBuf, Nick, Ident, Mask)) continue; if (!strcmp(Nick, ServerInfo.Nick)) { IRC_Quit(NULL); IRC_ShutdownChannelTree(); Auth_ShutdownAdmin(); CMD_SaveSeenDB(); Auth_ShutdownBlacklist(); exit(0); } break; } case IMSG_JOIN: { if (!IRC_BreakdownNick(MessageBuf, Nick, Ident, Mask)) continue; Log_WriteMsg(MessageBuf, IMSG_JOIN); while (CMD_ReadTellDB(Nick)); break; } case IMSG_PART: if (!IRC_BreakdownNick(MessageBuf, Nick, Ident, Mask)) continue; Log_WriteMsg(MessageBuf, IMSG_PART); break; case IMSG_NICK: { char NewNick[1024]; IRC_GetMessageData(MessageBuf, NewNick); while (CMD_ReadTellDB(*NewNick == ':' ? NewNick + 1 : NewNick)); } default: break; } } }
Bool IRC_Connect(void) { char UserString[2048], NickString[2048], MessageBuf[2048]; struct ChannelTree *Worker = Channels; Bool ServerLikesUs = false; int Code = 0; printf("Connecting to \"%s:%hu\"... ", ServerInfo.Hostname, ServerInfo.PortNum), fflush(stdout); if (!Net_Connect(ServerInfo.Hostname, ServerInfo.PortNum, &SocketDescriptor)) goto Error; snprintf(UserString, sizeof UserString, "USER %s 8 * :%s\r\n", ServerInfo.Ident, ServerInfo.RealName); snprintf(NickString, sizeof NickString, "NICK %s\r\n", ServerInfo.Nick); Net_Write(SocketDescriptor, UserString); Net_Write(SocketDescriptor, NickString); /*Check if the server likes us.*/ while (!ServerLikesUs) { if (!Net_Read(SocketDescriptor, MessageBuf, sizeof MessageBuf, true)) goto Error; IRC_GetStatusCode(MessageBuf, &Code); if (Code == 0) continue; switch (Code) { case IRC_CODE_OK: ServerLikesUs = true; break; case IRC_CODE_NICKTAKEN: fprintf(stderr, "Nickname taken. Shutting down.\n"); close(SocketDescriptor); exit(1); break; default: break; } } puts("Connected."); if (ServerInfo.SetBotmode) { char OutBuf[2048]; printf("Setting +B on ourselves..."); snprintf(OutBuf, sizeof OutBuf, "MODE %s +B\r\n", ServerInfo.Nick); Net_Write(SocketDescriptor, OutBuf); puts(" Done."); } if (ServerInfo.NickservPwd[0] != '\0') { char NickservString[2048]; printf("Authenticating with NickServ..."); snprintf(NickservString, 2048, "identify %s", ServerInfo.NickservPwd); IRC_Message("NickServ", NickservString); puts(" Done."); } if (Channels) { printf("Joining channels..."), fflush(stdout); for (; Worker != NULL; Worker = Worker->Next) { IRC_JoinChannel(Worker->Channel); printf(" %s", Worker->Channel), fflush(stdout); } putc('\n', stdout); } puts("\nEverything's up, ready to go.\n----"), fflush(NULL); return true; Error: fprintf(stderr, "Failed\n"); return false; }
void Conf_AddIRCChan(const char *ircchan, bool &) { conf.lists.irc_channels.push_back(ircchan); IRC_JoinChannel(ircchan); }