Caught signals that would otherwise be fatal and saveless.
[halbot.git] / basic_commands.py
blobf4d329165095b06670a09e13defda20a3b34f6c0
1 from __future__ import generators
2 import re
4 from irclib import irc_lower
6 import perms, whois
7 import globals
8 from globals import commands, private
9 from safety import safe_call
10 from common import get_timestamp, resize
12 waiting_commands = {}
14 def got_command(who, where, command, args=""):
15 from connection import hal
16 if not command in commands:
17 command = 'raise error'
18 args = "I don't understand that."
19 waiting = waiting_commands.get(who, [])
20 if not waiting:
21 (required_perms, do_it, wants_perms) = resize(commands[command], 3)
22 if where == private and required_perms <= perms.owner:
23 if wants_perms:
24 safe_call(do_it, (who, where, args, perms.owner))
25 else:
26 safe_call(do_it, (who, where, args))
27 elif not wants_perms and required_perms <= perms.voice \
28 and where in hal.channels:
29 if irc_lower(who) in whois.voice_or_better(where):
30 safe_call(do_it, (who, where, args))
31 else:
32 return
33 else:
34 waiting_commands[who] = [(where, command, args)]
35 hal.connection.whois((who,))
36 else:
37 waiting.append((where, command, args))
39 def do_commands(who, info):
40 for where, command, args in waiting_commands[who]:
41 actual_perms = perms.get_perms(who, where, info)
42 if command not in commands:
43 command = 'raise error'
44 args = "I don't understand that."
45 (required_perms, do_it, wants_perms) = resize(commands[command], 3)
46 if required_perms <= actual_perms:
47 if not wants_perms:
48 safe_call(do_it, (who, where, args))
49 else:
50 safe_call(do_it, (who, where, args, actual_perms))
51 elif required_perms > perms.voice <= actual_perms:
52 reply(who, where, "I'm sorry, %s, I'm afraid I can't do that." % who,
53 all = True)
54 waiting_commands[who] = []
55 whois.callback = do_commands
57 def reply(who, where, what, all=False):
58 from connection import hal
59 if where == private:
60 hal.connection.privmsg(who, what)
61 elif all:
62 hal.connection.privmsg(where, what)
63 else:
64 hal.connection.privmsg(where, "%s: %s" % (who, what))
66 commands['raise error'] = (perms.voice, reply)
68 def ping(who, where, args):
69 "$ping: Asks Hal to reply to you, so that you can tell you're both connected."
70 reply(who, where, "Pong!")
71 commands['ping'] = (perms.voice, ping)
73 class TestException(Exception): pass
75 def error(who, where, args):
76 "$error: Raises a test error."
77 raise TestException, str(args)
78 commands['error'] = (perms.ircop, error)
80 def join(who, where, args):
81 "Asks Hal to join the channel you're in. Always implicit, via /join."
82 from connection import hal
83 hal.connection.join(where)
84 commands['do join'] = (perms.op, join)
86 def shutdown(who, where, args):
87 "$shutdown: Shuts Hal down."
88 from connection import hal
89 hal.connection.quit("Daisy, daaaisy...")
90 raise SystemExit
91 commands['shutdown'] = (perms.ircop, shutdown)
93 def get_time(who, where, args):
94 "$time: Asks Hal what time it is, according to him."
95 reply(who, where, "Current time is: " + get_timestamp())
96 commands['time'] = (perms.voice, get_time)
98 weak_mask_re = re.compile(".+!.+@.+")
99 def ignore(who, where, args):
100 "$ignore <nick>!<user>@<host>: Makes Hal ignore someone."
101 if args.lower().strip() == "list":
102 banlist = ", ".join([user for user in globals.my_users if globals.my_users[user] == perms.ban])
103 reply(who, where, "Currently ignoring: %s" % banlist)
104 return
105 if not weak_mask_re.search(args):
106 reply(who, where, "Please give a full nick!user@host mask.")
107 return
108 globals.my_users[args] = perms.ban
109 reply(who, where, "Done.")
110 commands['ignore'] = (perms.ircop, ignore)
112 def unignore(who, where, args):
113 "$unignore <nick>!<user>@<host>: Makes Hal stop ignoring someone."
114 if args in globals.my_users and globals.my_users[args] == perms.ban:
115 globals.my_users[args] = perms.none
116 reply(who, where, "Done.")
117 else:
118 reply(who, where, "I wasn't ignoring them.")
119 commands['unignore'] = (perms.ircop, unignore)
121 def set_perm(who, where, args):
122 "$set-perm <who> <permission level>: Sets a user's minimum Hal permission level. The user must be identified with NickServ to gain the extra permissions. Available levels: none, halfop, op, admin, owner, ircop"
123 split = args.split()
124 if len(split) != 2:
125 reply(who, where, "Usage: $set-perm <who> <permission level>")
126 return
127 target, level_name = split
128 level = perms.Perms.from_name(level_name)
129 if level.name != level_name.lower():
130 reply(who, where, "Available levels: none, halfop, op, admin, owner, ircop")
131 return
132 globals.my_users[target] = level
133 reply(who, where, "%s's minimum permission level is now %s." % (target, level))
134 commands["set-perm"] = (perms.ircop, set_perm)
136 def tell_commands(who, where, args, user_perms):
137 "$commands: Shows you all the stuff you can do."
138 command_list = [command for command in commands
139 if " " not in command
140 if commands[command][0] <= user_perms]
141 command_list.sort()
142 commands_str = ", ".join(command_list)
143 reply(who, where,
144 "Available commands at your permission level: " + commands_str)
145 commands['commands'] = (perms.voice, tell_commands, "I want perms.")
147 def get_help(who, where, args):
148 "$help <command>: Gets help on a command. Use $commands to get a list of available commands. Confused? Try: $help basic"
149 args = args.lower()
150 if not args:
151 args = "help"
152 elif args in ("basic", "usage", "basic usage", "hal"):
153 reply(who, where, "If you're used to troggie, I may seem a bit odd, because I don't behave the same way. The easiest way to think of it is that in every channel, there's a separate copy of me, so what happens in one doesn't affect the others. The same is true if you PM me, it's your own personal Hal.")
154 return
155 elif args == "poker":
156 reply(who, where, "I announce Triplejack prize tournaments as they begin staging (5 minutes before they start). See $help subscribe for information on subscribing to them and $help poke-msg if you need me to /msg you instead of saying your name in channel. Available groups: poker, pp, fandango, laptop, finals, pokernight.")
157 return
158 elif " " in args:
159 reply(who, where, "One command at a time, please.")
160 return
161 elif args[0] == "$":
162 args = args[1:]
163 if args not in commands:
164 reply(who, where, "I don't have that command.")
165 return
166 (required_perms, command) = resize(commands[args],2)
167 if required_perms <= perms.voice:
168 permstr = ""
169 else:
170 permstr = " (Requires %s.)" % required_perms
171 docstr = getattr(command, '__doc__', None)
172 if not docstr:
173 docstr = "No help available for this command."
174 reply(who, where, docstr + permstr)
175 commands['help'] = (perms.voice, get_help)
177 def troggie(func):
178 def continue_if_no_troggie(who, where, *args, **kwargs):
179 from connection import hal
180 if where in hal.channels:
181 chan = hal.channels[where]
182 if "troggie" not in chan.userdict:
183 func(who, where, *args, **kwargs)
184 # Pass the docstring through.
185 continue_if_no_troggie.__doc__ = func.__doc__
186 return continue_if_no_troggie