Add delete votes and voting ban

This commit is contained in:
AlberLC
2022-10-29 03:16:54 +02:00
parent 967439846f
commit bdbc4d5e0d
3 changed files with 134 additions and 60 deletions

View File

@@ -6,7 +6,7 @@ import math
import random import random
import re import re
from abc import ABC from abc import ABC
from typing import Iterable, Sequence, Type from typing import Iterable, Sequence
import flanaapis.geolocation.functions import flanaapis.geolocation.functions
import flanaapis.weather.functions import flanaapis.weather.functions
@@ -45,6 +45,9 @@ class FlanaBot(MultiBot, ABC):
self.register(self._on_choose, constants.KEYWORDS['random'], priority=2) self.register(self._on_choose, constants.KEYWORDS['random'], priority=2)
self.register(self._on_choose, (constants.KEYWORDS['choose'], constants.KEYWORDS['random']), priority=2) self.register(self._on_choose, (constants.KEYWORDS['choose'], constants.KEYWORDS['random']), priority=2)
self.register(self._on_delete_votes, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['vote']))
self.register(self._on_delete_votes, (multibot_constants.KEYWORDS['delete'], constants.KEYWORDS['vote']))
self.register(self._on_dice, constants.KEYWORDS['dice']) 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'])
@@ -90,8 +93,12 @@ class FlanaBot(MultiBot, ABC):
self.register(self._on_unpunish, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['punish'])) self.register(self._on_unpunish, (multibot_constants.KEYWORDS['deactivate'], constants.KEYWORDS['punish']))
self.register(self._on_unpunish, (multibot_constants.KEYWORDS['activate'], multibot_constants.KEYWORDS['permission'])) self.register(self._on_unpunish, (multibot_constants.KEYWORDS['activate'], multibot_constants.KEYWORDS['permission']))
self.register(self._on_weather_chart, constants.KEYWORDS['weather_chart']) self.register(self._on_voting_ban, (multibot_constants.KEYWORDS['deactivate'], multibot_constants.KEYWORDS['permission'], constants.KEYWORDS['vote']))
self.register(self._on_weather_chart, (multibot_constants.KEYWORDS['show'], constants.KEYWORDS['weather_chart']))
self.register(self._on_voting_unban, (multibot_constants.KEYWORDS['activate'], multibot_constants.KEYWORDS['permission'], constants.KEYWORDS['vote']))
self.register(self._on_weather, constants.KEYWORDS['weather_chart'])
self.register(self._on_weather, (multibot_constants.KEYWORDS['show'], constants.KEYWORDS['weather_chart']))
self.register_button(self._on_poll_button_press, ButtonsGroup.POLL) self.register_button(self._on_poll_button_press, ButtonsGroup.POLL)
self.register_button(self._on_roles_button_press, ButtonsGroup.ROLES) self.register_button(self._on_roles_button_press, ButtonsGroup.ROLES)
@@ -149,6 +156,22 @@ class FlanaBot(MultiBot, ABC):
else: else:
return text.split() return text.split()
async def _get_poll_message(self, message: Message) -> Message | None:
if poll_message := message.replied_message:
if poll_message.contents.get('poll') is None:
return
return poll_message
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),)))
):
return await self.get_message(poll_message.chat.id, poll_message.id)
else:
return
@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):
@@ -298,6 +321,23 @@ class FlanaBot(MultiBot, ABC):
async def _unpunish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None): async def _unpunish(self, user: int | str | User, group_: int | str | Chat | Message, message: Message = None):
pass pass
async def _update_poll_buttons(self, message: Message):
if message.contents['poll']['is_multiple_answer']:
total_votes = len({option_vote[0] for option_votes in message.contents['poll']['votes'].values() if option_votes for option_vote in option_votes})
else:
total_votes = sum(len(option_votes) for option_votes in message.contents['poll']['votes'].values())
if total_votes:
buttons = []
for option, option_votes in message.contents['poll']['votes'].items():
ratio = f'{len(option_votes)}/{total_votes}'
names = f"({', '.join(option_vote[1] for option_vote in option_votes)})" if option_votes else ''
buttons.append(f'{option}{ratio} {names}')
else:
buttons = list(message.contents['poll']['votes'].keys())
await self.edit(self._distribute_buttons(buttons), message)
# ---------------------------------------------- # # ---------------------------------------------- #
# HANDLERS # # HANDLERS #
# ---------------------------------------------- # # ---------------------------------------------- #
@@ -339,6 +379,19 @@ class FlanaBot(MultiBot, ABC):
else: else:
await self.send(random.choice(('¿Que elija el qué?', '¿Y las opciones?', '?', '🤔')), message) await self.send(random.choice(('¿Que elija el qué?', '¿Y las opciones?', '?', '🤔')), message)
@admin
async def _on_delete_votes(self, message: Message):
if message.chat.is_group and not self.is_bot_mentioned(message) or not (poll_message := await self._get_poll_message(message)):
return
await self.delete_message(message)
for user in await self._find_users_to_punish(message):
for option_name, option_votes in poll_message.contents['poll']['votes'].items():
poll_message.contents['poll']['votes'][option_name] = [option_vote for option_vote in option_votes if option_vote[0] != user.id]
await self._update_poll_buttons(poll_message)
async def _on_dice(self, message: Message): async def _on_dice(self, message: Message):
if message.chat.is_group and not self.is_bot_mentioned(message): if message.chat.is_group and not self.is_bot_mentioned(message):
return return
@@ -414,23 +467,39 @@ class FlanaBot(MultiBot, ABC):
self._distribute_buttons(final_options), self._distribute_buttons(final_options),
message, message,
buttons_key=ButtonsGroup.POLL, buttons_key=ButtonsGroup.POLL,
contents={'poll': {'is_active': True, 'is_multiple_answer': is_multiple_answer, 'votes': {option: [] for option in final_options}}} contents={'poll': {
'is_active': True,
'is_multiple_answer': is_multiple_answer,
'votes': {option: [] for option in final_options},
'banned_users_tries': {}
}}
) )
else: else:
await self.send(random.choice(('¿Y las opciones?', '?', '🤔')), message) await self.send(random.choice(('¿Y las opciones?', '?', '🤔')), message)
async def _on_poll_multi(self, message: Message):
await self._on_poll(message, is_multiple_answer=True)
async def _on_poll_button_press(self, message: Message): async def _on_poll_button_press(self, message: Message):
await self.accept_button_event(message) await self.accept_button_event(message)
if not message.contents['poll']['is_active']: if not message.contents['poll']['is_active']:
return 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_id = message.buttons_info.presser_user.id
presser_name = message.buttons_info.presser_user.name.split('#')[0] presser_name = message.buttons_info.presser_user.name.split('#')[0]
if (presser_id_str := str(presser_id)) in message.contents['poll']['banned_users_tries']:
message.contents['poll']['banned_users_tries'][presser_id_str] += 1
message.save()
if message.contents['poll']['banned_users_tries'][presser_id_str] == 3:
await self.send(random.choice((
f'Deja de dar por culo {presser_name}, que no puedes votar aqui.',
f'No es pesao {presser_name}, que no tienes permitido votar aqui',
f'Deja de pulsar botones que no puedes votar aqui {presser_name}',
f'{presser_name} deja de intentar votar aqui que no puedes',
f'Te han prohibido votar aqui {presser_name}',
f'No puedes votar aqui {presser_name}'
)), reply_to=message)
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]
if [presser_id, presser_name] in selected_option_votes: if [presser_id, presser_name] in selected_option_votes:
selected_option_votes.remove([presser_id, presser_name]) selected_option_votes.remove([presser_id, presser_name])
@@ -445,21 +514,10 @@ class FlanaBot(MultiBot, ABC):
break break
selected_option_votes.append((presser_id, presser_name)) selected_option_votes.append((presser_id, presser_name))
if message.contents['poll']['is_multiple_answer']: await self._update_poll_buttons(message)
total_votes = len({option_vote[0] for option_votes in message.contents['poll']['votes'].values() if option_votes for option_vote in option_votes})
else:
total_votes = sum(len(option_votes) for option_votes in message.contents['poll']['votes'].values())
if total_votes: async def _on_poll_multi(self, message: Message):
buttons = [] await self._on_poll(message, is_multiple_answer=True)
for option, option_votes in message.contents['poll']['votes'].items():
ratio = f'{len(option_votes)}/{total_votes}'
names = f"({', '.join(option_vote[1] for option_vote in option_votes)})" if option_votes else ''
buttons.append(f'{option}{ratio} {names}')
else:
buttons = list(message.contents['poll']['votes'].keys())
await self.edit(self._distribute_buttons(buttons), message)
@bot_mentioned @bot_mentioned
@group @group
@@ -555,18 +613,7 @@ class FlanaBot(MultiBot, ABC):
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): async def _on_stop_poll(self, message: Message):
if poll_message := message.replied_message: if not (poll_message := await self._get_poll_message(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 return
winners = [] winners = []
@@ -603,34 +650,33 @@ class FlanaBot(MultiBot, ABC):
for user in await self._find_users_to_punish(message): for user in await self._find_users_to_punish(message):
await self.unpunish(user, message, message) await self.unpunish(user, message, message)
async def _on_weather_button_press(self, message: Message): @admin
await self.accept_button_event(message) async def _on_voting_ban(self, message: Message):
if message.chat.is_group and not self.is_bot_mentioned(message) or not (poll_message := await self._get_poll_message(message)):
return
match message.buttons_info.pressed_text: await self.delete_message(message)
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() for user in await self._find_users_to_punish(message):
message.weather_chart.draw() if str(user.id) not in poll_message.contents['poll']['banned_users_tries']:
poll_message.contents['poll']['banned_users_tries'][str(user.id)] = 0
poll_message.save()
image_bytes = message.weather_chart.to_image() @admin
await self.edit(Media(image_bytes, MediaType.IMAGE, 'jpg'), message) async def _on_voting_unban(self, message: Message):
if message.chat.is_group and not self.is_bot_mentioned(message) or not (poll_message := await self._get_poll_message(message)):
return
async def _on_weather_chart(self, message: Message): await self.delete_message(message)
for user in await self._find_users_to_punish(message):
try:
del poll_message.contents['poll']['banned_users_tries'][str(user.id)]
except KeyError:
pass
poll_message.save()
async def _on_weather(self, message: Message):
bot_state_message: Message | None = None bot_state_message: Message | None = None
if message.is_inline: if message.is_inline:
show_progress_state = False show_progress_state = False
@@ -775,6 +821,33 @@ class FlanaBot(MultiBot, ABC):
# noinspection PyTypeChecker # noinspection PyTypeChecker
BotAction(Action.AUTO_WEATHER_CHART, message, affected_objects=[bot_message]).save() BotAction(Action.AUTO_WEATHER_CHART, message, affected_objects=[bot_message]).save()
async def _on_weather_button_press(self, message: Message):
await self.accept_button_event(message)
match message.buttons_info.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, 'jpg'), message)
# -------------------------------------------------------- # # -------------------------------------------------------- #
# -------------------- PUBLIC METHODS -------------------- # # -------------------- PUBLIC METHODS -------------------- #
# -------------------------------------------------------- # # -------------------------------------------------------- #

View File

@@ -105,6 +105,7 @@ KEYWORDS = {
'nombre', 'sonaba', 'sonando', 'song', 'sono', 'sound', 'suena', 'title', 'titulo', 'nombre', 'sonaba', 'sonando', 'song', 'sono', 'sound', 'suena', 'title', 'titulo',
'video'), 'video'),
'unpunish': ('absolve', 'forgive', 'innocent', 'inocente', 'perdona', 'spare'), 'unpunish': ('absolve', 'forgive', 'innocent', 'inocente', 'perdona', 'spare'),
'vote': ('votacion', 'votar', 'vote', 'voting', 'voto'),
'weather_chart': ('atmosfera', 'atmosferico', 'calle', 'calor', 'caloret', 'clima', 'climatologia', 'cloud', 'weather_chart': ('atmosfera', 'atmosferico', 'calle', 'calor', 'caloret', 'clima', 'climatologia', 'cloud',
'cloudless', 'cloudy', 'cold', 'congelar', 'congelado', 'denbora', 'despejado', 'diluvio', 'frio', 'cloudless', 'cloudy', 'cold', 'congelar', 'congelado', 'denbora', 'despejado', 'diluvio', 'frio',
'frost', 'hielo', 'humedad', 'llover', 'llueva', 'llueve', 'lluvia', 'nevada', 'nieva', 'nieve', 'frost', 'hielo', 'humedad', 'llover', 'llueva', 'llueve', 'lluvia', 'nevada', 'nieva', 'nieve',

View File

@@ -182,4 +182,4 @@ class TestParseCallbacks(unittest.TestCase):
'hara mucho calor en egipto este fin de semana?', 'hara mucho calor en egipto este fin de semana?',
'pfff no ve que frio ahi en oviedo este finde' 'pfff no ve que frio ahi en oviedo este finde'
] ]
self._test_no_always_callbacks(phrases, self.flana_tele_bot._on_weather_chart) self._test_no_always_callbacks(phrases, self.flana_tele_bot._on_weather)