Zitat von
cruso:
Naja soviel ich weiß, müsste ich nur Nachrichten zum Server schicken, die halt entsprechend dem
IRC-Protokoll sind...
So einfach ist es nicht. Natürlich musst du dem Server einige Nachrichten schicken, aber das ganze ist mit einer gewissen Interaktion verbunden. Einfach verbinden, senden und wieder raus geht nicht. Schon alleine aus dem Grund, dass der Server dich nach dem Prinzip nach einigen Versuchen sperren wird. *g* (d.h. wenn überhaupt, dann muss der Bot durchlaufen)
Ok, mal zur Praxis zurück. Als ich eben schrieb "So einfach ist es nicht" wollte ich eigentlich nur sagen, dass es wahrscheinlich mehr als 15 Zeilen. Die Umsetzung selbst dürfte nicht das Problem sein. Ich schreibe mal ein paar Zeilen aus meinem Bot. (Der mittlerweile ca. 750 Zeilen hat und noch längst nicht fertig ist.)
Am sinnvollsten ist es, das ganze in eine Klasse zu packen. So zum Beispiel:
Code:
import socket
class
irc:
_socket = None
Dann noch eine connect-Methode reinmachen. (Ich übernehme einfach mal aus meinem Bot. Kannst ihn dann halt nicht 1:1 übernehmen, aber das machst du ja auch so nicht.
)
Code:
def connect(self, hostname, port):
if self._socket == None:
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self._socket.connect((str(hostname), int(port)))
except:
self.log("Connection to "+str(hostname)+":"+str(port)+" failed.")
self._socket = None
return False
self._hostname = str(hostname)
self._host = int(port)
self.log("Connection established to "+str(hostname)+":"+str(port)+".")
return True
else:
self.log("Socket already connected to: "+str(self._hostname)+":"+str(self._port)+"!")
return False
Und dann einen Main-Loop. Der Main-Loop ist (wie der Name auch schon sagt) eine Schleife, die immer und immer wieder durchläuft. In ihr wird überprüft ob ein neuer Befehl von Server eingetroffen ist und ggf. wird ein Befehl zurückgesendet. Wenn man diese Methode einmal aufruft wird der Code danach erstmal nicht ausgeführt. Das erwähne ich hier, weil es schonmal ziemlich verwirren kann, wenn man den Main-Loop startet und in der nächsten Zeile in einen Channel reinwill. *g*
Code:
def main_loop(self):
if self._socket == None:
self.log("Socket is not connected to an
IRC-Server!")
return False
else:
// Dieser Code muss nur EINMAL beim Verbinden gesendet werden.
// Eigentlich ist dies garnicht der richtige Ort fuer den Code,
// denn er gehoert eigentlich zum connect. Dennoch ist er hier nicht
// ganz falsch. Wichtig ist, dass man nach dem Connect gleich den
// Main-Loop aufruft, sonst kann es sein dass der Server dich
// wegen einem Timeout rausschmeisst.
if not self.send("NICK :"+self._nickname):
self.log("Couldn't send NICK-message!")
self.disconnect()
else:
if not self.send("USER "+self._nickname+" _ _ :"+self._realname):
self.log("Couldn't send USER-message!")
self.disconnect()
recv = ""
while self._socket != None:
buffer = self._socket.recv(1)
if buffer == "\n" or buffer == "\r":
if recv.strip("\n\r ") != "":
// Die parse-Methode parst die Nachricht und bringt sie in ein
// benutzbares Format. In meinem Fall ein indiziertes Array,
// bzw unter Python "dict".
message = self.parse(recv)
// message_dispatch reagiert auf die jeweiligen Nachrichten
// vom Server. Gibt bei einer Nachricht eines Users zum Beispiel
// die Nachricht aus oder antwortet auf einen Ping.
self.message_dispatch(message)
recv = ""
else:
recv += buffer
self.log("Main-loop finished. ")
Was noch wichtig zu erwähnen ist: Der Server sendet in regelmäßigen Abständen einen Befehl namens "Ping" zu dir. Du musst auf diesen Befehl mit einem "Pong" antworten, sonst fliegt dein Bot aus dem
IRC. (Das nennt man dann Ping-Timeout)
Also jetzt viel Spaß beim implementieren des
IRC-Protokolls. Es werden mehr als 15 Zeilen.
Eines möchte ich dir noch mitgeben. Das wird in den nächsten Stunden dein Freund sein. Hier die
IRC-Spezifikation. Halte dich an die und du schaffst das.
RFC 1459
Mit freundlichen Grüßen,
Valle