16 Commits

Author SHA1 Message Date
AlberLC
c2e7e68619 Fix _check_message_flood 2022-06-15 00:46:31 +02:00
AlberLC
f12d0c18c1 Fix insults 2022-06-14 04:41:26 +02:00
AlberLC
b55f933a32 Add new insults 2022-06-14 04:01:16 +02:00
AlberLC
5fa102b157 Fix _on_scraping with replied message 2022-06-12 00:13:33 +02:00
AlberLC
1e8a33c0c4 Improve button registration 2022-06-08 22:05:02 +02:00
AlberLC
daef039ce5 Change _manage_exceptions context arg 2022-06-06 04:22:26 +02:00
AlberLC
7ad4c4052e Remove twitch bot at main 2022-06-06 02:31:16 +02:00
AlberLC
641dc72738 Update requirements.txt 2022-06-04 03:33:59 +02:00
AlberLC
cafa7ce1c5 Fix recover original message 2022-06-04 02:58:32 +02:00
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
13 changed files with 213 additions and 210 deletions

View File

@@ -1,3 +1,5 @@
__all__ = ['FlanaBot']
import asyncio
import datetime
import random
@@ -10,12 +12,13 @@ import flanaapis.geolocation.functions
import flanaapis.weather.functions
import flanautils
import plotly.graph_objects
import pymongo
from flanaapis import InstagramLoginError, MediaNotFoundError, Place, PlaceNotFoundError, WeatherEmoji, instagram, tiktok, twitter
from flanautils import Media, MediaType, NotFoundError, OrderedSet, Source, TimeUnits, TraceMetadata, return_if_first_empty
from multibot import Action, BadRoleError, BotAction, MultiBot, SendError, User, admin, bot_mentioned, constants as multibot_constants, group, ignore_self_message, inline, reply
from flanabot import constants
from flanabot.models import ButtonsMessageType, Chat, Message, Punishment, WeatherChart
from flanabot.models import Chat, Message, Punishment, WeatherChart
# ----------------------------------------------------------------------------------------------------- #
@@ -128,7 +131,8 @@ class FlanaBot(MultiBot, ABC):
self.register(self._on_weather_chart_config_show, (constants.KEYWORDS['weather_chart'], multibot_constants.KEYWORDS['config']))
self.register(self._on_weather_chart_config_show, (multibot_constants.KEYWORDS['show'], constants.KEYWORDS['weather_chart'], multibot_constants.KEYWORDS['config']))
self.register_button(self._on_button_press)
self.register_button(self._on_config_button_press, list(Chat.DEFAULT_CONFIG.keys()))
self.register_button(self._on_weather_button_press, WeatherEmoji.values)
async def _change_config(self, config_name: str, message: Message, value: bool = None):
if value is None:
@@ -146,24 +150,19 @@ class FlanaBot(MultiBot, ABC):
return
last_2s_messages = Message.find({
'platform': self.bot_platform.value,
'platform': self.platform.value,
'author': message.author.object_id,
'last_update': {
'$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=2)
}
'last_update': {'$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=2)}
})
last_7s_messages = Message.find({
'platform': self.bot_platform.value,
'platform': self.platform.value,
'author': message.author.object_id,
'last_update': {
'$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=7),
'$lt': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=2)
}
'last_update': {'$gte': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=7)}
})
if len(last_2s_messages) >= 5 or len(last_7s_messages) >= 7:
if len(last_2s_messages) >= constants.FLOOD_2s_LIMIT or len(last_7s_messages) >= constants.FLOOD_7s_LIMIT:
n_punishments = len(Punishment.find({
'platform': self.bot_platform.value,
'platform': self.platform.value,
'user_id': message.author.id,
'group_id': message.chat.group_id
}))
@@ -175,23 +174,6 @@ class FlanaBot(MultiBot, ABC):
else:
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
def _get_config_buttons(config: dict | Chat | Message) -> list[list[str]]:
match config:
@@ -201,10 +183,11 @@ class FlanaBot(MultiBot, ABC):
config = message.chat.config
buttons_texts = [f"{'' if v else ''} {k}" for k, v in config.items()]
# noinspection PyTypeChecker
return flanautils.chunks(buttons_texts, 3)
@return_if_first_empty(exclude_self_types='FlanaBot', globals_=globals())
async def _manage_exceptions(self, exceptions: BaseException | Iterable[BaseException], message: Message):
async def _manage_exceptions(self, exceptions: BaseException | Iterable[BaseException], context: Chat | Message):
if not isinstance(exceptions, Iterable):
exceptions = (exceptions,)
@@ -212,15 +195,15 @@ class FlanaBot(MultiBot, ABC):
try:
raise exception
except BadRoleError as e:
await self.send_error(f'Rol no encontrado en {e}', message)
await self.send_error(f'Rol no encontrado en {e}', context)
except InstagramLoginError as e:
await self.send_error(f'No me puedo loguear en Instagram {random.choice(multibot_constants.SAD_EMOJIS)} 👉 {e}', message)
await self.send_error(f'No me puedo loguear en Instagram {random.choice(multibot_constants.SAD_EMOJIS)} 👉 {e}', context)
except MediaNotFoundError as e:
await self.send_error(f'No he podido sacar nada de {e.source} {random.choice(multibot_constants.SAD_EMOJIS)}', message)
await self.send_error(f'No he podido sacar nada de {e.source} {random.choice(multibot_constants.SAD_EMOJIS)}', context)
except PlaceNotFoundError as e:
await self.send_error(f'No he podido encontrar "{e}" {random.choice(multibot_constants.SAD_EMOJIS)}', message)
await self.send_error(f'No he podido encontrar "{e}" {random.choice(multibot_constants.SAD_EMOJIS)}', context)
except Exception as e:
await super()._manage_exceptions(e, message)
await super()._manage_exceptions(e, context)
@staticmethod
def _medias_sended_info(medias: Iterable[Media]) -> str:
@@ -261,7 +244,7 @@ class FlanaBot(MultiBot, ABC):
new_line = ' ' if len(medias_sended_info) == 1 else '\n'
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
async def _search_and_send_medias(self, message: Message, send_song_info=False) -> list[Message]:
@@ -303,67 +286,29 @@ class FlanaBot(MultiBot, ABC):
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)
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
# ---------------------------------------------- #
# HANDLERS #
# ---------------------------------------------- #
async def _on_button_press(self, message: Message):
await self._accept_button_event(message)
if message.author.is_admin is False:
return
match message.last_button_pressed:
case WeatherEmoji.ZOOM_IN.value:
buttons_message_type = ButtonsMessageType.WEATHER
message.weather_chart.zoom_in()
case WeatherEmoji.ZOOM_OUT.value:
buttons_message_type = ButtonsMessageType.WEATHER
message.weather_chart.zoom_out()
case WeatherEmoji.LEFT.value:
buttons_message_type = ButtonsMessageType.WEATHER
message.weather_chart.move_left()
case WeatherEmoji.RIGHT.value:
buttons_message_type = ButtonsMessageType.WEATHER
message.weather_chart.move_right()
case WeatherEmoji.PRECIPITATION_VOLUME.value:
buttons_message_type = ButtonsMessageType.WEATHER
message.weather_chart.trace_metadatas['rain_volume'].show = not message.weather_chart.trace_metadatas['rain_volume'].show
message.weather_chart.trace_metadatas['snow_volume'].show = not message.weather_chart.trace_metadatas['snow_volume'].show
case emoji if emoji in WeatherEmoji.values:
buttons_message_type = ButtonsMessageType.WEATHER
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
case _ if 'auto_' in (config := message.last_button_pressed.split()[1]):
buttons_message_type = ButtonsMessageType.CONFIG
message.chat.config[config] = not message.chat.config[config]
message.save()
await self.edit('<b>Estos son los ajustes del grupo:</b>\n\n', self._get_config_buttons(message), message)
case _:
buttons_message_type = None
if buttons_message_type is ButtonsMessageType.WEATHER:
message.weather_chart.apply_zoom()
message.weather_chart.draw()
message.save()
image_bytes = message.weather_chart.to_image()
await self.edit(Media(image_bytes, MediaType.IMAGE), message)
async def _on_bye(self, message: Message):
if not message.chat.is_group or self.is_bot_mentioned(message):
await self.send_bye(message)
async def _on_config_button_press(self, message: Message):
await self._accept_button_event(message)
if not message.button_pressed_user.is_admin or 'auto_' not in (config := message.button_pressed_text.split()[1]):
return
message.chat.config[config] = not message.chat.config[config]
await self.edit('<b>Estos son los ajustes del grupo:</b>\n\n', self._get_config_buttons(message), message)
@group
@bot_mentioned
async def _on_config_list_show(self, message: Message):
# config_info = pprint.pformat(message.chat.config)
# config_info = flanautils.translate(config_info, {'{': None, '}': None, ',': None, 'True': '', "'": None, 'False': '❌'})
# config_info = config_info.splitlines()
# config_info = '\n'.join(config_info_.strip() for config_info_ in config_info)
# await self.send(f'<b>Estos son los ajustes del grupo:</b>\n\n<code>{config_info}</code>', message)
await self.send('<b>Estos son los ajustes del grupo:</b>\n\n', self._get_config_buttons(message), message)
async def _on_covid_chart(self, message: Message): # todo2
@@ -447,7 +392,7 @@ class FlanaBot(MultiBot, ABC):
(
message.chat.config['auto_insult']
and
random.random() < 0.5
random.random() < constants.INSULT_PROBABILITY
)
)
)
@@ -469,34 +414,41 @@ class FlanaBot(MultiBot, ABC):
@group
@admin(send_negative=True)
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):
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)
async def _on_recover_message(self, message: Message):
if message.replied_message:
message_deleted_bot_action = BotAction.find_one({'action': bytes(Action.MESSAGE_DELETED), 'chat': message.chat.object_id, 'affected_objects': message.replied_message.object_id})
message_deleted_bot_action = BotAction.find_one({'action': Action.MESSAGE_DELETED.value, 'chat': message.chat.object_id, 'affected_objects': message.replied_message.object_id})
elif self.is_bot_mentioned(message):
message_deleted_bot_action = BotAction.find_one({'action': bytes(Action.MESSAGE_DELETED), 'chat': message.chat.object_id, 'date': {'$gt': datetime.datetime.now(datetime.timezone.utc) - constants.RECOVERY_DELETED_MESSAGE_BEFORE}})
message_deleted_bot_action = BotAction.find_one({
'action': Action.MESSAGE_DELETED.value,
'chat': message.chat.object_id,
'date': {'$gt': datetime.datetime.now(datetime.timezone.utc) - constants.RECOVERY_DELETED_MESSAGE_BEFORE}
}, sort_keys=(('date', pymongo.DESCENDING),))
else:
return
if not message_deleted_bot_action:
await self.send_error(random.choice(constants.RECOVER_PHRASES), message)
await self.send_error('No hay nada que recuperar.', message)
return
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:
await self.send(deleted_message.text, message)
message_deleted_bot_action.delete()
async def _on_scraping(self, message: Message, delete_original: bool = None) -> OrderedSet[Media]:
sended_media_messages = await self._search_and_send_medias(message.replied_message) if message.replied_message else OrderedSet()
sended_media_messages = OrderedSet()
if message.replied_message:
word_matches = flanautils.cartesian_product_string_matching(message.text, constants.KEYWORDS['scraping'], min_ratio=multibot_constants.PARSE_CALLBACKS_MIN_RATIO_DEFAULT)
if sum(max(matches.values()) for matches in word_matches.values()):
sended_media_messages += await self._search_and_send_medias(message.replied_message)
sended_media_messages += await self._search_and_send_medias(message)
await self.send_inline_results(message)
@@ -509,6 +461,8 @@ class FlanaBot(MultiBot, ABC):
(
delete_original is None
and
not message.replied_message
and
message.chat.config['auto_delete_original']
)
or
@@ -563,7 +517,35 @@ class FlanaBot(MultiBot, ABC):
@bot_mentioned
@admin(send_negative=True)
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_button_press(self, message: Message):
await self._accept_button_event(message)
match message.button_pressed_text:
case WeatherEmoji.ZOOM_IN.value:
message.weather_chart.zoom_in()
case WeatherEmoji.ZOOM_OUT.value:
message.weather_chart.zoom_out()
case WeatherEmoji.LEFT.value:
message.weather_chart.move_left()
case WeatherEmoji.RIGHT.value:
message.weather_chart.move_right()
case WeatherEmoji.PRECIPITATION_VOLUME.value:
message.weather_chart.trace_metadatas['rain_volume'].show = not message.weather_chart.trace_metadatas['rain_volume'].show
message.weather_chart.trace_metadatas['snow_volume'].show = not message.weather_chart.trace_metadatas['snow_volume'].show
case emoji if emoji in WeatherEmoji.values:
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
case _:
return
message.weather_chart.apply_zoom()
message.weather_chart.draw()
image_bytes = message.weather_chart.to_image()
await self.edit(Media(image_bytes, MediaType.IMAGE), message)
async def _on_weather_chart(self, message: Message):
bot_state_message: Message | None = None
@@ -571,7 +553,7 @@ class FlanaBot(MultiBot, ABC):
show_progress_state = False
elif message.chat.is_group and not self.is_bot_mentioned(message):
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
show_progress_state = False
else:
@@ -584,8 +566,10 @@ class FlanaBot(MultiBot, ABC):
possible_mentioned_ids.append(user.name.lower())
possible_mentioned_ids.append(user.name.split('#')[0].lower())
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_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 = original_text_words.replace(',', ' ').replace(';', ' ').replace('-', ' -')
@@ -733,31 +717,13 @@ class FlanaBot(MultiBot, ABC):
# -------------------------------------------------------- #
# -------------------- 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
async def punish(self, user: int | str | User, group_: int | str | Chat, time: int | datetime.timedelta, message: Message = None):
user_id = self._get_user_id(user)
group_id = self._get_group_id(group_)
if isinstance(time, int):
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 punish(self, user: int | str | User, group_: int | str | Chat | Message, time: int | datetime.timedelta, message: Message = None):
# noinspection PyTypeChecker
punish = Punishment(self.platform, self.get_user_id(user), self.get_group_id(group_), time)
await punish.punish(self._punish, self._unpunish, 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)
@@ -780,7 +746,7 @@ class FlanaBot(MultiBot, ABC):
bot_state_message: Message = await self.send('Descargando...', message)
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:
if not media.content:
@@ -791,10 +757,7 @@ class FlanaBot(MultiBot, ABC):
message.song_infos.add(media.song_info)
message.save()
try:
bot_message = await self.send(media, message)
except SendError as e:
await self._manage_exceptions(e, message)
if not (bot_message := await self.send(media, message)):
fails += 1
else:
sended_media_messages.append(bot_message)
@@ -825,18 +788,7 @@ class FlanaBot(MultiBot, ABC):
if song_info:
await self.send(song_info, message)
async def unpunish(self, user: int | str | User, group_: int | str | Chat, message: Message = None):
user_id = self._get_user_id(user)
group_id = self._get_group_id(group_)
try:
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
async def unpunish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
# noinspection PyTypeChecker
punish = Punishment(self.platform, self.get_user_id(user), self.get_group_id(group_))
await punish.unpunish(self._unpunish, message)

View File

@@ -1,3 +1,5 @@
__all__ = ['FlanaDiscBot']
import asyncio
import os
@@ -6,7 +8,7 @@ from multibot import BadRoleError, DiscordBot, User
from flanabot import constants
from flanabot.bots.flana_bot import FlanaBot
from flanabot.models import Chat, Punishment
from flanabot.models import Chat, Message, Punishment
HEAT_NAMES = [
'Canal Congelado',
@@ -38,7 +40,7 @@ class FlanaDiscBot(DiscordBot, FlanaBot):
# ----------------------------------------------------------- #
def _add_handlers(self):
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):
while True:
@@ -57,16 +59,16 @@ class FlanaDiscBot(DiscordBot, FlanaBot):
await channel.edit(name=HEAT_NAMES[int(self.heat_level)])
async def _punish(self, user: int | str | User, group_: int | str | Chat):
user_id = self._get_user_id(user)
async def _punish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
user_id = self.get_user_id(user)
try:
await self.add_role(user_id, group_, 'Castigado')
await self.remove_role(user_id, group_, 'Persona')
except AttributeError:
raise BadRoleError(str(self._punish))
async def _unpunish(self, user: int | str | User, group_: int | str | Chat):
user_id = self._get_user_id(user)
async def _unpunish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
user_id = self.get_user_id(user)
try:
await self.add_role(user_id, group_, 'Persona')
await self.remove_role(user_id, group_, 'Castigado')
@@ -92,11 +94,11 @@ class FlanaDiscBot(DiscordBot, FlanaBot):
# -------------------------------------------------------- #
# -------------------- 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_)
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({
'platform': self.bot_platform.value,
'platform': self.platform.value,
'user_id': user.id,
'group_id': group_id,
'is_active': True

View File

@@ -1,5 +1,7 @@
from __future__ import annotations # todo0 remove in 3.11
__all__ = ['whitelisted_event', 'FlanaTeleBot']
import functools
import os
from typing import Callable
@@ -53,7 +55,7 @@ class FlanaTeleBot(TelegramBot, FlanaBot):
@user_client
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 #

View File

@@ -4,13 +4,14 @@ import flanautils
AUTO_WEATHER_EVERY = datetime.timedelta(hours=6)
CHECK_PUNISHMENTS_EVERY_SECONDS = datetime.timedelta(hours=1).total_seconds()
FLOOD_2s_LIMIT = 4
FLOOD_7s_LIMIT = 7
HEAT_PERIOD_SECONDS = datetime.timedelta(minutes=15).total_seconds()
INSULT_PROBABILITY = 0.00166666667
MAX_PLACE_QUERY_LENGTH = 50
PUNISHMENT_INCREMENT_EXPONENT = 6
PUNISHMENTS_RESET = datetime.timedelta(weeks=6 * flanautils.WEEKS_IN_A_MONTH)
RECOVERY_DELETED_MESSAGE_BEFORE = datetime.timedelta(hours=1)
TIME_THRESHOLD_TO_MANUAL_UNPUNISH = datetime.timedelta(days=3)
SCRAPING_MESSAGE_WAITING_TIME = 0.1
BYE_PHRASES = ('Adiós.', 'adieu', 'adio', 'adioh', 'adios', 'adió', 'adiós', 'agur', 'bye', 'byyeeee', 'chao',
@@ -20,30 +21,67 @@ BYE_PHRASES = ('Adiós.', 'adieu', 'adio', 'adioh', 'adios', 'adió', 'adiós',
HELLO_PHRASES = ('alo', 'aloh', 'buenas', 'Hola.', 'hello', 'hey', 'hi', 'hola', 'holaaaa', 'holaaaaaaa', 'ola',
'ola k ase', 'pa ti mi cola', 'saludos')
INSULTS = (
'Cállate ya anda.',
'¿Quién te ha preguntado?',
'¿Tú eres así o te dan apagones cerebrales?',
'._.',
'aha',
'Aléjate de mi.',
'Ante la duda mi dedo corazón te saluda.',
'Enjoy cancer brain.',
'Calla noob.',
'Hablas tanta mierda que tu culo tiene envidia de tu boca.',
'jAJjajAJjajAJjajAJajJAJajJA',
'enjoy xd',
'Reported.',
'Baneito pa ti en breve.',
'Despídete de tu cuenta.',
'Flanagan es más guapo que tú.',
'jajaj',
'xd',
'Hay un concurso de hostias y tienes todas las papeletas.',
'¿Por qué no te callas?',
'Calla noob.',
'Cansino.',
'Cuentame menos.',
'Cuentame más.',
'Cállate ya anda.',
'Cállate.',
'Das penilla.',
'De verdad. Estás para encerrarte.',
'Deberían hacerte la táctica del C4.',
'Te voy romper las pelotas.',
'Más tonto y no naces.',
'Despídete de tu cuenta.',
'Déjame tranquilo.',
'Enjoy cancer brain.',
'Eres cortito, ¿eh?',
'Eres más malo que pegarle a un padre.',
'Eres más tonto que peinar bombillas.',
'Eres más tonto que pellizcar cristales.',
'Eres más malo que pegarle a un padre.'
'Estás mal de la azotea.',
'Estás mal de la cabeza.',
'Flanagan es más guapo que tú.',
'Hablas tanta mierda que tu culo tiene envidia de tu boca.',
'Hay un concurso de hostias y tienes todas las papeletas.',
'Loco.',
'Más tonto y no naces.',
'No eres muy avispado tú...',
'Pesado.',
'Que bien, ¿eh?',
'Que me dejes en paz.',
'Qué pesado.',
'Quita bicho.',
'Reportaito mi arma.',
'Reported.',
'Retard.',
'Te voy romper las pelotas.',
'Tú... no estás muy bien, ¿no?',
'Ya estamos otra vez...',
'Ya estamos...',
'enjoy xd',
'jAJjajAJjajAJjajAJajJAJajJA',
'jajaj',
'o_O',
'xd',
'¿Otra vez tú?',
'¿Pero cuándo te vas a callar?',
'¿Por qué no te callas?',
'¿Quién te ha preguntado?',
'¿Qúe quieres?',
'¿Te callas o te callo?',
'¿Te imaginas que me interesa?',
'¿Te quieres callar?',
'¿Todo bien?',
'¿Tú eres así o te dan apagones cerebrales?',
'🖕',
'😑',
'🙄',
'🤔',
'🤨'
)
KEYWORDS = {
@@ -72,14 +110,5 @@ KEYWORDS = {
'wetter')
}
RECOVER_PHRASES = (
'No hay nada que recuperar.',
'Ya lo he recuperado y enviado, así que callate ya.',
'Ya lo he recuperado y enviado, así que mejor estás antento antes de dar por culo.',
'Ya lo he recuperado y enviado, no lo voy a hacer dos veces.',
'Ya lo he recuperado y enviado. A ver si leemos más y jodemos menos.',
'Ya lo he reenviado.'
)
SCRAPING_PHRASES = ('Analizando...', 'Buscando...', 'Hackeando internet... 👀', 'Rebuscando en la web...',
'Robando cosas...', 'Scrapeando...', 'Scraping...')

View File

@@ -5,7 +5,6 @@ import flanautils
os.environ |= flanautils.find_environment_variables('../.env')
import asyncio
from flanabot.bots.flana_disc_bot import FlanaDiscBot
from flanabot.bots.flana_tele_bot import FlanaTeleBot

View File

@@ -1,5 +1,4 @@
from flanabot.models.chat import *
from flanabot.models.enums import *
from flanabot.models.message import *
from flanabot.models.punishment import *
from flanabot.models.weather_chart import *

View File

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

View File

@@ -1,8 +0,0 @@
from enum import auto
from flanautils import FlanaEnum
class ButtonsMessageType(FlanaEnum):
CONFIG = auto()
WEATHER = auto()

View File

@@ -1,5 +1,7 @@
from __future__ import annotations # todo0 remove in 3.11
__all__ = ['Message']
from dataclasses import dataclass, field
from typing import Iterable
@@ -13,6 +15,7 @@ from flanabot.models.weather_chart import WeatherChart
@dataclass(eq=False)
class Message(MultiBotMessage):
author: User = None
button_pressed_user: User = None
mentions: Iterable[User] = field(default_factory=list)
chat: Chat = 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)
class Punishment(Mute):
class Punishment(PunishmentBase):
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()

View File

@@ -1,3 +1,5 @@
__all__ = ['Direction', 'WeatherChart']
import datetime
from dataclasses import dataclass, field

View File

@@ -1,9 +1,9 @@
aiohttp==3.7.4.post0
aiohttp==3.8.1
aiosignal==1.2.0
anyio==3.5.0
asgiref==3.4.1
async-generator==1.10
async-timeout==3.0.1
async-timeout==4.0.2
attrs==21.4.0
beautifulsoup4==4.10.0
certifi==2021.10.8
@@ -14,7 +14,7 @@ click==8.0.3
colorama==0.4.4
cryptg==0.2.post4
cryptography==36.0.1
discord.py==2.0.0a4269+gb7e25645
discord.py @ git+https://github.com/Rapptz/discord.py@b7e25645dc68bbb828bf1ede711d098c6b183237
fastapi==0.71.0
flanaapis
flanautils
@@ -47,6 +47,7 @@ selenium-stealth==1.0.6
six==1.16.0
sniffio==1.2.0
sortedcontainers==2.4.0
soupsieve==2.3.1
starlette==0.17.1
sympy==1.9
Telethon==1.24.0
@@ -54,7 +55,7 @@ tenacity==8.0.1
TikTokApi==4.1.0
trio==0.19.0
trio-websocket==0.9.2
twitchio==2.1.4
twitchio==2.3.0
typing_extensions==4.0.1
ujson==5.1.0
urllib3==1.26.8

View File

@@ -7,7 +7,6 @@ os.environ |= flanautils.find_environment_variables('../.env')
import unittest
from typing import Iterable
from multibot import constants as multibot_constants
from flanabot.bots.flana_tele_bot import FlanaTeleBot
@@ -15,7 +14,7 @@ class TestParseCallbacks(unittest.TestCase):
def _test_no_always_callbacks(self, phrases: Iterable[str], callback: callable):
for i, phrase in enumerate(phrases):
with self.subTest(phrase):
callbacks = [registered_callback.callback for registered_callback in self.flana_tele_bot._parse_callbacks(phrase, multibot_constants.RATIO_REWARD_EXPONENT, multibot_constants.KEYWORDS_LENGHT_PENALTY, multibot_constants.MINIMUM_RATIO_TO_MATCH)
callbacks = [registered_callback.callback for registered_callback in self.flana_tele_bot._parse_callbacks(phrase, self.flana_tele_bot._registered_callbacks)
if not registered_callback.always]
self.assertEqual(1, len(callbacks))
self.assertEqual(callback, callbacks[0], f'\n\nExpected: {callback.__name__}\nActual: {callbacks[0].__name__}')
@@ -92,8 +91,7 @@ class TestParseCallbacks(unittest.TestCase):
def test_on_delete_original_config_activate(self):
phrases = [
'activa el borrado automatico',
'flanabot pon el auto delete activado',
'flanabot activa el autodelete'
'flanabot pon el auto delete activado'
]
self._test_no_always_callbacks(phrases, self.flana_tele_bot._on_delete_original_config_activate)
@@ -104,8 +102,7 @@ class TestParseCallbacks(unittest.TestCase):
def test_on_delete_original_config_deactivate(self):
phrases = [
'desactiva el borrado automatico',
'flanabot pon el auto delete desactivado',
'flanabot desactiva el autodelete'
'flanabot pon el auto delete desactivado'
]
self._test_no_always_callbacks(phrases, self.flana_tele_bot._on_delete_original_config_deactivate)
@@ -119,9 +116,9 @@ class TestParseCallbacks(unittest.TestCase):
def test_on_mute(self):
phrases = [
# 'silencia',
# 'silencia al pavo ese',
# 'calla a ese pesao',
'silencia',
'silencia al pavo ese',
'calla a ese pesao',
'haz que se calle',
'quitale el microfono a ese',
'quitale el micro',