2020-11-04 22:46:09 +01:00
|
|
|
import random
|
|
|
|
|
2022-03-06 17:22:54 +01:00
|
|
|
from irc.client import NickMask
|
|
|
|
|
2020-11-04 22:46:09 +01:00
|
|
|
from edmond.plugin import Plugin
|
|
|
|
from edmond.utils import proc
|
|
|
|
|
|
|
|
|
|
|
|
class MiscReactionsPlugin(Plugin):
|
|
|
|
"""This plugin implements various reactions to the last message posted.
|
|
|
|
|
|
|
|
Enable reactions you want by setting the IDs from REACTIONS in the reactions
|
|
|
|
field on the plugin configuration. As all reactions are optional,
|
|
|
|
configurations for each reactions are optional as well and can be safely
|
|
|
|
removed from the configuration (as usual except fields in REQUIRED_CONFIGS).
|
2020-11-05 23:52:02 +01:00
|
|
|
|
|
|
|
The types of reactions can appear with a different probability if the
|
|
|
|
configured reaction has a suffix of ":n", n being a number defining the
|
|
|
|
reaction weight. The default weight when no suffix is used is 1.
|
2020-11-04 22:46:09 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
REQUIRED_CONFIGS = ["reactions", "rate"]
|
|
|
|
|
|
|
|
REACTIONS = set([
|
|
|
|
"sentence",
|
|
|
|
"stop",
|
|
|
|
"king",
|
|
|
|
"mmm",
|
|
|
|
"ooo",
|
|
|
|
"detector",
|
|
|
|
"repeat_letters",
|
2022-03-06 17:22:54 +01:00
|
|
|
"nudge",
|
2020-11-04 22:46:09 +01:00
|
|
|
])
|
|
|
|
|
|
|
|
def __init__(self, bot):
|
|
|
|
super().__init__(bot)
|
|
|
|
self.priority = -10
|
2020-11-06 11:43:07 +01:00
|
|
|
self.reactions = []
|
|
|
|
self.weights = []
|
|
|
|
|
|
|
|
def on_welcome(self, event):
|
2020-11-05 23:52:02 +01:00
|
|
|
self.reactions, self.weights = self.get_reactions()
|
2020-11-04 22:46:09 +01:00
|
|
|
|
|
|
|
def get_reactions(self):
|
2020-11-05 23:52:02 +01:00
|
|
|
"""Get configured reactions in a method list, maybe with weights."""
|
|
|
|
reactions = []
|
|
|
|
weights = []
|
|
|
|
for reaction in self.config["reactions"]:
|
|
|
|
weight = 1
|
|
|
|
if ":" in reaction:
|
|
|
|
reaction, weight_str = reaction.split(":", maxsplit=1)
|
|
|
|
try:
|
|
|
|
weight = int(weight_str)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
if reaction not in self.REACTIONS:
|
|
|
|
continue
|
|
|
|
reactions.append(getattr(self, f"react_with_{reaction}"))
|
|
|
|
weights.append(weight)
|
2020-11-06 12:38:07 +01:00
|
|
|
# Normalize weights.
|
|
|
|
total_weight = sum(weights)
|
|
|
|
weights = list(map(lambda w: w / total_weight, weights))
|
2020-11-08 16:48:13 +01:00
|
|
|
self.bot.log_d(f"Reactions: {[r.__name__ for r in reactions]}")
|
2020-11-06 12:38:07 +01:00
|
|
|
self.bot.log_d(f"Reaction weights: {weights}")
|
2020-11-05 23:52:02 +01:00
|
|
|
return reactions, weights
|
2020-11-04 22:46:09 +01:00
|
|
|
|
|
|
|
def on_pubmsg(self, event):
|
2021-07-03 01:36:18 +02:00
|
|
|
if not self.respects_handling_conditions():
|
|
|
|
return False
|
2020-11-04 22:46:09 +01:00
|
|
|
if proc(self.config["rate"]):
|
2020-11-09 15:09:29 +01:00
|
|
|
self.bot.log_d("Proc random reaction.")
|
2020-11-06 12:24:28 +01:00
|
|
|
self.react(event)
|
2020-11-05 23:52:02 +01:00
|
|
|
return True
|
|
|
|
return False
|
2020-11-04 22:46:09 +01:00
|
|
|
|
2020-11-06 12:24:28 +01:00
|
|
|
def react(self, event):
|
|
|
|
if self.weights:
|
|
|
|
method = random.choices(self.reactions, self.weights)[0]
|
|
|
|
else:
|
|
|
|
method = random.choice(self.reactions)
|
2020-11-09 15:09:29 +01:00
|
|
|
self.bot.log_d(f"Using reaction {method.__name__}.")
|
2020-11-06 12:24:28 +01:00
|
|
|
method(event)
|
|
|
|
|
2020-11-04 22:46:09 +01:00
|
|
|
def react_with_sentence(self, event):
|
|
|
|
"""React with a random sentence from config list."""
|
|
|
|
sentences = self.config.get("sentences")
|
|
|
|
if not sentences:
|
|
|
|
return
|
|
|
|
self.bot.say(event.target, random.choice(sentences))
|
|
|
|
|
|
|
|
def react_with_stop(self, event):
|
|
|
|
"""Threaten someone that it did its last... (insert last word here)."""
|
|
|
|
stop_message = self.config.get("stop_message")
|
|
|
|
if not stop_message:
|
|
|
|
return
|
|
|
|
words = event.arguments[0].split()
|
|
|
|
if len(words) == 0:
|
|
|
|
return
|
|
|
|
self.bot.say(event.target, stop_message.format(subject=words[-1]))
|
|
|
|
|
|
|
|
def react_with_king(self, event):
|
|
|
|
"""Tell the world that some emoji is the king of the last word."""
|
|
|
|
king_message = self.config.get("king_message")
|
|
|
|
if not king_message:
|
|
|
|
return
|
|
|
|
kings = self.config.get("kings")
|
|
|
|
if not kings or len(kings) == 0:
|
|
|
|
return
|
|
|
|
words = event.arguments[0].split()
|
|
|
|
if len(words) == 0:
|
|
|
|
return
|
|
|
|
king = random.choice(kings)
|
|
|
|
reply = king_message.format(king=king, subject=words[-1])
|
|
|
|
self.bot.say(event.target, reply)
|
|
|
|
|
|
|
|
def react_with_mmm(self, event):
|
|
|
|
"""Say a mixed (mm) Skype emote."""
|
|
|
|
num_chars = random.randint(1, 8)
|
|
|
|
mmm = ""
|
|
|
|
for _ in range(num_chars):
|
|
|
|
mmm += random.choice("(mmm)")
|
|
|
|
self.bot.say(event.target, mmm)
|
|
|
|
|
|
|
|
def react_with_ooo(self, event):
|
|
|
|
"""Just yell some Os."""
|
|
|
|
self.bot.say(event.target, "O" * random.randint(1, 10))
|
|
|
|
|
|
|
|
def react_with_detector(self, event):
|
|
|
|
"""Get the last word detector and react to it."""
|
|
|
|
words = event.arguments[0].split()
|
|
|
|
if len(words) == 0:
|
|
|
|
return
|
|
|
|
detector_message = self.config.get("detector_message")
|
|
|
|
detector_process = self.config.get("detector_process")
|
|
|
|
detector_pos = self.config.get("detector_pos")
|
|
|
|
detector_neg = self.config.get("detector_neg")
|
|
|
|
if any(
|
|
|
|
s is None
|
|
|
|
for s in (detector_message, detector_process, detector_pos,
|
|
|
|
detector_neg)
|
|
|
|
):
|
|
|
|
return
|
|
|
|
self.bot.say(event.target, detector_message.format(subject=words[-1]))
|
|
|
|
self.bot.say(event.target, detector_process)
|
|
|
|
if proc(50):
|
|
|
|
self.bot.say(event.target, detector_pos)
|
|
|
|
else:
|
|
|
|
self.bot.say(event.target, detector_neg)
|
|
|
|
|
|
|
|
def react_with_repeat_letters(self, event):
|
|
|
|
"""Make sure you understood the biggest word in a stupid way."""
|
|
|
|
words = event.arguments[0].split()
|
|
|
|
if len(words) == 0:
|
|
|
|
return
|
|
|
|
biggest_word = sorted(words, key=lambda w: len(w))[-1]
|
2021-12-02 11:31:30 +01:00
|
|
|
num_repeats = 2
|
|
|
|
repeated = biggest_word[:num_repeats]
|
|
|
|
while (
|
|
|
|
(not any(letter in repeated for letter in "aeiouy"))
|
|
|
|
and len(repeated) < len(biggest_word)
|
|
|
|
):
|
|
|
|
num_repeats += 1
|
|
|
|
repeated = biggest_word[:num_repeats]
|
2020-11-04 22:46:09 +01:00
|
|
|
word = biggest_word[:2] + biggest_word
|
|
|
|
question_mark = self.config["question_mark"]
|
|
|
|
reply = f"{word}{question_mark}"
|
|
|
|
self.bot.say(event.target, reply)
|
2022-03-06 17:22:54 +01:00
|
|
|
|
|
|
|
def react_with_nudge(self, event):
|
|
|
|
"""Nudge the last person who talked (unsure how or why)."""
|
|
|
|
nick = NickMask(event.source).nick
|
|
|
|
reply = self.config.get("nudging")
|
|
|
|
if reply is None:
|
|
|
|
return
|
|
|
|
self.bot.say(event.target, reply.format(target=nick))
|