Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 175 lines (156 sloc) 6.817 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
#!/usr/bin/python
##iibot framework - samurai
##version 3.0 - 09/25/2010

##IMPORTS## ... obviously?
import time
from random import randint

##BOT FUNCTIONS##
def sendMessage(resource, message):
if resource is logger:
message = str(time.time()) + ":" + message
if message[-1] != "\n":
message = message + "\n"
resource.write(message)
resource.flush()
return 0

def voice(nick, channel):
if users[nick]['voice'] != 1:
sendMessage(chanserv, "voice %s %s" %(channel, nick))
users[nick]['voice'] = 1
sendMessage(logger, "%s has been given voice" % (nick))

def kick(nick, channel, message):
if nick != state['mynick']:
sendMessage(chanserv, "KICK %s %s %s" % ( channel, nick, message))
sendMessage(logger, "%s was kicked from the channel - %s" % ( nick, message))
delUser(nick, users)

def addUser(nick, users):
if nick in users.keys():
return users
else:
users[nick] = {'message_times':[], 'joined':time.time(), 'voice':0} ##TODO: this init should probably be done better
if nick != state['mynick']:
sendMessage(output, "Welcome to the room, %s" % (nick))
##need to do this to initialize the PM FIFO's, there's a patch to auto-do this, but I'm not using it currently
sendMessage(output, "/j %s Welcome to %s, %s" % (nick, state['mychannel'], nick))
open("../"+nick.lower()+"/out","w").close() ## clear this
sendMessage(logger, "%s has joined the room" % (nick))
return users

def delUser(nick, users):
if nick in users.keys():
del(users[nick])
sendMessage(logger, "%s has left the room" % (nick))
return users


def resetUsers(users):
newusers = {}
for nick in users:
newusers = addUser(nick, newusers)
return newusers


##COMMAND FUNCTIONS## below here!
#print out the user object (mostly for debugging)
def stats(args, nick):
if not nick in users.keys():
return ""
result = "/j %s " % (nick)
for key in users[nick].keys():
result = result + key + ":" + str(users[nick][key]) + ","
return result + "\n"

#return to the user, in a PM, the "help menu"
def help(args, nick):
for cmd in COMMANDS.keys():
helpmsg = "" ##later this may support an info message
sendMessage(output,"/j %s !%s %s" % (nick, cmd, helpmsg))


##INITIALIZATIONS##
#connections
open("out","w").close() ## clear the file, to avoid issues when restarting the bot
input = open("out","r") ## ii is looking at these files from it's perspective, let's swap that so we dont confuse ourselves
output = open("in","a") ## see above
chanserv = open("../chanserv/in","a") ##handle to chanserv, so that we can do MODE changes
logger = open("./logs","a") ## log, you can also point this at one of ii's FIFO's :D

#state - so the bot knows what's up
state = {}
state['mynick'] = 'iibot' ##bot's nickname
state['mychannel'] = '#testingit' ##channel this bot is in (currently only supports 1 channel + PMs)
state['flood_max'] = 15.0 #sending more than 10 messages in 15 seconds? that's a kick for you!
state['last_event'] = time.time()
state['last_message'] = 0

#users object
users = addUser(state['mynick'],{}) ## init this and add the bot

#command config
COMMAND_CHAR = "!" ##commands will begin with this ,e.g. !help - would return the help menu (in a PM)
COMMANDS = {} ##init
COMMANDS['stats'] = stats ##the key for the array, is the command name, the value is the funciton
COMMANDS['help'] = help ##e.g. COMMANDS['cmd'] = help, would make !cmd return the help menu

##RUNTIME##
lines = ['']
while 1:
while '' in lines and len(lines) > 1: ##incase we ate up any null lines, we dont need to process those
lines.remove('')
line = lines.pop() ##get the message we want to respond to, this is processed below
lines.append(input.readline().replace("\n","")) ##get a new message and push it onto our input list
if line != "": ##if the line actually has data (pythonw will return "" when readline fails)
message_time = line[:17] ##get the time ii reports
nick = line[17:].split(" ")[0].replace("<","").replace(">","") ##nick (sometimes this is part of a join/part message and not the actual nick... yet)
message = " ".join(line[17:].split(" ")[1:]) ## grab the message
##flood control
if nick in users.keys(): ##if we've already added this user
if len(users[nick]['message_times']) >= 10: ## this keeps a list of the 10 last message times, for flood kicking and such
users[nick]['message_times'] = users[nick]['message_times'][1:]
users[nick]['message_times'].append(time.time())
if users[nick]['message_times'][9] - users[nick]['message_times'][0] < state['flood_max']: ##here's that kick I promised
kick(nick, state['mychannel'], "No Flooding!")
else:
users[nick]['message_times'].append(time.time())
##users entering or leaving
if nick == "-!-":
nick = tmp[0]
if "has joined" in message:
tmp = message.split("(")
nick = tmp[0]
users = addUser(nick, users)
if "has left" in message and nick in users.keys():
tmp = message.split("(")
nick = tmp[0]
users = delUser(nick, users)
if "ChanServ kicked" in message:
tmp = message.split("kicked ")
tmp2 = tmp[1].split(" ")
nick = tmp2[0]
users = delUser(nick, users)
#got a message from someone
elif nick[0] == "<" and nick[-1] == ">":
nick = nick[1:-1]
users = addUser(nick, users)
if nick != state['mynick']:
state['last_message'] = time.time()
#entered a room, let's grab the user's list
elif "=" == nick and state['mynick'] in message:
tmp = message.split(" ")[1:-1]
for i in xrange(len(tmp)):
if tmp[i][0] in ("@","%","+"):
tmp[i] = tmp[i][1:]
if tmp[i] != state['mynick']:
users = addUser(tmp[i],users)
##anythign else
else:
sendMessage(logger, "Something invalid or unexpected came into my pipe for 'nick':")
sendMessage(logger, "[NICK]" + nick + "| [MSG]" + message + "|")

##we've got a command
if len(message) > 0 and message[0] == COMMAND_CHAR and nick != state['mynick']: ##command processing
tmp = message[1:].split(" ") ##parsing out the command/args
command = tmp[0].lower()
args = " ".join(tmp[1:])
if command in COMMANDS.keys(): ##if this command is allowed
result = COMMANDS[command](args, nick) ##run and return
if result != None and result != "":
sendMessage(output, result)
else: ##when we dont know the command
sendMessage(output, "Eh?\n")
else: ##when no message comes through, aka non-response code
for nick in users.keys(): ##check the bot's PMs
if nick != state['mynick']:
pm = open("../"+nick.lower()+"/out","r") ##remember we cleared this when we add the user
for i in pm.read().split("\n"):
if i != "": ##we dont need to add null lines
lines.append(i) ##add the line to our input processing list
pm.close() ##close this handle
open("../"+nick.lower()+"/out","w").close() ##clean up
Something went wrong with that request. Please try again.