Fix for Issue #14 and PEP8 changes.
This commit is contained in:
parent
371ba9d58b
commit
6717db316f
244
bot.py
244
bot.py
@ -1,146 +1,218 @@
|
||||
#########################################################################
|
||||
################# Abundant notes are appreciated here! ##################
|
||||
#########################################################################
|
||||
|
||||
# Import some necessary libraries.
|
||||
import socket
|
||||
import time
|
||||
import csv
|
||||
import string
|
||||
import Queue
|
||||
import random
|
||||
from threading import Thread
|
||||
from re import search
|
||||
|
||||
# Some basic variables used to configure the bot
|
||||
# Some basic variables used to configure the bot.
|
||||
server = "irc.freenode.net"
|
||||
channel = "#openhatch"
|
||||
botnick = "WelcomeBot"
|
||||
waitTime = 60 # Amount of time after joining before bot replies to someone
|
||||
channel = "#openhatch"
|
||||
botnick = 'WelcomeBot'
|
||||
channel_admins = ('shauna', 'paulproteus', 'marktraceur')
|
||||
wait_time = 60 # amount of time after joining before bot replies to someone
|
||||
change_wait = botnick + " --wait-time "
|
||||
|
||||
# Classes
|
||||
class newcomer(object): # Newcomer class created when someone joins the room
|
||||
|
||||
#################### Classes ####################
|
||||
# Newcomer class that is created when someone joins the room.
|
||||
class NewComer(object):
|
||||
|
||||
def __init__(self, nick):
|
||||
self.nick = nick
|
||||
self.born = time.time()
|
||||
self.status = 0
|
||||
|
||||
def updateStatus(self):
|
||||
def update_status(self):
|
||||
self.status = 1
|
||||
|
||||
def aroundFor(self):
|
||||
def around_for(self):
|
||||
return int(time.time() - self.born)
|
||||
|
||||
# Functions!
|
||||
def joinchan(chan): # Joins channels
|
||||
ircsock.send("JOIN " + chan + "\n")
|
||||
|
||||
def getIRC(): # Creates separate thread for reading messages from the server
|
||||
#################### Functions! ####################
|
||||
# Joins specified channel.
|
||||
def join_channel(chan):
|
||||
ircsock.send("JOIN {} \n".format(chan))
|
||||
|
||||
|
||||
# Reads the messages from the server and adds them to the Queue and prints
|
||||
# them to the console. This function will be run in a thread, see below.
|
||||
def msg_handler():
|
||||
while True:
|
||||
ircmsg = ircsock.recv(2048) # receive data from the server
|
||||
ircmsg = ircmsg.strip('\n\r') # removing any unnecessary linebreaks.
|
||||
q.put(ircmsg) # Put in queue for main loop to read
|
||||
print(ircmsg)
|
||||
new_msg = ircsock.recv(2048) # receive data from the server
|
||||
new_msg = new_msg.strip('\n\r') # removing any unnecessary linebreaks
|
||||
q.put(new_msg) # put in queue for main loop to read
|
||||
print(new_msg)
|
||||
|
||||
def ping(): # Responds to server Pings.
|
||||
|
||||
# Responds to server Pings.
|
||||
def pong():
|
||||
ircsock.send("PONG :pingis\n")
|
||||
|
||||
def hello(actor, greeting, chan=channel): # This function responds to a user that inputs "Hello Mybot"
|
||||
ircsock.send("PRIVMSG " + chan + " :" + greeting + " " + actor + "\n")
|
||||
|
||||
def help(actor, chan=channel): # This function explains what the bot is when queried.
|
||||
ircsock.send("PRIVMSG " + chan + " :I'm a bot! I'm from here: <https://github.com/shaunagm/oh-irc-bot>. You can change my behavior by submitting a pull request or by talking to shauna. \n")
|
||||
# This function responds to a user that inputs "Hello Mybot".
|
||||
def bot_hello(greeting):
|
||||
ircsock.send("PRIVMSG {0} :{1} {2}\n".format(channel, greeting, actor))
|
||||
|
||||
def welcome(newcomer): # This welcomes a specific person.
|
||||
ircsock.send("PRIVMSG " + channel + " :Welcome " + newcomer + "! The channel's pretty quiet right now, so I thought I'd say hello, and ping some people (like shauna, paulproteus, marktraceur) that you're here. If no one responds for a while, try emailing us at hello@openhatch.org or just coming back later. FYI, you're now on my list of known nicknames, so I won't bother you again.\n")
|
||||
|
||||
def makeNickArray(): # On startup, makes array of nicks from Nicks.txt. New info will be written to both array and txt file.
|
||||
nickArray = []
|
||||
with open('nicks.csv', 'rb') as csvfile:
|
||||
nicksData = csv.reader(csvfile, delimiter=',', quotechar='|')
|
||||
for row in nicksData:
|
||||
nickArray.append(row)
|
||||
return nickArray
|
||||
# This function explains what the bot is when queried.
|
||||
def bot_help():
|
||||
ircsock.send("PRIVMSG {} :I'm a bot! I'm from here <https://github"
|
||||
".com/shaunagm/oh-irc-bot>. You can change my behavior by "
|
||||
"submitting a pull request or by talking to 'fill in "
|
||||
"the blank'.\n".format(channel))
|
||||
|
||||
def addPerson(person): # Adds newcomer to list of known nicks
|
||||
person = person.replace("_","")
|
||||
nickArray.append([person])
|
||||
|
||||
# This welcomes the "person" passed to it.
|
||||
def welcome(newcomer):
|
||||
ircsock.send("PRIVMSG {0} :Welcome {1}! The channel is pretty quiet "
|
||||
"right now, so I though I'd say hello, and ping some people "
|
||||
"(like {2}) that you're here. If no one responds for a "
|
||||
"while, try emailing us at hello@openhatch.org or just try "
|
||||
"coming back later. FYI, you're now on my list of known "
|
||||
"nicknames, so I won't bother you again."
|
||||
"\n".format(channel, newcomer, channel_admins))
|
||||
|
||||
|
||||
# Adds the current NewComer's nick to nicks.csv and known_nicks.
|
||||
def add_known_nick(new_known_nick):
|
||||
new_known_nick = new_known_nick.replace("_", "")
|
||||
known_nicks.append([new_known_nick])
|
||||
with open('nicks.csv', 'a') as csvfile:
|
||||
nickwriter = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||
nickwriter.writerow([person])
|
||||
nickwriter = csv.writer(csvfile, delimiter=',', quotechar='|',
|
||||
quoting=csv.QUOTE_MINIMAL)
|
||||
nickwriter.writerow([new_known_nick])
|
||||
|
||||
def getWelcomeRegEx(stringArray):
|
||||
|
||||
# "I NEED NOTES!!!!", said the function.
|
||||
def get_welcome_regex(string_array):
|
||||
#make regex case-insenstive
|
||||
pattern = r'(?i)'
|
||||
for s in stringArray:
|
||||
for s in string_array:
|
||||
pattern += r'(?:[ :]'+s+r'(?:[ \.!\?,\)]|$))|'
|
||||
#delete trailing '|'
|
||||
pattern = pattern[:-1]
|
||||
return pattern
|
||||
|
||||
# Startup
|
||||
ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
ircsock.connect((server, 6667)) # Here we connect to the server using the port 6667
|
||||
ircsock.send("USER " + botnick + " " + botnick + " " + botnick + " :This is http://openhatch.org/'s greeter bot.\n") # user authentication
|
||||
ircsock.send("NICK " + botnick + "\n") # here we actually assign the nick to the bot
|
||||
joinchan(channel)
|
||||
|
||||
# Starts a separate thread to get messages from server
|
||||
q = Queue.LifoQueue()
|
||||
t = Thread(target=getIRC) # calls getIRC() (defined above) in a separate thread
|
||||
# This function is used to change the wait time from the channel.
|
||||
# It confirms that the attempt is allowed and then returns the requested value.
|
||||
# If the attempt is not allowed, a message is sent to help
|
||||
def wait_time_change():
|
||||
for admin in channel_admins:
|
||||
if actor == admin:
|
||||
finder = search(r'\d\d*', search(r'--wait-time \d\d*', ircmsg)
|
||||
.group())
|
||||
ircsock.send("PRIVMSG {0} :{1} the wait time is changing to {2} "
|
||||
"seconds.\n".format(channel, actor, finder.group()))
|
||||
return finder.group()
|
||||
ircsock.send("PRIVMSG {0} :{1} you are not authorized to make that "
|
||||
"change. Please contact one of the channel admins {2} for "
|
||||
"assistance.\n".format(channel, actor, channel_admins))
|
||||
|
||||
|
||||
#################### Startup ####################
|
||||
# Creates a socket that will be used to send and receive messages,
|
||||
# then connects the socket to an IRC server and joins the channel.
|
||||
ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
ircsock.connect((server, 6667)) # Here we connect to server using port 6667.
|
||||
ircsock.send("USER {0} {0} {0} :This is http://openhatch.org/'s greeter bot"
|
||||
".\n".format(botnick)) # bot authentication
|
||||
ircsock.send("NICK {}\n".format(botnick)) # Assign the nick to the bot.
|
||||
join_channel(channel)
|
||||
|
||||
# Creates a list of known nicks from nicks.csv.
|
||||
# The list is checked to ensure that people are only greeted once.
|
||||
# NewComers will be added to the list and the csv.
|
||||
known_nicks = []
|
||||
with open('nicks.csv', 'rb') as csv_file:
|
||||
csv_file_data = csv.reader(csv_file, delimiter=',', quotechar='|')
|
||||
for row in csv_file_data:
|
||||
known_nicks.append(row)
|
||||
|
||||
# Creates a Queue that will hold the incoming messages.
|
||||
q = Queue.Queue()
|
||||
# Creates a separate thread that will listen on the server and add any
|
||||
# messages to the Queue. The thread is created to run target which equals
|
||||
# the msg_handler function from above.
|
||||
t = Thread(target=msg_handler)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
nickArray = makeNickArray()
|
||||
# This is the array of NewComer objects that people who join are added to.
|
||||
newcomers = []
|
||||
|
||||
newList = [] # This is the array of newcomer objects that people who join the room are added to.
|
||||
helloArray = [r'hello',r'hi',r'hey',r'yo',r'sup']
|
||||
helpArray = [r'help',r'info',r'faq',r'explain yourself']
|
||||
helloPattern = getWelcomeRegEx(helloArray)
|
||||
helpPattern = getWelcomeRegEx(helpArray)
|
||||
hello_list = [r'hello', r'hi', r'hey', r'yo', r'sup']
|
||||
help_list = [r'help', r'info', r'faq', r'explain yourself']
|
||||
hello_pattern = get_welcome_regex(hello_list)
|
||||
help_pattern = get_welcome_regex(help_list)
|
||||
|
||||
while 1: # Loop forever
|
||||
|
||||
for i in newList:
|
||||
if i.status == 0 and i.aroundFor() > waitTime:
|
||||
#################### The Workhorse ####################
|
||||
# This is the main loop that monitors the channel and sends and receives the
|
||||
# messages, either in the below code or by calling a function. This is the
|
||||
# brain of this code.
|
||||
while 1: # loop forever
|
||||
|
||||
for i in newcomers:
|
||||
if i.status == 0 and i.around_for() > wait_time:
|
||||
welcome(i.nick)
|
||||
i.updateStatus()
|
||||
addPerson(i.nick)
|
||||
newList.remove(i)
|
||||
i.update_status()
|
||||
add_known_nick(i.nick)
|
||||
newcomers.remove(i)
|
||||
|
||||
# If the queue is not empty...
|
||||
if q.empty() == 0:
|
||||
# get the next msg in the queue
|
||||
ircmsg = q.get()
|
||||
# and get the nick of the msg sender
|
||||
actor = ircmsg.split(":")[1].split("!")[0]
|
||||
|
||||
# Welcome functions
|
||||
if ircmsg.find("PRIVMSG " + channel) != -1: # If someone has spoken into the channel
|
||||
for i in newList:
|
||||
if actor != i.nick: # Don't turn off response if the person speaking is the person who joined.
|
||||
i.updateStatus() # Sets status to 1
|
||||
addPerson(i.nick)
|
||||
newList.remove(i)
|
||||
## Else: Do we want to do something extra if the person who joined the chat says something with no response?
|
||||
##### Welcome functions #####
|
||||
# If someone has spoken into the channel...
|
||||
if ircmsg.find("PRIVMSG " + channel) != -1:
|
||||
for i in newcomers:
|
||||
if actor != i.nick: # and is not the new NewComer
|
||||
i.update_status() # set the status to 1
|
||||
add_known_nick(i.nick)
|
||||
newcomers.remove(i)
|
||||
## Else: Do we want to do something extra if the person who
|
||||
# joined the chat says something with no response?
|
||||
|
||||
if ircmsg.find("JOIN " + channel) != -1: # If someone joins #channel
|
||||
if actor != botnick: # Remove the case where the bot gets a message that the bot has joined.
|
||||
if [actor.replace("_","")] not in nickArray:
|
||||
if actor not in (i.nick for i in newList):
|
||||
newList.append(newcomer(actor))
|
||||
# If someone joins #channel...
|
||||
if ircmsg.find("JOIN " + channel) != -1:
|
||||
if actor != botnick: # and it is not the bot
|
||||
if [actor.replace("_", "")] not in known_nicks:
|
||||
if actor not in (i.nick for i in newcomers):
|
||||
newcomers.append(NewComer(actor))
|
||||
|
||||
if ircmsg.find("PART " + channel) != -1 or ircmsg.find("QUIT") != -1: # If someone parts or quits the #channel
|
||||
for i in newList: # And that person is on the newlist (has entered channel within last 60 seconds)
|
||||
# If someone parts or quits the #channel...
|
||||
if ircmsg.find("PART " + channel) != -1 or ircmsg.find("QUIT") != -1:
|
||||
for i in newcomers: # and that person is on the newlist
|
||||
if actor == i.nick:
|
||||
newList.remove(i) # Remove them from the list
|
||||
newcomers.remove(i) # remove them from the list
|
||||
|
||||
# Unwelcome functions
|
||||
if ircmsg.find(botnick) != -1 and ircmsg.find("PRIVMSG") != -1: # If someone talks to (or refers to) the bot
|
||||
chan = channel
|
||||
matchHello = search(helloPattern,ircmsg)
|
||||
matchHelp = search(helpPattern,ircmsg)
|
||||
if ircmsg.find("PRIVMSG " + botnick) != -1:
|
||||
chan = actor
|
||||
##### Unwelcome functions #####
|
||||
# If someone talks to (or refers to) the bot.
|
||||
if ircmsg.find(botnick) != -1 and ircmsg.find("PRIVMSG") != -1:
|
||||
matchHello = search(hello_pattern, ircmsg)
|
||||
matchHelp = search(help_pattern, ircmsg)
|
||||
if matchHello:
|
||||
hello(actor,random.choice(helloArray), chan)
|
||||
bot_hello(random.choice(hello_list))
|
||||
if matchHelp:
|
||||
help(actor, chan)
|
||||
bot_help()
|
||||
|
||||
if ircmsg.find("PING :") != -1: # if the server pings us then we've got to respond!
|
||||
ping()
|
||||
# If someone tries to change the wait time...
|
||||
if ircmsg.find(change_wait) != -1:
|
||||
wait_time = wait_time_change() # call this to check and change it
|
||||
|
||||
# If the server pings us then we've got to respond!
|
||||
if ircmsg.find("PING :") != -1:
|
||||
pong()
|
||||
|
Loading…
Reference in New Issue
Block a user