Table of Contents
- Python Bootcamp
- Installing Python
- Basic Data Types
- Using Functions and Modules
- Modules, Scripts, Packages and Classes
- Using NumPy
- Graphing with MatPlotLib
- Using Scipy
- Statistics in Python with R
- Working With Python
- Using Python and FORTRAN with F2py
- Extending python with C/C++ using SWIG
- Using the C/Python Interface
- Speeding up Python with Cython
- Python/C Extension: PyTables
- Python/C Extension: PyTAPS
- Creating IRC and Email Bots
- Web Development: An introduction to Django
- GIS and Hardware Interface Example
- Advanced Python
- Making GUI's with WxPython
- Batteries Included - The Python Standard Library
Creating IRC and Email Bots
Thanks to a rich set of libraries, Python makes it extremely simple to perform otherwise complicated tasks. In this instance, we'll be looking at using Python to create email and IRC bots that automatically reply to messages. Specifically, we'll be translating any incoming messages to Pig Latin. Before we get started, make sure you have python-irclib (typing sudo easy_install python-irclib should be sufficient on Linux systems). Also be sure to download the Pig Latin module and place it in your working directory.
Creating an Email Bot
First, let's create a Gmail account so that we have a place for messages to go. In our case, the account is pybc.bot@gmail.com. Once we have the account set up, we can start checking for messages. For simplicity, we'll be using POP. This first version of our email bot merely logs into Gmail, retrieves a list of the new messages, and then prints out their contents. For testing, you may want to comment out the last line, pop.quit(), since removing it will let you retrieve the same messages over and over again.
import getpass import poplib passwd = getpass.getpass() pop = poplib.POP3_SSL("pop.gmail.com") pop.user("pybc.bot@gmail.com") pop.pass_(passwd) messages = pop.list()[1] for i in messages: num = int(i.split()[0]) contents = "\n".join(pop.retr(num)[1]) print contents print pop.quit()
If you run this, you'll end up with a dump of all the new messages in your Inbox. Unfortunately, it's not in a very useful format yet, and it would be a headache to try to parse the email headers manually. Luckily, Python's standard library includes the email module, which will parse the message for us.
Hands-on Example
Using the documentation for the email module, modify our above script so that it only prints the subjects of each message.
Extracting Data
Email messages can have multiple parts (e.g. attachments, HTML versions of the message, etc). To keep this simple, we're only going to look at plain text, but we still have to be aware of multipart messages. To do this, we can "walk" through each of the email payloads until we find one with a content type of "text/plain". Once we've found this, we can use it as the body of the message we're reading.
import email import getpass import poplib passwd = getpass.getpass() pop = poplib.POP3_SSL("pop.gmail.com") pop.user("pybc.bot@gmail.com") pop.pass_(passwd) messages = pop.list()[1] for i in messages: num = int(i.split()[0]) contents = "\n".join(pop.retr(num)[1]) message = email.message_from_string(contents) body = None for i in message.walk(): if i.get_content_type() == "text/plain": body = i.get_payload() print "Subject:", message["Subject"] print "Body:", body print pop.quit()
Hands-on Example
Print out the Pig Latin-ized version of the message subject and body.
Sending Email
Sending email is just as easy as receiving email. Even though Gmail requires STARTTLS security and authentication, it's still only a few lines of code:
import getpass import smtplib passwd = getpass.getpass() smtp = smtplib.SMTP("smtp.gmail.com", 587) smtp.ehlo() smtp.starttls() smtp.login("pybc.bot@gmail.com", passwd) smtp.sendmail("pybc.bot@gmail.com", "your@address.here", "testing") smtp.quit()
This creates an anemic message with no subject and a body of "testing". To make sure we have all the appropriate headers, we can use the email module again.
Hands-on Example
Using the email documentation, create an email message with the following headers: From, To, and Subject. Don't forget to add an interesting body!
Gluing the Pieces Together
All that remains is for us to glue together the mail-checking and mail-sending scripts we've written, and then run them in an infinite loop to keep our brand new bot alive!
import email import getpass import piglatin import poplib import smtplib import time myaddr = "pybc.bot@gmail.com" passwd = getpass.getpass() while True: pop = poplib.POP3_SSL("pop.gmail.com") pop.user(myaddr) pop.pass_(passwd) smtp = smtplib.SMTP("smtp.gmail.com") smtp.ehlo() smtp.starttls() smtp.login(myaddr, passwd) messages = pop.list()[1] for i in messages: num = int(i.split()[0]) contents = "\n".join(pop.retr(num)[1]) message = email.message_from_string(contents) body = None for i in message.walk(): if i.get_content_type() == "text/plain": body = i.get_payload() if body == None: print "HTML only message detected:", message["Subject"] continue reply = email.message.Message() reply["From"] = myaddr reply["To"] = message["From"] reply["Subject"] = piglatin.translate(message["Subject"]) reply.set_payload(piglatin.translate(body)) smtp.sendmail(reply["From"], reply["To"], reply.as_string()) smtp.quit() pop.quit() time.sleep(60)
Creating an IRC Bot
Before we get started, let's go over a brief summary of how IRC works for those who don't know. IRC ("internet relay chat") is a protocol designed to let groups of users chat in individual rooms ("channels") on one or more networks. Most networks have several servers to minimize the load, and the servers stay in constant communication to allow users from one server on a network to talk to users on other servers on that network. There are hundreds of IRC networks available on the internet, each with thousands of channels. The actual protocol is pretty simple, and we could probably implement an IRC bot in Python just using network sockets, but why reinvent the wheel?
Getting Started
The first thing any IRC bot needs to do is connect to a server and (usually) join a channel. Using python-irclib, this is a simple matter.
import irclib server = "irc.synirc.org" port = 6667 nick = "pybcbot" channel = "#botsploitation" class pybc_bot(irclib.SimpleIRCClient): def __init__(self, server, port, nick, channel): irclib.SimpleIRCClient.__init__(self) self.connect(server, port, nick) self.channel = channel def on_welcome(self, connection, event): connection.join(self.channel) irc = pybc_bot(server, port, nick, channel) irc.start()
Hands-on Example
Modify our IRC bot so that it sends a message to the channel when it joins. Hint: in IRC, the command to send a message to a channel (or user) is PRIVMSG.
Replying to Messages
In order to make our IRC bot useful, we need to make it respond to messages from other users. We're going to make our bot respond to messages in channels that begin with "!pig". When our bot sees a message like that, it will look at the text after the "!pig" and translate it into Pig Latin and send it back to the user. To eliminate confusion, we'll also figure out the username of the person who sent the command and prefix our reply with that name.
import irclib import piglatin import re server = "irc.synirc.org" port = 6667 nick = "pybcbot" channel = "#botsploitation" class pybc_bot(irclib.SimpleIRCClient): def __init__(self, server, port, nick, channel): irclib.SimpleIRCClient.__init__(self) self.connect(server, port, nick) self.channel = channel def on_welcome(self, connection, event): connection.join(self.channel) def on_pubmsg(self, connection, event): msg = event.arguments()[0].split(' ', 1) user = event.source().split('!')[0] if msg[0] == "!pig": if len(msg) == 1: connection.action(self.channel, "glares at "+user) else: connection.privmsg(self.channel, user+": "+ piglatin.translate(msg[1])) irc = pybc_bot(server, port, nick, channel) irc.start()
Attachments
-
piglatin.py
(0.6 KB) - added by jvporter
7 months ago.
Pig Latin Module
![(please configure the [header_logo] section in trac.ini)](/cgi-bin/hackerwithin.fcgi/chrome/site/thwlogo-small.png)