Support Forums

Full Version: C IRC bot skeleton
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
(11-23-2010, 08:08 PM)Old Dirty Bastard Wrote: [ -> ]--off topic--
-no hate intended--
( why are all IRC Bot sources here for linux? )

Code:
#ifdef NIX
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif

#ifdef WIN32
#define _WIN32_WINNT 0x0501 //Minimum winapi "version" to use
#include <winsock2.h>
#include <ws2tcpip.h>
#define close closesocket
#endif

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#define BUFSIZE 512
#define PSYCHO  NULL

/***********************
* argv[1] -> host
* argv[2] -> port
* argv[3] -> chan
* argv[4] -> nick
* argv[5] -> user
***********************/

struct irc_data {
    char nick[32];
    char user[32];
    char host[64];
    char chan[32];
    char message[512];
    int is_ready;
};

void die(const char*,int);
void parse_data(char*,struct irc_data**);
int  sayc(int,const char*,const char*, ...);

int main(int argc, char **argv){
    
    #ifdef WIN32
    WSADATA wsaData;
    WORD wVersionRequested = MAKEWORD(2, 2);
    if (WSAStartup(wVersionRequested, &wsaData) != 0) {
        fprintf(stderr,"Winsock error");
    }
    #endif
    
    if(argc!=6){
        fprintf(stderr,"usage: %s <host> <port> <chan> <nick> <ident>\n",argv[0]);
        exit(1);
    }

    const char *host = argv[1];
    const char *port = argv[2];
    const char *chan = argv[3];
    const char *nick = argv[4];
    const char *user = argv[5];

    char buff[BUFSIZE], ip[INET_ADDRSTRLEN];
    int sfd,status,sent,recvd,i;
    struct addrinfo hints,*serv;
    struct sockaddr_in *sip;
    struct irc_data *irc = malloc(sizeof(struct irc_data));

    memset(&hints,0,sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    if((status=getaddrinfo(host,port,&hints,&serv))<0)
        die("getaddrinfo",status);
    if((sfd=socket(serv->ai_family,serv->ai_socktype,serv->ai_protocol))<0)
        die("socket",sfd);
    if((status=connect(sfd,serv->ai_addr,serv->ai_addrlen))<0)
        die("connect",status);

    sip = (struct sockaddr_in*)serv->ai_addr;
    //inet_ntop(serv->ai_family,&sip->sin_addr,ip,sizeof(ip)); No idea why Psycho put this here since he is not storing the result.

    snprintf(buff,BUFSIZE,"USER %s 8 * :\x50\x73\x79\x63\x68\x6F\x20\x42\x6F\x74\r\nNICK %s\r\nJOIN #%s\r\n",user,nick,chan);
    if((sent=send(sfd,buff,strlen(buff),0))<0)
        die("send",sent);

    while((recvd=recv(sfd,buff,BUFSIZE-1,0))>=0){
        buff[recvd-1]=0;
        puts(buff);
        parse_data(buff,&irc);
        if(irc->is_ready)
            if(strstr(irc->message,nick) != NULL)
                sayc(sfd,irc->chan,"sup %s",irc->nick);
        if(sscanf(buff,"PING :%s",buff)==1){
            snprintf(buff,BUFSIZE,"PONG :%s",buff);
            if(send(sfd,buff,strlen(buff),0)>0)
                puts("PONG!");
            else puts("PONG failed...just sayin");
        }
        
    }
    free(irc);
    close(sfd);
    freeaddrinfo(serv);
    
    #ifdef WIN32
    WSACleanup ();
    #endif
    
    return 0;
}


void die(const char *msg, int err){
    fprintf(stderr,"%s: %s\n",msg,gai_strerror(err));
    exit(1);
}

void parse_data(char *buff,struct irc_data **fat){
    if(sscanf(buff,":%[^!]!%[^@]@%[^ ] %*[^ ] %[^ :] :%[^\r\n]",(*fat)->nick,(*fat)->user,(*fat)->host,(*fat)->chan,(*fat)->message) == 5){
        (*fat)->is_ready = 1;
        if((*fat)->chan[0] != '#') strcpy((*fat)->chan,(*fat)->nick);
    } else (*fat)->is_ready = 0;
}

int sayc(int sockfd, const char *chan, const char *fmt, ...){
    char msg[BUFSIZE], k[BUFSIZE];    //need to change sizes..do it later
    va_list list;
    va_start(list,fmt);
    vsnprintf(k,BUFSIZE,fmt,list);
    snprintf(msg,BUFSIZE,"PRIVMSG %s :%s\r\n",chan,k); //potential problem with \r\n being truncated if string is too large..do it later
    va_end(list);
    return send(sockfd,msg,strlen(msg),0);
}
// Psycho

BAM and it can now be compiled for *nix or windows. Make sure to define WIN32 and link winsock2 if you want to compile it for windows or NIX if you want to compile it for some unix-like operating system. How I compile it:
For windows:
Code:
i586-mingw32msvc-cc -DWIN32 ircbot.c -o ircbot.exe -lws2_32
For Linux:
Code:
cc -DNIX ircbot.c -o ircbot
Nice share pyscho Smile
Amazing, works under linux Smile
Thanks alot Salmon
Thanks for the share, I'm sure this will help a lot of people out!
Hope to see more from you soon Smile
This is going to be very useful for me, thank you so much for sharing this with us all.
Well, sorry for takeing up an old thread, but I really have to say, that i really like your code!

There's just one thing i don't get: My Client (in this case XChat), tells me that the real name from this bot is "Psycho Bot", but where do you set that Name? I don't get it out of the source code.


Thanks

~ Tectu
What a cool bot source thank you for your share you kind sir Smile
Pages: 1 2