/
hedgehogbot.py
executable file
·207 lines (175 loc) · 6.61 KB
/
hedgehogbot.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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#! /usr/bin/env python
# Simple IRC bot, originally by:
# Joel Rosdahl <joel@rosdahl.net>
#
# Modified to be a bridge to SWI-Prolog by:
# Owain Jones <tehdoomcat@gmail.com>
"""HogBot
This is the SingleServerIRCBot class from
irc.bot. The bot enters a channel and listens for commands in
private messages and channel traffic. Commands in channel messages
are given by prefixing the text by the bot name followed by a colon.
The known commands are:
disconnect -- Disconnect the bot. The bot will try to reconnect
after 60 seconds.
die -- Let the bot cease to exist.
ignore user -- add a nick to the 'ignore' list. When they attempt to talk to
the bot they'll be greeted with 'EAT A DICK' or something equally as nice.
NOTE: Not persistent! If you want certain people (Bots) always ignored, look
at config.py
unignore user -- remove someone from the 'ignore' list.
admin user -- add someone to the 'admins' list... allows them to run !pl statements.
!pl statement -- run a raw prolog statement. only runs once you add the final '.'
!restart -- restart the prolog side of the bot, in case it's crashed.
!say statement -- say something (apologise for spamming up channels with 'false.')
!fact data,of,fact -- add a fact to the database. all facts must be of form:
Who,What,Where/When,Who - as the prolog predicate is fact/3.
Anything prexied with the bot's nick will be interpreted as
a question, e.g. "HedgehogBot: what bigger sun?" to which the reply will be
<HedgehogBot> Nick: moon bigger sun.
"""
import irc.bot, simpl, config
from util import *
from irc.client import nm_to_n, irc_lower, ip_numstr_to_quad, ip_quad_to_numstr
from os import system
lastUpdated = file_get_contents('hook.txt')
class HedgehogBot(irc.bot.SingleServerIRCBot):
def __init__(self, channel, nickname, server, port=6667):
irc.bot.SingleServerIRCBot.__init__(self, [(server, port)], nickname, nickname)
self.channel = channel
self.ignore = config.GLOBAL_IGNORE
self.admins = config.GLOBAL_ADMINS
self.prolog = simpl.Prolog()
self.cmdbuffer = {}
def on_nicknameinuse(self, c, e):
c.nick(c.get_nickname() + "_")
def on_welcome(self, c, e):
c.join(self.channel)
def on_privmsg(self, c, e):
#self.do_command(c, e, e.arguments()[0])
self.on_pubmsg(c, e)
def on_pubmsg(self, c, e):
#print e.arguments()[0]
global lastUpdated
if file_get_contents('hook.txt') != lastUpdated:
lastUpdated = file_get_contents('hook.txt')
system('git pull')
out = self.prolog.communicate("['hedgehogbot.pl'].")
print 'Git updated! Reloaded prolog scripts...'
print out
a = e.arguments()[0].split(":", 1)
if len(a) > 1 and irc_lower(a[0]) == irc_lower(self.connection.get_nickname()):
self.do_command(c, e, a[1].strip())
elif e.arguments()[0][:3] == "!pl":
if nm_to_n(e.source()).lower() in self.admins:
self.eval_command(c, e, e.arguments()[0][3:])
elif e.arguments()[0][:4] == "!say":
c.privmsg(self.channel, e.arguments()[0][5:])
elif e.arguments()[0].startswith("!restart"):
if nm_to_n(e.source()).lower() in self.admins:
#c.privmsg("Restarting prolog side...")
print "Restarting prolog side..."
self.prolog.restart()
elif e.arguments()[0][:5] == "!fact":
fact = "assert(fact("+e.arguments()[0][6:]+")). remember."
self.eval_command(c, e, fact)
elif "om" in e.arguments()[0] and "nom" in e.arguments()[0]:
c.privmsg(self.channel, simpl.omnom())
return
def on_dccmsg(self, c, e):
c.privmsg("You said: " + e.arguments()[0])
def on_dccchat(self, c, e):
if len(e.arguments()) != 2:
return
args = e.arguments()[1].split()
if len(args) == 4:
try:
address = ip_numstr_to_quad(args[2])
port = int(args[3])
except ValueError:
return
self.dcc_connect(address, port)
def eval_command(self,c, e, cmd):
nick = nm_to_n(e.source()).lower()
c = self.connection
if len(cmd) <= 1: return
if cmd[-1] == '.':
if nick in self.cmdbuffer.keys():
cmd = ''.join(self.cmdbuffer[nick]) + cmd
self.cmdbuffer[nick] = []
else:
self.cmdbuffer[nick] = []
out = self.prolog.communicate(cmd)
print nick,'-',out
c.privmsg(self.channel, nick+": "+out)
else:
if nick in self.cmdbuffer.keys():
self.cmdbuffer[nick].append(cmd)
else:
self.cmdbuffer[nick] = []
self.cmdbuffer[nick].append(cmd)
def do_command(self, c, e, cmd):
nick = nm_to_n(e.source())
c = self.connection
if nick.lower() in config.BOT_IGNORE:
return
elif nick.lower() in self.ignore:
c.privmsg(self.channel, nick+": EAT A DICK")
return
if cmd == "disconnect":
self.prolog.terminate()
self.disconnect()
elif cmd == "die":
self.prolog.terminate()
self.die()
elif cmd[:5] == "admin":
self.admins.update([cmd[6:].lower()])
elif cmd[:6] == "ignore":
print cmd[:6], '-', cmd[7:].lower()
self.ignore.update([cmd[7:].lower()])
elif cmd == "stats":
for chname, chobj in self.channels.items():
c.notice(nick, "--- Channel statistics ---")
c.notice(nick, "Channel: " + chname)
users = chobj.users()
users.sort()
c.notice(nick, "Users: " + ", ".join(users))
opers = chobj.opers()
opers.sort()
c.notice(nick, "Opers: " + ", ".join(opers))
voiced = chobj.voiced()
voiced.sort()
c.notice(nick, "Voiced: " + ", ".join(voiced))
elif cmd == "dcc":
dcc = self.dcc_listen()
c.ctcp("DCC", nick, "CHAT chat %s %d" % (
ip_quad_to_numstr(dcc.localaddress),
dcc.localport))
elif cmd[:8] == "unignore":
self.ignore.discard(cmd[9:].lower())
else:
out = self.prolog.communicate("single. \""+cmd+"\".")
if(len(out) >= 1):
print nick,'-',out
c.privmsg(self.channel, nick+": "+out)
def main():
import sys
if len(sys.argv) != 4:
print "Usage: hedgehogbot <server[:port]> <channel> <nickname>"
sys.exit(1)
s = sys.argv[1].split(":", 1)
server = s[0]
if len(s) == 2:
try:
port = int(s[1])
except ValueError:
print "Error: Erroneous port."
sys.exit(1)
else:
port = 6667
channel = sys.argv[2]
nickname = sys.argv[3]
bot = HedgehogBot(channel, nickname, server, port)
bot.start()
if __name__ == "__main__":
main()