IRC Bot
-
Hallo,
ich weiss nicht ob ich hier richtig bin, aber ich weiss einfach nicht wo es hingehört. Ich will einen IRC Bot in C++ schreiben (über Winsock2). Der Aufbau der Verbindung klappt auch einbandfrei, mein Problem ist eher die Anmeldung am IRC Server. In meinem Fall gehe ich über "irc.gamesurge.net" und benutze den Port 6667 , wie es auch in meinem Clienten (Trillian) eingestellt ist.
Normalerweise sollte ich ja NICK und USER senden und darauf sollte ein PING kommen. Wenn dieser kommt, antworte ich mit PONG. Schön und gut, der Ping kommt auch, aber nach meinem Pong passiert nix mehr.
Ich poste euch mal die releveanten Codeteile. Zuerst einmal die Ausgabe in meinem Logfile:
BUFFER: >NOTICE AUTH :*** Looking up your hostname<
BUFFER: >NOTICE AUTH :*** Found your hostname, cachedNOTICE AUTH :*** Checking Ident<
BUFFER: >PING :1796413591<
SENDING COMMAND: >PONG :1796413591
<
BUFFER: >ERROR :Closing Link: BH-Bot by Kanzi.CA.US.GameSurge.net (Registration Timeout)<So in der main sieht das ganze folgendermaßen aus
/* Einstellung der Verbindung */ #define SERVER "irc.gamesurge.net" #define SERVICE_PORT 6667 /* IRC Kommandos */ #define PING "PING " #define PONG "PONG " #define PASS "PASS " #define USER "USER " #define NICK "NICK " static IRC_CONNECTION* con; static COMMAND_PARSER* command; static FILE* file; int main (int argc, char** argv) { static char* buffer = new char [1024 + 1 ]; con = new IRC_CONNECTION ( SERVER, SERVICE_PORT ); command = new COMMAND_PARSER (); (void)strcpy (buffer, LEERSTRING ); if ( (file = fopen ("BH-bot.log", "w")) == (FILE*)NULL) { printf ("Could not create logfile.\n"); return -1; } con->write_command ("NICK BH-Bot\n"); con->write_command ("USER ~BH-Bot localhost localhost : Bot BeyondHell\n"); while (true) { (void)con->read_command (&buffer); if (strcmp (buffer, LEERSTRING) == 0 ) continue; (void)fprintf (file, "BUFFER: >%s<\n", buffer); (void)printf ("%s\n", buffer); command->parse (buffer); if ( strcmp ( command->getCommand(), PING ) == 0 ) { char buffer [100]; (void)sprintf ( buffer, "%s:%s\n", PONG, command->getValue() ); (void)fprintf ( file, "SENDING COMMAND: >%s<\n", buffer ); if (con->write_command (buffer) < 1 ) { printf ("Error writing PONG\n"); } } (void)strcpy (buffer, LEERSTRING ); } fclose (file); }
Hier die Methoden write_command und read_command:
unsigned long IRC_CONNECTION::write_command (char* cmd) { return send (*m_socket, cmd, strlen(cmd)+1, 0); }
unsigned long IRC_CONNECTION::read_command (char** buffer ) { int bytes = 0; char* buf = *buffer; bytes = recv (*m_socket, buf, 1024, 0); buf[bytes - 2] = '\0'; return 0; }
So ich hoffe ich habe euch genug informationen gegeben, damit ihr mir vernünftig helfen könnt. Eventuell ist es auch ein Verständnisproblem in der denkweise des IRC. Ich hoffe hier gibts nen paar Spezialisten.
-
Hab sowas mal mit der MFC gemacht (also asynchron), bei mir sah das so aus:
OnConnect, also sobald ich zu dem Server verbunden war:USER DerTester DerTesterHost MyHost :Peter Mustermann
NICK DerTester
join #cpp
privmsg #cpp :hiund wenn ein PING kam, hab ich den Wert zurückgeschickt:
PING :523097542
PONG :523097542Vielleicht fehlt bei dir der USER oder NICK-Command?
-
Naja das NICK und USER mache ich doch schon davor. Daraufhin kommen doch erst die anderen Ausgaben. Und der Ping kommt ja auch an und darauf reagiere ich auch. Aber der Server schickt mir nix mehr zurück, das finde ich etwas komisch.
-
ach ja... stimmt. seltsam. magst mal den quellcode schicken? dEUs@c-plusplus.net
-
Klar, zum Glück ist das Probjekt noch nicht sehr groß. Ich schicks gleich raus.
-
Hallo,
dank Deus funktioniert das mit dem Connecten jetzt ganz gut, mein Userbefehl war wohl nicht ganz richtig.
Allerdings werden die IRC-Befehle die ich danach empfange ziemlich kompliziert. Ich habe mir den allgemeinen Aufbau mal angeschaut, aber nicht wirklich verstanden. Verstanden habe ich, dass es einen Befehl mit einem Wert und optional mehreren Parametern gibt. Kennt vielleicht jemand einen link wo das gut erklärt wird oder kann mir das hier erklären?
Es geht nun noch darum, das was vom IRC kommt, in Vernünftiger weise zu splitten.
-
Hallo,
nicht nur dein User-Befehl, sondern auch dein WriteCommand war falsch.
Vielleicht hilft dir das RFC weiter?
-
Ja ich weiss das auch noch.
Naja ich habe da mal reingeschaut aber so ganz blick ich da net durch
-
Also im Protokoll steht es folgendermaßen:
Das Nachrichten-Format
Um zu zeigen, wie die Nachrichten aufgebaut sind, mit denen innerhalb eines IRC-Netzwerkes die Informationen transportiert werden, wird in der folgenden Definition eine etwas vereinfachte Backus-Naur-Form ([Claus88]) verwendet:
<nachricht> ::= [':' <sender> <SPACE>] <befehl> <parameter> <crlf>
<sender> ::= [<dienst> '@'] <server> | <nick> ['!' <benutzer>]
['@' <rechner>]<befehl> ::= <buchstabe> {<buchstabe>}
| <ziffer> <ziffer> <ziffer><SPACE> ::= ' ' {' '}
<parameter> ::= <SPACE> [':' <mitteilung> | <zusatz> <parameter>]
<zusatz> ::= <Jede nicht leere Folge von Bytes, die keine
Leerzeichen, NULL, CR oder LF beinhaltet und
keinen Doppelpunkt am Anfang besitzt.><mitteilung> ::= <Jede, möglicherweise leere Folge von Bytes, die
nicht NULL, CR oder LF beinhaltet.><crlf> ::= CR LF
Mein Problem ist das ich bei den Nachrichten, die ich mit recv vom IRC Server erhalte, ein :: schonmal gar nicht enthalten ist. Ein = finde ich auch nicht. Von daher fällt es mir schwer, das Format nachzuvollziehen.
Blickt da vielleicht jemand durch? Also wenn ich das nachvollziehen könnte, wären da mit sicherheit alle Informationen drin, die ich brauche. Vielleicht hat ja noch jemand ne bessere Beschreibung.
Gruß Para
-
ne. das := soll heissen 'ist definiert als'
die in [] stehenden dinge sind optional. alle anderen zwingend.alle irc befehle muessen mit <crlf> (carriage return/linefeed) enden,
damit deine meldungen korrekt erkannt werden.
du kannst '\n' nicht (sicher) nehmen.void Sende(string msg) { char* carrigeReturnLinefeed = "\x0D\x0A"; msg += carrigeReturnLinefeed; // ... und das ganze senden... }
-
Achso das ist ne Beschreibungssprache... Naja und was bedeutet das { Buchstabe } beim Befehl? Also ich habe mir das nun nochmal angeschaut und bisher passt es soweit das alles mit nem : eingeleitet wird und dann entweder der Servername (optinal mit dienst) oder der Nickname kommt.
Danach soll dann wohl eine 3 Stellige Zahl kommen oder dieses mit den Buchstabe in dem {}, wie darf ich das denn verstehen?