-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiibot.py
174 lines (156 loc) · 6.66 KB
/
iibot.py
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'] = 'AyEye' ##bot's nickname
state['mychannel'] = '#rawptest' ##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