Skip to content

Commit 1a7c2d5

Browse files
authored
Merge pull request CloudBotIRC#182 from linuxdaemon/gonzobot+nick-validity
Move nick validity checks out of various plugins and in to the core
2 parents d89431b + 1213a01 commit 1a7c2d5

7 files changed

Lines changed: 57 additions & 49 deletions

File tree

cloudbot/client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ def part(self, channel):
122122
"""
123123
raise NotImplementedError
124124

125+
def is_nick_valid(self, nick):
126+
"""
127+
Determines if a nick is valid for this connection
128+
:param nick: The nick to check
129+
:return: True if it is valid, otherwise false
130+
"""
131+
raise NotImplementedError
132+
125133
@property
126134
def connected(self):
127135
raise NotImplementedError

cloudbot/clients/irc.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
irc_netmask_re = re.compile(r"([^!@]*)!([^@]*)@(.*)")
1717
irc_param_re = re.compile(r"(?:^|(?<= ))(:.*|[^ ]+)")
1818

19+
irc_nick_re = re.compile(r'[A-Za-z0-9^{\}\[\]\-`_|\\]')
20+
1921
irc_bad_chars = ''.join([chr(x) for x in list(range(0, 1)) + list(range(4, 32)) + list(range(127, 160))])
2022
irc_clean_re = re.compile('[{}]'.format(re.escape(irc_bad_chars)))
2123

@@ -225,6 +227,9 @@ def _send(self, line):
225227
def connected(self):
226228
return self._connected
227229

230+
def is_nick_valid(self, nick):
231+
return bool(irc_nick_re.fullmatch(nick))
232+
228233

229234
class _IrcProtocol(asyncio.Protocol):
230235
"""

cloudbot/event.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,14 @@ def async_call(self, func, *args, **kwargs):
324324
result = yield from self.loop.run_in_executor(executor, part)
325325
return result
326326

327+
def is_nick_valid(self, nick):
328+
"""
329+
Returns whether a nick is valid for a given connection
330+
:param nick: The nick to check
331+
:return: Whether or not it is valid
332+
"""
333+
return self.conn.is_nick_valid(nick)
334+
327335
if sys.version_info < (3, 7, 0):
328336
# noinspection PyCompatibility
329337
@asyncio.coroutine

plugins/admin_bot.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,15 @@ def cycle(text, conn, chan, notice):
298298

299299
@asyncio.coroutine
300300
@hook.command(permissions=["botcontrol"])
301-
def nick(text, conn, notice):
301+
def nick(text, conn, notice, is_nick_valid):
302302
"""<nick> - changes my nickname to <nick>
303303
:type text: str
304304
:type conn: cloudbot.client.Client
305305
"""
306-
if not re.match("^[a-z0-9_|.-\]\[]*$", text.lower()):
306+
if not is_nick_valid(text):
307307
notice("Invalid username '{}'".format(text))
308308
return
309+
309310
notice("Attempting to change nick to '{}'...".format(text))
310311
conn.set_nick(text)
311312

plugins/attacks.py

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
1+
import asyncio
12
import codecs
23
import json
34
import os
45
import random
5-
import asyncio
66
import re
77

88
from cloudbot import hook
99
from cloudbot.util import textgen
1010

11-
nick_re = re.compile("^[A-Za-z0-9_|.\-\]\[\{\}]*$", re.I)
12-
13-
14-
def is_valid(target):
15-
""" Checks if a string is a valid IRC nick. """
16-
if nick_re.match(target):
17-
return True
18-
else:
19-
return False
20-
2111

2212
def is_self(conn, target):
2313
""" Checks if a string is "****self" or contains conn.name. """
@@ -64,11 +54,11 @@ def load_attacks(bot):
6454

6555
@asyncio.coroutine
6656
@hook.command
67-
def lart(text, conn, nick, action):
57+
def lart(text, conn, nick, action, is_nick_valid):
6858
"""<user> - LARTs <user>"""
6959
target = text.strip()
7060

71-
if not is_valid(target):
61+
if not is_nick_valid(target):
7262
return "I can't lart that."
7363

7464
if is_self(conn, target):
@@ -83,11 +73,11 @@ def lart(text, conn, nick, action):
8373

8474
@asyncio.coroutine
8575
@hook.command("flirt", "sexup", "jackmeoff")
86-
def flirt(text, conn, nick, message):
76+
def flirt(text, conn, nick, message, is_nick_valid):
8777
"""<user> - flirts with <user>"""
8878
target = text.strip()
8979

90-
if not is_valid(target):
80+
if not is_nick_valid(target):
9181
return "I can't flirt with that."
9282

9383
if is_self(conn, target):
@@ -99,11 +89,11 @@ def flirt(text, conn, nick, message):
9989

10090
@asyncio.coroutine
10191
@hook.command("kill", "end")
102-
def kill(text, conn, nick, action):
92+
def kill(text, conn, nick, action, is_nick_valid):
10393
"""<user> - kills <user>"""
10494
target = text.strip()
10595

106-
if not is_valid(target):
96+
if not is_nick_valid(target):
10797
return "I can't attack that."
10898

10999
if is_self(conn, target):
@@ -118,11 +108,11 @@ def kill(text, conn, nick, action):
118108

119109
@asyncio.coroutine
120110
@hook.command
121-
def slap(text, action, nick, conn):
111+
def slap(text, action, nick, conn, is_nick_valid):
122112
"""<user> -- Makes the bot slap <user>."""
123113
target = text.strip()
124114

125-
if not is_valid(target):
115+
if not is_nick_valid(target):
126116
return "I can't slap that."
127117

128118
if is_self(conn, target):
@@ -140,11 +130,11 @@ def slap(text, action, nick, conn):
140130

141131
@asyncio.coroutine
142132
@hook.command
143-
def compliment(text, action, nick, conn):
133+
def compliment(text, action, nick, conn, is_nick_valid):
144134
"""<user> -- Makes the bot compliment <user>."""
145135
target = text.strip()
146136

147-
if not is_valid(target):
137+
if not is_nick_valid(target):
148138
return "I can't compliment that."
149139

150140
if is_self(conn, target):
@@ -159,20 +149,21 @@ def compliment(text, action, nick, conn):
159149
# act out the message
160150
action(generator.generate_string())
161151

152+
162153
@hook.command(autohelp=False)
163-
def strax(text, conn, message, nick):
154+
def strax(text, conn, message, nick, is_nick_valid):
164155
"""Strax quote."""
165156

166157
if text:
167158
target = text.strip()
168-
if not is_valid(target):
169-
return "I can't do that."
159+
if not is_nick_valid(target):
160+
return "I can't do that."
170161

171162
if is_self(conn, target):
172-
# user is trying to make the bot attack itself!
173-
target = nick
163+
# user is trying to make the bot attack itself!
164+
target = nick
174165
variables = {
175-
"user": target
166+
"user": target
176167
}
177168

178169
generator = textgen.TextGenerator(strax["target_template"], strax["parts"], variables=variables)
@@ -182,24 +173,26 @@ def strax(text, conn, message, nick):
182173
# Become Strax
183174
message(generator.generate_string())
184175

176+
185177
@hook.command(autohelp=False)
186178
def nk(chan, message):
187179
"""outputs a random North Korea propoganda slogan"""
188-
index = random.randint(0,len(north_korea)-1)
180+
index = random.randint(0, len(north_korea) - 1)
189181
slogan = north_korea[index]
190182
message(slogan, chan)
191183

184+
192185
@asyncio.coroutine
193186
@hook.command()
194-
def insult(text, conn, nick, notice, message):
187+
def insult(text, conn, nick, notice, message, is_nick_valid):
195188
"""<user> - insults <user>
196189
:type text: str
197190
:type conn: cloudbot.client.Client
198191
:type nick: str
199192
"""
200193
target = text.strip()
201194

202-
if " " in target:
195+
if not is_nick_valid(target):
203196
notice("Invalid username!")
204197
return
205198

@@ -209,20 +202,22 @@ def insult(text, conn, nick, notice, message):
209202

210203
message("{}, {}".format(target, random.choice(insults)))
211204

205+
212206
@asyncio.coroutine
213207
@hook.command("present", "gift")
214-
def present(text, conn, nick, action):
208+
def present(text, conn, nick, action, is_nick_valid):
215209
"""<user> - gives gift to <user>"""
216210
target = text.strip()
217211

218-
if not is_valid(target):
212+
if not is_nick_valid(target):
219213
return "I can't gift that."
220214

221215
if is_self(conn, target):
222-
#user is trying to make the bot gift itself!
216+
# user is trying to make the bot gift itself!
223217
target = nick
218+
224219
variables = {
225-
"user": target
220+
"user": target
226221
}
227222

228223
generator = textgen.TextGenerator(presents["templates"], presents["parts"], variables=variables)

plugins/foods.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,6 @@
5151
basic_food_data = defaultdict(dict)
5252

5353

54-
def is_valid(target):
55-
""" Checks if a string is a valid IRC nick. """
56-
if nick_re.match(target):
57-
return True
58-
else:
59-
return False
60-
61-
6254
def load_template_data(bot, filename, data_dict):
6355
data_dict.clear()
6456
food_dir = os.path.join(bot.data_dir, "food")
@@ -95,8 +87,8 @@ def make_cmd_list(value):
9587

9688

9789
def basic_food(food):
98-
def func(text, action):
99-
if not is_valid(text):
90+
def func(text, action, is_nick_valid):
91+
if not is_nick_valid(text):
10092
return "I can't give {} to that user.".format(food.unitname)
10193

10294
action(basic_format(text, basic_food_data[food.name]))

plugins/jokes.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,11 @@ def boobies(text):
100100

101101

102102
@hook.command("awesome", "iscool", "cool")
103-
def awesome(text):
103+
def awesome(text, is_nick_valid):
104104
"""- Prints a webpage to show <nick> how awesome they are."""
105-
nick_re = re.compile("^[A-Za-z0-9_|.\-\]\[]*$", re.I)
106105
link = 'http://is-awesome.cool/{}'
107106
nick = text.split(' ')[0]
108-
if nick_re.match(nick):
107+
if is_nick_valid(nick):
109108
return "{}: I am blown away by your recent awesome action(s). Please read \x02{}\x02".format(
110109
nick, link.format(nick)
111110
)

0 commit comments

Comments
 (0)