| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
IRC-botin runko unixilleempty 15.01.05 12:20 Eli pelkkä ircbotin runko joka connectaa servulle ja yhdistää johonkin kannulle mutta ei sitten teekkään mitään muuta :) toimii vain *nix puolella!
/* bot.c */ /* TUROKIN IRC-BOTTI */ /* gcc bot.c -o bot */ /* tee tiedosto botdata.h ja käsittele siellä funktiossa parsedata() kaikki data mitä servu lähettää*/ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <netdb.h> #include "botdata.h" /*botdata.h sisältää kaiken datan parserointiin liittyvän*/ int fd; void usage(char *nimi); void ircconnect(char *servu, int port, char *name); void printbuffer(char *puskuri); int parsedata(char *data, int sokka, char *kannu); int main(int argc, char *argv[]) { int bytes, i; char buffer[1000], pingi[50], joini[50], message[200], nick[100]; printf("Turokki's IRC-bot starting...\n"); if(argc != 5) { usage(argv[0]); } else { ircconnect(argv[1], atoi(argv[2]), argv[4]); } /*Looppi joka vastaanottaa dataa serveriltä, printtaa sen näytölle, ja lähettää sen eteenpäin käsiteltäväksi*/ while(1) { for(i=0; i<1000; i++) buffer[i] = '\0'; recv(fd, buffer, 1000, 0); /*Jos halutaan nähdä mitä servu lähettää käytetään printbufferia, muutoin tämän rivin voi ottaa pois*/ printbuffer(buffer); /*Eli tee tiedosto botdata.h ja laita sinne parsedata funktio (prototyyppi yllä), jossa tarkistat mitä dataa tulee ja sitä sitten käsitellään*/ parsedata(buffer, fd, argv[3]); } /*Loppujen lopuksi suljetaan yhteys ja sammutetaan ohjelma*/ close(fd); printf("Disconnected!!!\n"); return(0); } /*Tämä funktio yhdistää servulle annettujen argumenttien perusteella*/ void ircconnect(char *servu, int port, char *name) { int i; char buffer[1000]; /*Rakentajat joita tarvitaan socketeissa*/ struct hostent *he; struct sockaddr_in server; /*Selvitetään servun IP osoite annetusta nimestä*/ printf("Looking up server... "); if((he = gethostbyname(servu)) == NULL) { printf("Invalid server!!!\n"); printf("Exiting...\n"); exit(0); } /*Printataan kaivettu tieto ylös*/ printf("found!!!\n"); printf("Hostname: %s\n", he->h_name); printf("IP Address: %s\n", (inet_ntoa(*((struct in_addr *) he->h_addr)))); /*Muodostetaan socketti*/ printf("Trying to connect on port %i... ", port); if((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("Error in socket()!!!\n"); exit(0); } /*Laitetaan tarvittava data samaan pakettiin*/ server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(server.sin_zero), 8); /*Ja lopuksi yhdistetään määrättyyn porttiin*/ if(connect(fd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) { printf("\nCould not connect!!!\n"); exit(0); } printf("Connected!!!\n"); /*Kaikki sujui hienosti mutta laitetaan vielä nickname stringi servulle että servu vaihtaa nikin oikeaksi*/ printf("Sending nick name string..."); for(i=0; i<1000; i++) buffer[i] = '\0'; sprintf(buffer, "NICK %s\r\nUSER %s \"\" \"%s\" :x\r\n", name, name, (inet_ntoa(*((struct in_addr *) he->h_addr)))); send(fd, buffer, strlen(buffer), 0); printf(" done!!!\n"); } /*Käytin debuggauksessa tälläistä funktiota jolla tarkistin mitä se servu oikein lähetti, ei ole pakko ottaa mukaan*/ void printbuffer(char *puskuri) { int i; for(i=0; i<1000; i++) { if(puskuri[i] != '\0') printf("%c", puskuri[i]); } } /*Tästä tuskin tarvitsee sanoa mitään*/ void usage(char *nimi) { printf("Usage: %s <IRC-SERVER> <PORT> <CHANNEL> <NICKNAME>\n", nimi); exit(0); } ----------EOF------------ /*Tosilyhyt esimerkki parsedata.h tiedostosta, vastaa vain pingeihin mitä servu lähettää että botti pysyisi servulla disconnectaamatta*/ /*ELI SIIS ÄLKÄÄ OTTAKO TÄSTÄ OPPIA!!! :)*/ #include <stdio.h> #include <stdlib.h> #include <string.h> int parsedata(char *data, int sokka, char *kannu) { int i, y; char pong[100]; char puskuri[1000]; for(i=0; i<1000; i++) { /*Tämä tarkistus on yhtä helvettiä näin mutta en tiedä miten sen olisin järkevämmin toteuttanut :F*/ if(data[i] == 'P' && data[i+1] == 'I' && data[i+2] == 'N' && data[i+3] == 'G' && data[i+4] == ' ' && data[i+5] == ':') { for(y=0; y<100; y++) pong[y] = '\0'; /*Sitä samaa purkkaa eli kerätään serverin lähettämä numero/kirjain sarja ylös*/ for(y=0; y<40; y++) { if(data[i+6+y] != '\0') pong[y] = data[i+6+y]; } for(y=0; y<40; y++) { if(pong[y] != '\0') printf("%c", pong[y]); } /*ja vastataan servulle takaisin kyseisellä sarjalla*/ for(y=0; y<1000; y++) puskuri[y] == '\0'; sprintf(puskuri, "PONG :%s\r\n", pong); send(sokka, puskuri, strlen(puskuri), 0); /*Tein botilleni omat authit jolloin botti saa aina opit kun joinii kannullemme, eli laita kohtaan tunnus ja salasana omat tietosi*/ if(authed == 0) { for(y=0; y<1000; y++) puskuri[y] == '\0'; sprintf(puskuri, "PRIVMSG Q@CServe.quakenet.org :AUTH tunnus salasana\r\n"); send(sokka, puskuri, strlen(puskuri), 0); authed = 1; } /*Loppujen lopuksi joinitaan kyseiselle kannulle joka on jo määritelty*/ for(y=0; y<1000; y++) puskuri[y] == '\0'; sprintf(puskuri, "JOIN #%s\r\n", kannu); send(sokka, puskuri, strlen(puskuri), 0); } } } -----------------EOF------------- empty 12:23 15.1.05 Eli siis itselläni parsedata.h tiedostossa on vaikka mitä, siellä on muunmuassa laskuri joka laskee kaksi annettua numeroa ja lähettää vastauksen takaisin serverille, sitten siellä on se googlefight mistä kyselin jne. Mutta ne saattekin suunnitella itse :) Kommentteja? weicco 14:58 15.1.05 if (!strncmp(data, "PING", 4)) { pingi... } phadej 00:17 16.1.05 jos data[] = "PING :11111" niin data+6 = "11111" for(y=0; y<1000; y++) puskuri[y] == '\0'; on sama kun memset(puskuri,0,1000); mutta taitaa olla koko rivi turha muutenkin, kun siihen seuraavaksi sprintf:ataan jotain. ja miksi jos lauseen sisällä laitetaan authed=1; jos silti ehdon jälkein se laitetaan ykköseksi? editoitu: 00:53 16.1.05 empty 00:52 16.1.05 oho joo sinne on jäänyt kaikkea kun en sitä ole jaksanut siistiä, ei siitä parsedata funktiosta kannata oppia ottaakkaan vaan lähinnä tuon pelkän rungon tarjosin mikä yhdistää serverille sillä monella sokketit ovat hakusassa. Tuostahan ei ole vaikea enää muokata omanlaistaan :) Kuitenkaan tuo botti ei serverille pääsisi ilman tuota pingiin vastausta niin se oli sinne pakko laittaa :P editoitu: 01:02 16.1.05 Ceez 00:58 16.1.05 *SENSUROITU*, koska huolimattomuuttani toheloitsin.. remix 15:27 16.1.05 for(i=0; i<1000; i++) buffer[i] = '\0'; rivin voi hoitaa helpmmin memsetillä: memset( buffer, '\0', 1000 * sizeof( char ) ); editoitu: 12:11 18.1.05 Ztane 12:06 18.1.05 Hmm en ny tiiä muttas eiks riittäs if (strncmp(buf, "PING :", 6) == 0) { char *pong = strdup(buf); pong[1] = 'O'; lähetä free(pong); } ja yleensä teen recv(fd, buf, n...) ja sitten buf[n - 1] = 0; jollon toimii printf("%s\n", buf)? ja mistä tiiät ettei se "ping" oo splittautunu kahteen satsiin? Oikeampi tapa (tm) lienee feedata jotain puskuria noilla recvin hömppeillä kunnes tulee rivinvaihto tms. Ja komentosanat merkkaa vaan rivin alussa? (huomatkaa, en määkää osaa IRCkiä) weicco 13:07 18.1.05 Joo. Eli vastaanotossa pitäisi käyttää puskurointia. Verkosta luetaan tauhkaa erilliseen puskuriin ja sieltä etsitään \r\n eroittimella viestejä oikeaan puskuriin. Tällaisen toteuttaminen on aika kivaa, vaatii hieman ajattelua, että siitä saa toimivan ja nopskan. empty 19:59 19.1.05 Joo ei riitä mun aivot vielä tollaiseen joten tälläinen purkkaviritelmäkin toimii :) Mutta jokainenhan saa ottaa oppia ja muokata tuota itse paremmaksi! pienipoika 02:18 8.8.08 niin saa ja niin minä tein. tein tuosta rungosta ensin quakenettiin kanavalleni ylläpitobotin joka auto-oppasi jne jne.. sitten koodasin itse kaiken muun kuin socetin koska en sitä osannut.. myöhemmin kirjoitin botin kokonaan uudestaan käyttäen SDL:n nettikirjastoa. nytten botti on kokonaan itsekirjoittamani (tosin en olisi tehnyt sitä ilman tätä koodivinkkiä) ja hoitaa tärkeitä asioita omalla irc serverilläni yhteistyössä toisen botin kanssa. se ylläpitää mysql tietokantaa käyttäjistä sekä kanavista ja tarjoaa muutamia ylläpitokomentoja authanneille operaattoreille. kiitos empty :) |
![]() Haku
|