refactored trigger

This commit is contained in:
iou1name 2020-01-07 18:58:19 -05:00
parent 7159deb7f8
commit 1b71e73757
47 changed files with 297 additions and 441 deletions

22
bot.py
View File

@ -166,10 +166,10 @@ class Fulvia(irc.IRCClient):
self.commands.pop(command)
if func.hook:
self._hooks.remove(func.__name__)
self._hooks.remove(func)
if func.rate or func.channel_rate or func.global_rate:
self._times.pop(func.__name__)
self._times.pop(func)
if hasattr(func, 'url_callback'):
for url in func.url_callback:
@ -253,26 +253,26 @@ class Fulvia(irc.IRCClient):
funcs += self._hooks
for func in funcs:
trigger = Trigger(user, channel, message, "PRIVMSG")
trigger = Trigger(user, channel, message)
bot = FulviaWrapper(self, trigger)
if func.rate:
t = self._times[func_name].get(trigger.nick, 0)
t = self._times[func.__name__].get(trigger.nick, 0)
if time.time() - t < func.rate and not trigger.admin:
return
self._times[func_name][trigger.nick] = time.time()
self._times[func.__name__][trigger.nick] = time.time()
if func.channel_rate:
t = self._times[func_name].get(trigger.channel, 0)
t = self._times[func.__name__].get(trigger.channel, 0)
if time.time() - t < func.channel_rate and not trigger.admin:
return
self._times[func_name][trigger.channel] = time.time()
self._times[func.__name__][trigger.channel] = time.time()
if func.global_rate:
t = self._times[func_name].get("global", 0)
t = self._times[func.__name__].get("global", 0)
if time.time() - t < func.channel_rate and not trigger.admin:
return
self._times[func_name]["global"] = time.time()
self._times[func.__name__]["global"] = time.time()
if func.thread == True:
t = threading.Thread(target=self.call,args=(func, bot, trigger))
@ -394,9 +394,9 @@ class Fulvia(irc.IRCClient):
self.channels[channel].users[nick] = new_user
for func in self._user_joined:
trigger = Trigger(user, channel, f"{user} has joined", "PRIVMSG")
trigger = Trigger(user, channel, f"{user} has joined")
bot = FulviaWrapper(self, trigger)
t = threading.Thread(target=self.call,args=(func, bot, trigger))
t = threading.Thread(target=self.call, args=(func, bot, trigger))
t.start()

View File

@ -10,7 +10,8 @@ import module
@module.example('.join #example or .join #example key')
def join(bot, trigger):
"""Join the specified channel. This is an admin-only command."""
channel, key = trigger.group(3), trigger.group(4)
channel = trigger.args[1] if len(trigger.args) >= 2 else None
key = trigger.args[2] if len(trigger.args) >= 3 else None
if not channel:
return
elif not key:
@ -24,7 +25,14 @@ def join(bot, trigger):
@module.example('.part #example')
def part(bot, trigger):
"""Part the specified channel. This is an admin-only command."""
channel, _, part_msg = trigger.group(2).partition(' ')
if len(trigger.args) < 2:
return
channel = trigger.args[1]
if len(trigger.args) >= 3:
part_msg = ' '.join(trigger.args[2:])
else:
part_msg = None
if not channel.startswith("#"):
part_msg = channel
channel = ""
@ -40,8 +48,9 @@ def part(bot, trigger):
@module.commands('quit')
def quit(bot, trigger):
"""Quit from the server. This is an owner-only command."""
quit_message = trigger.group(2)
if not quit_message:
if len(trigger.args) >= 2:
quit_message = ' '.join(trigger.args[1:])
else:
quit_message = f"Quitting on command from {trigger.nick}"
bot.quit(quit_message)
@ -54,13 +63,10 @@ def msg(bot, trigger):
"""
Send a message to a given channel or nick. Can only be done by an admin.
"""
if trigger.group(2) is None:
return
channel, _, message = trigger.group(2).partition(' ')
message = message.strip()
if not channel or not message:
if len(trigger.args) < 3:
return
channel = trigger.args[1]
message = ' '.join(trigger.args[2:])
bot.msg(channel, message)
@ -73,13 +79,10 @@ def me(bot, trigger):
Send an ACTION (/me) to a given channel or nick. Can only be done by an
admin.
"""
if trigger.group(2) is None:
return
channel, _, action = trigger.group(2).partition(' ')
action = action.strip()
if not channel or not action:
if len(trigger.args) < 3:
return
channel = trigger.args[1]
action = ' '.join(trigger.args[2:])
# msg = '\x01ACTION %s\x01' % action
bot.describe(channel, action)
@ -90,6 +93,8 @@ def me(bot, trigger):
@module.example(".mode +B")
def self_mode(bot, trigger):
"""Set a user mode on Fulvia. Can only be done in privmsg by an admin."""
mode = trigger.group(3)
if len(trigger.args) < 2:
return
mode = trigger.args[1]
add_mode = mode.startswith("+")
bot.mode(bot.nickname, add_mode, mode)

View File

@ -21,11 +21,12 @@ def kick(bot, trigger):
"""
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
return bot.reply("I'm not a channel operator!")
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Who do you want me to kick?")
target, _, reason = trigger.group(2).partition(" ")
if not reason:
target = trigger.args[1]
if len(trigger.args) >= 3:
reason = ' '.join(trigger.args[2:])
else:
reason = "Stop doing the bad."
if target == bot.nick:
@ -45,10 +46,10 @@ def ban(bot, trigger):
"""
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
return bot.reply("I'm not a channel operator!")
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Who do you want me to ban?")
banmask = configureHostMask(trigger.group(2))
banmask = configureHostMask(trigger.args[1])
bot.mode(trigger.channel, True, "b", mask=banmask)
@ -63,10 +64,10 @@ def unban(bot, trigger):
"""
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
return bot.reply("I'm not a channel operator!")
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Who do you want me to ban?")
banmask = configureHostMask(trigger.group(2))
banmask = configureHostMask(trigger.args[1])
bot.mode(trigger.channel, False, "b", mask=banmask)
@ -81,17 +82,18 @@ def kickban(bot, trigger):
"""
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
return bot.reply("I'm not a channel operator!")
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Who do you want me to ban?")
target, _, reason = trigger.group(2).partition(" ")
if not reason:
target = trigger.args[1]
if len(trigger.args) >= 3:
reason = ' '.join(trigger.args[2:])
else:
reason = "Stop doing the bad."
if target == bot.nick:
return bot.reply("I can't let you do that.")
banmask = configureHostMask(trigger.group(2).strip())
banmask = configureHostMask(trigger.args[1])
bot.mode(trigger.channel, False, "b", mask=banmask)
bot.kick(trigger.channel, target, reason)
@ -107,7 +109,7 @@ def settopic(bot, trigger):
"""
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
return bot.reply("I'm not a channel operator!")
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("What do you want the topic set to?")
bot.topic(trigger.channel, trigger.group(2).strip())
bot.topic(trigger.channel, ' '.join(trigger.args[1:]))

View File

@ -2,18 +2,18 @@
"""
Sends a message to all channels the bot is currently in.
"""
from module import commands, example
from module import commands, example, require_admin
@require_admin
@commands('announce')
@example('.announce Some important message here')
def announce(bot, trigger):
"""
Send an announcement to all channels the bot is in.
"""
if not trigger.admin:
bot.reply("Sorry, I can't let you do that")
return
if len(trigger.args) < 2:
return bot.reply("What message?")
for channel in bot.channels.keys():
bot.msg(channel, f"[ANNOUNCEMENT] {trigger.group(2)}")
bot.msg(channel, f"[ANNOUNCEMENT] {trigger.args[1]}")
bot.reply('Announce complete.')

View File

@ -233,7 +233,7 @@ def ascii(bot, trigger):
"""
Downloads an image and converts it to ascii.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.msg()
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("imagePath")
@ -243,7 +243,7 @@ def ascii(bot, trigger):
parser.add_argument("-B", "--brail2", action="store_true")
parser.add_argument("-a", "--animated", action="store_true")
parser.add_argument("-h", "--help", action="store_true")
args = parser.parse_args(trigger.group(2).split())
args = parser.parse_args(trigger.args[1:])
if args.help:
return bot.msg(parser.print_help())

View File

@ -16,10 +16,10 @@ def away(bot, trigger):
"""
Stores in the user's name and away message in memory.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
bot.memory['away'][trigger.nick] = ""
else:
bot.memory['away'][trigger.nick] = trigger.group(2)
bot.memory['away'][trigger.nick] = ' '.join(trigger.args[1:])
@hook(True)
@ -27,7 +27,7 @@ def message(bot, trigger):
"""
If an away users name is said, print their away message.
"""
name = trigger.group(1)
name = trigger.args[0]
if name.endswith(":") or name.endswith(","):
name = name[:-1]
if name in bot.memory["away"]:
@ -41,6 +41,6 @@ def notAway(bot, trigger):
"""
If an away user says something, remove them from the away dict.
"""
if not trigger.group(0).startswith(".away"):
if not trigger.args[0] == ".away":
if trigger.nick in bot.memory["away"]:
bot.memory["away"].pop(trigger.nick)

View File

@ -16,7 +16,8 @@ def banhe(bot, trigger):
Bans he for a set period of time. Admins may set the period of time,
non-admins only get 20 second bans.
"""
banhee, period = trigger.group(3), trigger.group(4)
banhee = trigger.args[1] if len(trigger.args) >= 2 else ''
period = trigger.args[2] if len(trigger.args) >= 3 else ''
if not trigger.admin:
period = 20
@ -24,7 +25,7 @@ def banhe(bot, trigger):
conv = {'s':1, 'm':60, 'h':3600, 'd':86400}
try:
period = conv[period[-1]] * int(period[:-1])
except (KeyError, ValueError, TypeError):
except (KeyError, ValueError, TypeError, IndexError):
period = 0
banmask = configureHostMask(banhee)
@ -47,7 +48,7 @@ def banheall(bot, trigger):
"""
Ban them all, Johnny.
"""
period = trigger.group(2)
period = trigger.args[1] if len(trigger.args) >= 2 else '20s'
conv = {'s':1, 'm':60, 'h':3600, 'd':86400}
try:
period = conv[period[-1]] * int(period[:-1])

View File

@ -15,10 +15,9 @@ BASE_TUMBOLIA_URI = 'https://tumbolia-two.appspot.com/'
@example('.c 5 + 3', '8')
def c(bot, trigger):
"""Evaluate some calculation."""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Nothing to calculate.")
# Account for the silly non-Anglophones and their silly radix point.
eqn = trigger.group(2).replace(',', '.')
eqn = ' '.join(trigger.args[1:])
try:
result = eval_equation(eqn)
result = "{:.10g}".format(result)
@ -33,10 +32,10 @@ def c(bot, trigger):
@example('.py len([1,2,3])', '3')
def py(bot, trigger):
"""Evaluate a Python expression."""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.msg("Need an expression to evaluate")
query = trigger.group(2)
query = trigger.args[1]
uri = BASE_TUMBOLIA_URI + 'py/'
res = requests.get(uri + query)
res.raise_for_status()

View File

@ -14,9 +14,9 @@ def generic_countdown(bot, trigger):
"""
.countdown <year> <month> <day> - displays a countdown to a given date.
"""
text = trigger.group(2)
if not text:
if len(trigger.args) < 2:
return bot.msg("Please use correct format: .countdown 2012 12 21")
text = trigger.args[1]
text = text.split()
if (len(text) != 3 or not text[0].isdigit() or not text[1].isdigit()
@ -28,5 +28,5 @@ def generic_countdown(bot, trigger):
return bot.msg("Please use correct format: .countdown 2012 12 21")
msg = relativeTime(datetime.now(), date)
msg += " until " + trigger.group(2)
msg += " until " + trigger.args[1]
bot.msg(msg)

View File

@ -23,7 +23,9 @@ def crypto(bot, trigger):
"key": config.coinlib_api_key,
"pref": "USD",
}
symbol = trigger.group(3)
if len(trigger.args) < 2:
return bot.reply("What coin?")
symbol = trigger.args[1]
if symbol:
params["symbol"] = symbol
res = requests.get(URI + "/coin", params=params)

View File

@ -19,14 +19,12 @@ def exchange(bot, trigger):
Supported currencies: https://www.exchangerate-api.com/supported-currencies
"""
amount = trigger.group(3)
cur_from = trigger.group(4)
cur_to = trigger.group(5)
if cur_to == "to":
cur_to = trigger.group(6)
if len(trigger.args) < 5:
return bot.reply("Insuffcient arguments.")
amount = trigger.args[1]
cur_from = trigger.args[2]
cur_to = trigger.args[4]
if not all((amount, cur_to, cur_from)):
return bot.reply("I didn't understand that. Try: .cur 20 EUR to USD")
try:
amount = float(amount)
except ValueError:
@ -58,10 +56,11 @@ def bitcoin(bot, trigger):
Show the current bitcoin value in USD. Optional parameter allows non-USD
conversion.
"""
cur_to = trigger.group(3)
if not cur_to:
if len(trigger.args) < 2:
cur_to = "USD"
cur_to = cur_to.upper()
else:
cur_to = trigger.args[1]
cur_to = cur_to.upper()
url = BTC_URI.format(**{"CUR_TO": cur_to})
res = requests.get(url, verify=True)

View File

@ -178,9 +178,9 @@ def roll(bot, trigger):
# Get a list of all dice expressions, evaluate them and then replace the
# expressions in the original string with the results. Replacing is done
# using string formatting, so %-characters must be escaped.
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("No dice to roll.")
arg_str = trigger.group(2)
arg_str = ' '.join(trigger.args[1:])
dice_expressions = re.findall(dice_regexp, arg_str)
arg_str = arg_str.replace("%", "%%")
arg_str = re.sub(dice_regexp, "%s", arg_str)
@ -215,7 +215,7 @@ def roll(bot, trigger):
return
bot.reply("You roll %s: %s = %d" % (
trigger.group(2), pretty_str, result))
' '.join(trigger.args[1:]), pretty_str, result))
@module.commands("choice", "choose")
@ -224,16 +224,17 @@ def choose(bot, trigger):
"""
.choice option1|option2|option3 - Makes a difficult choice easy.
"""
if not trigger.group(2):
return bot.reply('I\'d choose an option, but you didn\'t give me any.')
choices = [trigger.group(2)]
if len(trigger.args) < 2:
return bot.reply("I'd choose an option, but you didn't give me any.")
msg = ' '.join(trigger.args[1:])
choices = [msg]
for delim in '|\\/,':
choices = trigger.group(2).split(delim)
choices = msg.split(delim)
if len(choices) > 1:
break
# Use a different delimiter in the output, to prevent ambiguity.
for show_delim in ',|/\\':
if show_delim not in trigger.group(2):
if show_delim not in msg:
show_delim += ' '
break

View File

@ -8,5 +8,5 @@ from module import commands, example
@example('.echo balloons')
def echo(bot, trigger):
"""Echos the given string."""
if trigger.group(2):
bot.msg(trigger.group(2))
if len(trigger.args) >= 2:
bot.msg(' '.join(trigger.args[1:]))

View File

@ -18,8 +18,8 @@ def grog(bot, trigger):
data = file.read().splitlines()
num = None
try:
num = int(trigger.group(2)) - 1
except:
num = int(trigger.args[1]) - 1
except (IndexError, ValueError):
pass
if num == None:
num = random.randint(0, len(data)-1)
@ -38,8 +38,8 @@ def magic(bot, trigger):
data = file.read().splitlines()
num = None
try:
num = int(trigger.group(2)) - 1
except:
num = int(trigger.args[1]) - 1
except (IndexError, ValueError):
pass
if num == None:
num = random.randint(0, len(data)-1)

View File

@ -40,10 +40,10 @@ def hangman(bot, trigger):
Plays hangman. --start [-s] to start a new game, otherwise words are
taken as attempts to solve and single characters are taken as guesses.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Hang what?")
if trigger.group(3) == "--start" or trigger.group(3) == "-s":
if trigger.args[1] == "--start" or trigger.args[1] == "-s":
if bot.memory["hangman"].get(trigger.channel):
return bot.reply("There is already a game running in this channel.")
@ -59,8 +59,8 @@ def hangman(bot, trigger):
+ "Use '.hangman --start' to start one"
return bot.reply(msg)
if len(trigger.group(2)) > 1:
if trigger.group(2) == bot.memory["hangman"][trigger.channel].word:
if len(trigger.args[1]) > 1:
if trigger.args[1] == bot.memory["hangman"][trigger.channel].word:
bot.msg(f"{trigger.nick} has won!")
bot.msg(bot.memory["hangman"][trigger.channel].word)
bot.memory["hangman"].pop(trigger.channel)
@ -71,10 +71,10 @@ def hangman(bot, trigger):
+ f"{bot.memory['hangman'][trigger.channel].tries} tries left."
bot.reply(msg)
elif len(trigger.group(2)) == 1:
if trigger.group(2) in bot.memory["hangman"][trigger.channel].word:
elif len(trigger.args[1]) == 1:
if trigger.args[1] in bot.memory["hangman"][trigger.channel].word:
bot.reply("Correct!")
bot.memory["hangman"][trigger.channel].update(trigger.group(2))
bot.memory["hangman"][trigger.channel].update(trigger.args[1])
else:
bot.memory["hangman"][trigger.channel].tries -= 1

View File

@ -22,8 +22,8 @@ def clean_docstring(doc):
@example('.help tell')
def help(bot, trigger):
"""Shows a command's documentation, and possibly an example."""
if trigger.group(2):
command = trigger.group(2)
if len(trigger.args) >= 2:
command = trigger.args[1]
command = command.lower()
if command not in bot.commands:
return bot.msg("Command not found.")

View File

@ -10,10 +10,10 @@ from module import commands, require_chanmsg
@commands('isup')
def isup(bot, trigger):
"""Queries the given url to check if it's up or not."""
url = trigger.group(2)
if not url:
if len(trigger.args) < 2:
return bot.reply("What URL do you want to check?")
url = trigger.args[1]
if url.startswith("192") and not trigger.owner:
return bot.reply("Do not violate the LAN.")

View File

@ -7,6 +7,6 @@ from module import commands
@commands('lmgtfy')
def googleit(bot, trigger):
"""Let me just... google that for you."""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.msg('http://google.com/')
bot.msg('http://lmgtfy.com/?q=' + trigger.group(2).replace(' ', '+'))
bot.msg('http://lmgtfy.com/?q=' + trigger.args[1].replace(' ', '+'))

View File

@ -16,7 +16,7 @@ def minecraft_start_server(bot, trigger):
cmd = ["tmux", "send", "-t", "main:2", "./start.sh", "ENTER"]
cmd_re = ["tmux", "send", "-t", "main:2", "^C", "ENTER"]
msg = "Start signal sent to the minecraft server."
if trigger.group(2) == "-r":
if len(trigger.args) >= 2:
msg = "Re-" + msg
subprocess.run(cmd_re, check=True)
subprocess.run(cmd, check=True)

View File

@ -46,10 +46,9 @@ def movieInfo(bot, trigger):
Returns some information about a movie, like Title, Year, Rating,
Genre and IMDB Link.
"""
word = trigger.group(2)
if not word:
if len(trigger.args) < 2:
return bot.reply("What movie?")
word = word.replace(" ", "+")
word = '+'.join(trigger.args[1:])
api_key = config.tmdb_api_key
uri = "https://api.themoviedb.org/3/search/movie?" + \
@ -151,8 +150,8 @@ def pickMovie(bot, trigger):
else:
bot.reply(movie[0])
if trigger.group(2) == "-m":
trigger.set_group(f".movie {movie}")
if len(trigger.args) >= 2:
trigger.args = f".movie {movie}".strip().split(' ')
movieInfo(bot, trigger)
@ -163,8 +162,10 @@ def addMovie(bot, trigger):
"""
Adds the specified movie to the movie database.
"""
if len(trigger.args) < 2:
return bot.reply("What movie?")
movie = ' '.join(trigger.args[1:])
bot.memory['movie_lock'].acquire()
movie = trigger.group(2)
try:
bot.db.execute("INSERT INTO movie (movie_title, added_by) VALUES(?,?)",
(movie, trigger.nick))

View File

@ -12,8 +12,8 @@ def check_privilege(bot, trigger):
"""
Checks the user's privilege.
"""
if trigger.group(2):
nick = trigger.group(2)
if len(trigger.args) < 2:
nick = trigger.args[1]
else:
nick = trigger.nick

View File

@ -16,19 +16,12 @@ from module import commands, example
@example(".rand 10 99", "random(10, 99) = 29")
def rand(bot, trigger):
"""Replies with a random number between first and second argument."""
arg1 = trigger.group(3)
arg2 = trigger.group(4)
arg1 = trigger.args[1] if len(trigger.args) >= 2 else 0
arg2 = trigger.args[2] if len(trigger.args) >= 3 else sys.maxsize
try:
if arg2 is not None:
low = int(arg1)
high = int(arg2)
elif arg1 is not None:
low = 0
high = int(arg1)
else:
low = 0
high = sys.maxsize
low = int(arg1)
high = int(arg2)
except (ValueError, TypeError):
return bot.reply("Arguments must be of integer type")
@ -48,8 +41,14 @@ def rand_letters(bot, trigger):
Generates a series of string of random letters.
"""
num_letters = int(trigger.group(3)) if trigger.group(3) else 8
num_vowels = int(trigger.group(4)) if trigger.group(4) else 2
arg1 = trigger.args[1] if len(trigger.args) >= 2 else 8
arg2 = trigger.args[2] if len(trigger.args) >= 3 else 2
try:
num_letters = int(arg1)
num_vowels = int(arg2)
except (ValueError, TypeError):
return bot.reply("Arguments must be of integer type")
msg = []
for _ in range(num_letters):

View File

@ -13,9 +13,11 @@ import module
@module.thread(False)
def f_reload(bot, trigger):
"""Reloads a module, for use by admins only."""
name = trigger.group(2)
if len(trigger.args) < 2:
return boy.reply("Reload what?")
name = trigger.args[1]
if not name or name == "*" or name.upper() == "ALL THE THINGS":
if name == "*" or name.upper() == "ALL THE THINGS":
bot.load_modules()
return bot.msg("done")
@ -35,9 +37,9 @@ def f_reload(bot, trigger):
@module.thread(False)
def f_load(bot, trigger):
"""Loads a module, for use by admins only."""
name = trigger.group(2)
if not name:
if len(trigger.args) < 2:
return bot.msg('Load what?')
name = trigger.args[1]
if name in sys.modules:
return bot.msg('Module already loaded, use reload.')
@ -61,9 +63,9 @@ def f_load(bot, trigger):
@module.thread(False)
def f_unload(bot, trigger):
"""Unloads a module, for use by admins only."""
name = trigger.group(2)
if not name:
if len(trigger.args) < 2:
return bot.msg('Unload what?')
name = trigger.args[1]
if name not in sys.modules:
name = "modules." + name

View File

@ -6,9 +6,8 @@ import os
import re
import time
import sqlite3
import datetime
import threading
import collections
from datetime import datetime
import config
from module import commands, example
@ -133,15 +132,15 @@ multiplier = [
@example('.remind 3h45m Go to class')
def remind(bot, trigger):
"""Gives you a reminder in the given amount of time."""
if not trigger.group(2):
if len(trigger.args) == 1:
return bot.msg("Missing arguments for reminder command.")
if trigger.group(3) and not trigger.group(4):
if len(trigger.args) == 2:
reminder = ''
else:
reminder = ' '.join(trigger.group[4:])
reminder = ' '.join(trigger.args[2:])
duration = 0
for n, group in enumerate(re.search(regex, trigger.group(3)).groups()):
for n, group in enumerate(re.search(regex, trigger.args[1]).groups()):
if not group:
continue
duration += int(group) * multiplier[n]
@ -154,48 +153,24 @@ def remind(bot, trigger):
@example('.at 14:45:45 Remove dick from oven')
def at(bot, trigger):
"""
Gives you a reminder at the given time. Takes hh:mm:ssUTC+/-##
message. Timezone, if provided, must be in UTC format. 24 hour
clock format only.
Gives you a reminder at the given time and date. Datetime must be in
YYYY-MM-DD HH:MM:SS format. Only the bot's timezone is used.
"""
if not trigger.group(2):
return bot.msg("No arguments given for reminder command.")
if trigger.group(3) and not trigger.group(4):
return bot.msg("No message given for reminder.")
regex = re.compile(r"(\d+):(\d+)(?::(\d+))?(?:UTC([+-]\d+))? (.*)")
match = regex.match(trigger.group(2))
if not match:
return bot.reply("Sorry, but I didn't understand your input.")
hour, minute, second, tz, message = match.groups()
if not second:
second = '0'
if tz:
try:
tz = int(tz.replace("UTC", ""))
except ValueError:
bot.msg("Invalid timezone. Using the bot's current timezone.")
tz = None
if tz:
timezone = datetime.timezone(datetime.timedelta(hours=tz))
if len(trigger.args) == 1:
return bot.msg("Missing arguments for reminder command.")
if len(trigger.args) == 2:
reminder = ''
else:
timezone = datetime.datetime.now().astimezone().tzinfo
# current timezone the bot is in
reminder = ' '.join(trigger.args[2:])
now = datetime.datetime.now(timezone)
at_time = datetime.datetime(now.year, now.month, now.day,
int(hour), int(minute), int(second),
tzinfo=timezone)
timediff = at_time - now
try:
at_time = datetime.strptime(trigger.args[1], '%Y-%m-%d %H:%M:%S')
except ValueError:
return bot.msg("Datetime improperly formatted.")
diff = at_time - datetime.now()
duration = diff.seconds
duration = timediff.seconds
if duration < 0:
duration += 86400
create_reminder(bot, trigger, duration, message)
create_reminder(bot, trigger, duration, reminder)
def create_reminder(bot, trigger, duration, message):
@ -213,9 +188,9 @@ def create_reminder(bot, trigger, duration, message):
insert_reminder(bot, t, reminder)
if duration >= 60:
remind_at = datetime.datetime.fromtimestamp(t)
remind_at = datetime.fromtimestamp(t)
t_format = config.default_time_format
timef = datetime.datetime.strftime(remind_at, t_format)
timef = datetime.strftime(remind_at, t_format)
bot.reply('Okay, will remind at %s' % timef)
else:

View File

@ -60,13 +60,13 @@ def resist(bot, trigger):
"""
Displays the color band code of a resistor for the given resistance.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.msg("Please specify a value")
parser = argparse.ArgumentParser()
parser.add_argument("value", nargs="+")
parser.add_argument("-r", "--reverse", action="store_true")
parser.add_argument("-n", "--num_bands", type=int, choices=[3,4,5,6], default=4)
args = parser.parse_args(trigger.group(2).split())
args = parser.parse_args(trigger.args[1:])
if args.reverse: # bands-to-value
bot.msg(bands_to_value(" ".join(args.value)))

View File

@ -13,9 +13,10 @@ def rundown(bot, trigger):
"""
Provides rundown on demand. -c, --cabal for the IRCabal version.
"""
if trigger.group(2) in ["-c", "--cabal"]:
with open(os.path.join(bot.static, "cabaldown.txt"), "r") as file:
data = file.read()
if len(trigger.args) > 2:
if trigger.args[1] in ["-c", "--cabal"]:
with open(os.path.join(bot.static, "cabaldown.txt"), "r") as file:
data = file.read()
else:
with open(os.path.join(bot.static, "rundown.txt"), "r") as file:
data = file.read()

View File

@ -54,10 +54,10 @@ def scramble(bot, trigger):
Plays scramble. --start [-s] to start a new game, otherwise arguments
are taken as attempts to solve.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Scramble what?")
if trigger.group(3) == "--start" or trigger.group(3) == "-s":
if trigger.args[1] == "--start" or trigger.args[1] == "-s":
if bot.memory["scramble"].get(trigger.channel):
return bot.reply("There is already a game running in this channel.")
@ -74,7 +74,7 @@ def scramble(bot, trigger):
return bot.reply(msg)
word = bot.memory["scramble"][trigger.channel].word
if isAnagram(bot, word, trigger.group(2)):
if isAnagram(bot, word, trigger.args[1]):
bot.msg(f"{trigger.nick} has won!")
msg = "Original word: " \
+ bot.memory["scramble"][trigger.channel].word

View File

@ -8,135 +8,96 @@ using the sed notation (s///) commonly found in vi/vim.
import re
from module import hook
from tools import FulviaMemory
def setup(bot):
bot.memory['find_lines'] = FulviaMemory()
bot.memory['sed_lines'] = {}
@hook(True)
def collectlines(bot, trigger):
"""Create a temporary log of what people say"""
# Don't log things in PM
if trigger.is_privmsg:
return
# Add a log for the channel and nick, if there isn't already one
if trigger.channel not in bot.memory['find_lines']:
bot.memory['find_lines'][trigger.channel] = FulviaMemory()
if trigger.nick not in bot.memory['find_lines'][trigger.channel]:
bot.memory['find_lines'][trigger.channel][trigger.nick] = list()
if trigger.channel not in bot.memory['sed_lines']:
bot.memory['sed_lines'][trigger.channel] = {}
if trigger.nick not in bot.memory['sed_lines'][trigger.channel]:
bot.memory['sed_lines'][trigger.channel][trigger.nick] = []
# Create a temporary list of the user's lines in a channel
templist = bot.memory['find_lines'][trigger.channel][trigger.nick]
line = trigger.group()
templist = bot.memory['sed_lines'][trigger.channel][trigger.nick]
line = ' '.join(trigger.args)
if line.startswith("s/"): # Don't remember substitutions
return
elif line.startswith("\x01ACTION"): # For /me messages
line = line[:-1]
templist.append(line)
else:
templist.append(line)
templist.append(line)
del templist[:-10] # Keep the log to 10 lines per person
bot.memory['find_lines'][trigger.channel][trigger.nick] = templist
bot.memory['sed_lines'][trigger.channel][trigger.nick] = templist
#Match nick, s/find/replace/flags. Flags and nick are optional, nick can be
#followed by comma or colon, anything after the first space after the third
#slash is ignored, you can escape slashes with backslashes, and if you want to
#search for an actual backslash followed by an actual slash, you're shit out of
#luck because this is the fucking regex of death as it is.
# @rule(r"""(?:
# (\S+) # Catch a nick in group 1
# [:,]\s+)? # Followed by colon/comma and whitespace, if given
# s/ # The literal s/
# ( # Group 2 is the thing to find
# (?:\\/ | [^/])+ # One or more non-slashes or escaped slashes
# )/( # Group 3 is what to replace with
# (?:\\/ | [^/])* # One or more non-slashes or escaped slashes
# )
# (?:/(\S+))? # Optional slash, followed by group 4 (flags)
# """)
@hook(True)
def findandreplace(bot, trigger):
# Don't bother in PM
if trigger.is_privmsg:
return
rule = re.compile(r"(\S+)?(?:[:,]\s|^)s\/((?:\\\/|[^/])+)\/((?:\\\/|[^/])*"\
+ r")(?:\/(\S+))?")
group = rule.search(trigger.group(0))
if not group:
if not trigger.args[0].startswith('s') and trigger.args[0][-1] not in ':,':
return
g = (trigger.group(0),) + group.groups()
trigger.set_group(g)
# Correcting other person vs self.
rnick = (trigger.group(1) or trigger.nick)
search_dict = bot.memory['find_lines']
# only do something if there is conversation to work with
if trigger.channel not in search_dict:
return
if rnick not in search_dict[trigger.channel]:
line = ' '.join(trigger.args)
if 's/' not in line:
return
#TODO rest[0] is find, rest[1] is replace. These should be made variables of
#their own at some point.
rest = [trigger.group(2), trigger.group(3)]
rest[0] = rest[0].replace(r'\/', '/')
rest[1] = rest[1].replace(r'\/', '/')
me = False # /me command
flags = (trigger.group(4) or '')
print(flags)
items = []
line = line[line.index('s/')+2:]
i = 0
while True:
i = line.find('/', i)
if i == -1:
break
if line[max(i-1, 0)] == '\\' and line[max(i-2, 0)] != '\\':
i += 1
pass
else:
items.append(line[:i])
line = line[i+1:]
i = 0
items.append(line)
if len(items) < 2:
return
find, replace = items[:2]
find = find.replace(r'\/', '/')
flags = items[2] if len(items) >= 3 else ''
# If g flag is given, replace all. Otherwise, replace once.
if 'g' in flags:
count = 0
else:
count = 1
# repl is a lambda function which performs the substitution. i flag turns
# off case sensitivity. re.U turns on unicode replacement.
if 'i' in flags:
regex = re.compile(re.escape(rest[0]), re.U | re.I)
repl = lambda s: re.sub(regex, rest[1], s, count == 1)
else:
repl = lambda s: re.sub(rest[0], rest[1], s, count)
# Look back through the user's lines in the channel until you find a line
# where the replacement works
new_phrase = None
for line in reversed(search_dict[trigger.channel][rnick]):
if line.startswith("\x01ACTION"):
me = True # /me command
line = line[8:]
try:
if 'i' in flags:
regex = re.compile(find, re.I)
else:
me = False
new_phrase = repl(line)
if new_phrase != line: # we are done
break
regex = re.compile(find)
except re.error:
return
if not new_phrase or new_phrase == line:
return # Didn't find anything
# Save the new "edited" message.
action = (me and '\x01ACTION ') or '' # If /me message, prepend \x01ACTION
templist = search_dict[trigger.channel][rnick]
templist.append(action + new_phrase)
search_dict[trigger.channel][rnick] = templist
bot.memory['find_lines'] = search_dict
# output
if not me:
new_phrase = f"\x02meant\x0f to say: {new_phrase}"
if trigger.group(1):
phrase = f"{trigger.nick} thinks {rnick} {new_phrase}"
if not trigger.args[0].startswith('s'):
nick = trigger.args[0][:-1]
if nick not in bot.memory['sed_lines'][trigger.channel]:
return
else:
phrase = f"{trigger.nick} {new_phrase}"
nick = trigger.nick
bot.msg(phrase)
for line in reversed(bot.memory['sed_lines'][trigger.channel][nick]):
new_line = re.sub(regex, replace, line, count)
if new_line != line:
break
else:
return
if trigger.args[0].startswith('s'):
msg = f"{trigger.nick} \x02meant\x0f to say: {new_line}"
else:
msg = f"{trigger.nick} thinks {nick} \x02meant\x0f to say: {new_line}"
bot.msg(msg)

View File

@ -65,7 +65,7 @@ def seen(bot, trigger):
-m, --message - includes the first/last message the user sent.
-c, --context - includes irc logs before and after their last message as context. Implies --message.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Seen who?")
parser = argparse.ArgumentParser()
@ -74,7 +74,7 @@ def seen(bot, trigger):
parser.add_argument("-f", "--first", action="store_true")
parser.add_argument("-m", "--message", action="store_true")
parser.add_argument("-c", "--context", action="store_true")
args = parser.parse_args(trigger.group[3:])
args = parser.parse_args(trigger.args[1:])
if args.nick == bot.nick:
return bot.reply("I'm right here!")
@ -142,9 +142,9 @@ def dump_seen_db(bot):
@require_chanmsg
def seen_hook(bot, trigger):
bot.memory["seen_lock"].acquire()
last = (time.time(), trigger.channel, trigger.group(0))
last = (time.time(), trigger.channel, ' '.join(trigger.args))
if not trigger.nick in bot.memory["seen"]:
first = (time.time(), trigger.channel, trigger.group(0))
first = (time.time(), trigger.channel, ' '.join(trigger.args))
else:
first = bot.memory["seen"][trigger.nick][:3]
seen = first + last

View File

@ -37,7 +37,7 @@ def slur(bot, trigger):
parser.add_argument("-r", "--race", type=str, nargs='+')
parser.add_argument("-s", "--slur", type=str)
parser.add_argument("-l", "--list", action="store_true")
args = parser.parse_args(trigger.group[3:])
args = parser.parse_args(trigger.args[1:])
if args.list:
races = bot.db.execute("SELECT DISTINCT race FROM slur").fetchall()

View File

@ -13,9 +13,9 @@ def spellcheck(bot, trigger):
Says whether the given word is spelled correctly, and gives suggestions if
it's not.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("What word?")
word = trigger.group(2)
word = trigger.args[1]
if " " in word:
return bot.msg("One word at a time, please")
dictionary = enchant.Dict("en_US")

View File

@ -67,12 +67,14 @@ def setup(bot):
@example('.tell iou1name you broke something again.')
def tell(bot, trigger):
"""Give someone a message the next time they're seen"""
if not trigger.group(3):
if len(trigger.args) < 2:
return bot.reply("Tell whom?")
if len(trigger.args) < 3:
return bot.reply("Tell them what?")
teller = trigger.nick
tellee = trigger.group(3).rstrip('.,:;')
message = trigger.group(2).replace(tellee, "", 1).strip()
tellee = trigger.args[1].rstrip('.,:;')
message = ' '.join(trigger.args[2:])
if not message:
return bot.reply(f"Tell {tellee} what?")

View File

@ -13,11 +13,9 @@ URI = 'https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains'
@example('.tld me')
def gettld(bot, trigger):
"""Show information about the given Top Level Domain."""
word = trigger.group(2).strip()
if not word:
if len(trigger.args) < 2:
return bot.reply("What TLD?")
if " " in word:
return bot.reply("One TLD at a time.")
word = trigger.args[1]
if not word.startswith("."):
word = "." + word

View File

@ -48,9 +48,9 @@ def addTopic(bot, trigger):
"""
Adds the specified topic to the topic database.
"""
topic = trigger.group(2)
if not topic:
if len(trigger.args) < 2:
return bot.msg("Please be providing a topic sir.")
topic = trigger.args[1]
bot.memory['topic_lock'].acquire()
try:
bot.db.execute("INSERT INTO topic (topic, added_by) VALUES(?,?)",

View File

@ -42,14 +42,14 @@ def tr2(bot, trigger):
-i LANG, --inlang LANG - specifies the assumed input language.
-o LANG, --outlang LANG - specifies the desired output language.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Translate what?")
parser = argparse.ArgumentParser()
parser.add_argument("text", nargs=argparse.REMAINDER)
parser.add_argument("-i", "--inlang", default="auto")
parser.add_argument("-o", "--outlang", default="en")
args = parser.parse_args(trigger.group(2).split())
args = parser.parse_args(trigger.args[1:])
args.text = " ".join(args.text)
tr_text, in_lang = translate(args.text, in_lang=args.inlang,
@ -60,9 +60,9 @@ def tr2(bot, trigger):
@commands('mangle')
def mangle(bot, trigger):
"""Repeatedly translate the input until it makes absolutely no sense."""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Mangle what?")
tr_text = trigger.group(2)
tr_text = ' '.join(trigger.args[1:])
long_lang_list = ['fr', 'de', 'es', 'it', 'no', 'he', 'la', 'ja', 'cy',
'ar', 'yi', 'zh', 'nl', 'ru', 'fi', 'hi', 'af', 'jw', 'mr', 'ceb',

View File

@ -11,9 +11,9 @@ from module import commands, example
@example('.u 203D', 'U+203D INTERROBANG (‽)')
def codepoint(bot, trigger):
"""Looks up unicode information."""
arg = trigger.group(2)
if not arg:
if len(trigger.args) < 2:
return bot.reply('What code point do you want me to look up?')
arg = ' '.join(trigger.args[1])
stripped = arg.strip()
if len(stripped) > 0:
arg = stripped

View File

@ -43,7 +43,7 @@ def temperature(bot, trigger):
Convert temperatures
"""
try:
source = find_temp.match(trigger.group(2)).groups()
source = find_temp.match(' '.join(trigger.args[1:])).groups()
except (AttributeError, TypeError):
return bot.reply("That's not a valid temperature.")
unit = source[1].upper()
@ -77,7 +77,7 @@ def distance(bot, trigger):
Convert distances
"""
try:
source = find_length.match(trigger.group(2)).groups()
source = find_length.match(' '.join(trigger.args[1:])).groups()
except (AttributeError, TypeError):
return bot.reply("That's not a valid length unit.")
unit = source[1].lower()
@ -151,7 +151,7 @@ def mass(bot, trigger):
Convert mass
"""
try:
source = find_mass.match(trigger.group(2)).groups()
source = find_mass.match(' '.join(trigger.args[1:])).groups()
except (AttributeError, TypeError):
return bot.reply("That's not a valid mass unit.")
unit = source[1].lower()

View File

@ -27,12 +27,12 @@ def uptime(bot, trigger):
@commands('updick')
def updick(bot, trigger):
""".updick - Returns the uptime of Fulvia, measured in dicks."""
if trigger.group(2):
if trigger.group(2) in bot.users:
if len(trigger.args) < 2:
if trigger.args[1] in bot.users:
d = defer.Deferred()
d.addCallback(idleTime, bot)
bot.memory["idle_callbacks"][trigger.group(2)] = d
bot.whois(trigger.group(2))
bot.memory["idle_callbacks"][trigger.args[1]] = d
bot.whois(trigger.args[1])
else:
delta = datetime.datetime.now() - bot.memory["uptime"]
bot.msg("8" + "="*delta.days + "D")
@ -41,12 +41,12 @@ def updick(bot, trigger):
@commands('upwulf')
def upwulf(bot, trigger):
""".upwulf - Returns the uptime of Fulvia, measured in Adalwulfs."""
if trigger.group(2):
if trigger.group(2) in bot.users:
if len(trigger.args) < 2:
if trigger.args[1] in bot.users:
d = defer.Deferred()
d.addCallback(idleTimeWulf, bot)
bot.memory["idle_callbacks"][trigger.group(2)] = d
bot.whois(trigger.group(2))
d.addCallback(idleTime, bot)
bot.memory["idle_callbacks"][trigger.args[1]] = d
bot.whois(trigger.args[1])
else:
delta = datetime.datetime.now() - bot.memory["uptime"]
bot.msg("Adalwulf" + "_"*delta.days)
@ -75,7 +75,9 @@ def idleTimeWulf(result, bot):
@commands('unix')
def unixtolocal(bot, trigger):
"""Converts the given timestamp from unix time to local time."""
unix = int(trigger.group(2))
if len(trigger.args) < 2:
return bot.reply("Unix what?")
unix = int(trigger.args[1])
dt = datetime.datetime.utcfromtimestamp(unix)
dt = dt.replace(tzinfo=datetime.timezone.utc)
bot.msg(dt.astimezone(tz=None).strftime('%Y-%m-%d %H:%M:%S'))

View File

@ -36,11 +36,11 @@ def title_auto(bot, trigger):
Automatically show titles for URLs. For shortened URLs/redirects, find
where the URL redirects to and show the title for that.
"""
if "http" not in trigger.group(0):
if "http" not in ' '.join(trigger.args):
return
url_finder = re.compile(r"((?:http|https)(?::\/\/\S+))", re.IGNORECASE)
urls = re.findall(url_finder, trigger.group(0))
urls = re.findall(url_finder, ' '.join(trigger.args))
if len(urls) == 0:
return

View File

@ -85,10 +85,10 @@ def watch(bot, trigger):
"""
A thread watcher for 4chan.
"""
url = trigger.group(3)
name = trigger.group(4)
if not name:
name = "Anonymous"
if len(trigger.args) < 2:
boy.reply("What thread?")
url = trigger.args[1]
name = trigger.args[2] if len(trigger.args) >= 3 else "Anonymous"
if url in bot.memory["watcher"].keys():
return bot.msg("Error: I'm already watching that thread.")
@ -120,7 +120,9 @@ def unwatch(bot, trigger):
"""
Stops the thread watcher thread for that thread.
"""
url = trigger.group(2)
if len(trigger.args) < 2:
boy.reply("What thread?")
url = trigger.args[1]
try:
bot.memory["watcher"][url].stop.set()
bot.memory["watcher"].pop(url)

View File

@ -17,11 +17,13 @@ def weather(bot, trigger):
-m, --metric - uses metric units instead of imperial.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("Weather where?")
location = trigger.group(3)
location = trigger.args[1]
if location == '-m' or location == '--metric':
location = trigger.group(4)
if len(trigger.args) < 3:
return bot.reply("Weather where?")
location = trigger.args[2]
units = 'metric'
else:
units = 'imperial'

View File

@ -74,10 +74,10 @@ def wiki_info(bot, url):
@example('.wiki San Francisco')
def wikipedia(bot, trigger):
"""Search wikipedia and return a snippet of the results."""
if trigger.group(2) is None:
if len(trigger.args) < 2:
return bot.reply("What do you want me to look up?")
query = trigger.group(2)
query = ' '.join(trigger.args[1:])
if not query:
return bot.reply("What do you want me to look up?")

View File

@ -76,9 +76,9 @@ def format(result, definitions, number=2):
@example('.dict bailiwick')
def wiktionary(bot, trigger):
"""Look up a word on Wiktionary."""
word = trigger.group(2)
if word is None:
if len(trigger.args) < 2:
return bot.reply('You must tell me what to look up!')
word = trigger.args[1]
_, definitions = wikt(word)
if not definitions:

View File

@ -8,7 +8,7 @@ from module import commands, example
@example('.willilike Banished Quest')
def willilike(bot, trigger):
"""An advanced AI that will determine if you like something."""
if trigger.group(2):
if len(trigger.args) >= 2:
bot.reply("No.")
@commands('upvote')

View File

@ -15,11 +15,11 @@ def wa_command(bot, trigger):
"""
Queries WolframAlpha.
"""
if not trigger.group(2):
if len(trigger.args) < 2:
return bot.reply("You must provide a query.")
if not config.wolfram_app_id:
bot.reply("Wolfram|Alpha API app ID not configured.")
query = trigger.group(2).strip()
query = ' '.join(trigger.args[1:])
app_id = config.wolfram_app_id
units = config.wolfram_units

View File

@ -54,9 +54,9 @@ def xkcd(bot, trigger):
"""
latest = get_info()
max_int = latest['num']
if trigger.group(2):
if len(trigger.args) >= 2:
try:
num = int(trigger.group(2))
num = int(trigger.args[1])
except ValueError:
return bot.reply("Invalid input.")
num = validate_num(num, max_int)

View File

@ -2,8 +2,6 @@
"""
The trigger abstraction layer.
"""
import datetime
import config
def split_user(user):
@ -18,75 +16,14 @@ def split_user(user):
return nick, ident, host
class Group(list):
"""
Custom list class that permits calling it like a function so as to
emulate a re.group instance.
"""
def __init__(self, message):
"""
Initializes the group class. If 'message' is a string, we split
it into groups according to the usual trigger.group structure.
Otherwise we assume it's already been split appropriately.
"""
if type(message) == str:
message = self.split_group(message)
list.__init__(self, message)
def __call__(self, n=0):
"""
Allows you to call the instance like a function. Or a re.group
instance ;^).
If calling would result in an index error, None is returned instead.
"""
try:
item = list.__getitem__(self, n)
except IndexError:
item = None
return item
def split_group(self, message):
"""
Splits the message by spaces.
group(0) is always the entire message.
group(1) is always the first word of the message minus the prefix, if
present. This is usually just the command.
group(2) is always the entire message after the first word.
group(3+) is always every individual word after the first word.
"""
group = []
group.append(message)
words = message.split()
group.append(words[0].replace(config.prefix, "", 1))
group.append(" ".join(words[1:]))
group += words[1:]
return group
class Trigger():
def __init__(self, user, channel, message, event):
def __init__(self, user, channel, message):
self.channel = channel
"""
The channel from which the message was sent.
In a private message, this is the nick that sent the message.
"""
self.time = datetime.datetime.now()
"""
A datetime object at which the message was received by the IRC server.
If the server does not support server-time, then `time` will be the time
that the message was received by Fulvia.
"""
self.raw = ""
"""
The entire message, as sent from the server. This includes the CTCP
\\x01 bytes and command, if they were included.
"""
self.is_privmsg = not channel.startswith("#")
"""True if the trigger is from a user, False if it's from a channel."""
@ -107,50 +44,15 @@ class Trigger():
self.host = host
"""The hostname of the person who sent the message"""
self.event = event
"""
The IRC event (e.g. ``PRIVMSG`` or ``MODE``) which triggered the
message.
"""
self.group = Group(message)
"""The ``group`` function of the ``match`` attribute.
See Python :mod:`re` documentation for details."""
self.args = ()
"""
A tuple containing each of the arguments to an event. These are the
strings passed between the event name and the colon. For example,
setting ``mode -m`` on the channel ``#example``, args would be
``('#example', '-m')``
"""
self.args = message.strip().split(' ')
"""Pseudo-ARGV for a bot command."""
admins = config.admins + [config.owner]
self.admin = any([self.compare_hostmask(admin) for admin in admins])
self.admin = any([user == admin for admin in admins])
"""
True if the nick which triggered the command is one of the bot's
True if the user which triggered the command is one of the bot's
admins.
"""
self.owner = self.compare_hostmask(config.owner)
self.owner = user == config.owner
"""True if the nick which triggered the command is the bot's owner."""
def compare_hostmask(self, compare_against):
"""
Compares the current hostmask against the given one. If ident is not
None, it uses that, otherwise it only uses <nick>@<host>.
"""
if self.ident:
return compare_against == self.hostmask
else:
return compare_against == "@".join(self.nick, self.host)
def set_group(self, line):
"""
Allows a you to easily change the current group to a new Group
instance.
"""
self.group = Group(line)