2019-05-25 20:40:06 +00:00
|
|
|
#--depends-on commands
|
|
|
|
#--depends-on config
|
|
|
|
|
2019-06-26 13:37:26 +00:00
|
|
|
import random, re, time
|
2019-05-03 15:40:12 +00:00
|
|
|
from src import EventManager, ModuleManager, utils
|
2018-08-31 03:14:56 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
DUCK = "・゜゜・。。・゜゜\_o< QUACK!"
|
|
|
|
NO_DUCK = "There was no duck!"
|
2018-09-08 15:15:43 +00:00
|
|
|
|
2019-05-11 17:26:53 +00:00
|
|
|
DEFAULT_MIN_MESSAGES = 100
|
2019-05-11 16:19:31 +00:00
|
|
|
|
2019-06-28 22:16:05 +00:00
|
|
|
@utils.export("channelset", utils.BoolSetting("ducks-enabled",
|
|
|
|
"Whether or not to spawn ducks"))
|
|
|
|
@utils.export("channelset", utils.IntSetting("ducks-min-messages",
|
|
|
|
"Minimum messages between ducks spawning", example="50"))
|
|
|
|
@utils.export("channelset", utils.BoolSetting("ducks-kick",
|
|
|
|
"Whether or not to kick someone talking to non-existent ducks"))
|
2018-10-12 17:07:23 +00:00
|
|
|
class Module(ModuleManager.BaseModule):
|
2018-10-03 12:22:37 +00:00
|
|
|
@utils.hook("new.channel")
|
2018-09-08 21:01:47 +00:00
|
|
|
def new_channel(self, event):
|
2019-05-03 14:42:39 +00:00
|
|
|
self.bootstrap_channel(event["channel"])
|
|
|
|
|
|
|
|
def bootstrap_channel(self, channel):
|
2019-05-03 14:44:13 +00:00
|
|
|
if not hasattr(channel, "duck_active"):
|
2019-06-08 11:10:27 +00:00
|
|
|
channel.duck_active = None
|
2019-05-03 14:44:13 +00:00
|
|
|
channel.duck_lines = 0
|
2018-09-09 07:59:36 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
def _activity(self, channel):
|
2019-05-03 14:42:39 +00:00
|
|
|
self.bootstrap_channel(channel)
|
|
|
|
|
2018-09-08 15:15:43 +00:00
|
|
|
ducks_enabled = channel.get_setting("ducks-enabled", False)
|
2019-05-03 14:42:39 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
if ducks_enabled and not channel.duck_active:
|
|
|
|
channel.duck_lines += 1
|
2019-05-11 16:19:31 +00:00
|
|
|
min_lines = channel.get_setting("ducks-min-messages",
|
|
|
|
DEFAULT_MIN_MESSAGES)
|
2018-08-31 03:14:56 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
if channel.duck_lines >= min_lines:
|
2019-05-03 15:47:56 +00:00
|
|
|
show_duck = random.SystemRandom().randint(1, 20) == 1
|
2018-08-31 17:23:46 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
if show_duck:
|
|
|
|
self._trigger_duck(channel)
|
2018-08-31 17:23:46 +00:00
|
|
|
|
2019-06-26 13:37:26 +00:00
|
|
|
@utils.hook("command.regex")
|
|
|
|
@utils.kwarg("expect_output", False)
|
|
|
|
@utils.kwarg("ignore_action", False)
|
|
|
|
@utils.kwarg("command", "duck-trigger")
|
2019-07-01 21:50:58 +00:00
|
|
|
@utils.kwarg("pattern", re.compile(".+"))
|
2018-09-08 15:15:43 +00:00
|
|
|
def channel_message(self, event):
|
2019-06-05 13:18:41 +00:00
|
|
|
self._activity(event["target"])
|
2018-09-08 15:15:43 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
def _trigger_duck(self, channel):
|
2019-05-15 15:48:20 +00:00
|
|
|
channel.duck_lines = 0
|
2019-06-08 11:10:27 +00:00
|
|
|
channel.duck_active = time.time()
|
2019-05-03 14:34:54 +00:00
|
|
|
channel.send_message(DUCK)
|
2018-08-31 05:27:41 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
def _duck_action(self, channel, user, action, setting):
|
2019-06-08 11:10:27 +00:00
|
|
|
duck_timestamp = channel.duck_active
|
|
|
|
channel.duck_active = None
|
2018-08-31 13:36:25 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
user_id = user.get_id()
|
|
|
|
action_count = channel.get_user_setting(user_id, setting, 0)
|
|
|
|
action_count += 1
|
|
|
|
channel.set_user_setting(user_id, setting, action_count)
|
2018-08-31 04:48:53 +00:00
|
|
|
|
2019-06-08 11:10:27 +00:00
|
|
|
seconds = round(time.time()-duck_timestamp, 2)
|
|
|
|
|
2019-06-12 21:57:04 +00:00
|
|
|
ducks_plural = "duck" if action_count == 1 else "ducks"
|
2019-06-12 21:36:26 +00:00
|
|
|
|
|
|
|
return "%s %s a duck in %s seconds! You've %s %d %s in %s!" % (
|
|
|
|
user.nickname, action, seconds, action, action_count, ducks_plural,
|
|
|
|
channel.name)
|
2018-08-31 03:14:56 +00:00
|
|
|
|
2019-06-05 14:37:58 +00:00
|
|
|
def _no_duck(self, channel, user, stderr):
|
2019-05-03 14:34:54 +00:00
|
|
|
if channel.get_setting("ducks-kick"):
|
|
|
|
channel.send_kick(user.nickname, NO_DUCK)
|
2018-09-08 15:15:43 +00:00
|
|
|
else:
|
2019-06-19 09:22:46 +00:00
|
|
|
stderr.write("%s: %s" % (user.nickname, NO_DUCK))
|
2018-08-31 03:14:56 +00:00
|
|
|
|
2019-05-03 14:34:54 +00:00
|
|
|
@utils.hook("received.command.bef", alias_of="befriend")
|
|
|
|
@utils.hook("received.command.befriend", channel_only=True)
|
2018-09-08 15:15:43 +00:00
|
|
|
def befriend(self, event):
|
2019-06-10 15:41:32 +00:00
|
|
|
"""
|
|
|
|
:help: Befriend a duck
|
|
|
|
"""
|
2019-05-03 14:34:54 +00:00
|
|
|
if event["target"].duck_active:
|
2019-06-14 16:11:44 +00:00
|
|
|
action = self._duck_action(event["target"], event["user"],
|
|
|
|
"befriended", "ducks-befriended")
|
2019-05-03 14:34:54 +00:00
|
|
|
event["stdout"].write(action)
|
|
|
|
else:
|
2019-06-05 14:37:58 +00:00
|
|
|
self._no_duck(event["target"], event["user"], event["stderr"])
|
2019-05-03 14:34:54 +00:00
|
|
|
|
2019-06-05 14:37:58 +00:00
|
|
|
@utils.hook("received.command.trap", channel_only=True)
|
|
|
|
def trap(self, event):
|
2019-06-10 15:41:32 +00:00
|
|
|
"""
|
|
|
|
:help: Trap a duck
|
|
|
|
"""
|
2019-05-03 14:34:54 +00:00
|
|
|
if event["target"].duck_active:
|
2019-06-14 16:11:36 +00:00
|
|
|
action = self._duck_action(event["target"], event["user"],
|
|
|
|
"trapped", "ducks-shot")
|
2019-05-03 14:34:54 +00:00
|
|
|
event["stdout"].write(action)
|
|
|
|
else:
|
2019-06-05 14:37:58 +00:00
|
|
|
self._no_duck(event["target"], event["user"], event["stderr"])
|
2018-09-08 15:15:43 +00:00
|
|
|
|
2019-05-03 15:34:41 +00:00
|
|
|
@utils.hook("received.command.friends")
|
|
|
|
def friends(self, event):
|
2019-06-10 15:41:32 +00:00
|
|
|
"""
|
|
|
|
:help: Show top 10 duck friends
|
|
|
|
:usage: [channel]
|
|
|
|
"""
|
2019-05-03 15:34:41 +00:00
|
|
|
stats = self._duck_stats(event["server"], "ducks-befriended", "friends",
|
|
|
|
event["args_split"][0] if event["args"] else None)
|
|
|
|
event["stdout"].write(stats)
|
|
|
|
@utils.hook("received.command.enemies")
|
|
|
|
def enemies(self, event):
|
2019-06-10 15:41:32 +00:00
|
|
|
"""
|
|
|
|
:help: Show top 10 duck enemies
|
|
|
|
:usage: [channel]
|
|
|
|
"""
|
2019-05-03 15:34:41 +00:00
|
|
|
stats = self._duck_stats(event["server"], "ducks-shot", "enemies",
|
|
|
|
event["args_split"][0] if event["args"] else None)
|
|
|
|
event["stdout"].write(stats)
|
|
|
|
|
|
|
|
def _duck_stats(self, server, setting, description, channel_query):
|
|
|
|
channel_query_str = ""
|
|
|
|
if not channel_query == None:
|
|
|
|
channel_query = server.irc_lower(channel_query)
|
|
|
|
channel_query_str = " in %s" % channel_query
|
|
|
|
|
|
|
|
stats = server.find_all_user_channel_settings(setting)
|
|
|
|
|
|
|
|
user_stats = {}
|
|
|
|
for channel, nickname, value in stats:
|
|
|
|
if not channel_query or channel_query == channel:
|
|
|
|
if not nickname in user_stats:
|
|
|
|
user_stats[nickname] = 0
|
|
|
|
user_stats[nickname] += value
|
|
|
|
|
2019-05-04 22:28:51 +00:00
|
|
|
top_10 = utils.top_10(user_stats,
|
|
|
|
convert_key=lambda nickname: server.get_user(nickname).nickname)
|
2019-05-03 15:34:41 +00:00
|
|
|
return "Top duck %s%s: %s" % (description, channel_query_str,
|
|
|
|
", ".join(top_10))
|
|
|
|
|