refactored trigger
This commit is contained in:
parent
7159deb7f8
commit
1b71e73757
22
bot.py
22
bot.py
|
@ -166,10 +166,10 @@ class Fulvia(irc.IRCClient):
|
||||||
self.commands.pop(command)
|
self.commands.pop(command)
|
||||||
|
|
||||||
if func.hook:
|
if func.hook:
|
||||||
self._hooks.remove(func.__name__)
|
self._hooks.remove(func)
|
||||||
|
|
||||||
if func.rate or func.channel_rate or func.global_rate:
|
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'):
|
if hasattr(func, 'url_callback'):
|
||||||
for url in func.url_callback:
|
for url in func.url_callback:
|
||||||
|
@ -253,26 +253,26 @@ class Fulvia(irc.IRCClient):
|
||||||
funcs += self._hooks
|
funcs += self._hooks
|
||||||
|
|
||||||
for func in funcs:
|
for func in funcs:
|
||||||
trigger = Trigger(user, channel, message, "PRIVMSG")
|
trigger = Trigger(user, channel, message)
|
||||||
bot = FulviaWrapper(self, trigger)
|
bot = FulviaWrapper(self, trigger)
|
||||||
|
|
||||||
if func.rate:
|
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:
|
if time.time() - t < func.rate and not trigger.admin:
|
||||||
return
|
return
|
||||||
self._times[func_name][trigger.nick] = time.time()
|
self._times[func.__name__][trigger.nick] = time.time()
|
||||||
|
|
||||||
if func.channel_rate:
|
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:
|
if time.time() - t < func.channel_rate and not trigger.admin:
|
||||||
return
|
return
|
||||||
self._times[func_name][trigger.channel] = time.time()
|
self._times[func.__name__][trigger.channel] = time.time()
|
||||||
|
|
||||||
if func.global_rate:
|
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:
|
if time.time() - t < func.channel_rate and not trigger.admin:
|
||||||
return
|
return
|
||||||
self._times[func_name]["global"] = time.time()
|
self._times[func.__name__]["global"] = time.time()
|
||||||
|
|
||||||
if func.thread == True:
|
if func.thread == True:
|
||||||
t = threading.Thread(target=self.call,args=(func, bot, trigger))
|
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
|
self.channels[channel].users[nick] = new_user
|
||||||
|
|
||||||
for func in self._user_joined:
|
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)
|
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()
|
t.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ import module
|
||||||
@module.example('.join #example or .join #example key')
|
@module.example('.join #example or .join #example key')
|
||||||
def join(bot, trigger):
|
def join(bot, trigger):
|
||||||
"""Join the specified channel. This is an admin-only command."""
|
"""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:
|
if not channel:
|
||||||
return
|
return
|
||||||
elif not key:
|
elif not key:
|
||||||
|
@ -24,7 +25,14 @@ def join(bot, trigger):
|
||||||
@module.example('.part #example')
|
@module.example('.part #example')
|
||||||
def part(bot, trigger):
|
def part(bot, trigger):
|
||||||
"""Part the specified channel. This is an admin-only command."""
|
"""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("#"):
|
if not channel.startswith("#"):
|
||||||
part_msg = channel
|
part_msg = channel
|
||||||
channel = ""
|
channel = ""
|
||||||
|
@ -40,8 +48,9 @@ def part(bot, trigger):
|
||||||
@module.commands('quit')
|
@module.commands('quit')
|
||||||
def quit(bot, trigger):
|
def quit(bot, trigger):
|
||||||
"""Quit from the server. This is an owner-only command."""
|
"""Quit from the server. This is an owner-only command."""
|
||||||
quit_message = trigger.group(2)
|
if len(trigger.args) >= 2:
|
||||||
if not quit_message:
|
quit_message = ' '.join(trigger.args[1:])
|
||||||
|
else:
|
||||||
quit_message = f"Quitting on command from {trigger.nick}"
|
quit_message = f"Quitting on command from {trigger.nick}"
|
||||||
|
|
||||||
bot.quit(quit_message)
|
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.
|
Send a message to a given channel or nick. Can only be done by an admin.
|
||||||
"""
|
"""
|
||||||
if trigger.group(2) is None:
|
if len(trigger.args) < 3:
|
||||||
return
|
|
||||||
|
|
||||||
channel, _, message = trigger.group(2).partition(' ')
|
|
||||||
message = message.strip()
|
|
||||||
if not channel or not message:
|
|
||||||
return
|
return
|
||||||
|
channel = trigger.args[1]
|
||||||
|
message = ' '.join(trigger.args[2:])
|
||||||
|
|
||||||
bot.msg(channel, message)
|
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
|
Send an ACTION (/me) to a given channel or nick. Can only be done by an
|
||||||
admin.
|
admin.
|
||||||
"""
|
"""
|
||||||
if trigger.group(2) is None:
|
if len(trigger.args) < 3:
|
||||||
return
|
|
||||||
|
|
||||||
channel, _, action = trigger.group(2).partition(' ')
|
|
||||||
action = action.strip()
|
|
||||||
if not channel or not action:
|
|
||||||
return
|
return
|
||||||
|
channel = trigger.args[1]
|
||||||
|
action = ' '.join(trigger.args[2:])
|
||||||
|
|
||||||
# msg = '\x01ACTION %s\x01' % action
|
# msg = '\x01ACTION %s\x01' % action
|
||||||
bot.describe(channel, action)
|
bot.describe(channel, action)
|
||||||
|
@ -90,6 +93,8 @@ def me(bot, trigger):
|
||||||
@module.example(".mode +B")
|
@module.example(".mode +B")
|
||||||
def self_mode(bot, trigger):
|
def self_mode(bot, trigger):
|
||||||
"""Set a user mode on Fulvia. Can only be done in privmsg by an admin."""
|
"""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("+")
|
add_mode = mode.startswith("+")
|
||||||
bot.mode(bot.nickname, add_mode, mode)
|
bot.mode(bot.nickname, add_mode, mode)
|
||||||
|
|
|
@ -21,11 +21,12 @@ def kick(bot, trigger):
|
||||||
"""
|
"""
|
||||||
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||||
return bot.reply("I'm not a channel operator!")
|
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?")
|
return bot.reply("Who do you want me to kick?")
|
||||||
|
target = trigger.args[1]
|
||||||
target, _, reason = trigger.group(2).partition(" ")
|
if len(trigger.args) >= 3:
|
||||||
if not reason:
|
reason = ' '.join(trigger.args[2:])
|
||||||
|
else:
|
||||||
reason = "Stop doing the bad."
|
reason = "Stop doing the bad."
|
||||||
|
|
||||||
if target == bot.nick:
|
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:
|
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||||
return bot.reply("I'm not a channel operator!")
|
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?")
|
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)
|
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:
|
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||||
return bot.reply("I'm not a channel operator!")
|
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?")
|
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)
|
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:
|
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||||
return bot.reply("I'm not a channel operator!")
|
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?")
|
return bot.reply("Who do you want me to ban?")
|
||||||
|
target = trigger.args[1]
|
||||||
target, _, reason = trigger.group(2).partition(" ")
|
if len(trigger.args) >= 3:
|
||||||
if not reason:
|
reason = ' '.join(trigger.args[2:])
|
||||||
|
else:
|
||||||
reason = "Stop doing the bad."
|
reason = "Stop doing the bad."
|
||||||
|
|
||||||
if target == bot.nick:
|
if target == bot.nick:
|
||||||
return bot.reply("I can't let you do that.")
|
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.mode(trigger.channel, False, "b", mask=banmask)
|
||||||
bot.kick(trigger.channel, target, reason)
|
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:
|
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||||
return bot.reply("I'm not a channel operator!")
|
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?")
|
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:]))
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
"""
|
"""
|
||||||
Sends a message to all channels the bot is currently in.
|
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')
|
@commands('announce')
|
||||||
@example('.announce Some important message here')
|
@example('.announce Some important message here')
|
||||||
def announce(bot, trigger):
|
def announce(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Send an announcement to all channels the bot is in.
|
Send an announcement to all channels the bot is in.
|
||||||
"""
|
"""
|
||||||
if not trigger.admin:
|
if len(trigger.args) < 2:
|
||||||
bot.reply("Sorry, I can't let you do that")
|
return bot.reply("What message?")
|
||||||
return
|
|
||||||
for channel in bot.channels.keys():
|
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.')
|
bot.reply('Announce complete.')
|
||||||
|
|
|
@ -233,7 +233,7 @@ def ascii(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Downloads an image and converts it to ascii.
|
Downloads an image and converts it to ascii.
|
||||||
"""
|
"""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.msg()
|
return bot.msg()
|
||||||
parser = argparse.ArgumentParser(add_help=False)
|
parser = argparse.ArgumentParser(add_help=False)
|
||||||
parser.add_argument("imagePath")
|
parser.add_argument("imagePath")
|
||||||
|
@ -243,7 +243,7 @@ def ascii(bot, trigger):
|
||||||
parser.add_argument("-B", "--brail2", action="store_true")
|
parser.add_argument("-B", "--brail2", action="store_true")
|
||||||
parser.add_argument("-a", "--animated", action="store_true")
|
parser.add_argument("-a", "--animated", action="store_true")
|
||||||
parser.add_argument("-h", "--help", 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:
|
if args.help:
|
||||||
return bot.msg(parser.print_help())
|
return bot.msg(parser.print_help())
|
||||||
|
|
|
@ -16,10 +16,10 @@ def away(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Stores in the user's name and away message in memory.
|
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] = ""
|
bot.memory['away'][trigger.nick] = ""
|
||||||
else:
|
else:
|
||||||
bot.memory['away'][trigger.nick] = trigger.group(2)
|
bot.memory['away'][trigger.nick] = ' '.join(trigger.args[1:])
|
||||||
|
|
||||||
|
|
||||||
@hook(True)
|
@hook(True)
|
||||||
|
@ -27,7 +27,7 @@ def message(bot, trigger):
|
||||||
"""
|
"""
|
||||||
If an away users name is said, print their away message.
|
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(","):
|
if name.endswith(":") or name.endswith(","):
|
||||||
name = name[:-1]
|
name = name[:-1]
|
||||||
if name in bot.memory["away"]:
|
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 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"]:
|
if trigger.nick in bot.memory["away"]:
|
||||||
bot.memory["away"].pop(trigger.nick)
|
bot.memory["away"].pop(trigger.nick)
|
||||||
|
|
|
@ -16,7 +16,8 @@ def banhe(bot, trigger):
|
||||||
Bans he for a set period of time. Admins may set the period of time,
|
Bans he for a set period of time. Admins may set the period of time,
|
||||||
non-admins only get 20 second bans.
|
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:
|
if not trigger.admin:
|
||||||
period = 20
|
period = 20
|
||||||
|
@ -24,7 +25,7 @@ def banhe(bot, trigger):
|
||||||
conv = {'s':1, 'm':60, 'h':3600, 'd':86400}
|
conv = {'s':1, 'm':60, 'h':3600, 'd':86400}
|
||||||
try:
|
try:
|
||||||
period = conv[period[-1]] * int(period[:-1])
|
period = conv[period[-1]] * int(period[:-1])
|
||||||
except (KeyError, ValueError, TypeError):
|
except (KeyError, ValueError, TypeError, IndexError):
|
||||||
period = 0
|
period = 0
|
||||||
|
|
||||||
banmask = configureHostMask(banhee)
|
banmask = configureHostMask(banhee)
|
||||||
|
@ -47,7 +48,7 @@ def banheall(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Ban them all, Johnny.
|
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}
|
conv = {'s':1, 'm':60, 'h':3600, 'd':86400}
|
||||||
try:
|
try:
|
||||||
period = conv[period[-1]] * int(period[:-1])
|
period = conv[period[-1]] * int(period[:-1])
|
||||||
|
|
|
@ -15,10 +15,9 @@ BASE_TUMBOLIA_URI = 'https://tumbolia-two.appspot.com/'
|
||||||
@example('.c 5 + 3', '8')
|
@example('.c 5 + 3', '8')
|
||||||
def c(bot, trigger):
|
def c(bot, trigger):
|
||||||
"""Evaluate some calculation."""
|
"""Evaluate some calculation."""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.reply("Nothing to calculate.")
|
return bot.reply("Nothing to calculate.")
|
||||||
# Account for the silly non-Anglophones and their silly radix point.
|
eqn = ' '.join(trigger.args[1:])
|
||||||
eqn = trigger.group(2).replace(',', '.')
|
|
||||||
try:
|
try:
|
||||||
result = eval_equation(eqn)
|
result = eval_equation(eqn)
|
||||||
result = "{:.10g}".format(result)
|
result = "{:.10g}".format(result)
|
||||||
|
@ -33,10 +32,10 @@ def c(bot, trigger):
|
||||||
@example('.py len([1,2,3])', '3')
|
@example('.py len([1,2,3])', '3')
|
||||||
def py(bot, trigger):
|
def py(bot, trigger):
|
||||||
"""Evaluate a Python expression."""
|
"""Evaluate a Python expression."""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.msg("Need an expression to evaluate")
|
return bot.msg("Need an expression to evaluate")
|
||||||
|
|
||||||
query = trigger.group(2)
|
query = trigger.args[1]
|
||||||
uri = BASE_TUMBOLIA_URI + 'py/'
|
uri = BASE_TUMBOLIA_URI + 'py/'
|
||||||
res = requests.get(uri + query)
|
res = requests.get(uri + query)
|
||||||
res.raise_for_status()
|
res.raise_for_status()
|
||||||
|
|
|
@ -14,9 +14,9 @@ def generic_countdown(bot, trigger):
|
||||||
"""
|
"""
|
||||||
.countdown <year> <month> <day> - displays a countdown to a given date.
|
.countdown <year> <month> <day> - displays a countdown to a given date.
|
||||||
"""
|
"""
|
||||||
text = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
if not text:
|
|
||||||
return bot.msg("Please use correct format: .countdown 2012 12 21")
|
return bot.msg("Please use correct format: .countdown 2012 12 21")
|
||||||
|
text = trigger.args[1]
|
||||||
|
|
||||||
text = text.split()
|
text = text.split()
|
||||||
if (len(text) != 3 or not text[0].isdigit() or not text[1].isdigit()
|
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")
|
return bot.msg("Please use correct format: .countdown 2012 12 21")
|
||||||
|
|
||||||
msg = relativeTime(datetime.now(), date)
|
msg = relativeTime(datetime.now(), date)
|
||||||
msg += " until " + trigger.group(2)
|
msg += " until " + trigger.args[1]
|
||||||
bot.msg(msg)
|
bot.msg(msg)
|
||||||
|
|
|
@ -23,7 +23,9 @@ def crypto(bot, trigger):
|
||||||
"key": config.coinlib_api_key,
|
"key": config.coinlib_api_key,
|
||||||
"pref": "USD",
|
"pref": "USD",
|
||||||
}
|
}
|
||||||
symbol = trigger.group(3)
|
if len(trigger.args) < 2:
|
||||||
|
return bot.reply("What coin?")
|
||||||
|
symbol = trigger.args[1]
|
||||||
if symbol:
|
if symbol:
|
||||||
params["symbol"] = symbol
|
params["symbol"] = symbol
|
||||||
res = requests.get(URI + "/coin", params=params)
|
res = requests.get(URI + "/coin", params=params)
|
||||||
|
|
|
@ -19,14 +19,12 @@ def exchange(bot, trigger):
|
||||||
|
|
||||||
Supported currencies: https://www.exchangerate-api.com/supported-currencies
|
Supported currencies: https://www.exchangerate-api.com/supported-currencies
|
||||||
"""
|
"""
|
||||||
amount = trigger.group(3)
|
if len(trigger.args) < 5:
|
||||||
cur_from = trigger.group(4)
|
return bot.reply("Insuffcient arguments.")
|
||||||
cur_to = trigger.group(5)
|
amount = trigger.args[1]
|
||||||
if cur_to == "to":
|
cur_from = trigger.args[2]
|
||||||
cur_to = trigger.group(6)
|
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:
|
try:
|
||||||
amount = float(amount)
|
amount = float(amount)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -58,10 +56,11 @@ def bitcoin(bot, trigger):
|
||||||
Show the current bitcoin value in USD. Optional parameter allows non-USD
|
Show the current bitcoin value in USD. Optional parameter allows non-USD
|
||||||
conversion.
|
conversion.
|
||||||
"""
|
"""
|
||||||
cur_to = trigger.group(3)
|
if len(trigger.args) < 2:
|
||||||
if not cur_to:
|
|
||||||
cur_to = "USD"
|
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})
|
url = BTC_URI.format(**{"CUR_TO": cur_to})
|
||||||
res = requests.get(url, verify=True)
|
res = requests.get(url, verify=True)
|
||||||
|
|
|
@ -178,9 +178,9 @@ def roll(bot, trigger):
|
||||||
# Get a list of all dice expressions, evaluate them and then replace the
|
# Get a list of all dice expressions, evaluate them and then replace the
|
||||||
# expressions in the original string with the results. Replacing is done
|
# expressions in the original string with the results. Replacing is done
|
||||||
# using string formatting, so %-characters must be escaped.
|
# 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.")
|
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)
|
dice_expressions = re.findall(dice_regexp, arg_str)
|
||||||
arg_str = arg_str.replace("%", "%%")
|
arg_str = arg_str.replace("%", "%%")
|
||||||
arg_str = re.sub(dice_regexp, "%s", arg_str)
|
arg_str = re.sub(dice_regexp, "%s", arg_str)
|
||||||
|
@ -215,7 +215,7 @@ def roll(bot, trigger):
|
||||||
return
|
return
|
||||||
|
|
||||||
bot.reply("You roll %s: %s = %d" % (
|
bot.reply("You roll %s: %s = %d" % (
|
||||||
trigger.group(2), pretty_str, result))
|
' '.join(trigger.args[1:]), pretty_str, result))
|
||||||
|
|
||||||
|
|
||||||
@module.commands("choice", "choose")
|
@module.commands("choice", "choose")
|
||||||
|
@ -224,16 +224,17 @@ def choose(bot, trigger):
|
||||||
"""
|
"""
|
||||||
.choice option1|option2|option3 - Makes a difficult choice easy.
|
.choice option1|option2|option3 - Makes a difficult choice easy.
|
||||||
"""
|
"""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.reply('I\'d choose an option, but you didn\'t give me any.')
|
return bot.reply("I'd choose an option, but you didn't give me any.")
|
||||||
choices = [trigger.group(2)]
|
msg = ' '.join(trigger.args[1:])
|
||||||
|
choices = [msg]
|
||||||
for delim in '|\\/,':
|
for delim in '|\\/,':
|
||||||
choices = trigger.group(2).split(delim)
|
choices = msg.split(delim)
|
||||||
if len(choices) > 1:
|
if len(choices) > 1:
|
||||||
break
|
break
|
||||||
# Use a different delimiter in the output, to prevent ambiguity.
|
# Use a different delimiter in the output, to prevent ambiguity.
|
||||||
for show_delim in ',|/\\':
|
for show_delim in ',|/\\':
|
||||||
if show_delim not in trigger.group(2):
|
if show_delim not in msg:
|
||||||
show_delim += ' '
|
show_delim += ' '
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -8,5 +8,5 @@ from module import commands, example
|
||||||
@example('.echo balloons')
|
@example('.echo balloons')
|
||||||
def echo(bot, trigger):
|
def echo(bot, trigger):
|
||||||
"""Echos the given string."""
|
"""Echos the given string."""
|
||||||
if trigger.group(2):
|
if len(trigger.args) >= 2:
|
||||||
bot.msg(trigger.group(2))
|
bot.msg(' '.join(trigger.args[1:]))
|
||||||
|
|
|
@ -18,8 +18,8 @@ def grog(bot, trigger):
|
||||||
data = file.read().splitlines()
|
data = file.read().splitlines()
|
||||||
num = None
|
num = None
|
||||||
try:
|
try:
|
||||||
num = int(trigger.group(2)) - 1
|
num = int(trigger.args[1]) - 1
|
||||||
except:
|
except (IndexError, ValueError):
|
||||||
pass
|
pass
|
||||||
if num == None:
|
if num == None:
|
||||||
num = random.randint(0, len(data)-1)
|
num = random.randint(0, len(data)-1)
|
||||||
|
@ -38,11 +38,11 @@ def magic(bot, trigger):
|
||||||
data = file.read().splitlines()
|
data = file.read().splitlines()
|
||||||
num = None
|
num = None
|
||||||
try:
|
try:
|
||||||
num = int(trigger.group(2)) - 1
|
num = int(trigger.args[1]) - 1
|
||||||
except:
|
except (IndexError, ValueError):
|
||||||
pass
|
pass
|
||||||
if num == None:
|
if num == None:
|
||||||
num = random.randint(0, len(data)-1)
|
num = random.randint(0, len(data)-1)
|
||||||
if num >= len(data)-1:
|
if num >= len(data)-1:
|
||||||
num = len(data)-1
|
num = len(data)-1
|
||||||
bot.msg(data[num])
|
bot.msg(data[num])
|
||||||
|
|
|
@ -40,10 +40,10 @@ def hangman(bot, trigger):
|
||||||
Plays hangman. --start [-s] to start a new game, otherwise words are
|
Plays hangman. --start [-s] to start a new game, otherwise words are
|
||||||
taken as attempts to solve and single characters are taken as guesses.
|
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?")
|
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):
|
if bot.memory["hangman"].get(trigger.channel):
|
||||||
return bot.reply("There is already a game running in this 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"
|
+ "Use '.hangman --start' to start one"
|
||||||
return bot.reply(msg)
|
return bot.reply(msg)
|
||||||
|
|
||||||
if len(trigger.group(2)) > 1:
|
if len(trigger.args[1]) > 1:
|
||||||
if trigger.group(2) == bot.memory["hangman"][trigger.channel].word:
|
if trigger.args[1] == bot.memory["hangman"][trigger.channel].word:
|
||||||
bot.msg(f"{trigger.nick} has won!")
|
bot.msg(f"{trigger.nick} has won!")
|
||||||
bot.msg(bot.memory["hangman"][trigger.channel].word)
|
bot.msg(bot.memory["hangman"][trigger.channel].word)
|
||||||
bot.memory["hangman"].pop(trigger.channel)
|
bot.memory["hangman"].pop(trigger.channel)
|
||||||
|
@ -71,10 +71,10 @@ def hangman(bot, trigger):
|
||||||
+ f"{bot.memory['hangman'][trigger.channel].tries} tries left."
|
+ f"{bot.memory['hangman'][trigger.channel].tries} tries left."
|
||||||
bot.reply(msg)
|
bot.reply(msg)
|
||||||
|
|
||||||
elif len(trigger.group(2)) == 1:
|
elif len(trigger.args[1]) == 1:
|
||||||
if trigger.group(2) in bot.memory["hangman"][trigger.channel].word:
|
if trigger.args[1] in bot.memory["hangman"][trigger.channel].word:
|
||||||
bot.reply("Correct!")
|
bot.reply("Correct!")
|
||||||
bot.memory["hangman"][trigger.channel].update(trigger.group(2))
|
bot.memory["hangman"][trigger.channel].update(trigger.args[1])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
bot.memory["hangman"][trigger.channel].tries -= 1
|
bot.memory["hangman"][trigger.channel].tries -= 1
|
||||||
|
|
|
@ -22,8 +22,8 @@ def clean_docstring(doc):
|
||||||
@example('.help tell')
|
@example('.help tell')
|
||||||
def help(bot, trigger):
|
def help(bot, trigger):
|
||||||
"""Shows a command's documentation, and possibly an example."""
|
"""Shows a command's documentation, and possibly an example."""
|
||||||
if trigger.group(2):
|
if len(trigger.args) >= 2:
|
||||||
command = trigger.group(2)
|
command = trigger.args[1]
|
||||||
command = command.lower()
|
command = command.lower()
|
||||||
if command not in bot.commands:
|
if command not in bot.commands:
|
||||||
return bot.msg("Command not found.")
|
return bot.msg("Command not found.")
|
||||||
|
|
|
@ -10,10 +10,10 @@ from module import commands, require_chanmsg
|
||||||
@commands('isup')
|
@commands('isup')
|
||||||
def isup(bot, trigger):
|
def isup(bot, trigger):
|
||||||
"""Queries the given url to check if it's up or not."""
|
"""Queries the given url to check if it's up or not."""
|
||||||
url = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
|
|
||||||
if not url:
|
|
||||||
return bot.reply("What URL do you want to check?")
|
return bot.reply("What URL do you want to check?")
|
||||||
|
url = trigger.args[1]
|
||||||
|
|
||||||
if url.startswith("192") and not trigger.owner:
|
if url.startswith("192") and not trigger.owner:
|
||||||
return bot.reply("Do not violate the LAN.")
|
return bot.reply("Do not violate the LAN.")
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,6 @@ from module import commands
|
||||||
@commands('lmgtfy')
|
@commands('lmgtfy')
|
||||||
def googleit(bot, trigger):
|
def googleit(bot, trigger):
|
||||||
"""Let me just... google that for you."""
|
"""Let me just... google that for you."""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.msg('http://google.com/')
|
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(' ', '+'))
|
||||||
|
|
|
@ -16,7 +16,7 @@ def minecraft_start_server(bot, trigger):
|
||||||
cmd = ["tmux", "send", "-t", "main:2", "./start.sh", "ENTER"]
|
cmd = ["tmux", "send", "-t", "main:2", "./start.sh", "ENTER"]
|
||||||
cmd_re = ["tmux", "send", "-t", "main:2", "^C", "ENTER"]
|
cmd_re = ["tmux", "send", "-t", "main:2", "^C", "ENTER"]
|
||||||
msg = "Start signal sent to the minecraft server."
|
msg = "Start signal sent to the minecraft server."
|
||||||
if trigger.group(2) == "-r":
|
if len(trigger.args) >= 2:
|
||||||
msg = "Re-" + msg
|
msg = "Re-" + msg
|
||||||
subprocess.run(cmd_re, check=True)
|
subprocess.run(cmd_re, check=True)
|
||||||
subprocess.run(cmd, check=True)
|
subprocess.run(cmd, check=True)
|
||||||
|
|
|
@ -46,10 +46,9 @@ def movieInfo(bot, trigger):
|
||||||
Returns some information about a movie, like Title, Year, Rating,
|
Returns some information about a movie, like Title, Year, Rating,
|
||||||
Genre and IMDB Link.
|
Genre and IMDB Link.
|
||||||
"""
|
"""
|
||||||
word = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
if not word:
|
|
||||||
return bot.reply("What movie?")
|
return bot.reply("What movie?")
|
||||||
word = word.replace(" ", "+")
|
word = '+'.join(trigger.args[1:])
|
||||||
|
|
||||||
api_key = config.tmdb_api_key
|
api_key = config.tmdb_api_key
|
||||||
uri = "https://api.themoviedb.org/3/search/movie?" + \
|
uri = "https://api.themoviedb.org/3/search/movie?" + \
|
||||||
|
@ -151,8 +150,8 @@ def pickMovie(bot, trigger):
|
||||||
else:
|
else:
|
||||||
bot.reply(movie[0])
|
bot.reply(movie[0])
|
||||||
|
|
||||||
if trigger.group(2) == "-m":
|
if len(trigger.args) >= 2:
|
||||||
trigger.set_group(f".movie {movie}")
|
trigger.args = f".movie {movie}".strip().split(' ')
|
||||||
movieInfo(bot, trigger)
|
movieInfo(bot, trigger)
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,8 +162,10 @@ def addMovie(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Adds the specified movie to the movie database.
|
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()
|
bot.memory['movie_lock'].acquire()
|
||||||
movie = trigger.group(2)
|
|
||||||
try:
|
try:
|
||||||
bot.db.execute("INSERT INTO movie (movie_title, added_by) VALUES(?,?)",
|
bot.db.execute("INSERT INTO movie (movie_title, added_by) VALUES(?,?)",
|
||||||
(movie, trigger.nick))
|
(movie, trigger.nick))
|
||||||
|
|
|
@ -12,8 +12,8 @@ def check_privilege(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Checks the user's privilege.
|
Checks the user's privilege.
|
||||||
"""
|
"""
|
||||||
if trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
nick = trigger.group(2)
|
nick = trigger.args[1]
|
||||||
else:
|
else:
|
||||||
nick = trigger.nick
|
nick = trigger.nick
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,12 @@ from module import commands, example
|
||||||
@example(".rand 10 99", "random(10, 99) = 29")
|
@example(".rand 10 99", "random(10, 99) = 29")
|
||||||
def rand(bot, trigger):
|
def rand(bot, trigger):
|
||||||
"""Replies with a random number between first and second argument."""
|
"""Replies with a random number between first and second argument."""
|
||||||
arg1 = trigger.group(3)
|
arg1 = trigger.args[1] if len(trigger.args) >= 2 else 0
|
||||||
arg2 = trigger.group(4)
|
arg2 = trigger.args[2] if len(trigger.args) >= 3 else sys.maxsize
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if arg2 is not None:
|
low = int(arg1)
|
||||||
low = int(arg1)
|
high = int(arg2)
|
||||||
high = int(arg2)
|
|
||||||
elif arg1 is not None:
|
|
||||||
low = 0
|
|
||||||
high = int(arg1)
|
|
||||||
else:
|
|
||||||
low = 0
|
|
||||||
high = sys.maxsize
|
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
return bot.reply("Arguments must be of integer type")
|
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.
|
Generates a series of string of random letters.
|
||||||
"""
|
"""
|
||||||
num_letters = int(trigger.group(3)) if trigger.group(3) else 8
|
arg1 = trigger.args[1] if len(trigger.args) >= 2 else 8
|
||||||
num_vowels = int(trigger.group(4)) if trigger.group(4) else 2
|
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 = []
|
msg = []
|
||||||
for _ in range(num_letters):
|
for _ in range(num_letters):
|
||||||
|
|
|
@ -13,9 +13,11 @@ import module
|
||||||
@module.thread(False)
|
@module.thread(False)
|
||||||
def f_reload(bot, trigger):
|
def f_reload(bot, trigger):
|
||||||
"""Reloads a module, for use by admins only."""
|
"""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()
|
bot.load_modules()
|
||||||
return bot.msg("done")
|
return bot.msg("done")
|
||||||
|
|
||||||
|
@ -35,9 +37,9 @@ def f_reload(bot, trigger):
|
||||||
@module.thread(False)
|
@module.thread(False)
|
||||||
def f_load(bot, trigger):
|
def f_load(bot, trigger):
|
||||||
"""Loads a module, for use by admins only."""
|
"""Loads a module, for use by admins only."""
|
||||||
name = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
if not name:
|
|
||||||
return bot.msg('Load what?')
|
return bot.msg('Load what?')
|
||||||
|
name = trigger.args[1]
|
||||||
|
|
||||||
if name in sys.modules:
|
if name in sys.modules:
|
||||||
return bot.msg('Module already loaded, use reload.')
|
return bot.msg('Module already loaded, use reload.')
|
||||||
|
@ -61,9 +63,9 @@ def f_load(bot, trigger):
|
||||||
@module.thread(False)
|
@module.thread(False)
|
||||||
def f_unload(bot, trigger):
|
def f_unload(bot, trigger):
|
||||||
"""Unloads a module, for use by admins only."""
|
"""Unloads a module, for use by admins only."""
|
||||||
name = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
if not name:
|
|
||||||
return bot.msg('Unload what?')
|
return bot.msg('Unload what?')
|
||||||
|
name = trigger.args[1]
|
||||||
|
|
||||||
if name not in sys.modules:
|
if name not in sys.modules:
|
||||||
name = "modules." + name
|
name = "modules." + name
|
||||||
|
|
|
@ -6,9 +6,8 @@ import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import datetime
|
|
||||||
import threading
|
import threading
|
||||||
import collections
|
from datetime import datetime
|
||||||
|
|
||||||
import config
|
import config
|
||||||
from module import commands, example
|
from module import commands, example
|
||||||
|
@ -133,15 +132,15 @@ multiplier = [
|
||||||
@example('.remind 3h45m Go to class')
|
@example('.remind 3h45m Go to class')
|
||||||
def remind(bot, trigger):
|
def remind(bot, trigger):
|
||||||
"""Gives you a reminder in the given amount of time."""
|
"""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.")
|
return bot.msg("Missing arguments for reminder command.")
|
||||||
if trigger.group(3) and not trigger.group(4):
|
if len(trigger.args) == 2:
|
||||||
reminder = ''
|
reminder = ''
|
||||||
else:
|
else:
|
||||||
reminder = ' '.join(trigger.group[4:])
|
reminder = ' '.join(trigger.args[2:])
|
||||||
|
|
||||||
duration = 0
|
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:
|
if not group:
|
||||||
continue
|
continue
|
||||||
duration += int(group) * multiplier[n]
|
duration += int(group) * multiplier[n]
|
||||||
|
@ -154,48 +153,24 @@ def remind(bot, trigger):
|
||||||
@example('.at 14:45:45 Remove dick from oven')
|
@example('.at 14:45:45 Remove dick from oven')
|
||||||
def at(bot, trigger):
|
def at(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Gives you a reminder at the given time. Takes hh:mm:ssUTC+/-##
|
Gives you a reminder at the given time and date. Datetime must be in
|
||||||
message. Timezone, if provided, must be in UTC format. 24 hour
|
YYYY-MM-DD HH:MM:SS format. Only the bot's timezone is used.
|
||||||
clock format only.
|
|
||||||
"""
|
"""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) == 1:
|
||||||
return bot.msg("No arguments given for reminder command.")
|
return bot.msg("Missing arguments for reminder command.")
|
||||||
if trigger.group(3) and not trigger.group(4):
|
if len(trigger.args) == 2:
|
||||||
return bot.msg("No message given for reminder.")
|
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))
|
|
||||||
else:
|
else:
|
||||||
timezone = datetime.datetime.now().astimezone().tzinfo
|
reminder = ' '.join(trigger.args[2:])
|
||||||
# current timezone the bot is in
|
|
||||||
|
|
||||||
now = datetime.datetime.now(timezone)
|
try:
|
||||||
at_time = datetime.datetime(now.year, now.month, now.day,
|
at_time = datetime.strptime(trigger.args[1], '%Y-%m-%d %H:%M:%S')
|
||||||
int(hour), int(minute), int(second),
|
except ValueError:
|
||||||
tzinfo=timezone)
|
return bot.msg("Datetime improperly formatted.")
|
||||||
timediff = at_time - now
|
diff = at_time - datetime.now()
|
||||||
|
duration = diff.seconds
|
||||||
|
|
||||||
duration = timediff.seconds
|
create_reminder(bot, trigger, duration, reminder)
|
||||||
|
|
||||||
if duration < 0:
|
|
||||||
duration += 86400
|
|
||||||
create_reminder(bot, trigger, duration, message)
|
|
||||||
|
|
||||||
|
|
||||||
def create_reminder(bot, trigger, duration, message):
|
def create_reminder(bot, trigger, duration, message):
|
||||||
|
@ -213,9 +188,9 @@ def create_reminder(bot, trigger, duration, message):
|
||||||
insert_reminder(bot, t, reminder)
|
insert_reminder(bot, t, reminder)
|
||||||
|
|
||||||
if duration >= 60:
|
if duration >= 60:
|
||||||
remind_at = datetime.datetime.fromtimestamp(t)
|
remind_at = datetime.fromtimestamp(t)
|
||||||
t_format = config.default_time_format
|
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)
|
bot.reply('Okay, will remind at %s' % timef)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -60,13 +60,13 @@ def resist(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Displays the color band code of a resistor for the given resistance.
|
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")
|
return bot.msg("Please specify a value")
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("value", nargs="+")
|
parser.add_argument("value", nargs="+")
|
||||||
parser.add_argument("-r", "--reverse", action="store_true")
|
parser.add_argument("-r", "--reverse", action="store_true")
|
||||||
parser.add_argument("-n", "--num_bands", type=int, choices=[3,4,5,6], default=4)
|
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
|
if args.reverse: # bands-to-value
|
||||||
bot.msg(bands_to_value(" ".join(args.value)))
|
bot.msg(bands_to_value(" ".join(args.value)))
|
||||||
|
|
|
@ -13,9 +13,10 @@ def rundown(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Provides rundown on demand. -c, --cabal for the IRCabal version.
|
Provides rundown on demand. -c, --cabal for the IRCabal version.
|
||||||
"""
|
"""
|
||||||
if trigger.group(2) in ["-c", "--cabal"]:
|
if len(trigger.args) > 2:
|
||||||
with open(os.path.join(bot.static, "cabaldown.txt"), "r") as file:
|
if trigger.args[1] in ["-c", "--cabal"]:
|
||||||
data = file.read()
|
with open(os.path.join(bot.static, "cabaldown.txt"), "r") as file:
|
||||||
|
data = file.read()
|
||||||
else:
|
else:
|
||||||
with open(os.path.join(bot.static, "rundown.txt"), "r") as file:
|
with open(os.path.join(bot.static, "rundown.txt"), "r") as file:
|
||||||
data = file.read()
|
data = file.read()
|
||||||
|
|
|
@ -54,10 +54,10 @@ def scramble(bot, trigger):
|
||||||
Plays scramble. --start [-s] to start a new game, otherwise arguments
|
Plays scramble. --start [-s] to start a new game, otherwise arguments
|
||||||
are taken as attempts to solve.
|
are taken as attempts to solve.
|
||||||
"""
|
"""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.reply("Scramble what?")
|
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):
|
if bot.memory["scramble"].get(trigger.channel):
|
||||||
return bot.reply("There is already a game running in this 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)
|
return bot.reply(msg)
|
||||||
|
|
||||||
word = bot.memory["scramble"][trigger.channel].word
|
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!")
|
bot.msg(f"{trigger.nick} has won!")
|
||||||
msg = "Original word: " \
|
msg = "Original word: " \
|
||||||
+ bot.memory["scramble"][trigger.channel].word
|
+ bot.memory["scramble"][trigger.channel].word
|
||||||
|
|
153
modules/sed.py
153
modules/sed.py
|
@ -8,135 +8,96 @@ using the sed notation (s///) commonly found in vi/vim.
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from module import hook
|
from module import hook
|
||||||
from tools import FulviaMemory
|
|
||||||
|
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
bot.memory['find_lines'] = FulviaMemory()
|
bot.memory['sed_lines'] = {}
|
||||||
|
|
||||||
|
|
||||||
@hook(True)
|
@hook(True)
|
||||||
def collectlines(bot, trigger):
|
def collectlines(bot, trigger):
|
||||||
"""Create a temporary log of what people say"""
|
"""Create a temporary log of what people say"""
|
||||||
|
|
||||||
# Don't log things in PM
|
|
||||||
if trigger.is_privmsg:
|
if trigger.is_privmsg:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Add a log for the channel and nick, if there isn't already one
|
if trigger.channel not in bot.memory['sed_lines']:
|
||||||
if trigger.channel not in bot.memory['find_lines']:
|
bot.memory['sed_lines'][trigger.channel] = {}
|
||||||
bot.memory['find_lines'][trigger.channel] = FulviaMemory()
|
if trigger.nick not in bot.memory['sed_lines'][trigger.channel]:
|
||||||
if trigger.nick not in bot.memory['find_lines'][trigger.channel]:
|
bot.memory['sed_lines'][trigger.channel][trigger.nick] = []
|
||||||
bot.memory['find_lines'][trigger.channel][trigger.nick] = list()
|
|
||||||
|
|
||||||
# Create a temporary list of the user's lines in a channel
|
templist = bot.memory['sed_lines'][trigger.channel][trigger.nick]
|
||||||
templist = bot.memory['find_lines'][trigger.channel][trigger.nick]
|
line = ' '.join(trigger.args)
|
||||||
line = trigger.group()
|
|
||||||
if line.startswith("s/"): # Don't remember substitutions
|
if line.startswith("s/"): # Don't remember substitutions
|
||||||
return
|
return
|
||||||
elif line.startswith("\x01ACTION"): # For /me messages
|
templist.append(line)
|
||||||
line = line[:-1]
|
|
||||||
templist.append(line)
|
|
||||||
else:
|
|
||||||
templist.append(line)
|
|
||||||
|
|
||||||
del templist[:-10] # Keep the log to 10 lines per person
|
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)
|
@hook(True)
|
||||||
def findandreplace(bot, trigger):
|
def findandreplace(bot, trigger):
|
||||||
# Don't bother in PM
|
|
||||||
if trigger.is_privmsg:
|
if trigger.is_privmsg:
|
||||||
return
|
return
|
||||||
|
if not trigger.args[0].startswith('s') and trigger.args[0][-1] not in ':,':
|
||||||
rule = re.compile(r"(\S+)?(?:[:,]\s|^)s\/((?:\\\/|[^/])+)\/((?:\\\/|[^/])*"\
|
|
||||||
+ r")(?:\/(\S+))?")
|
|
||||||
group = rule.search(trigger.group(0))
|
|
||||||
if not group:
|
|
||||||
return
|
return
|
||||||
g = (trigger.group(0),) + group.groups()
|
line = ' '.join(trigger.args)
|
||||||
trigger.set_group(g)
|
if 's/' not in line:
|
||||||
|
|
||||||
# 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]:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
#TODO rest[0] is find, rest[1] is replace. These should be made variables of
|
items = []
|
||||||
#their own at some point.
|
line = line[line.index('s/')+2:]
|
||||||
rest = [trigger.group(2), trigger.group(3)]
|
i = 0
|
||||||
rest[0] = rest[0].replace(r'\/', '/')
|
while True:
|
||||||
rest[1] = rest[1].replace(r'\/', '/')
|
i = line.find('/', i)
|
||||||
me = False # /me command
|
if i == -1:
|
||||||
flags = (trigger.group(4) or '')
|
break
|
||||||
print(flags)
|
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:
|
if 'g' in flags:
|
||||||
count = 0
|
count = 0
|
||||||
else:
|
else:
|
||||||
count = 1
|
count = 1
|
||||||
|
|
||||||
# repl is a lambda function which performs the substitution. i flag turns
|
try:
|
||||||
# off case sensitivity. re.U turns on unicode replacement.
|
if 'i' in flags:
|
||||||
if 'i' in flags:
|
regex = re.compile(find, re.I)
|
||||||
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:]
|
|
||||||
else:
|
else:
|
||||||
me = False
|
regex = re.compile(find)
|
||||||
new_phrase = repl(line)
|
except re.error:
|
||||||
if new_phrase != line: # we are done
|
return
|
||||||
break
|
|
||||||
|
|
||||||
if not new_phrase or new_phrase == line:
|
if not trigger.args[0].startswith('s'):
|
||||||
return # Didn't find anything
|
nick = trigger.args[0][:-1]
|
||||||
|
if nick not in bot.memory['sed_lines'][trigger.channel]:
|
||||||
# Save the new "edited" message.
|
return
|
||||||
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}"
|
|
||||||
else:
|
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)
|
||||||
|
|
|
@ -65,7 +65,7 @@ def seen(bot, trigger):
|
||||||
-m, --message - includes the first/last message the user sent.
|
-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.
|
-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?")
|
return bot.reply("Seen who?")
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
@ -74,7 +74,7 @@ def seen(bot, trigger):
|
||||||
parser.add_argument("-f", "--first", action="store_true")
|
parser.add_argument("-f", "--first", action="store_true")
|
||||||
parser.add_argument("-m", "--message", action="store_true")
|
parser.add_argument("-m", "--message", action="store_true")
|
||||||
parser.add_argument("-c", "--context", 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:
|
if args.nick == bot.nick:
|
||||||
return bot.reply("I'm right here!")
|
return bot.reply("I'm right here!")
|
||||||
|
@ -142,9 +142,9 @@ def dump_seen_db(bot):
|
||||||
@require_chanmsg
|
@require_chanmsg
|
||||||
def seen_hook(bot, trigger):
|
def seen_hook(bot, trigger):
|
||||||
bot.memory["seen_lock"].acquire()
|
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"]:
|
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:
|
else:
|
||||||
first = bot.memory["seen"][trigger.nick][:3]
|
first = bot.memory["seen"][trigger.nick][:3]
|
||||||
seen = first + last
|
seen = first + last
|
||||||
|
|
|
@ -37,7 +37,7 @@ def slur(bot, trigger):
|
||||||
parser.add_argument("-r", "--race", type=str, nargs='+')
|
parser.add_argument("-r", "--race", type=str, nargs='+')
|
||||||
parser.add_argument("-s", "--slur", type=str)
|
parser.add_argument("-s", "--slur", type=str)
|
||||||
parser.add_argument("-l", "--list", action="store_true")
|
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:
|
if args.list:
|
||||||
races = bot.db.execute("SELECT DISTINCT race FROM slur").fetchall()
|
races = bot.db.execute("SELECT DISTINCT race FROM slur").fetchall()
|
||||||
|
|
|
@ -13,9 +13,9 @@ def spellcheck(bot, trigger):
|
||||||
Says whether the given word is spelled correctly, and gives suggestions if
|
Says whether the given word is spelled correctly, and gives suggestions if
|
||||||
it's not.
|
it's not.
|
||||||
"""
|
"""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.reply("What word?")
|
return bot.reply("What word?")
|
||||||
word = trigger.group(2)
|
word = trigger.args[1]
|
||||||
if " " in word:
|
if " " in word:
|
||||||
return bot.msg("One word at a time, please")
|
return bot.msg("One word at a time, please")
|
||||||
dictionary = enchant.Dict("en_US")
|
dictionary = enchant.Dict("en_US")
|
||||||
|
|
|
@ -67,12 +67,14 @@ def setup(bot):
|
||||||
@example('.tell iou1name you broke something again.')
|
@example('.tell iou1name you broke something again.')
|
||||||
def tell(bot, trigger):
|
def tell(bot, trigger):
|
||||||
"""Give someone a message the next time they're seen"""
|
"""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?")
|
return bot.reply("Tell whom?")
|
||||||
|
if len(trigger.args) < 3:
|
||||||
|
return bot.reply("Tell them what?")
|
||||||
|
|
||||||
teller = trigger.nick
|
teller = trigger.nick
|
||||||
tellee = trigger.group(3).rstrip('.,:;')
|
tellee = trigger.args[1].rstrip('.,:;')
|
||||||
message = trigger.group(2).replace(tellee, "", 1).strip()
|
message = ' '.join(trigger.args[2:])
|
||||||
|
|
||||||
if not message:
|
if not message:
|
||||||
return bot.reply(f"Tell {tellee} what?")
|
return bot.reply(f"Tell {tellee} what?")
|
||||||
|
|
|
@ -13,11 +13,9 @@ URI = 'https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains'
|
||||||
@example('.tld me')
|
@example('.tld me')
|
||||||
def gettld(bot, trigger):
|
def gettld(bot, trigger):
|
||||||
"""Show information about the given Top Level Domain."""
|
"""Show information about the given Top Level Domain."""
|
||||||
word = trigger.group(2).strip()
|
if len(trigger.args) < 2:
|
||||||
if not word:
|
|
||||||
return bot.reply("What TLD?")
|
return bot.reply("What TLD?")
|
||||||
if " " in word:
|
word = trigger.args[1]
|
||||||
return bot.reply("One TLD at a time.")
|
|
||||||
if not word.startswith("."):
|
if not word.startswith("."):
|
||||||
word = "." + word
|
word = "." + word
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,9 @@ def addTopic(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Adds the specified topic to the topic database.
|
Adds the specified topic to the topic database.
|
||||||
"""
|
"""
|
||||||
topic = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
if not topic:
|
|
||||||
return bot.msg("Please be providing a topic sir.")
|
return bot.msg("Please be providing a topic sir.")
|
||||||
|
topic = trigger.args[1]
|
||||||
bot.memory['topic_lock'].acquire()
|
bot.memory['topic_lock'].acquire()
|
||||||
try:
|
try:
|
||||||
bot.db.execute("INSERT INTO topic (topic, added_by) VALUES(?,?)",
|
bot.db.execute("INSERT INTO topic (topic, added_by) VALUES(?,?)",
|
||||||
|
|
|
@ -42,14 +42,14 @@ def tr2(bot, trigger):
|
||||||
-i LANG, --inlang LANG - specifies the assumed input language.
|
-i LANG, --inlang LANG - specifies the assumed input language.
|
||||||
-o LANG, --outlang LANG - specifies the desired output 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?")
|
return bot.reply("Translate what?")
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("text", nargs=argparse.REMAINDER)
|
parser.add_argument("text", nargs=argparse.REMAINDER)
|
||||||
parser.add_argument("-i", "--inlang", default="auto")
|
parser.add_argument("-i", "--inlang", default="auto")
|
||||||
parser.add_argument("-o", "--outlang", default="en")
|
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)
|
args.text = " ".join(args.text)
|
||||||
|
|
||||||
tr_text, in_lang = translate(args.text, in_lang=args.inlang,
|
tr_text, in_lang = translate(args.text, in_lang=args.inlang,
|
||||||
|
@ -60,9 +60,9 @@ def tr2(bot, trigger):
|
||||||
@commands('mangle')
|
@commands('mangle')
|
||||||
def mangle(bot, trigger):
|
def mangle(bot, trigger):
|
||||||
"""Repeatedly translate the input until it makes absolutely no sense."""
|
"""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?")
|
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',
|
long_lang_list = ['fr', 'de', 'es', 'it', 'no', 'he', 'la', 'ja', 'cy',
|
||||||
'ar', 'yi', 'zh', 'nl', 'ru', 'fi', 'hi', 'af', 'jw', 'mr', 'ceb',
|
'ar', 'yi', 'zh', 'nl', 'ru', 'fi', 'hi', 'af', 'jw', 'mr', 'ceb',
|
||||||
|
|
|
@ -11,9 +11,9 @@ from module import commands, example
|
||||||
@example('.u 203D', 'U+203D INTERROBANG (‽)')
|
@example('.u 203D', 'U+203D INTERROBANG (‽)')
|
||||||
def codepoint(bot, trigger):
|
def codepoint(bot, trigger):
|
||||||
"""Looks up unicode information."""
|
"""Looks up unicode information."""
|
||||||
arg = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
if not arg:
|
|
||||||
return bot.reply('What code point do you want me to look up?')
|
return bot.reply('What code point do you want me to look up?')
|
||||||
|
arg = ' '.join(trigger.args[1])
|
||||||
stripped = arg.strip()
|
stripped = arg.strip()
|
||||||
if len(stripped) > 0:
|
if len(stripped) > 0:
|
||||||
arg = stripped
|
arg = stripped
|
||||||
|
|
|
@ -43,7 +43,7 @@ def temperature(bot, trigger):
|
||||||
Convert temperatures
|
Convert temperatures
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
source = find_temp.match(trigger.group(2)).groups()
|
source = find_temp.match(' '.join(trigger.args[1:])).groups()
|
||||||
except (AttributeError, TypeError):
|
except (AttributeError, TypeError):
|
||||||
return bot.reply("That's not a valid temperature.")
|
return bot.reply("That's not a valid temperature.")
|
||||||
unit = source[1].upper()
|
unit = source[1].upper()
|
||||||
|
@ -77,7 +77,7 @@ def distance(bot, trigger):
|
||||||
Convert distances
|
Convert distances
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
source = find_length.match(trigger.group(2)).groups()
|
source = find_length.match(' '.join(trigger.args[1:])).groups()
|
||||||
except (AttributeError, TypeError):
|
except (AttributeError, TypeError):
|
||||||
return bot.reply("That's not a valid length unit.")
|
return bot.reply("That's not a valid length unit.")
|
||||||
unit = source[1].lower()
|
unit = source[1].lower()
|
||||||
|
@ -151,7 +151,7 @@ def mass(bot, trigger):
|
||||||
Convert mass
|
Convert mass
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
source = find_mass.match(trigger.group(2)).groups()
|
source = find_mass.match(' '.join(trigger.args[1:])).groups()
|
||||||
except (AttributeError, TypeError):
|
except (AttributeError, TypeError):
|
||||||
return bot.reply("That's not a valid mass unit.")
|
return bot.reply("That's not a valid mass unit.")
|
||||||
unit = source[1].lower()
|
unit = source[1].lower()
|
||||||
|
|
|
@ -27,12 +27,12 @@ def uptime(bot, trigger):
|
||||||
@commands('updick')
|
@commands('updick')
|
||||||
def updick(bot, trigger):
|
def updick(bot, trigger):
|
||||||
""".updick - Returns the uptime of Fulvia, measured in dicks."""
|
""".updick - Returns the uptime of Fulvia, measured in dicks."""
|
||||||
if trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
if trigger.group(2) in bot.users:
|
if trigger.args[1] in bot.users:
|
||||||
d = defer.Deferred()
|
d = defer.Deferred()
|
||||||
d.addCallback(idleTime, bot)
|
d.addCallback(idleTime, bot)
|
||||||
bot.memory["idle_callbacks"][trigger.group(2)] = d
|
bot.memory["idle_callbacks"][trigger.args[1]] = d
|
||||||
bot.whois(trigger.group(2))
|
bot.whois(trigger.args[1])
|
||||||
else:
|
else:
|
||||||
delta = datetime.datetime.now() - bot.memory["uptime"]
|
delta = datetime.datetime.now() - bot.memory["uptime"]
|
||||||
bot.msg("8" + "="*delta.days + "D")
|
bot.msg("8" + "="*delta.days + "D")
|
||||||
|
@ -41,12 +41,12 @@ def updick(bot, trigger):
|
||||||
@commands('upwulf')
|
@commands('upwulf')
|
||||||
def upwulf(bot, trigger):
|
def upwulf(bot, trigger):
|
||||||
""".upwulf - Returns the uptime of Fulvia, measured in Adalwulfs."""
|
""".upwulf - Returns the uptime of Fulvia, measured in Adalwulfs."""
|
||||||
if trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
if trigger.group(2) in bot.users:
|
if trigger.args[1] in bot.users:
|
||||||
d = defer.Deferred()
|
d = defer.Deferred()
|
||||||
d.addCallback(idleTimeWulf, bot)
|
d.addCallback(idleTime, bot)
|
||||||
bot.memory["idle_callbacks"][trigger.group(2)] = d
|
bot.memory["idle_callbacks"][trigger.args[1]] = d
|
||||||
bot.whois(trigger.group(2))
|
bot.whois(trigger.args[1])
|
||||||
else:
|
else:
|
||||||
delta = datetime.datetime.now() - bot.memory["uptime"]
|
delta = datetime.datetime.now() - bot.memory["uptime"]
|
||||||
bot.msg("Adalwulf" + "_"*delta.days)
|
bot.msg("Adalwulf" + "_"*delta.days)
|
||||||
|
@ -75,7 +75,9 @@ def idleTimeWulf(result, bot):
|
||||||
@commands('unix')
|
@commands('unix')
|
||||||
def unixtolocal(bot, trigger):
|
def unixtolocal(bot, trigger):
|
||||||
"""Converts the given timestamp from unix time to local time."""
|
"""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 = datetime.datetime.utcfromtimestamp(unix)
|
||||||
dt = dt.replace(tzinfo=datetime.timezone.utc)
|
dt = dt.replace(tzinfo=datetime.timezone.utc)
|
||||||
bot.msg(dt.astimezone(tz=None).strftime('%Y-%m-%d %H:%M:%S'))
|
bot.msg(dt.astimezone(tz=None).strftime('%Y-%m-%d %H:%M:%S'))
|
||||||
|
|
|
@ -36,11 +36,11 @@ def title_auto(bot, trigger):
|
||||||
Automatically show titles for URLs. For shortened URLs/redirects, find
|
Automatically show titles for URLs. For shortened URLs/redirects, find
|
||||||
where the URL redirects to and show the title for that.
|
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
|
return
|
||||||
url_finder = re.compile(r"((?:http|https)(?::\/\/\S+))", re.IGNORECASE)
|
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:
|
if len(urls) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -85,10 +85,10 @@ def watch(bot, trigger):
|
||||||
"""
|
"""
|
||||||
A thread watcher for 4chan.
|
A thread watcher for 4chan.
|
||||||
"""
|
"""
|
||||||
url = trigger.group(3)
|
if len(trigger.args) < 2:
|
||||||
name = trigger.group(4)
|
boy.reply("What thread?")
|
||||||
if not name:
|
url = trigger.args[1]
|
||||||
name = "Anonymous"
|
name = trigger.args[2] if len(trigger.args) >= 3 else "Anonymous"
|
||||||
|
|
||||||
if url in bot.memory["watcher"].keys():
|
if url in bot.memory["watcher"].keys():
|
||||||
return bot.msg("Error: I'm already watching that thread.")
|
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.
|
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:
|
try:
|
||||||
bot.memory["watcher"][url].stop.set()
|
bot.memory["watcher"][url].stop.set()
|
||||||
bot.memory["watcher"].pop(url)
|
bot.memory["watcher"].pop(url)
|
||||||
|
|
|
@ -17,11 +17,13 @@ def weather(bot, trigger):
|
||||||
|
|
||||||
-m, --metric - uses metric units instead of imperial.
|
-m, --metric - uses metric units instead of imperial.
|
||||||
"""
|
"""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.reply("Weather where?")
|
return bot.reply("Weather where?")
|
||||||
location = trigger.group(3)
|
location = trigger.args[1]
|
||||||
if location == '-m' or location == '--metric':
|
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'
|
units = 'metric'
|
||||||
else:
|
else:
|
||||||
units = 'imperial'
|
units = 'imperial'
|
||||||
|
|
|
@ -74,10 +74,10 @@ def wiki_info(bot, url):
|
||||||
@example('.wiki San Francisco')
|
@example('.wiki San Francisco')
|
||||||
def wikipedia(bot, trigger):
|
def wikipedia(bot, trigger):
|
||||||
"""Search wikipedia and return a snippet of the results."""
|
"""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?")
|
return bot.reply("What do you want me to look up?")
|
||||||
|
|
||||||
query = trigger.group(2)
|
query = ' '.join(trigger.args[1:])
|
||||||
if not query:
|
if not query:
|
||||||
return bot.reply("What do you want me to look up?")
|
return bot.reply("What do you want me to look up?")
|
||||||
|
|
||||||
|
|
|
@ -76,9 +76,9 @@ def format(result, definitions, number=2):
|
||||||
@example('.dict bailiwick')
|
@example('.dict bailiwick')
|
||||||
def wiktionary(bot, trigger):
|
def wiktionary(bot, trigger):
|
||||||
"""Look up a word on Wiktionary."""
|
"""Look up a word on Wiktionary."""
|
||||||
word = trigger.group(2)
|
if len(trigger.args) < 2:
|
||||||
if word is None:
|
|
||||||
return bot.reply('You must tell me what to look up!')
|
return bot.reply('You must tell me what to look up!')
|
||||||
|
word = trigger.args[1]
|
||||||
|
|
||||||
_, definitions = wikt(word)
|
_, definitions = wikt(word)
|
||||||
if not definitions:
|
if not definitions:
|
||||||
|
|
|
@ -8,7 +8,7 @@ from module import commands, example
|
||||||
@example('.willilike Banished Quest')
|
@example('.willilike Banished Quest')
|
||||||
def willilike(bot, trigger):
|
def willilike(bot, trigger):
|
||||||
"""An advanced AI that will determine if you like something."""
|
"""An advanced AI that will determine if you like something."""
|
||||||
if trigger.group(2):
|
if len(trigger.args) >= 2:
|
||||||
bot.reply("No.")
|
bot.reply("No.")
|
||||||
|
|
||||||
@commands('upvote')
|
@commands('upvote')
|
||||||
|
|
|
@ -15,11 +15,11 @@ def wa_command(bot, trigger):
|
||||||
"""
|
"""
|
||||||
Queries WolframAlpha.
|
Queries WolframAlpha.
|
||||||
"""
|
"""
|
||||||
if not trigger.group(2):
|
if len(trigger.args) < 2:
|
||||||
return bot.reply("You must provide a query.")
|
return bot.reply("You must provide a query.")
|
||||||
if not config.wolfram_app_id:
|
if not config.wolfram_app_id:
|
||||||
bot.reply("Wolfram|Alpha API app ID not configured.")
|
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
|
app_id = config.wolfram_app_id
|
||||||
units = config.wolfram_units
|
units = config.wolfram_units
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,9 @@ def xkcd(bot, trigger):
|
||||||
"""
|
"""
|
||||||
latest = get_info()
|
latest = get_info()
|
||||||
max_int = latest['num']
|
max_int = latest['num']
|
||||||
if trigger.group(2):
|
if len(trigger.args) >= 2:
|
||||||
try:
|
try:
|
||||||
num = int(trigger.group(2))
|
num = int(trigger.args[1])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return bot.reply("Invalid input.")
|
return bot.reply("Invalid input.")
|
||||||
num = validate_num(num, max_int)
|
num = validate_num(num, max_int)
|
||||||
|
|
110
trigger.py
110
trigger.py
|
@ -2,8 +2,6 @@
|
||||||
"""
|
"""
|
||||||
The trigger abstraction layer.
|
The trigger abstraction layer.
|
||||||
"""
|
"""
|
||||||
import datetime
|
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
|
||||||
def split_user(user):
|
def split_user(user):
|
||||||
|
@ -18,75 +16,14 @@ def split_user(user):
|
||||||
return nick, ident, host
|
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():
|
class Trigger():
|
||||||
def __init__(self, user, channel, message, event):
|
def __init__(self, user, channel, message):
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
"""
|
"""
|
||||||
The channel from which the message was sent.
|
The channel from which the message was sent.
|
||||||
In a private message, this is the nick that sent the message.
|
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("#")
|
self.is_privmsg = not channel.startswith("#")
|
||||||
"""True if the trigger is from a user, False if it's from a channel."""
|
"""True if the trigger is from a user, False if it's from a channel."""
|
||||||
|
|
||||||
|
@ -107,50 +44,15 @@ class Trigger():
|
||||||
self.host = host
|
self.host = host
|
||||||
"""The hostname of the person who sent the message"""
|
"""The hostname of the person who sent the message"""
|
||||||
|
|
||||||
self.event = event
|
self.args = message.strip().split(' ')
|
||||||
"""
|
"""Pseudo-ARGV for a bot command."""
|
||||||
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')``
|
|
||||||
"""
|
|
||||||
|
|
||||||
admins = config.admins + [config.owner]
|
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.
|
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."""
|
"""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)
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user