Soyez le premier à donner votre avis sur cette source.
Snippet vu 16 045 fois - Téléchargée 37 fois
/********************************************************************/ /*** IrrealBot v1.0: ***/ /*** Se compile sous nux avec gcc ou sous win avec gcc ou vc++ ***/ /*** ***/ /*** Version de démonstration : peu de fonctions implémentées ***/ /*** Les fonctions sont normalement réparties dans plusieurs .c ***/ /*** Mais jai ici tout rassemblé pour cppfrance.com (pour ke les ***/ /*** non enregistrés puissent visualiser le code :) ***/ /*** Bon mattez le code maintenant :p ***/ /*** ***/ /*** Pour l'utiliser: ***/ /*** ./bot serveur port nick chan founder [ident] [nom réel] ***/ /*** exemple : ./bot irc.freenode.net 6667 botirc linux groar ***/ /*** ***/ /*** l ident et le nom réel ne sont pas obligatoires ***/ /*** /!\ le Chan ne doit pas avoir de # ;) car sous nux ca ***/ /*** fait bugger ***/ /********************************************************************/ /* Les includes communs a windows et linux */ #include <stdio.h> #include <string.h> /* includes de windows */ #ifdef WIN32 #include <winsock.h> typedef unsigned int u_int32_t; /* utilisé par linux mais non défini dans winsock.h */ /* les includes de linux */ #else #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <sys/types.h> #define SOCKET_ERROR (-1) /* défini dans winsock.h */ typedef struct sockaddr_in SOCKADDR_IN; /* idem */ #endif /* différentes commandes IRC */ #define IRC_USER "USER %s %s %s :%s\n" #define IRC_NICK "NICK %s\n" #define IRC_MSG "PRIVMSG %s :%s\n" #define IRC_JOIN "JOIN %s\n" #define IRC_PART "PART %s\n" #define PING_CMD "PING :%s\n" #define PONG_CMD "PONG :%s\n" #define IRC_QUIT "QUIT :%s\n" /* structure définissant un utilisateur IRC : plus pratique */ typedef struct irc_user{ char *nick; char *ident; char *name; char *host; }irc_user; /* quelques fonctions maison */ int my_sock_init(); char *my_sock_recv_line(int sock); int my_sock_client(char Fip[],int port); int my_error(char *file,int line,int severity,char *texte); char *my_last_arg(char *chaine); char *strleft(char *chaine,int lft) ; /* fonction servant a se connecter a un server irc */ int irc_connect(char *serveur,int port,irc_user u1,char *chan); int irc_shell(int sock1,char *master); // la fonction traitant les commandes du bot /* commandes du parser: on lui donne a manger ce que nous envoie le serveur et nous renvoie : */ char *parser_get_nick(char *data); // le nick de celui ki a executé une commande char *parser_get_ident(char *data); // son ident char *parser_get_host(char *data) ; // son host :p char *parser_get_cmd(char *data); // la commande (NOTICE,PRIVMSG,etc...) char *parser_get_dest(char *data); // la destination : le chan ou le nick a qui est adressé la commande char *parser_get_buf(char *data); // ce qui est envoyé (le message par exemple) /* J ai délibérément utilisé ici des int a la place des SOCKET (les SOCKET sont des int) pour que cela ressemble un peu plus au code linux (souvenez vous que ce code compile également sous linux */ int main(int argc, char *argv[]) { irc_user bot; int retval=0; int mainsock; // le sock utilisé du debut a la fin char *chan; // buffer pour recevoir le chan + le # ki va avec ;) if(argc < 6) // si on a pas mis tous les arguments obligatoires { printf("USAGE: %s <serveur> <port> <nick> <chan> <propriétaire> [ident] [name]\n",argv[0]); return (-1); } if(argc == 6) // si ya pas d ident et de name { bot.ident = "default"; bot.name = "Je suis irréel"; } if(argc == 7) // si ya pas de name { bot.ident = (char *)malloc(strlen(argv[6])); bot.ident = argv[6]; bot.name = "Je suis irréel"; } if(argc == 8) // si ya tout { bot.ident = (char *)malloc(strlen(argv[6])); bot.ident = argv[6]; bot.name = (char *)malloc(strlen(argv[7])); bot.name = argv[7]; } bot.nick = (char *)malloc(strlen(argv[3])); // jaime bien les malloc (sinon ca segfault souvent sous nux) bot.nick = argv[3]; bot.host = "abyssal"; // sert a rien chan =(char *)malloc(strlen(argv[4]) + 2); sprintf(chan,"#%s",argv[4]); // on prend le nom du chan et on rajoute le # devant while(retval != 1) { mainsock = irc_connect(argv[1],atoi(argv[2]),bot,chan); // on connecte a irc et on renvoit une socket retval = irc_shell(mainsock,argv[5]); // le sock est reutilisé dans le shell } return 0; } // FONCTION irc_connect int irc_connect(char *serveur,int port,irc_user u1,char *chan) { int sock1; int i; char *buf_send=(char *)malloc(sizeof(char)*50); // le buffer avec lekel on envoit les données char *buf_recv=(char *)malloc(sizeof(char)); // le buffer dans lequel sont stockées les données recues char *tmpbuf; #ifdef WIN32 my_sock_init(); // fonction seulement pour win #endif sock1 = my_sock_client(serveur,port); // on fait une connection cliente sprintf(buf_send,IRC_USER,u1.ident,u1.nick,u1.nick,u1.name); // on envoit la commande USER if(send(sock1,buf_send,strlen(buf_send),0) == SOCKET_ERROR) my_error(__FILE__,__LINE__,0,"Send Error"); sprintf(buf_send,IRC_NICK,u1.nick); // on envoit la commande NICK if(send(sock1,buf_send,strlen(buf_send),0) == SOCKET_ERROR) my_error(__FILE__,__LINE__,0,"send error"); buf_recv=(char *)my_sock_recv_line(sock1); if((tmpbuf = strstr(buf_recv,"PING")) != NULL) // si PING on repond { printf("PING ? PONG !\n"); tmpbuf[1]='O'; send(sock1,tmpbuf,strlen(tmpbuf),0); } for(i=0;i<1000;i++); // c un temps d attente c tout :) sprintf(buf_send,IRC_JOIN,chan); // on join le chan demandé if(send(sock1,buf_send,strlen(buf_send),0) == SOCKET_ERROR) my_error(__FILE__,__LINE__,0,"send error"); return sock1; } int irc_shell(int sock2,char *master) { int sock1 = sock2; int retval = 0; char *buf_send=(char *)malloc(sizeof(char)*50); char *buf_recv=(char *)malloc(sizeof(char)); char *tmpbuf,*buf2; struct timeval tv; fd_set rfds; tv.tv_sec=0; // on va attendre 0seconde tv.tv_usec=0; // et 0 µs :) while(retval == 0) { FD_ZERO(&rfds); // on met a zero le fd_set FD_SET(sock1,&rfds); // on ajoute sock1 kommme descripteur a l ensemble select(sock1 + 1,&rfds,NULL,NULL,&tv); // man select :] /* est ce qu on sock1 a subi un changement (arrivée de données par exemple) */ if(FD_ISSET(sock1,&rfds)) { buf_recv=(char *)my_sock_recv_line(sock1); // on recoit une ligne if((parser_get_cmd(buf_recv)) != NULL) {if((strcmp(parser_get_cmd(buf_recv),"PRIVMSG")) == 0) // si la commande est un PRIVMSG printf("<%s> %s\r\n",parser_get_nick(buf_recv),parser_get_buf(buf_recv)); } // on affiche facon mirc :) if((tmpbuf = strstr(buf_recv,"PING")) != NULL) // PING ? PONG ! { tmpbuf[1]='O'; send(sock1,tmpbuf,strlen(tmpbuf),0); printf("PING ? PONG !\n"); } // si le nick de celui ki parle est celui ki controle le bot if((strcmp(parser_get_nick(buf_recv),master)) == 0) { if((tmpbuf = strstr(buf_recv,"!join")) != NULL) { if((buf2 = strstr(tmpbuf," ")) != NULL) // ca prend tout ce kya apres le !join { // strleft me sert ici a enlever l espace devant le chan printf("*** JOINING %s",strleft(buf2,1)); sprintf(buf_send,IRC_JOIN,strleft(buf2,1));// cmd JOIN send(sock1,buf_send,strlen(buf_send),0); // on join le chan } } if((tmpbuf = strstr(buf_recv,"!part")) != NULL) // idem avec part { if((buf2 = strstr(tmpbuf," ")) != NULL) { printf("*** PARTING %s",strleft(buf2,1)); sprintf(buf_send,IRC_PART,strleft(buf2,1)); send(sock1,buf_send,strlen(buf_send),0); } } // quit qui en + de faire partir du serv fait sortir du while if((tmpbuf = strstr(buf_recv,"!quit")) != NULL) { if((buf2 = strstr(tmpbuf," ")) != NULL) { printf("*** QUIT(%s)",strleft(buf2,1)); sprintf(buf_send,IRC_QUIT,strleft(buf2,1)); send(sock1,buf_send,strlen(buf_send),0); retval = 1; } } if((tmpbuf = strstr(buf_recv,"!exit")) != NULL) { send(sock1,"QUIT\n",strlen("QUIT\n"),0); retval = 2;// avec ca le bot quit et revient } if((tmpbuf = strstr(buf_recv,"!say")) != NULL) { if((buf2 = strstr(tmpbuf," ")) != NULL) { printf("*** %s",strleft(buf2,1)); sprintf(buf_send,IRC_MSG,parser_get_dest(buf_recv),strleft(buf2,1)); send(sock1,buf_send,strlen(buf_send),0); } } // ex: !raw PRIVMSG #groar :lol <-- raw sert a envoyer des donneés au server if((tmpbuf = strstr(buf_recv,"!raw")) != NULL) { if((buf2 = strstr(tmpbuf," ")) != NULL) { printf("RAW :%s",buf2); sprintf(buf_send,strleft(buf2,1)); send(sock1,buf_send,strlen(buf_send),0); } } if((tmpbuf = strstr(buf_recv,"!nick")) != NULL) // change de nick { printf("*** je change de nick : %s",my_last_arg(tmpbuf)); sprintf(buf_send,IRC_NICK,my_last_arg(tmpbuf)); send(sock1,buf_send,strlen(buf_send),0); } } } else { // si vous avez kelke chose a mettre :p } } #ifdef WIN32 closesocket(sock1); // facon win #else close(sock1); // facon nux #endif return retval; } char *parser_get_nick(char *data) { char *buf=(char *)malloc(100*sizeof(char)); char *delimit = ":!" ; char *buf1 = strdup(data); buf = strtok(buf1, delimit); // on prend le char * entre le : et le ! return (char *)buf; // c le nick } char *parser_get_ident(char *data) { // meme systeme : man strtok char *buf; char *delimit = "~@" ; char *buf1 = strdup(data); buf = strtok(buf1, ":!"); buf = strtok(NULL, delimit); return (char *)buf; } char *parser_get_host(char *data) { char *buf; char *delimit = " " ; char *buf1 = strdup(data); buf = strtok(buf1, ":!"); buf = strtok(NULL, "~@"); buf = strtok(NULL, delimit); return (char *)buf; } char *parser_get_cmd(char *data) { char *buf; char *delimit = " " ; char *buf1 = strdup(data); buf = strtok(buf1, ":!"); buf = strtok(NULL, "~@"); buf = strtok(NULL, " "); buf = strtok(NULL, delimit); return (char *)buf; } char *parser_get_dest(char *data) { char *buf; char *delimit = ":" ; char *buf1 = strdup(data); buf = strtok(buf1, ":!"); buf = strtok(NULL, "~@"); buf = strtok(NULL, " "); buf = strtok(NULL, " "); buf = strtok(NULL, delimit); return (char *)buf; } char *parser_get_buf(char *data) { char *buf; char *delimit = "\n" ; char *buf1 = strdup(data); buf = strtok(buf1, ":!"); buf = strtok(NULL, "~@"); buf = strtok(NULL, " "); buf = strtok(NULL, " "); buf = strtok(NULL, ":"); buf = strtok(NULL, delimit); return (char *)buf; } // decale une char * vers la gauche : exemple : strleft("groar",1); = roar char *strleft(char *chaine,int lft) { int i = 0; char *buf = (char *)malloc(strlen(chaine) - lft); for(i = lft; i < strlen(chaine); i++) { buf[i - lft] = chaine[i]; } return (char *)buf; } // avec ca on recoit ligne par ligne ce ke le serv envoie char *my_sock_recv_line(int sock) { int pos = 0; char c; int buf_len; char *buf_str; buf_str = (char *)malloc(10 * sizeof(char)); buf_len = 10; c = '\0'; while(c != '\n') { recv(sock,&c,sizeof(char),0); buf_str[pos] = c; pos++; if(pos == buf_len) { buf_len += 10; buf_str = (char *)realloc(buf_str,buf_len * sizeof(char)); } } buf_str[pos] = '\0'; return (char *)buf_str; } int my_sock_client(char Fip[],int port) // pour se connnect a un serv { int s; unsigned int addr; struct hostent *hp; struct sockaddr_in sin; if (isalpha(Fip[0])) hp=gethostbyname(Fip); else { addr = inet_addr(Fip); hp = gethostbyaddr((char *)&addr,4,AF_INET); } sin.sin_addr.s_addr = *((u_int32_t *) hp->h_addr);; sin.sin_family = AF_INET; sin.sin_port=htons(port); s = socket(PF_INET, SOCK_STREAM, 0); if (connect(s,(struct sockaddr *)&sin,sizeof(SOCKADDR_IN))==SOCKET_ERROR) my_error(__FILE__,__LINE__,0,"erreur de connect"); return s; } char *my_last_arg(char *chaine) // retourne le dernier mot d une chaine { char* p; char* buffer,*temp; char* separateurs = { " " }; buffer = strdup(chaine); p = strtok( buffer, separateurs ); temp = (char *)malloc(strlen(p)+1); while((p = strtok( NULL, separateurs )) != NULL ) { free(temp); temp = (char *)malloc(strlen(p)+1); sprintf(temp,p); } return (char*)temp; } // erreur : c pourri comme error mais bon int my_error(char *file,int line,int severity,char *texte) { printf("%s:%d # %s\n",file,line,texte); return 0; } int my_sock_init() // init pour winsock { #ifdef WIN32 WSADATA wsaData; WORD verreq; verreq=MAKEWORD(2,2); if(WSAStartup(verreq,&wsaData) != 0) return -1; #endif return 0; }
23 mai 2006 à 11:23
sprintf(buf_send,IRC_JOIN,buf2+1);
idem que sprintf(buf_send,IRC_JOIN,strleft(buf2,1));
mais il serait judicieux de faire une fonction strleft qui gère les erreur comme décallage trop grand.
23 mai 2006 à 11:11
6 avril 2006 à 20:47
6 avril 2006 à 19:51
6 avril 2006 à 00:19
outre le fait que ce soit portable, au niveau experience utilisateur ou juste codage, qu'est ce qui est plus interessant. ne peut t on pas faire un mix pour eviter de recoder sans cesse l'irc tout en gardant une bonne simplicité d'utilisation, et pourquoi pas a portabilité
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.