Simple C++ IRC Bot Template


IRC Funny CartoonI searched the Internet, for quit a while, and I couldn’t find the source for a simple IRC bot in C plus plus, so I decided to write one using a TCP Stream Socket in C++. It works by setting up a simple TCP Socket to a IRC server on port 6667. The IRC Bot then assigns a NICK to the connection and connects to a IRC Channel. From here you can code you own commands and replies. I originally developed this to monitor IRC channels, however I came across a problem, PING. IRC servers periodically ping all clients to see if they are connected, so I added some more code to reply to these ping’s so that the bot stays connected.

Like I said this is only a base for a IRC Bot written in C Plus Plus, at the moment all it can do is reply to ping’s and reply to commands, however with a little bit of time you could create a full featured IRC bot in C++ from this code, so here it is:




DOWNLOAD SOURCE

USAGE:
int main()
{
	IrcBot bot = IrcBot("NICK testBOT\r\n","USER guest tolmoon tolsun :Ronnie Reagan\r\n");
	bot.start();

  return 0;

}
HEADER:
/*
 * IrcBot.h
 *
 *  Created on: 15 Jul 2011
 *      Author: Tyler Allen
 */

#ifndef IRCBOT_H_
#define IRCBOT_H_

class IrcBot
{
public:
	IrcBot(char * _nick, char * _usr);
	virtual ~IrcBot();

	bool setup;

	void start();
	bool charSearch(char *toSearch, char *searchFor);

private:
	char *port;
	int s; //the socket descriptor

	char *nick;
	char *usr;

	bool isConnected(char *buf);
	char * timeNow();
	bool sendData(char *msg);
	void sendPong(char *buf);
	void msgHandel(char *buf);
};

#endif /* IRCBOT_H_ */
CPP File
/*
 * IrcBot.cpp
 *
 *  Created on: 15 Jul 2011
 *      Author: Tyler Allen
 */

#include "IrcBot.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>

using namespace std;

#define MAXDATASIZE 100

IrcBot::IrcBot(char * _nick, char * _usr)
{
	nick = _nick;
	usr = _usr;
}

IrcBot::~IrcBot()
{
	close (s);
}

void IrcBot::start()
{
	struct addrinfo hints, *servinfo;

	//Setup run with no errors
	setup = true;

	port = "6667";

	//Ensure that servinfo is clear
	memset(&hints, 0, sizeof hints); // make sure the struct is empty

	//setup hints
	hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
	hints.ai_socktype = SOCK_STREAM; // TCP stream sockets

	//Setup the structs if error print why
	int res;
	if ((res = getaddrinfo("irc.ubuntu.com",port,&hints,&servinfo)) != 0)
	{
		setup = false;
		fprintf(stderr,"getaddrinfo: %s\n", gai_strerror(res));
	}

	//setup the socket
	if ((s = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol)) == -1)
	{
		perror("client: socket");
	}

	//Connect
	if (connect(s,servinfo->ai_addr, servinfo->ai_addrlen) == -1)
	{
		close (s);
		perror("Client Connect");
	}

	//We dont need this anymore
	freeaddrinfo(servinfo);

	//Recv some data
	int numbytes;
	char buf[MAXDATASIZE];

	int count = 0;
	while (1)
	{
		//declars
		count++;

		switch (count) {
			case 3:
					//after 3 recives send data to server (as per IRC protacol)
					sendData(nick);
					sendData(usr);
				break;
			case 4:
					//Join a channel after we connect, this time we choose beaker
				sendData("JOIN #ubuntu\r\n");
			default:
				break;
		}

		//Recv & print Data
		numbytes = recv(s,buf,MAXDATASIZE-1,0);
		buf[numbytes]='\0';
		cout << buf;
		//buf is the data that is recived

		//Pass buf to the message handeler
		msgHandel(buf);

		//If Ping Recived
		/*
		 * must reply to ping overwise connection will be closed
		 * see http://www.irchelp.org/irchelp/rfc/chapter4.html
		 */
		if (charSearch(buf,"PING"))
		{
			sendPong(buf);
		}

		//break if connection closed
		if (numbytes==0)
		{
			cout << "----------------------CONNECTION CLOSED---------------------------"<< endl;
			cout << timeNow() << endl;

			break;
		}
	}
}

bool IrcBot::charSearch(char *toSearch, char *searchFor)
{
	int len = strlen(toSearch);
	int forLen = strlen(searchFor); // The length of the searchfor field

	//Search through each char in toSearch
	for (int i = 0; i < len;i++)
	{
		//If the active char is equil to the first search item then search toSearch
		if (searchFor[0] == toSearch[i])
		{
			bool found = true;
			//search the char array for search field
			for (int x = 1; x < forLen; x++)
			{
				if (toSearch[i+x]!=searchFor[x])
				{
					found = false;
				}
			}

			//if found return true;
			if (found == true)
				return true;
		}
	}

	return 0;
}

bool IrcBot::isConnected(char *buf)
{//returns true if "/MOTD" is found in the input strin
	//If we find /MOTD then its ok join a channel
	if (charSearch(buf,"/MOTD") == true)
		return true;
	else
		return false;
}

char * IrcBot::timeNow()
{//returns the current date and time
	time_t rawtime;
	struct tm * timeinfo;

	time ( &rawtime );
	timeinfo = localtime ( &rawtime );

	return asctime (timeinfo);
}

bool IrcBot::sendData(char *msg)
{//Send some data
	//Send some data
	int len = strlen(msg);
	int bytes_sent = send(s,msg,len,0);

	if (bytes_sent == 0)
		return false;
	else
		return true;
}

void IrcBot::sendPong(char *buf)
{
	//Get the reply address
	//loop through bug and find the location of PING
	//Search through each char in toSearch

	char * toSearch = "PING ";

	for (int i = 0; i < strlen(buf);i++)
		{
			//If the active char is equil to the first search item then search toSearch
			if (buf[i] == toSearch[0])
			{
				bool found = true;
				//search the char array for search field
				for (int x = 1; x < 4; x++)
				{
					if (buf[i+x]!=toSearch[x])
					{
						found = false;
					}
				}

				//if found return true;
				if (found == true)
				{
					int count = 0;
					//Count the chars
					for (int x = (i+strlen(toSearch)); x < strlen(buf);x++)
					{
						count++;
					}

					//Create the new char array
					char returnHost[count + 5];
					returnHost[0]='P';
					returnHost[1]='O';
					returnHost[2]='N';
					returnHost[3]='G';
					returnHost[4]=' ';

					count = 0;
					//set the hostname data
					for (int x = (i+strlen(toSearch)); x < strlen(buf);x++)
					{
						returnHost[count+5]=buf[x];
						count++;
					}

					//send the pong
					if (sendData(returnHost))
					{
						cout << timeNow() <<"  Ping Pong" << endl;
					}

					return;
				}
			}
		}

}

void IrcBot::msgHandel(char * buf)
{
	/*
	 * TODO: add you code to respod to commands here
	 * the example below replys to the command hi scooby
	 */
	if (charSearch(buf,"hi scooby"))
	{
		sendData("PRIVMSG #ubuntu :hi, hows it going\r\n");
	}

}

DOWNLOAD SOURCE



NOTES

To change the server you wish the IRC bot to connect to change “irc.ubuntu.com” to the desired server at line 57.

You can change which channel you the IRC bot to connect to by changing “#ubuntu” at line 97 to the desired channel, I know there are better ways then hard coding thease commands however I was rushed for time and just trying to create a simple base for a IRC bot, not a full featured bot.

The msgHandel() function at line 256 is where you’ll add your message handling code, at the moment the bot will reply to any command with the words “hi scooby” in it with the reply “Hi, hows it going”. To add more simply copy the if statement at line 262 and substitute the “hi scooby” for the command. Then change “hi, hows it going” to the required reply. Remember that all messages sent must finish with “\r\n” otherwise the server will wait for more commands.

For more information on the messages used in the IRC Protocol goto http://www.irchelp.org/irchelp/rfc/chapter4.html.

Please remember that IRC Bots are banned by many IRC Servers so be careful not to get banned, if you want to test on your own IRC server I have a tutorial on how to setup your own IRC Server here. I haven’t tested this bot on a server setup following this tutorial so please comment if you have any difficulty here, thanks. I hope this comes in useful, and I apologize for the spelling mistakes in my comment’s I’m just too lazy to go through them all and correct.

, , , , , , , ,

  1. No comments yet.

You must be logged in to post a comment.