All pastes #1928588 Raw Edit

Mine

public text v1 · immutable
#1928588 ·published 2010-08-29 21:57 UTC
rendered paste body
#Todo:
#
#
#4. Control panel for bot.
#
# send(messagetype, target, subtarget, message)

import socket
import sys
from time import sleep
import random

chambered_round = 0

#Maintains connection to server
#Allows messages to be sent by other methods/classes
class irc_connection:
  def __init__(self):
    try:
      #Get the target server(s) and nickname(s) from the config file ircbot.cfg
      configfile = open("fullmetalmadda.cfg", "r")
      self.servers = configfile.readline().partition("=")[2].split(";")
      configfile.close()
      self.connection = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
    except:
      #Config file could not be opened, bail out
      print("Could not read config file fullmetalmadda.cfg. Time to die.")
      sys.exit(1)
    
    if(len(self.servers) == 0):
      #No servers? What do you want the poor bot to do?
      print("No servers found on line 1 of fullmetalmadda.cfg.")
      print("First line of file should read:")
      print("servers=irc.something.net:6667;irc.somethingelse.net:6667;irc.andsoon.etc:6667")
      sys.exit(2)
    
    for server in self.servers:
      try:
        #Are we connected?
        if(self.connection.getpeername()):
          #Yes, we don't need to keep trying
          break
      except:
        #No, we should try to connect to this server
        #try:
        server = server.rstrip("\n").split(":")
        self.connection.connect( (server[0], int(server[1])) )
        #except:
          #We can't connect to this server. Move on.
          #pass

  def readbuffer(self):
    data = self.connection.recv(2048)
    return str(data, "ascii").split("\n") 
 
  def sendraw(self,message):
    #Send a raw message- must be sent as bytes
    try:
      self.connection.send(message)
    except:
      #Probably not encoded correctly, attempt a fix
      self.connection.send(bytes(message, "ascii"))

  def sendaction(self, target, message):
    self.connection.send(bytes("PRIVMSG " + target + " :\x01ACTION " + message + "\x01\r\n", "ascii"))
      
  def send(self,messagetype, target, subtarget, message):
    #Send a message of a specific type
    if(messagetype == "PONG"):
      self.connection.send(bytes(messagetype + " " + message + "\r\n", "ascii"))
    elif(messagetype == "JOIN"):
      self.connection.send(bytes(messagetype + " :" + target + "\r\n", "ascii"))
    elif(messagetype == "KICK"):
      self.connection.send(bytes(messagetype + " " + target + " " + subtarget + " :" + message + " \r\n", "ascii"))
    elif(messagetype == "PART"):
      self.connection.send(bytes(messagetype + " " + target + " :" + message + "\r\n", "ascii"))
    elif(messagetype == "QUIT"):
      self.connection.send(bytes(messagetype + " :" + message + "\r\n", "ascii"))
    elif(messagetype == "PRIVMSG" or messagetype == "NOTICE"):
      self.connection.send(bytes(messagetype + " " + target + " :" + message + "\r\n", "ascii"))
    elif(messagetype == "INVITE"):
      #Peculiar format to this one- INVITE user :#channel
      self.connection.send(bytes(messagetype + " " + subtarget + " :" + target + "\r\n", "ascii"))
    elif(messagetype == "NICK"):
      self.connection.send(bytes(messagetype + " " + target + "\r\n", "ascii"))
    elif(messagetype == "USER"):
      self.connection.send(bytes(messagetype + " " + target + " " + subtarget + " * :" + message + "\r\n", "ascii"))
    elif(messagetype == "MODE"):
      self.connection.send(bytes(messagetype + " " + target + " " + message + " " + subtarget + "\r\n", "ascii"))
    else:
      #Probably a typo. For the moment we'll just silently ignore it
      pass
 

 
#Class for processing messages from IRC  
class irc_message:  
  #Method to initialise message processing class
  def __init__(self, data, conn, mynick):
    self.data = data.rstrip("\r").rstrip("\n")
    self.nickname = ""
    self.fullname = ""
    self.hostaddress = ""
    self.messagetype = ""
    self.message = ""
    self.target = ""
    self.channel = ""
    self.irc_connection = conn
    self.my_nickname = mynick
    
    procdata = data.partition(" ")
    
    #Get the details of the message sender
    userdetails = procdata[0].partition("!")
    if(userdetails[1] == ""):
      #Server, use placeholders for nickname and fullname
      self.nickname = "#:server:#"
      self.fullname = self.nickname
      self.hostaddress = userdetails[2].rstrip()
    else:
      #User, get full details
      self.nickname = userdetails[0].lstrip(":").rstrip()
      self.userdetails = userdetails[2].partition("@")
      self.fullname = userdetails[0].rstrip()
      self.hostaddress = userdetails[2].rstrip()
    
    #Get the message type- PING is a special case
    if(procdata[0].rstrip() == "PING"):
      self.messagetype = "PING"
    else:
      procdata = procdata[2].partition(" ")
      self.messagetype = procdata[0].rstrip()
    
    #Process the message based on its type    
    if(self.messagetype == "PING"):
      #Server checking client is still responsive. Automatically respond
      self.message = procdata[2].rstrip()
      self.target = "#:self:#"
      self.channel = self.target
      self.irc_connection.send("PONG", "", "", self.message)
    elif(self.messagetype == "433"):
      #Server response indicating nickname already in use.
      self.message = procdata[2].rstrip()
      self.target = "#:self:#"
      self.channel = self.target
    elif(self.messagetype == "JOIN"):
      #Someone joined a channel
      self.message = ""
      self.target = procdata[2].lstrip(":").rstrip()
      self.channel = self.target
    elif(self.messagetype == "KICK"):
      #Someone got kicked
      procdata = procdata[2].partition(" ")
      self.message = procdata[2].partition(":")[2].rstrip()
      self.target = procdata[2].partition(":")[0].rstrip()
      self.channel = procdata[0].rstrip()
    elif(self.messagetype == "QUIT" or self.messagetype == "PART"):
      #Someone left a channel or the network
      procdata = procdata[2].partition(" ")
      self.message = procdata[2].lstrip(":").rstrip()
      self.target = procdata[0].rstrip()
      self.channel = self.target
    elif(self.messagetype == "PRIVMSG" or self.messagetype == "NOTICE"):
      #Someone is communicating with the client or a channel
      procdata = procdata[2].partition(" ")
      self.message = procdata[2].lstrip(":").rstrip()
      self.target = procdata[0].rstrip()
      if(self.target.find("#") > -1 or self.target.find("&") > -1):
        #It's public communication on a channel
        self.channel = self.target
      else:
        #It's private communication
        self.channel = "#:PRIVATE:#"
    elif(self.messagetype == "INVITE"):
      #Someone has sent an invite to somewhere
      procdata = procdata[2].partition(" ")
      self.message = ""
      self.target = procdata[0].rstrip()
      self.channel = procdata[2].lstrip(":").rstrip()
    else:
      #This message type is unknown
      self.message = procdata[2].rstrip()
      self.target = "#:UNKNOWN:#"
      self.channel = self.target
      
  def reply(self,response):
    #Define how to respond to each type of action
    if(self.messagetype == "NOTICE"):
      #These should not be subject to an auto-reply, so we will not define a reply method for them
      #If they are to be replied to, it must be done explicitly as a new message
      pass
    elif(self.messagetype == "KICK"):
      if(self.target == self.my_nickname):
        #Someone just kicked the client. A reply should rejoin then send a message to the channel
        self.irc_connection.send("JOIN", self.channel, "", "")
        self.irc_connection.send("PRIVMSG", self.channel, "", response)
      else:
        #Someone else just got kicked from a channel. Our default response will be a message to the channel
        self.irc_connection.send("PRIVMSG", self.channel, "", response)
    elif(self.messagetype == "PRIVMSG"):
      #Someone is talking to us or to a channel we're in. Respond to them/the channel
      if(self.channel == "#:PRIVATE:#"):
        self.irc_connection.send("PRIVMSG", self.nickname, "", response)
      else:
        self.irc_connection.send("PRIVMSG", self.target, "", response)
    elif(self.messagetype == "JOIN"):
      #We saw someone join a channel, respond to the channel they're on
      self.irc_connection.send("PRIVMSG", self.nickname, "", response)
    elif(self.messagetype == "PART" or self.messagetype == "QUIT"):
      #We saw someone leave a channel we can see, or the network itself. Respond to the channel they were in.
      self.irc_connection.send("PRIVMSG", self.channel, "", response)
    elif(self.messagetype == "INVITE"):
      #We saw an invite to a channel
      #Just in case some quirk of our status or the server allows us to see other invites,
      #we check to make sure the invite is to us
      if(self.target == self.my_nickname):
        #Default response is to join te channel then send a message
        self.irc_connection.send("JOIN", self.channel, "", "")
        self.irc_connection.send("PRIVMSG", self.channel, "", response)
        
if __name__ == "__main__":
  messagequeue = []
  irc = irc_connection()
  user_defined = False
  nickname_set = False
  channels_joined = False
  nickname_index = 0
  mynick = ""
  
  #Get nickname(s) to use and channel(s) to join
  configfile = open("fullmetalmadda.cfg", "r")
  #First line is servers, ignore it
  configfile.readline()
  
  nicknames = configfile.readline().partition("=")[2].split(";")
  channels = configfile.readline().partition("=")[2].split(";")
  
  configfile.close()
  
  if(len(nicknames) == 0):
    #No nickname? Sadly we can't be the nameless one.
    print("No nicknames found on line 2 of fullmetalmadda.cfg.")
    print("Second line of file should read:")
    print("nicknames=FullMetalMadda;AnotherNick;Yetanothernick;etcetcnick")
    sys.exit(3)
    
  if(len(channels) == 0):
    #No channels defined. Non-critical, but print warning
    print("No channels found on line 3 of fullmetalmadda.cfg.")
    print("Third line of file should read:")
    print("channels=#channel1;#channel2")
    print("No channels will be joined as none have been specified.")
    channels_joined = True
  
  while True:
    if(len(messagequeue) == 0):
      data = irc.readbuffer()
      for msg in data:
        msg.rstrip("\r")
        if(msg != ""):
          messagequeue.append(msg)
    else:      
      message = irc_message(messagequeue.pop(), irc, mynick)
    
    
      print("NICK:" + message.nickname + " TYPE:" + message.messagetype + " TARGET:" + message.target + " CHANNEL:" + message.channel + " MESSAGE:" + message.message + ":")
      print(message.data)
    
      if(message.messagetype == "433"):
        #Nickname already in use, use next one
        nickname_index+=1
        nickname_set = False
        if(nickname_index > len(nicknames)):
          #All nickname options in use, bomb out
          print("All nicknames specified in fullmetalmadda.cfg are in use on the network.")
          print("Exiting.")
          sys.exit(4)
    
      #Check logoon process has been completed
      if(not nickname_set):
        irc.send("NICK", nicknames[nickname_index], "", "")
        nickname_set = True
        mynick = nicknames[nickname_index]
        print("Nick:" + mynick)
      elif(not user_defined):
        irc.send("USER", nicknames[nickname_index], "8", "Python IRC bot")
        user_defined = True
      elif(not channels_joined):
        for channel in channels:
          irc.send("JOIN", channel, "", "")
        channels_joined = True
      else:
        
        if(message.messagetype == "PRIVMSG" and message.message == "!roll"):
          message.reply(str(random.randint(1,6)))
        if(message.messagetype == "KICK"):
          message.reply("test")
        if(message.messagetype == "PRIVMSG" and message.message == "kick"):
          irc.send("KICK",message.channel,message.nickname,"Fine, knock yourself out.")

	#Auto Ops
	allowedopslist = ['Oot', 'syn', 'ryll', 'rince']
        if(message.messagetype == "JOIN"and message.nickname in allowedops):
          irc.send("MODE", message.channel, "+o")
	

	#Comical command responses
	if(message.messagetype == "PRIVMSG" and message.message == "!boobs"):
        message.reply("boing")
	if(message.messagetype == "PRIVMSG" and message.message == "!rickroll"):
	rickroll=['Never gonna give you up','Never gonna let you down']
         message.reply(random.sample(rickroll,1))
	if(message.messagetype == "PRIVMSG" and message.message == "!donk"):
        donk = ['Put A Donk On It!', 'Electro', 'Bassline', 'Thats sick That Is']
	message.reply(random.sample(donk,1))

        
        #Conditional trigger
        if(message.messagetype == "PRIVMSG" and message.message == "Hehe"):
          chambered_round = 1
        if(chambered_round == 1 and message.nickname == "Skei"):
          chambered_round = 0
          irc.send("KICK", message.channel, message.nickname, "What does this button do?")