Make bot less vulnerable
The bot still stores any number of explanations for a given word, and prints all of them when using !wtf detail <word>. This means that it is still vulnerable to some types of attacks. Maybe I'll fix that sometime in the future.
This commit is contained in:
parent
f80a8e0b7c
commit
7d7c5a0c5f
2 changed files with 57 additions and 18 deletions
65
wtf.py
65
wtf.py
|
|
@ -12,6 +12,11 @@ else:
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
class Wtf(yaboli.Module):
|
||||
MAX_TERMS = 5
|
||||
MAX_TERM_LENGTH = 1024
|
||||
MAX_EXPLANATIONS = 15
|
||||
MAX_EXPLANATION_LENGTH = 1024
|
||||
|
||||
DESCRIPTION = ("a database of explanations for words, acronyms and"
|
||||
" initialisms")
|
||||
HELP_GENERAL = DESCRIPTION
|
||||
|
|
@ -53,49 +58,75 @@ class Wtf(yaboli.Module):
|
|||
|
||||
self.register_general("wtf", self.cmd_wtf)
|
||||
|
||||
@staticmethod
|
||||
def _format_explanations(explanations, detail=False):
|
||||
def _format_explanations(self, explanations, detail=False):
|
||||
# Id, Term, Explanation, Author
|
||||
if detail:
|
||||
return [f"{i}: {t} — {e} (by {a})" for i, t, e, a in explanations]
|
||||
explanations = [f"{i}: {t} — {e} (by {a})" for i, t, e, a in explanations]
|
||||
else:
|
||||
return [f"{t} — {e}" for _, t, e, _ in explanations]
|
||||
explanations = [f"{t} — {e}" for _, t, e, _ in explanations]
|
||||
|
||||
if len(explanations) > self.MAX_EXPLANATIONS:
|
||||
message = ("Some explanations were omitted because this bot only"
|
||||
f" displays {self.MAX_EXPLANATIONS} explanations per"
|
||||
" term.")
|
||||
explanations = explanations[:-1] + [message]
|
||||
|
||||
return explanations
|
||||
|
||||
async def _find_explanations(self, terms, detail=False):
|
||||
lines = []
|
||||
for term in terms:
|
||||
explanations = await self.db.find_full(term)
|
||||
explanations = await self.db.find_full(term, self.MAX_EXPLANATIONS + 1)
|
||||
if explanations:
|
||||
lines.extend(self._format_explanations(explanations, detail=detail))
|
||||
else:
|
||||
lines.append(f"{term!r} not found.")
|
||||
return lines
|
||||
|
||||
async def send_explanations(self, message, termstr):
|
||||
terms = [term for term in termstr.split() if term]
|
||||
terms = terms[:self.MAX_TERMS]
|
||||
|
||||
if not terms: return
|
||||
|
||||
if max(map(len, terms)) > self.MAX_TERM_LENGTH:
|
||||
await message.reply(("A term can be at most"
|
||||
f" {self.MAX_TERM_LENGTH} characters long."))
|
||||
return
|
||||
|
||||
lines = await self._find_explanations(terms)
|
||||
await message.reply("\n".join(lines))
|
||||
return
|
||||
|
||||
async def on_send(self, room, message):
|
||||
await super().on_send(room, message)
|
||||
|
||||
match = self.RE_WTF_IS.fullmatch(message.content)
|
||||
if match:
|
||||
terms = match.group(1)
|
||||
terms = [term for term in terms.split() if term]
|
||||
if not terms: return
|
||||
lines = await self._find_explanations(terms)
|
||||
await message.reply("\n".join(lines))
|
||||
await self.send_explanations(message, terms)
|
||||
|
||||
async def cmd_wtf(self, room, message, args):
|
||||
match_is = self.RE_IS.fullmatch(args.raw)
|
||||
if match_is:
|
||||
terms = match_is.group(1)
|
||||
terms = [term for term in terms.split() if term]
|
||||
if not terms: return
|
||||
lines = await self._find_explanations(terms)
|
||||
await message.reply("\n".join(lines))
|
||||
return
|
||||
await self.send_explanations(message, terms)
|
||||
|
||||
match_add = self.RE_ADD.fullmatch(args.raw)
|
||||
if match_add:
|
||||
term = match_add.group(1)
|
||||
explanation = match_add.group(2).strip()
|
||||
|
||||
if len(term) > self.MAX_TERM_LENGTH:
|
||||
await message.reply(("A term can be at most"
|
||||
f" {self.MAX_TERM_LENGTH} characters long."))
|
||||
return
|
||||
|
||||
if len(explanation) > self.MAX_EXPLANATION_LENGTH:
|
||||
await message.reply(("An explanation can be at most"
|
||||
f" {self.MAX_EXPLANATION_LENGTH} characters long."))
|
||||
return
|
||||
|
||||
await self.db.add(term, explanation, message.sender.nick)
|
||||
logger.info((f"{message.sender.atmention} added explanation:"
|
||||
f" {term} - {explanation}"))
|
||||
|
|
@ -124,6 +155,12 @@ class Wtf(yaboli.Module):
|
|||
if match_replace:
|
||||
aid = match_replace.group(1)
|
||||
explanation = match_replace.group(2).strip()
|
||||
|
||||
if len(explanation) > self.MAX_EXPLANATION_LENGTH:
|
||||
await message.reply(("An explanation can be at most"
|
||||
f" {self.MAX_EXPLANATION_LENGTH} characters long."))
|
||||
return
|
||||
|
||||
term = await self.db.get(aid)
|
||||
if term is None:
|
||||
await message.reply(f"No explanation with id {aid} exists.")
|
||||
|
|
|
|||
10
wtfdb.py
10
wtfdb.py
|
|
@ -31,21 +31,23 @@ class WtfDB(yaboli.Database):
|
|||
""", (acronym, explanation, author))
|
||||
|
||||
@yaboli.operation
|
||||
def find(self, db, acronym):
|
||||
def find(self, db, acronym, limit):
|
||||
c = db.execute("""
|
||||
SELECT acronym, explanation FROM acronyms
|
||||
WHERE NOT deleted AND p_lower(acronym) = ?
|
||||
ORDER BY acronym_id ASC
|
||||
""", (acronym.lower(),))
|
||||
LIMIT ?
|
||||
""", (acronym.lower(), limit))
|
||||
return c.fetchall()
|
||||
|
||||
@yaboli.operation
|
||||
def find_full(self, db, acronym):
|
||||
def find_full(self, db, acronym, limit):
|
||||
c = db.execute("""
|
||||
SELECT acronym_id, acronym, explanation, author FROM acronyms
|
||||
WHERE NOT deleted AND p_lower(acronym) = ?
|
||||
ORDER BY acronym_id ASC
|
||||
""", (acronym.lower(),))
|
||||
LIMIT ?
|
||||
""", (acronym.lower(), limit))
|
||||
return c.fetchall()
|
||||
|
||||
@yaboli.operation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue