slacky Skrevet 30. april 2011 Del Skrevet 30. april 2011 (endret) Jeg er helt fersk på pyton, kommer fra en verden av php... Men jeg digger python allerde (Tving meg ikke til å satse på noe annet..) Jeg får til å koble meg på "irc.freenode.net", men målet er å få den inn på "irc.quakenet.org", noe som viste seg vanskeligere.. Det krever at jeg svarer på en PING, med en random string bak. Hvor jeg da skal svare noe ala: def ping(): # This is our first function! It will respond to server Pings. ircsock.send("/QUOTE PONG "+ pingrespons +"\n") #hvordan lage respons med random nummeret som kommer? PING: 1163268885 #tallet er en random string som jeg får (må snappes opp og returneres).. import socket server = "irc.freenode.net" # Server channel = "#slacky" # Channel botnick = "slacky" # Your bots nick port = 6667 def ping(): # This is our first function! It will respond to server Pings. #ircsock.send("/QUOTE PONG"+ HVORDAN +"\n") ircsock.send("PONG :pingis\n") def sendmsg(chan , msg): # This is the send message function, it simply sends messages to the channel. ircsock.send("PRIVMSG "+ chan +" :"+ msg +"\n") def joinchan(chan): # This function is used to join channels. ircsock.send("JOIN "+ chan +"\n") def beer(): ircsock.send("PRIVMSG "+ channel +" :I would like som beer now!\n") ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ircsock.connect((server, port)) # Here we connect to the server using the port 6667 ircsock.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :slackbot.\n") # user authentication ircsock.send("NICK "+ botnick +"\n") # here we actually assign the nick to the bot joinchan(channel) # Join the channel using the functions we previously defined while 1: # Be careful with these! it might send you to an infinite loop ircmsg = ircsock.recv(2048) # receive data from the server ircmsg = ircmsg.strip('\n\r') # removing any unnecessary linebreaks. print(ircmsg) # Here we print what's coming from the server if ircmsg.find(":beer") != -1: beer() if ircmsg.find("PING :") != -1: # if the server pings us then we've got to respond! ping() http://img828.imageshack.us/img828/2280/pingpongh.jpg Endret 30. april 2011 av tROOP4H Lenke til kommentar
etse Skrevet 30. april 2011 Del Skrevet 30. april 2011 (endret) Et lite tips er å skrive ting objektorientert, selv om du er i starten av å lære ting. Spesielt i Python er det å kunne OOP godt en veldig god egenskap. Når det kommer til IRC protokollen husk følgende: - Alle argumenter deles opp med mellomrom, ikke etter ":" - PING skal svares med PONG {alt bak} ----- Feks. "PING :1234" svares med "PONG :1234" - Du kan ikke vite at du er connected til en server før du får welcome message fra serveren (kode "001") Det du ønsker å gjøre er noe følgende: cmdParts = msg.split(' ') if cmdParts[0] == 'PING': self.sendCmd("PONG %s" % cmdParts[1]) Skrev et objektorientert eksempel du kan se på om du ønsker, basert på din kode og som bruker file-sockets. (slik at du kan lese fra sockets som om de var filer). Denne kan fint connecte til f.eks. quakenet. import socket server = "irc.quakenet.org" # Server channel = "#slacky" # Channel botnick = "slacky" # Your bots nick port = 6667 class IrcBot: def __init__(self, server, port, channel, nick): # Save some variables for later self.connected = False self.channel = channel self.host = server # Setup the socket, fsock is a python-implementation to let you read # from TCP as if it was a normal file. self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.fsock = self.socket.makefile() # Connect to server print "Connecting to %s:%d" % (server, port) self.socket.connect((server, port)) self.sendCmd("USER %s 0 * :%s" % (nick, nick)) self.sendCmd("NICK "+ botnick) # Run it self._run() # Just to make code easier to read def sendCmd(self, cmd): print "<<<", cmd self.fsock.write(cmd + "\r\n") self.fsock.flush() # Send a message to a channel def sendmsg(self, chan , msg): self.sendCmd("PRIVMSG "+ chan +" :"+ msg) # Join a channel def joinChan(self, chan): # This function is used to join channels. self.sendCmd("JOIN " + chan) # This is the main-loop of the IrcBot. Reads info from TCP def _run(self): while 1: msg = self.fsock.readline() if msg is "": # If we get a blank line, no new message recieved continue msg = msg.rstrip() print ">>>", msg self.parse(msg) # Parses a line, and handles it correctly def parse(self, msg): cmdParts = msg.split(' ') if cmdParts[0] == 'PING': self.sendCmd("PONG %s" % cmdParts[1]) elif msg[0] == ':': # A server msg if cmdParts[1] == '001': # The welcome message, we are now connected self.connected = True self.joinChan(self.channel) if __name__ == '__main__': bot = IrcBot(server, port, channel, botnick) Endret 30. april 2011 av etse 1 Lenke til kommentar
slacky Skrevet 30. april 2011 Forfatter Del Skrevet 30. april 2011 (endret) Ser man det ja! Dette likte jeg virkelig! Vel, jeg ser ikke helt hvordan jeg skal lage en slik "beer"-respons, som jeg hadde i tidligere.. Der skrev jeg simpelthen "beer" på IRC og den svarte et eller annet tilbake.. EDIT: Nesten fikset :S ... # Parses a line, and handles it correctly def parse(self, msg): cmdParts = msg.split(' ') if cmdParts[0] == 'PING': self.sendCmd("PONG %s" % cmdParts[1]) elif msg[0] == ':': # A server msg if cmdParts[1] == '001': # The welcome message, we are now connected self.connected = True self.joinChan(self.channel) def beer(): self.sendCmd("PRIVMSG "+ channel +" :I would like som beer now!\n") if msg.find(":beer") != -1: # Oh noes! I must respond!! beer() if __name__ == '__main__': bot = IrcBot(server, port, channel, botnick) Men da fikk jeg problmet: Legger jeg til flere kommandoer krasher botten, og ga meg "Quit (Read error: EOF from client)" Endret 30. april 2011 av tROOP4H Lenke til kommentar
etse Skrevet 30. april 2011 Del Skrevet 30. april 2011 (endret) om du ser i mitt eksempel har jeg en metode i klassen min som heter "parse". Denne brukes til å behandle ulike tilfeller. # Parses a line, and handles it correctly def parse(self, msg): cmdParts = msg.split(' ') if cmdParts[0] == 'PING': self.sendCmd("PONG %s" % cmdParts[1]) elif msg[0] == ':': # A server msg if cmdParts[1] == '001': # The welcome message, we are now connected self.connected = True self.joinChan(self.channel) Vi tar å legger til håndtering for privmsg.: om du ser i mitt eksempel har jeg en metode i klassen min som heter "parse". Denne brukes til å behandle ulike tilfeller. # Parses a line, and handles it correctly def parse(self, msg): cmdParts = msg.split(' ') if cmdParts[0] == 'PING': self.sendCmd("PONG %s" % cmdParts[1]) elif msg[0] == ':': # A server msg if cmdParts[1] == '001': # The welcome message, we are now connected self.connected = True self.joinChan(self.channel) elif cmdParts[1] == "PRIVMSG": # Whispers and chat channel = cmdParts[2] cmdParts[3] = cmdParts[3][1:] # Remove the starting colon if "beer" in cmdParts[3:]: self.sendmsg(channel, "I like beer! CHEERS!") Eksempel i vedlegg Endret 30. april 2011 av etse Lenke til kommentar
slacky Skrevet 30. april 2011 Forfatter Del Skrevet 30. april 2011 (endret) Jo, fikk det til å fungere på samme vis, bare på min litt mer tungvindte måte.. Men, problemet kommer når jeg ønsker flere kommandoer, mer morro etc.. Forsøker å legge til flere kommandoer så krasher boten under oppstart... Merkelig mener jeg :S elif cmdParts[1] == "PRIVMSG": # Whispers and chat channel = cmdParts[2] cmdParts[3] = cmdParts[3][1:] # Remove the starting colon if "beer" in cmdParts[3:]: self.sendmsg(channel, "I like beer! CHEERS!") if "haha" in cmdParts[3:]: self.sendmsg(channel, "Hahaha! That is funny, I need to grab some popcorn!!!xD") Hvordan får jeg lagt in flere ti-talls "kommandoer"? Det lat seg ikke gjøre se enkelt.. Den krashet bare.. Endret 30. april 2011 av tROOP4H Lenke til kommentar
etse Skrevet 1. mai 2011 Del Skrevet 1. mai 2011 burde ikke være så ille. Bruke heller else-if etter min smak though. Dette betyr at om flere inlegg skulle bli sagt på en gang kan flere beskjeder blir sendt for en enkelt setning though. du sier det kræsjer? Kjører du det gjennom IDLE? I så fall er det problemet. Koden din fungerer i hvertfall helt fint her. Lenke til kommentar
slacky Skrevet 1. mai 2011 Forfatter Del Skrevet 1. mai 2011 (endret) "Kjører du det gjennom IDLE?" - Jeg kjører bare "python script.py" i kommandolinja.. Leste det meg til at det var rett måte å gå frem på? Kan også simpelthen dobbeltklikke på scriptet, da starter det opp, men krsher instant, også. Har det noe å si at jeg ikke bruker 3.2 men sitter med 2.7.1? Fikk den til å starte, merkelig nok, uten endring... Men, da jeg satt å testet den på IRC kjedde dette -> <tROOP4H> beer <beerbot> I like beer! CHEERS! <tROOP4H> hahaha <beerbot> Hahaha! That is FUNNY! I need to grab some popcorn!!!xD <tROOP4H> party * beerbot ([email protected]) Quit (Read error: EOF from client) Endret 1. mai 2011 av tROOP4H Lenke til kommentar
etse Skrevet 1. mai 2011 Del Skrevet 1. mai 2011 (endret) Jeg klarer ikke reprodusere problemet her. Kjører selv versjon 2.6.6, så versjon 3 skulle ikke være noe krav. Edit: Kan det være at serveren ga deg feilmeldingen "You are trying to reconnect to fast!" ? Scriptet har ingen håndteringer av eventuelle feil og exceptions, så om serveren skulle gi en slik feilmelding så vil programmet kræsje. Endret 1. mai 2011 av etse Lenke til kommentar
slacky Skrevet 1. mai 2011 Forfatter Del Skrevet 1. mai 2011 (endret) Nei, den bare blinket.. "Startet", og "stoppet" like fort... Men, fikk den i gang med 3 kommandoer. Men alt virker bare litt fukka merkelig her... elif cmdParts[1] == "PRIVMSG": # Whispers and chat channel = cmdParts[2] cmdParts[3] = cmdParts[3][1:] # Remove the starting colon if "popcorn" in cmdParts[3:]: self.sendmsg(channel, "Put the Beer Down and walk away with your popcorn!") if "beer" in cmdParts[3:]: self.sendmsg(channel, "I like beer! CHEERS!") if "haha" in cmdParts[3:]: self.sendmsg(channel, "Hahaha! That is FUNNY! I need to grab some popcorn!!!xD") Jeg kopierer en av de statementsa over, og legger til en under, da fungerer det ofte... Men, om jeg da endrer fra "beer" til f.eks "Hei", og statement til "hei der!", så kan den krashe.. Kopierer jeg bare "clean", uten endring så fungerer det oftest.. :S Mener det er veldig rart, og merkverdig ustabilt.. :S Endret 1. mai 2011 av tROOP4H Lenke til kommentar
etse Skrevet 1. mai 2011 Del Skrevet 1. mai 2011 grunnen til at det blinker er vel fordi du starter det med å dobbeltklikke på fila i stede for å skrive "python bot.py", så du får ikke med deg de eventuelle feilmeldingene. Det rare er at jeg har hatt min kjørende nå i en halvtime, og den er meget stabil. 1 Lenke til kommentar
slacky Skrevet 2. mai 2011 Forfatter Del Skrevet 2. mai 2011 (endret) Vel, da var det iallefall på plass! Fikk scriptet til å fungere, så da må jeg lære meg litt andre smågreier, som blir brukt med boten: Python + mysql, data som skal lagres, som også skal kunne nå's med php. Endret 2. mai 2011 av tROOP4H Lenke til kommentar
etse Skrevet 2. mai 2011 Del Skrevet 2. mai 2011 (endret) hva med å heller prøve å sette deg inn i django for å lage web-grensesnitt med python? Det er virkelig å anbefale, da blir du kjent med en stadig voksende rammeverk samtidig som du kan lære deg mer python Endret 2. mai 2011 av etse 1 Lenke til kommentar
slacky Skrevet 2. mai 2011 Forfatter Del Skrevet 2. mai 2011 (endret) Hei igjen! Kom over et lite problem *sjokk* Virket småvanskelig å lese seg til (for meg, som er uerfaren med python) Forsøker å liste brukere fra en tabell i MySQL, på en channal, jeg får den til å starte opp, koble seg til, men den vil krashe om jeg skirver .users.. Happy edit: def parse(self, msg): cmdParts = msg.split(' ') if cmdParts[0] == 'PING': self.sendCmd("PONG %s" % cmdParts[1]) elif msg[0] == ':': # A server msg if cmdParts[1] == '001': # The welcome message, we are now connected self.connected = True self.joinChan(self.channel) elif cmdParts[1] == "PRIVMSG": # Whispers and chat # MYSQL conn = mdb.connect('localhost', 'root', '', 'test'); cursor = conn.cursor(mdb.cursors.DictCursor) cursor.execute("SELECT * FROM users") rows = cursor.fetchall() channel = cmdParts[2] cmdParts[3] = cmdParts[3][1:] # Remove the starting colon if ".users" in cmdParts[3:]: for row in rows: self.sendmsg(channel, (row["username"])) Hoho, da har jeg klart det også! Kansje ikke vakkert.. Og ikke komplett da det lister litt feil : <@tROOP4H> .users <@ThePyBot> tROOP4H <@ThePyBot> slacky Slik ønsker jeg det: <@tROOP4H> .users <@ThePyBot> tROOP4H, slacky Edit: Ang. django, så vet jeg ikke helt hva det brukes til, har kjeldent hatt behov for rammeverk, innen php. Web-grensesnitt (nermer seg php sitt område?). Vil mer over på små "programmer" innen nettverk/web - Vekk fra browseren. Web-applikasjoner kan jeg lage i php (om det ikke er snakk om noe annet en det jeg forsto). Har grodd meg lei php-området etter 5år. Starter iallefall med en liten bot, hvordan det utvikler seg, får vi se Endret 2. mai 2011 av tROOP4H Lenke til kommentar
etse Skrevet 2. mai 2011 Del Skrevet 2. mai 2011 Angående django: Det er enkelt og greit et rammeverk for python som gjør at du kan lage websider som fungerer via Apache - bare med å bruke python i stede for PHP. Det minner litt om ruby on rails on du har prøvd eller hørt om det. Djang oer rett og slett bare en måte å lage websider ved å bruke python Så la oss si du skal lage en bot som du kan styre gjennom en web-grensesnitt. Hvor kommunikasjon mellom boten og web-siden går gjennom en database. Du har skrevet boten i python, og så skriver du websiden i PHP; det kan fungere helt fint. Men hvorfor ikke bare gjøre alt i Python? Anbefaling: Når du gjør store ting som kan gå galt, og om de gjør det så kræsjer programmet er det ofte fordi det skjer en exception. Til det har man "try" og "catch". try: connect_to_server() do_stuff() except Exception: print "Something bad happened here... oops!" 1 Lenke til kommentar
slacky Skrevet 3. mai 2011 Forfatter Del Skrevet 3. mai 2011 (endret) Du virker ril å ha god kjenskap, så jeg lurer på hvordan jeg skal hente ut nick fra en person? Edit: Jeg spør for mye før jeg selv har testet det som er logisk å gjøre # Get Nick rmpt = msg.split('.') str = rmpt[0] rmalfa = str.split('@') nstr = rmalfa[0][1:] nickname = nstr.split('!') Endret 3. mai 2011 av tROOP4H Lenke til kommentar
etse Skrevet 3. mai 2011 Del Skrevet 3. mai 2011 Jeg kan litt om IRC protokollen siden jeg holder på å prøve å lage en fullverdig klient i C#.NET for tiden. I denne versjonen har jeg laget en "back-end" IRC-klasse som jeg bruker for å lese input fra sockets og sende de til GUI til behandling. Regner med du skal hente ut nick til en person når han gjør en priv-msg? I C# bruker jeg følgende til å hente ut nicket user = cmdParts[0].Split('!')[0].Remove(0,1); I python blir dette noe lignende: nick = cmdParts[0].split('!')[0][1:] Om du ikke er helt med på hva den koden gjør, siden du er ny i python skal jeg prøve å forklare hva den koden gjør. Men først husk følgende fra IRC-protokollen: 1: Første argumentet er senderen av en kommando (for privmsg er det brukeren som sendte beskjeden) 2: Andre argument er kommandoen, i vårt tilfelle "PRIVMSG" som viser at det er en message. 3: Argument 3 er i hvilken kanal kommandoen ble skrevet. (om det er privat melding mellom 2 brukere er navnet på kanalen navnet på brukeren, ellers starter navnet med #) 4: For PRIVMSG er alt fra og med 4 argument selve meldingen. 5: Argument 1, med senderen, kommer på følgende format: ":NICKNAME!VHOST" Koden på kompakt form gjør følgende: Plukkter ut første argumentet fra meldingen (cmdParts[0]) og splitter denne opp en liste med hensyn på utropstegn. Den tar så å lager en ny streng fra første element i den nye listen som inneholder alle bokstaver utenom den første. liste[1:] betyr rett og slett bare "plukk elementer fra 1 til SISTE ELEMENT fra listen liste". Dette fungerer og for strenger. 1 Lenke til kommentar
slacky Skrevet 3. mai 2011 Forfatter Del Skrevet 3. mai 2011 (endret) Forsto den, klarte også å få det til! Men, kom over et problem jeg har diklet med en times tid nå...: if "!cl" in cmdParts[3:]: cpt = cmdParts[4] try: self.sendmsg(channel, ""+ nickname[0] +" just challanged "+ cpt +".") self.sendmsg(channel, "A new game has started, type !sign to join the game.") except Exception: print "Error in !cl" Om de bare skriver !cl vil botten crashe.. Jeg kommer meg ikke rundt den, har forsøkt mye rart. EDIT: Selvfølgelig forsøker jeg ikke det som er åpenbart! Nei, nå trenger jeg en pause snart - alt jeg ble nødt til var å "putte" cpt = cmdParts[4], inn i try: Endret 3. mai 2011 av tROOP4H Lenke til kommentar
etse Skrevet 3. mai 2011 Del Skrevet 3. mai 2011 Når det kommer til strenger i python, lær deg å bruke formatering; gjør det mye enklere å lese. >>> tall = 16 >>> streng = "En tekst-streng" >>> print "Tallet vårt er %d, og strengen vår er '%s'." % (tall, streng) Tallet vårt er 16, og strengen vår er 'En tekst-streng'. Rett og slett bare skriv en streng hvor du setter inn %d der du ønsker tall, %s der du ønsker tekst-strenger og %f der du ønsker desimal-tall. Legg så argumentene til på slutten slik jeg har gjort, i rekkefølgen argumentene kommer i teksten. Det gjør tekst-strengene mye enklere å lese; spesielt når man har flere argumenter inni midten av setningene. Angående feilen din, er jeg ikke helt fan av måten du gjør det. Slik du har skrevet det nå vil den og reagere om jeg skriver "kommandoen er !cl" i chaten. Er vel bedre å sette som krav at det skal være det første ordet når det er kommandoer til boten? Prøv heller noe slik: if "!cl" == cmdParts[3][1:] if len(cmdParts) != 5: self.sendmsg(channel, "%s: invalid use of command. Use '!cp username'" % (nickname[0])) else: self.sendmsg(channel, "%s just challanged %s." % (nickname[0], cmdParts[4])) self.sendmsg(channel, "A new game has started, type !sign to join the game.") 1 Lenke til kommentar
slacky Skrevet 4. mai 2011 Forfatter Del Skrevet 4. mai 2011 (endret) Skal huske på det til jeg fortsetter med scriptet! "kommandoen er !cl" vil forrasten ikke bli lagt merke til.. Takket være split(' '), så den vil bare lagge merke til første ordet. Men, måten jeg koder på er ganske klumsete, er nybegynnerkoding En sak jeg ikke skjønner hvordan jeg skal gjøre, selv med MASSE googling (kom bare frem til CSV ett eller annet) Hvordan skal jeg separere output fra flere rader i mysql med komma? Må jeg gjøre noe ninja-klomsegreier, slik jeg bruker å gjøre når jeg ikke får til? cursor.execute("SELECT * FROM users") rows = cursor.fetchall() if "!users" in cmdParts[3:]: for row in rows: self.sendmsg(channel, (row["username"])) Nå looper jeg utenfor self.sendmsg, noe som ikke er slik jeg ønsker. Samt, over på IRC-delen... Ser ofte at boter skriver/svarer utenfor nicket.. f.eks: <asd> spam <asd> spam <asd> spam * @SpamBot hey stop spam, i dont like it! <asd> ... Er det magi? Endret 4. mai 2011 av tROOP4H Lenke til kommentar
etse Skrevet 4. mai 2011 Del Skrevet 4. mai 2011 om du er på IRC er det du nevner til på slutten der ikke magi. Fleste klienter støtter "/emote is running up a cliff." En standad beskjed sendes op følgende måte: "PRIVMSG #channel : The message to be sent" skal du sende emotes skal den være følgende: "PRIVMSG #channel :\x01ACTION the emote I am doing\x01" hvor \x01 er det andre tegnet i ASCII-tabellen. Eksempel er å lage en ny metode som heter "sendemote" i stede for "sendmsg": def sendemote(self, channel, emote): self.sendcmd("PRIVMSG %s :\x01ACTION %s\x01" % (channel, emote)) self.sendemote(chan, "just joined the channel!") angående det å gå ting på linje, hva med å først lage en string i løkken din? og så sende den etterpå? (er ikke kjent med mySQL sammen med python). Blir noe slikt som: outputString = "" for row in rows: outputString += row + ", " self.sendmsg(channel, outputString) 1 Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå