7 Commits

Author SHA1 Message Date
AlberLC
c9a46b2b07 Fix roles mentions in weather 2022-06-01 03:16:45 +02:00
AlberLC
92ee0e405d Fix env variable names 2022-05-31 23:08:36 +02:00
AlberLC
dc6bf7accb Refactor punishments and optimize chat objects 2022-05-31 22:11:16 +02:00
AlberLC
9e5f7a81ff Add user who pressed the button 2022-05-26 05:45:16 +02:00
AlberLC
28ff804d5a Improve discord user name printing 2022-05-25 05:30:09 +02:00
AlberLC
d47fdfb57e Fix bot insults ratio 2022-05-25 04:00:47 +02:00
AlberLC
20fb6e3223 Fix bot insults ratio 2022-05-25 02:55:28 +02:00
7 changed files with 70 additions and 91 deletions

View File

@@ -146,14 +146,14 @@ class FlanaBot(MultiBot, ABC):
return return
last_2s_messages = Message.find({ last_2s_messages = Message.find({
'platform': self.bot_platform.value, 'platform': self.platform.value,
'author': message.author.object_id, 'author': message.author.object_id,
'last_update': { 'last_update': {
'$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=2) '$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=2)
} }
}) })
last_7s_messages = Message.find({ last_7s_messages = Message.find({
'platform': self.bot_platform.value, 'platform': self.platform.value,
'author': message.author.object_id, 'author': message.author.object_id,
'last_update': { 'last_update': {
'$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=7), '$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=7),
@@ -163,7 +163,7 @@ class FlanaBot(MultiBot, ABC):
if len(last_2s_messages) >= 5 or len(last_7s_messages) >= 7: if len(last_2s_messages) >= 5 or len(last_7s_messages) >= 7:
n_punishments = len(Punishment.find({ n_punishments = len(Punishment.find({
'platform': self.bot_platform.value, 'platform': self.platform.value,
'user_id': message.author.id, 'user_id': message.author.id,
'group_id': message.chat.group_id 'group_id': message.chat.group_id
})) }))
@@ -175,23 +175,6 @@ class FlanaBot(MultiBot, ABC):
else: else:
await self.send(f'Castigado durante {TimeUnits(seconds=punishment_seconds).to_words()}.', message) await self.send(f'Castigado durante {TimeUnits(seconds=punishment_seconds).to_words()}.', message)
async def _check_punishments(self):
punishment_groups = self._get_grouped_punishments(Punishment)
now = datetime.datetime.now(datetime.timezone.utc)
for (user_id, group_id), sorted_punishments in punishment_groups:
if now < (last_punishment := sorted_punishments[-1]).until:
continue
if last_punishment.until + constants.PUNISHMENTS_RESET <= now:
for old_punishment in sorted_punishments:
old_punishment.delete()
if last_punishment.is_active:
await self.unpunish(user_id, group_id)
last_punishment.is_active = False
last_punishment.save()
@staticmethod @staticmethod
def _get_config_buttons(config: dict | Chat | Message) -> list[list[str]]: def _get_config_buttons(config: dict | Chat | Message) -> list[list[str]]:
match config: match config:
@@ -261,7 +244,7 @@ class FlanaBot(MultiBot, ABC):
new_line = ' ' if len(medias_sended_info) == 1 else '\n' new_line = ' ' if len(medias_sended_info) == 1 else '\n'
return f'{new_line}{medias_sended_info_joined}:' return f'{new_line}{medias_sended_info_joined}:'
async def _punish(self, user: int | str | User, group_: int | str | Chat): async def _punish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
pass pass
async def _search_and_send_medias(self, message: Message, send_song_info=False) -> list[Message]: async def _search_and_send_medias(self, message: Message, send_song_info=False) -> list[Message]:
@@ -303,7 +286,7 @@ class FlanaBot(MultiBot, ABC):
async def _show_config(self, config_name: str, message: Message): async def _show_config(self, config_name: str, message: Message):
await self.send(f"{config_name} está {'activado ✔' if message.chat.config.get(config_name) else 'desactivado ❌'}", message) await self.send(f"{config_name} está {'activado ✔' if message.chat.config.get(config_name) else 'desactivado ❌'}", message)
async def _unpunish(self, user: int | str | User, group_: int | str | Chat): async def _unpunish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
pass pass
# ---------------------------------------------- # # ---------------------------------------------- #
@@ -311,10 +294,8 @@ class FlanaBot(MultiBot, ABC):
# ---------------------------------------------- # # ---------------------------------------------- #
async def _on_button_press(self, message: Message): async def _on_button_press(self, message: Message):
await self._accept_button_event(message) await self._accept_button_event(message)
if message.author.is_admin is False:
return
match message.last_button_pressed: match message.button_pressed_text:
case WeatherEmoji.ZOOM_IN.value: case WeatherEmoji.ZOOM_IN.value:
buttons_message_type = ButtonsMessageType.WEATHER buttons_message_type = ButtonsMessageType.WEATHER
message.weather_chart.zoom_in() message.weather_chart.zoom_in()
@@ -335,13 +316,13 @@ class FlanaBot(MultiBot, ABC):
buttons_message_type = ButtonsMessageType.WEATHER buttons_message_type = ButtonsMessageType.WEATHER
trace_metadata_name = WeatherEmoji(emoji).name.lower() trace_metadata_name = WeatherEmoji(emoji).name.lower()
message.weather_chart.trace_metadatas[trace_metadata_name].show = not message.weather_chart.trace_metadatas[trace_metadata_name].show message.weather_chart.trace_metadatas[trace_metadata_name].show = not message.weather_chart.trace_metadatas[trace_metadata_name].show
case _ if 'auto_' in (config := message.last_button_pressed.split()[1]): case _ if message.button_pressed_user.is_admin and 'auto_' in (config := message.button_pressed_text.split()[1]):
buttons_message_type = ButtonsMessageType.CONFIG buttons_message_type = ButtonsMessageType.CONFIG
message.chat.config[config] = not message.chat.config[config] message.chat.config[config] = not message.chat.config[config]
message.save() message.save()
await self.edit('<b>Estos son los ajustes del grupo:</b>\n\n', self._get_config_buttons(message), message) await self.edit('<b>Estos son los ajustes del grupo:</b>\n\n', self._get_config_buttons(message), message)
case _: case _:
buttons_message_type = None return
if buttons_message_type is ButtonsMessageType.WEATHER: if buttons_message_type is ButtonsMessageType.WEATHER:
message.weather_chart.apply_zoom() message.weather_chart.apply_zoom()
@@ -447,7 +428,7 @@ class FlanaBot(MultiBot, ABC):
( (
message.chat.config['auto_insult'] message.chat.config['auto_insult']
and and
random.random() < 0.5 random.random() < constants.INSULT_PROBABILITY
) )
) )
) )
@@ -469,11 +450,12 @@ class FlanaBot(MultiBot, ABC):
@group @group
@admin(send_negative=True) @admin(send_negative=True)
async def _on_punish(self, message: Message): async def _on_punish(self, message: Message):
await self._update_punishment(self.punish, message, time=flanautils.words_to_time(message.text)) for user in await self._find_users_to_punish(message):
await self.punish(user, message, flanautils.words_to_time(message.text), message)
async def _on_ready(self): async def _on_ready(self):
await super()._on_ready() await super()._on_ready()
await flanautils.do_every(constants.CHECK_PUNISHMENTS_EVERY_SECONDS, self._check_punishments) await flanautils.do_every(constants.CHECK_PUNISHMENTS_EVERY_SECONDS, Punishment.check_olds, self._unpunish, self.platform)
@inline(False) @inline(False)
async def _on_recover_message(self, message: Message): async def _on_recover_message(self, message: Message):
@@ -489,7 +471,7 @@ class FlanaBot(MultiBot, ABC):
return return
affected_object_ids = [affected_message_object_id for affected_message_object_id in message_deleted_bot_action.affected_objects] affected_object_ids = [affected_message_object_id for affected_message_object_id in message_deleted_bot_action.affected_objects]
deleted_messages: list[Message] = [affected_message for affected_object_id in affected_object_ids if (affected_message := Message.find_one({'platform': self.bot_platform.value, '_id': affected_object_id})).author.id != self.bot_id] deleted_messages: list[Message] = [affected_message for affected_object_id in affected_object_ids if (affected_message := Message.find_one({'platform': self.platform.value, '_id': affected_object_id})).author.id != self.id]
for deleted_message in deleted_messages: for deleted_message in deleted_messages:
await self.send(deleted_message.text, message) await self.send(deleted_message.text, message)
@@ -563,7 +545,8 @@ class FlanaBot(MultiBot, ABC):
@bot_mentioned @bot_mentioned
@admin(send_negative=True) @admin(send_negative=True)
async def _on_unpunish(self, message: Message): async def _on_unpunish(self, message: Message):
await self._update_punishment(self.unpunish, message) for user in await self._find_users_to_punish(message):
await self.unpunish(user, message, message)
async def _on_weather_chart(self, message: Message): async def _on_weather_chart(self, message: Message):
bot_state_message: Message | None = None bot_state_message: Message | None = None
@@ -571,7 +554,7 @@ class FlanaBot(MultiBot, ABC):
show_progress_state = False show_progress_state = False
elif message.chat.is_group and not self.is_bot_mentioned(message): elif message.chat.is_group and not self.is_bot_mentioned(message):
if message.chat.config['auto_weather_chart']: if message.chat.config['auto_weather_chart']:
if BotAction.find_one({'action': bytes(Action.AUTO_WEATHER_CHART), 'chat': message.chat.object_id, 'date': {'$gt': datetime.datetime.now(datetime.timezone.utc) - constants.AUTO_WEATHER_EVERY}}): if BotAction.find_one({'action': Action.AUTO_WEATHER_CHART.value, 'chat': message.chat.object_id, 'date': {'$gt': datetime.datetime.now(datetime.timezone.utc) - constants.AUTO_WEATHER_EVERY}}):
return return
show_progress_state = False show_progress_state = False
else: else:
@@ -584,8 +567,10 @@ class FlanaBot(MultiBot, ABC):
possible_mentioned_ids.append(user.name.lower()) possible_mentioned_ids.append(user.name.lower())
possible_mentioned_ids.append(user.name.split('#')[0].lower()) possible_mentioned_ids.append(user.name.split('#')[0].lower())
possible_mentioned_ids.append(f'@{user.id}') possible_mentioned_ids.append(f'@{user.id}')
for role in message.chat.roles:
possible_mentioned_ids.append(f'@{role.id}') if roles := await self.get_group_roles(message):
for role in roles:
possible_mentioned_ids.append(f'@{role.id}')
original_text_words = flanautils.remove_accents(message.text.lower()) original_text_words = flanautils.remove_accents(message.text.lower())
original_text_words = original_text_words.replace(',', ' ').replace(';', ' ').replace('-', ' -') original_text_words = original_text_words.replace(',', ' ').replace(';', ' ').replace('-', ' -')
@@ -733,31 +718,13 @@ class FlanaBot(MultiBot, ABC):
# -------------------------------------------------------- # # -------------------------------------------------------- #
# -------------------- PUBLIC METHODS -------------------- # # -------------------- PUBLIC METHODS -------------------- #
# -------------------------------------------------------- # # -------------------------------------------------------- #
async def is_punished(self, user: int | str | User, group_: int | str | Chat) -> bool: async def is_punished(self, user: int | str | User, group_: int | str | Chat | Message) -> bool:
pass pass
async def punish(self, user: int | str | User, group_: int | str | Chat, time: int | datetime.timedelta, message: Message = None): async def punish(self, user: int | str | User, group_: int | str | Chat | Message, time: int | datetime.timedelta, message: Message = None):
user_id = self._get_user_id(user) # noinspection PyTypeChecker
group_id = self._get_group_id(group_) punish = Punishment(self.platform, self.get_user_id(user), self.get_group_id(group_), time)
if isinstance(time, int): await punish.punish(self._punish, self._unpunish, message)
time = datetime.timedelta(seconds=time)
try:
await self._punish(user_id, group_id)
except BadRoleError as e:
if message and message.chat.original_object:
await self._manage_exceptions(e, message)
else:
raise e
else:
if time:
until = datetime.datetime.now(datetime.timezone.utc) + time
if datetime.timedelta() < time <= constants.TIME_THRESHOLD_TO_MANUAL_UNPUNISH:
await flanautils.do_later(time, self._check_punishments)
else:
until = None
# noinspection PyTypeChecker
Punishment(self.bot_platform, user_id, group_id, until=until).save()
async def send_bye(self, message: Message) -> multibot_constants.ORIGINAL_MESSAGE: async def send_bye(self, message: Message) -> multibot_constants.ORIGINAL_MESSAGE:
return await self.send(random.choice((*constants.BYE_PHRASES, flanautils.CommonWords.random_time_greeting())), message) return await self.send(random.choice((*constants.BYE_PHRASES, flanautils.CommonWords.random_time_greeting())), message)
@@ -780,7 +747,7 @@ class FlanaBot(MultiBot, ABC):
bot_state_message: Message = await self.send('Descargando...', message) bot_state_message: Message = await self.send('Descargando...', message)
if message.chat.is_group: if message.chat.is_group:
sended_info_message = await self.send(f'{message.author.name} compartió{self._medias_sended_info(medias)}', message) sended_info_message = await self.send(f"{message.author.name.split('#')[0]} compartió{self._medias_sended_info(medias)}", message)
for media in medias: for media in medias:
if not media.content: if not media.content:
@@ -825,18 +792,7 @@ class FlanaBot(MultiBot, ABC):
if song_info: if song_info:
await self.send(song_info, message) await self.send(song_info, message)
async def unpunish(self, user: int | str | User, group_: int | str | Chat, message: Message = None): async def unpunish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
user_id = self._get_user_id(user) # noinspection PyTypeChecker
group_id = self._get_group_id(group_) punish = Punishment(self.platform, self.get_user_id(user), self.get_group_id(group_))
try: await punish.unpunish(self._unpunish, message)
await self._unpunish(user_id, group_id)
except BadRoleError as e:
if message and message.chat.original_object:
await self._manage_exceptions(e, message)
else:
raise e
else:
try:
Punishment.find_one({'platform': self.bot_platform.value, 'user_id': user_id, 'group_id': group_id, 'until': None}).delete()
except AttributeError:
pass

View File

@@ -6,7 +6,7 @@ from multibot import BadRoleError, DiscordBot, User
from flanabot import constants from flanabot import constants
from flanabot.bots.flana_bot import FlanaBot from flanabot.bots.flana_bot import FlanaBot
from flanabot.models import Chat, Punishment from flanabot.models import Chat, Message, Punishment
HEAT_NAMES = [ HEAT_NAMES = [
'Canal Congelado', 'Canal Congelado',
@@ -38,7 +38,7 @@ class FlanaDiscBot(DiscordBot, FlanaBot):
# ----------------------------------------------------------- # # ----------------------------------------------------------- #
def _add_handlers(self): def _add_handlers(self):
super()._add_handlers() super()._add_handlers()
self.bot_client.add_listener(self._on_voice_state_update, 'on_voice_state_update') self.client.add_listener(self._on_voice_state_update, 'on_voice_state_update')
async def _heat_channel(self, channel: discord.VoiceChannel): async def _heat_channel(self, channel: discord.VoiceChannel):
while True: while True:
@@ -57,16 +57,16 @@ class FlanaDiscBot(DiscordBot, FlanaBot):
await channel.edit(name=HEAT_NAMES[int(self.heat_level)]) await channel.edit(name=HEAT_NAMES[int(self.heat_level)])
async def _punish(self, user: int | str | User, group_: int | str | Chat): async def _punish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
user_id = self._get_user_id(user) user_id = self.get_user_id(user)
try: try:
await self.add_role(user_id, group_, 'Castigado') await self.add_role(user_id, group_, 'Castigado')
await self.remove_role(user_id, group_, 'Persona') await self.remove_role(user_id, group_, 'Persona')
except AttributeError: except AttributeError:
raise BadRoleError(str(self._punish)) raise BadRoleError(str(self._punish))
async def _unpunish(self, user: int | str | User, group_: int | str | Chat): async def _unpunish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
user_id = self._get_user_id(user) user_id = self.get_user_id(user)
try: try:
await self.add_role(user_id, group_, 'Persona') await self.add_role(user_id, group_, 'Persona')
await self.remove_role(user_id, group_, 'Castigado') await self.remove_role(user_id, group_, 'Castigado')
@@ -92,11 +92,11 @@ class FlanaDiscBot(DiscordBot, FlanaBot):
# -------------------------------------------------------- # # -------------------------------------------------------- #
# -------------------- PUBLIC METHODS -------------------- # # -------------------- PUBLIC METHODS -------------------- #
# -------------------------------------------------------- # # -------------------------------------------------------- #
async def is_punished(self, user: int | str | User, group_: int | str | Chat): async def is_punished(self, user: int | str | User, group_: int | str | Chat | Message):
user = await self.get_user(user, group_) user = await self.get_user(user, group_)
group_id = self._get_group_id(group_) group_id = self.get_group_id(group_)
return group_id in {punishment.group_id for punishment in Punishment.find({ return group_id in {punishment.group_id for punishment in Punishment.find({
'platform': self.bot_platform.value, 'platform': self.platform.value,
'user_id': user.id, 'user_id': user.id,
'group_id': group_id, 'group_id': group_id,
'is_active': True 'is_active': True

View File

@@ -53,7 +53,7 @@ class FlanaTeleBot(TelegramBot, FlanaBot):
@user_client @user_client
async def _update_whitelist(self): async def _update_whitelist(self):
self.whitelist_ids = [self.owner_id, self.bot_id] + await self._get_contacts_ids() self.whitelist_ids = [self.owner_id, self.id] + await self._get_contacts_ids()
# ---------------------------------------------- # # ---------------------------------------------- #
# HANDLERS # # HANDLERS #

View File

@@ -10,7 +10,6 @@ MAX_PLACE_QUERY_LENGTH = 50
PUNISHMENT_INCREMENT_EXPONENT = 6 PUNISHMENT_INCREMENT_EXPONENT = 6
PUNISHMENTS_RESET = datetime.timedelta(weeks=6 * flanautils.WEEKS_IN_A_MONTH) PUNISHMENTS_RESET = datetime.timedelta(weeks=6 * flanautils.WEEKS_IN_A_MONTH)
RECOVERY_DELETED_MESSAGE_BEFORE = datetime.timedelta(hours=1) RECOVERY_DELETED_MESSAGE_BEFORE = datetime.timedelta(hours=1)
TIME_THRESHOLD_TO_MANUAL_UNPUNISH = datetime.timedelta(days=3)
SCRAPING_MESSAGE_WAITING_TIME = 0.1 SCRAPING_MESSAGE_WAITING_TIME = 0.1
BYE_PHRASES = ('Adiós.', 'adieu', 'adio', 'adioh', 'adios', 'adió', 'adiós', 'agur', 'bye', 'byyeeee', 'chao', BYE_PHRASES = ('Adiós.', 'adieu', 'adio', 'adioh', 'adios', 'adió', 'adiós', 'agur', 'bye', 'byyeeee', 'chao',

View File

@@ -1,6 +1,6 @@
from dataclasses import dataclass, field from dataclasses import dataclass
from multibot.models import Chat as MultiBotChat, User from multibot.models import Chat as MultiBotChat
@dataclass(eq=False) @dataclass(eq=False)
@@ -11,7 +11,6 @@ class Chat(MultiBotChat):
'auto_insult': True, 'auto_insult': True,
'auto_scraping': True, 'auto_scraping': True,
'auto_weather_chart': True} 'auto_weather_chart': True}
users: list[User] = field(default_factory=list)
def __post_init__(self): def __post_init__(self):
super().__post_init__() super().__post_init__()

View File

@@ -13,6 +13,7 @@ from flanabot.models.weather_chart import WeatherChart
@dataclass(eq=False) @dataclass(eq=False)
class Message(MultiBotMessage): class Message(MultiBotMessage):
author: User = None author: User = None
button_pressed_user: User = None
mentions: Iterable[User] = field(default_factory=list) mentions: Iterable[User] = field(default_factory=list)
chat: Chat = None chat: Chat = None
replied_message: Message = None replied_message: Message = None

View File

@@ -1,8 +1,32 @@
from dataclasses import dataclass __all__ = ['Punishment']
from multibot.models import Mute, db import datetime
from dataclasses import dataclass
from typing import Callable
from multibot.models import Platform, PunishmentBase, db
from flanabot import constants
@dataclass(eq=False) @dataclass(eq=False)
class Punishment(Mute): class Punishment(PunishmentBase):
collection = db.punishment collection = db.punishment
@classmethod
async def check_olds(cls, unpunishment_method: Callable, platform: Platform):
punishment_groups = cls._get_grouped_punishments(platform)
now = datetime.datetime.now(datetime.timezone.utc)
for (_, _), sorted_punishments in punishment_groups:
if not (last_punishment := sorted_punishments[-1]).until or now < last_punishment.until:
continue
if last_punishment.until + constants.PUNISHMENTS_RESET <= now:
for old_punishment in sorted_punishments:
old_punishment.delete()
if last_punishment.is_active:
await last_punishment.unpunish(unpunishment_method)
last_punishment.is_active = False
last_punishment.save()