11 Commits

Author SHA1 Message Date
AlberLC
f402293c99 Upgrade _on_choose 2022-06-27 04:22:47 +02:00
AlberLC
99effad710 Fix constants accents 2022-06-23 04:51:49 +02:00
AlberLC
54cada0649 Fix _on_choose 2022-06-23 04:31:45 +02:00
AlberLC
0f5d3c333a Fix commands at private 2022-06-23 04:13:36 +02:00
AlberLC
5fb55404cf Fix commands at private 2022-06-23 03:10:49 +02:00
AlberLC
2768d8e949 Fix commands at private 2022-06-23 02:17:59 +02:00
AlberLC
b0ca5a2ded Add ports to db local access 2022-06-23 02:17:33 +02:00
AlberLC
697ba9e89e Add polls 2022-06-22 09:18:42 +02:00
AlberLC
09df75ea0b Update buttons logic (add ButtonsInfo) and add choose and dice functionalities 2022-06-19 13:34:12 +02:00
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
7 changed files with 201 additions and 59 deletions

View File

@@ -7,6 +7,8 @@ services:
mongodb: mongodb:
image: mongo image: mongo
ports:
- "27017:27017"
environment: environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_USER} - MONGO_INITDB_ROOT_USERNAME=${MONGO_USER}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD} - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}

View File

@@ -3,10 +3,11 @@ __all__ = ['FlanaBot']
import asyncio import asyncio
import datetime import datetime
import random import random
import re
import time as time_module import time as time_module
from abc import ABC from abc import ABC
from asyncio import Future from asyncio import Future
from typing import Iterable from typing import Iterable, Sequence
import flanaapis.geolocation.functions import flanaapis.geolocation.functions
import flanaapis.weather.functions import flanaapis.weather.functions
@@ -15,7 +16,7 @@ import plotly.graph_objects
import pymongo import pymongo
from flanaapis import InstagramLoginError, MediaNotFoundError, Place, PlaceNotFoundError, WeatherEmoji, instagram, tiktok, twitter 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 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 multibot import Action, BadRoleError, BotAction, ButtonsGroup, MultiBot, SendError, User, admin, bot_mentioned, constants as multibot_constants, group, ignore_self_message, inline, reply
from flanabot import constants from flanabot import constants
from flanabot.models import Chat, Message, Punishment, WeatherChart from flanabot.models import Chat, Message, Punishment, WeatherChart
@@ -37,6 +38,10 @@ class FlanaBot(MultiBot, ABC):
self.register(self._on_bye, multibot_constants.KEYWORDS['bye']) self.register(self._on_bye, multibot_constants.KEYWORDS['bye'])
self.register(self._on_choose, constants.KEYWORDS['choose'])
self.register(self._on_choose, constants.KEYWORDS['random'])
self.register(self._on_choose, (constants.KEYWORDS['choose'], constants.KEYWORDS['random']))
self.register(self._on_config_list_show, multibot_constants.KEYWORDS['config']) self.register(self._on_config_list_show, multibot_constants.KEYWORDS['config'])
self.register(self._on_config_list_show, (multibot_constants.KEYWORDS['show'], multibot_constants.KEYWORDS['config'])) self.register(self._on_config_list_show, (multibot_constants.KEYWORDS['show'], multibot_constants.KEYWORDS['config']))
@@ -79,6 +84,8 @@ class FlanaBot(MultiBot, ABC):
self.register(self._on_delete_original_config_show, (multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message'], multibot_constants.KEYWORDS['config'])) self.register(self._on_delete_original_config_show, (multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message'], multibot_constants.KEYWORDS['config']))
self.register(self._on_delete_original_config_show, (multibot_constants.KEYWORDS['show'], multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message'], multibot_constants.KEYWORDS['config'])) self.register(self._on_delete_original_config_show, (multibot_constants.KEYWORDS['show'], multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message'], multibot_constants.KEYWORDS['config']))
self.register(self._on_dice, constants.KEYWORDS['dice'])
self.register(self._on_hello, multibot_constants.KEYWORDS['hello']) self.register(self._on_hello, multibot_constants.KEYWORDS['hello'])
self.register(self._on_new_message_default, default=True) self.register(self._on_new_message_default, default=True)
@@ -88,6 +95,8 @@ class FlanaBot(MultiBot, ABC):
self.register(self._on_no_delete_original, (multibot_constants.KEYWORDS['negate'], multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message'])) self.register(self._on_no_delete_original, (multibot_constants.KEYWORDS['negate'], multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message']))
self.register(self._on_no_delete_original, (multibot_constants.KEYWORDS['deactivate'], multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message'])) self.register(self._on_no_delete_original, (multibot_constants.KEYWORDS['deactivate'], multibot_constants.KEYWORDS['delete'], multibot_constants.KEYWORDS['message']))
self.register(self._on_poll, constants.KEYWORDS['poll'])
self.register(self._on_punish, constants.KEYWORDS['punish']) self.register(self._on_punish, constants.KEYWORDS['punish'])
self.register(self._on_punish, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['unpunish'])) self.register(self._on_punish, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['unpunish']))
self.register(self._on_punish, (multibot_constants.KEYWORDS['deactivate'], multibot_constants.KEYWORDS['permission'])) self.register(self._on_punish, (multibot_constants.KEYWORDS['deactivate'], multibot_constants.KEYWORDS['permission']))
@@ -111,6 +120,11 @@ class FlanaBot(MultiBot, ABC):
self.register(self._on_song_info, constants.KEYWORDS['song_info']) self.register(self._on_song_info, constants.KEYWORDS['song_info'])
self.register(self._on_stop_poll, multibot_constants.KEYWORDS['deactivate'])
self.register(self._on_stop_poll, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['poll']))
self.register(self._on_stop_poll, multibot_constants.KEYWORDS['stop'])
self.register(self._on_stop_poll, (multibot_constants.KEYWORDS['stop'], constants.KEYWORDS['poll']))
self.register(self._on_unpunish, constants.KEYWORDS['unpunish']) self.register(self._on_unpunish, constants.KEYWORDS['unpunish'])
self.register(self._on_unpunish, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['punish'])) self.register(self._on_unpunish, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['punish']))
@@ -131,8 +145,9 @@ 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, (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(self._on_weather_chart_config_show, (multibot_constants.KEYWORDS['show'], constants.KEYWORDS['weather_chart'], multibot_constants.KEYWORDS['config']))
self.register_button(self._on_config_button_press, list(Chat.DEFAULT_CONFIG.keys())) self.register_button(self._on_config_button_press, ButtonsGroup.CONFIG)
self.register_button(self._on_weather_button_press, WeatherEmoji.values) self.register_button(self._on_poll_button_press, ButtonsGroup.POLL)
self.register_button(self._on_weather_button_press, ButtonsGroup.WEATHER)
async def _change_config(self, config_name: str, message: Message, value: bool = None): async def _change_config(self, config_name: str, message: Message, value: bool = None):
if value is None: if value is None:
@@ -152,20 +167,15 @@ class FlanaBot(MultiBot, ABC):
last_2s_messages = Message.find({ last_2s_messages = Message.find({
'platform': self.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.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),
'$lt': datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(seconds=2)
}
}) })
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({ n_punishments = len(Punishment.find({
'platform': self.platform.value, 'platform': self.platform.value,
'user_id': message.author.id, 'user_id': message.author.id,
@@ -179,18 +189,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)
@staticmethod
def _get_config_buttons(config: dict | Chat | Message) -> list[list[str]]:
match config:
case Chat() as chat:
config = chat.config
case Message() as message:
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()) @return_if_first_empty(exclude_self_types='FlanaBot', globals_=globals())
async def _manage_exceptions(self, exceptions: BaseException | Iterable[BaseException], context: Chat | Message): async def _manage_exceptions(self, exceptions: BaseException | Iterable[BaseException], context: Chat | Message):
if not isinstance(exceptions, Iterable): if not isinstance(exceptions, Iterable):
@@ -271,7 +269,7 @@ class FlanaBot(MultiBot, ABC):
return_exceptions=True return_exceptions=True
) )
if not message.is_inline and (self.is_bot_mentioned(message) or not message.chat.is_group): if not message.is_inline and (self.is_bot_mentioned(message) or message.chat.is_private):
while not results.done(): while not results.done():
if constants.SCRAPING_MESSAGE_WAITING_TIME <= time_module.perf_counter() - start_time: if constants.SCRAPING_MESSAGE_WAITING_TIME <= time_module.perf_counter() - start_time:
bot_state_message = await self.send(random.choice(constants.SCRAPING_PHRASES), message) bot_state_message = await self.send(random.choice(constants.SCRAPING_PHRASES), message)
@@ -298,23 +296,51 @@ class FlanaBot(MultiBot, ABC):
# HANDLERS # # HANDLERS #
# ---------------------------------------------- # # ---------------------------------------------- #
async def _on_bye(self, message: Message): async def _on_bye(self, message: Message):
if not message.chat.is_group or self.is_bot_mentioned(message): if message.chat.is_private or self.is_bot_mentioned(message):
await self.send_bye(message) await self.send_bye(message)
async def _on_config_button_press(self, message: Message): async def _on_choose(self, message: Message):
await self._accept_button_event(message) if message.chat.is_group and not self.is_bot_mentioned(message):
if not message.button_pressed_user.is_admin or 'auto_' not in (config := message.button_pressed_text.split()[1]):
return return
discarded_words = {
*constants.KEYWORDS['choose'],
*constants.KEYWORDS['random'],
self.name.lower(), f'<@{self.id}>',
*flanautils.CommonWords.get('conjunctions'),
'entre', 'between'
}
if final_words := [word for word in message.text.split() if not flanautils.cartesian_product_string_matching(word.lower(), discarded_words, min_ratio=multibot_constants.PARSE_CALLBACKS_MIN_RATIO_DEFAULT)]:
for i in range(1, len(final_words) - 1):
if final_words[i] in ('al', 'del', 'to'):
n1 = final_words[i - 1]
n2 = final_words[i + 1]
await self.send(random.randint(n1, n2), message)
return
await self.send(random.choice(final_words), message)
else:
await self.send(random.choice(('¿Que elija el qué?', '¿Y las opciones?', '?', '🤔')), message)
async def _on_config_button_press(self, message: Message):
await self.accept_button_event(message)
if message.buttons_info.presser_user.is_admin is False:
return
config = message.buttons_info.pressed_text.split()[1]
message.chat.config[config] = not message.chat.config[config] message.chat.config[config] = not message.chat.config[config]
message.save() pressed_button = message.buttons_info.pressed_button
await self.edit('<b>Estos son los ajustes del grupo:</b>\n\n', self._get_config_buttons(message), message) pressed_button.is_checked = not pressed_button.is_checked
pressed_button.text = f"{'' if pressed_button.is_checked else ''} {config}"
await self.edit('<b>Estos son los ajustes del grupo:</b>\n\n', message.buttons_info.buttons, message)
@group @group
@bot_mentioned @bot_mentioned
async def _on_config_list_show(self, message: Message): async def _on_config_list_show(self, message: Message):
await self.send('<b>Estos son los ajustes del grupo:</b>\n\n', self._get_config_buttons(message), message) buttons_texts = [(f"{'' if v else ''} {k}", v) for k, v in message.chat.config.items()]
await self.send('<b>Estos son los ajustes del grupo:</b>\n\n', flanautils.chunks(buttons_texts, 3), message, buttons_key=ButtonsGroup.CONFIG)
async def _on_covid_chart(self, message: Message): # todo2 async def _on_covid_chart(self, message: Message): # todo2
pass pass
@@ -370,8 +396,17 @@ class FlanaBot(MultiBot, ABC):
async def _on_delete_original_config_show(self, message: Message): async def _on_delete_original_config_show(self, message: Message):
await self._show_config('auto_delete_original', message) await self._show_config('auto_delete_original', message)
async def _on_dice(self, message: Message):
if message.chat.is_group and not self.is_bot_mentioned(message):
return
if top_number := flanautils.sum_numbers_in_text(message.text):
await self.send(random.randint(1, top_number), message)
else:
await self.send(random.choice(('¿De cuántas caras?', '¿Y el número?', '?', '🤔')), message)
async def _on_hello(self, message: Message): async def _on_hello(self, message: Message):
if not message.chat.is_group or self.is_bot_mentioned(message): if message.chat.is_private or self.is_bot_mentioned(message):
await self.send_hello(message) await self.send_hello(message)
async def _on_new_message_default(self, message: Message): async def _on_new_message_default(self, message: Message):
@@ -415,6 +450,55 @@ class FlanaBot(MultiBot, ABC):
if not await self._on_scraping(message, delete_original=False): if not await self._on_scraping(message, delete_original=False):
await self._on_recover_message(message) await self._on_recover_message(message)
def _distribute_poll_buttons(self, texts: Sequence[str]) -> list[list[str]]:
pass
async def _on_poll(self, message: Message):
if message.chat.is_group and not self.is_bot_mentioned(message):
return
discarded_words = {*constants.KEYWORDS['poll'], self.name.lower(), f'<@{self.id}>'}
if final_options := [option.title() for option in message.text.split() if not flanautils.cartesian_product_string_matching(option.lower(), discarded_words, min_ratio=multibot_constants.PARSE_CALLBACKS_MIN_RATIO_DEFAULT)]:
await self.send('Encuesta en curso...', self._distribute_poll_buttons(final_options), message, buttons_key=ButtonsGroup.POLL, contents={'poll': {'is_active': True, 'votes': {option: [] for option in final_options}}})
else:
await self.send(random.choice(('¿Y las opciones?', '?', '🤔')), message)
async def _on_poll_button_press(self, message: Message):
await self.accept_button_event(message)
if not message.contents['poll']['is_active']:
return
option_name = results[0] if (results := re.findall('(.*?) ➜.+', message.buttons_info.pressed_text)) else message.buttons_info.pressed_text
selected_option_votes = message.contents['poll']['votes'][option_name]
presser_id = message.buttons_info.presser_user.id
presser_name = message.buttons_info.presser_user.name.split('#')[0]
total_votes = sum(len(option_votes) for option_votes in message.contents['poll']['votes'].values())
if [presser_id, presser_name] in selected_option_votes:
selected_option_votes.remove([presser_id, presser_name])
total_votes -= 1
else:
for option_votes in message.contents['poll']['votes'].values():
try:
option_votes.remove([presser_id, presser_name])
except ValueError:
pass
else:
total_votes -= 1
break
selected_option_votes.append((presser_id, presser_name))
total_votes += 1
if total_votes:
buttons = []
for option, option_votes in message.contents['poll']['votes'].items():
percent = f'{round(len(option_votes) / total_votes * 100)}%'
names = f"({', '.join(option_vote[1] for option_vote in option_votes)})" if option_votes else ''
buttons.append(f'{option}{percent} {names}')
else:
buttons = list(message.contents['poll']['votes'].keys())
await self.edit(self._distribute_poll_buttons(buttons), message)
@bot_mentioned @bot_mentioned
@group @group
@admin(send_negative=True) @admin(send_negative=True)
@@ -515,9 +599,48 @@ class FlanaBot(MultiBot, ABC):
if song_infos: if song_infos:
for song_info in song_infos: for song_info in song_infos:
await self.send_song_info(song_info, message) await self.send_song_info(song_info, message)
elif self.is_bot_mentioned(message) or not message.chat.is_group: elif self.is_bot_mentioned(message) or message.chat.is_private:
await self._manage_exceptions(SendError('No hay información musical en ese mensaje.'), message) await self._manage_exceptions(SendError('No hay información musical en ese mensaje.'), message)
async def _on_stop_poll(self, message: Message):
if poll_message := message.replied_message:
if poll_message.contents.get('poll') is None:
return
elif (
(message.chat.is_private or self.is_bot_mentioned(message))
and
flanautils.cartesian_product_string_matching(message.text, constants.KEYWORDS['poll'], min_ratio=multibot_constants.PARSE_CALLBACKS_MIN_RATIO_DEFAULT)
and
(poll_message := Message.find_one({'contents.poll.is_active': True}, sort_keys=(('date', pymongo.DESCENDING),)))
):
poll_message = await self.get_message(poll_message.chat.id, poll_message.id)
else:
return
winners = []
max_votes = 1
for option, votes in poll_message.contents['poll']['votes'].items():
if len(votes) > max_votes:
winners = [option]
max_votes = len(votes)
elif len(votes) == max_votes:
winners.append(option)
match winners:
case [_, _, *_]:
winners = [f'<b>{winner}</b>' for winner in winners]
text = f"Encuesta finalizada. Los ganadores son: {flanautils.join_last_separator(winners, ', ', ' y ')}."
case [winner]:
text = f'Encuesta finalizada. Ganador: <b>{winner}</b>.'
case _:
text = 'Encuesta finalizada.'
poll_message.contents['poll']['is_active'] = False
await self.edit(text, poll_message)
if not message.replied_message:
await self.send(text, reply_to=poll_message)
@group @group
@bot_mentioned @bot_mentioned
@admin(send_negative=True) @admin(send_negative=True)
@@ -526,9 +649,9 @@ class FlanaBot(MultiBot, ABC):
await self.unpunish(user, message, message) await self.unpunish(user, message, message)
async def _on_weather_button_press(self, message: Message): async def _on_weather_button_press(self, message: Message):
await self._accept_button_event(message) await self.accept_button_event(message)
match message.button_pressed_text: match message.buttons_info.pressed_text:
case WeatherEmoji.ZOOM_IN.value: case WeatherEmoji.ZOOM_IN.value:
message.weather_chart.zoom_in() message.weather_chart.zoom_in()
case WeatherEmoji.ZOOM_OUT.value: case WeatherEmoji.ZOOM_OUT.value:
@@ -548,7 +671,6 @@ class FlanaBot(MultiBot, ABC):
message.weather_chart.apply_zoom() message.weather_chart.apply_zoom()
message.weather_chart.draw() message.weather_chart.draw()
message.save()
image_bytes = message.weather_chart.to_image() image_bytes = message.weather_chart.to_image()
await self.edit(Media(image_bytes, MediaType.IMAGE), message) await self.edit(Media(image_bytes, MediaType.IMAGE), message)
@@ -590,7 +712,7 @@ class FlanaBot(MultiBot, ABC):
- flanautils.cartesian_product_string_matching(original_text_words, multibot_constants.KEYWORDS['date'], min_ratio=0.85).keys() - flanautils.cartesian_product_string_matching(original_text_words, multibot_constants.KEYWORDS['date'], min_ratio=0.85).keys()
- flanautils.cartesian_product_string_matching(original_text_words, multibot_constants.KEYWORDS['thanks'], min_ratio=0.85).keys() - flanautils.cartesian_product_string_matching(original_text_words, multibot_constants.KEYWORDS['thanks'], min_ratio=0.85).keys()
- possible_mentioned_ids - possible_mentioned_ids
- flanautils.CommonWords.all_words - flanautils.CommonWords.get()
) )
if not place_words: if not place_words:
if not message.is_inline: if not message.is_inline:
@@ -682,6 +804,7 @@ class FlanaBot(MultiBot, ABC):
[WeatherEmoji.HUMIDITY.value, WeatherEmoji.PRECIPITATION_PROBABILITY.value, WeatherEmoji.PRECIPITATION_VOLUME.value, WeatherEmoji.PRESSURE.value, WeatherEmoji.WIND_SPEED.value] [WeatherEmoji.HUMIDITY.value, WeatherEmoji.PRECIPITATION_PROBABILITY.value, WeatherEmoji.PRECIPITATION_VOLUME.value, WeatherEmoji.PRESSURE.value, WeatherEmoji.WIND_SPEED.value]
], ],
message, message,
buttons_key=ButtonsGroup.WEATHER,
send_as_file=False send_as_file=False
) )
await self.send_inline_results(message) await self.send_inline_results(message)

View File

@@ -2,9 +2,11 @@ __all__ = ['FlanaDiscBot']
import asyncio import asyncio
import os import os
from typing import Sequence
import discord import discord
from multibot import BadRoleError, DiscordBot, User import flanautils
from multibot import BadRoleError, DiscordBot, User, constants as multibot_constants
from flanabot import constants from flanabot import constants
from flanabot.bots.flana_bot import FlanaBot from flanabot.bots.flana_bot import FlanaBot
@@ -42,6 +44,13 @@ class FlanaDiscBot(DiscordBot, FlanaBot):
super()._add_handlers() super()._add_handlers()
self.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')
# noinspection PyTypeChecker
def _distribute_poll_buttons(self, texts: Sequence[str]) -> list[list[str]]:
if len(texts) <= multibot_constants.DISCORD_BUTTONS_MAX:
return flanautils.chunks(texts, 1)
else:
return flanautils.chunks(texts, multibot_constants.DISCORD_BUTTONS_MAX)
async def _heat_channel(self, channel: discord.VoiceChannel): async def _heat_channel(self, channel: discord.VoiceChannel):
while True: while True:
await asyncio.sleep(constants.HEAT_PERIOD_SECONDS) await asyncio.sleep(constants.HEAT_PERIOD_SECONDS)

View File

@@ -4,8 +4,9 @@ __all__ = ['whitelisted_event', 'FlanaTeleBot']
import functools import functools
import os import os
from typing import Callable from typing import Callable, Sequence
import flanautils
import telethon.tl.functions import telethon.tl.functions
from multibot import TelegramBot, find_message, user_client from multibot import TelegramBot, find_message, user_client
@@ -46,6 +47,10 @@ class FlanaTeleBot(TelegramBot, FlanaBot):
# ----------------------------------------------------------- # # ----------------------------------------------------------- #
# -------------------- PROTECTED METHODS -------------------- # # -------------------- PROTECTED METHODS -------------------- #
# ----------------------------------------------------------- # # ----------------------------------------------------------- #
def _distribute_poll_buttons(self, texts: Sequence[str]) -> list[list[str]]:
# noinspection PyTypeChecker
return flanautils.chunks(texts, 1)
@user_client @user_client
async def _get_contacts_ids(self) -> list[int]: async def _get_contacts_ids(self) -> list[int]:
async with self.user_client: async with self.user_client:

View File

@@ -4,6 +4,8 @@ import flanautils
AUTO_WEATHER_EVERY = datetime.timedelta(hours=6) AUTO_WEATHER_EVERY = datetime.timedelta(hours=6)
CHECK_PUNISHMENTS_EVERY_SECONDS = datetime.timedelta(hours=1).total_seconds() 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() HEAT_PERIOD_SECONDS = datetime.timedelta(minutes=15).total_seconds()
INSULT_PROBABILITY = 0.00166666667 INSULT_PROBABILITY = 0.00166666667
MAX_PLACE_QUERY_LENGTH = 50 MAX_PLACE_QUERY_LENGTH = 50
@@ -20,13 +22,14 @@ HELLO_PHRASES = ('alo', 'aloh', 'buenas', 'Hola.', 'hello', 'hey', 'hi', 'hola',
'ola k ase', 'pa ti mi cola', 'saludos') 'ola k ase', 'pa ti mi cola', 'saludos')
INSULTS = ( INSULTS = (
'._.', '._.',
'aha',
'Aléjate de mi.', 'Aléjate de mi.',
'Ante la duda mi dedo corazón te saluda.', 'Ante la duda mi dedo corazón te saluda.',
'Baneito pa ti en breve.', 'Baneito pa ti en breve.',
'Calla noob.', 'Calla noob.',
'Cansino.', 'Cansino.',
'Cuentame menos.', 'Cuéntame menos.',
'Cuentame más.', 'Cuéntame más.',
'Cállate ya anda.', 'Cállate ya anda.',
'Cállate.', 'Cállate.',
'Das penilla.', 'Das penilla.',
@@ -47,8 +50,8 @@ INSULTS = (
'Loco.', 'Loco.',
'Más tonto y no naces.', 'Más tonto y no naces.',
'No eres muy avispado tú...', 'No eres muy avispado tú...',
'Pesado', 'Pesado.',
'Que bien, ¿eh?', 'Qué bien, ¿eh?',
'Que me dejes en paz.', 'Que me dejes en paz.',
'Qué pesado.', 'Qué pesado.',
'Quita bicho.', 'Quita bicho.',
@@ -70,7 +73,7 @@ INSULTS = (
'¿Quién te ha preguntado?', '¿Quién te ha preguntado?',
'¿Qúe quieres?', '¿Qúe quieres?',
'¿Te callas o te callo?', '¿Te callas o te callo?',
'¿Te imaginas que me interesa?aha', '¿Te imaginas que me interesa?',
'¿Te quieres callar?', '¿Te quieres callar?',
'¿Todo bien?', '¿Todo bien?',
'¿Tú eres así o te dan apagones cerebrales?', '¿Tú eres así o te dan apagones cerebrales?',
@@ -82,16 +85,20 @@ INSULTS = (
) )
KEYWORDS = { KEYWORDS = {
'choose': ('choose', 'elige', 'escoge'),
'covid_chart': ('case', 'caso', 'contagiado', 'contagio', 'corona', 'coronavirus', 'covid', 'covid19', 'death', 'covid_chart': ('case', 'caso', 'contagiado', 'contagio', 'corona', 'coronavirus', 'covid', 'covid19', 'death',
'disease', 'enfermedad', 'enfermos', 'fallecido', 'incidencia', 'jacovid', 'mascarilla', 'muerte', 'disease', 'enfermedad', 'enfermos', 'fallecido', 'incidencia', 'jacovid', 'mascarilla', 'muerte',
'muerto', 'pandemia', 'sick', 'virus'), 'muerto', 'pandemia', 'sick', 'virus'),
'currency_chart': ('argentina', 'bitcoin', 'cardano', 'cripto', 'crypto', 'criptodivisa', 'cryptodivisa', 'currency_chart': ('argentina', 'bitcoin', 'cardano', 'cripto', 'crypto', 'criptodivisa', 'cryptodivisa',
'cryptomoneda', 'cryptocurrency', 'currency', 'dinero', 'divisa', 'ethereum', 'inversion', 'cryptomoneda', 'cryptocurrency', 'currency', 'dinero', 'divisa', 'ethereum', 'inversion',
'moneda', 'pasta'), 'moneda', 'pasta'),
'dice': ('dado', 'dice'),
'poll': ('encuesta', 'poll', 'quiz'),
'punish': ('acaba', 'aprende', 'ataca', 'atalo', 'azota', 'boss', 'castiga', 'castigo', 'condena', 'controla', 'punish': ('acaba', 'aprende', 'ataca', 'atalo', 'azota', 'boss', 'castiga', 'castigo', 'condena', 'controla',
'destroy', 'destroza', 'duro', 'ejecuta', 'enseña', 'escarmiento', 'execute', 'finish', 'fuck', 'fusila', 'destroy', 'destroza', 'duro', 'ejecuta', 'enseña', 'escarmiento', 'execute', 'fuck', 'fusila', 'hell',
'hell', 'humos', 'infierno', 'jefe', 'jode', 'learn', 'leccion', 'lesson', 'manda', 'purgatorio', 'humos', 'infierno', 'jefe', 'jode', 'learn', 'leccion', 'lesson', 'manda', 'purgatorio', 'sancion',
'sancion', 'shoot', 'teach', 'termina', 'whip'), 'shoot', 'teach', 'whip'),
'random': ('aleatorio', 'azar', 'random'),
'scraping': ('api', 'aqui', 'busca', 'contenido', 'content', 'descarga', 'descargar', 'download', 'envia', 'habia', 'scraping': ('api', 'aqui', 'busca', 'contenido', 'content', 'descarga', 'descargar', 'download', 'envia', 'habia',
'media', 'redes', 'scrap', 'scraping', 'search', 'send', 'social', 'sociales', 'tenia', 'video', 'media', 'redes', 'scrap', 'scraping', 'search', 'send', 'social', 'sociales', 'tenia', 'video',
'videos'), 'videos'),

View File

@@ -15,7 +15,6 @@ 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

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