From 481e67e5d968b76df4f2085acea6eb435f2a13cc Mon Sep 17 00:00:00 2001 From: Perceval ARENOU Date: Thu, 16 Nov 2023 14:17:00 +0000 Subject: [PATCH 1/4] cleanup admin commands --- src/flantier/_commands_admin.py | 79 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/src/flantier/_commands_admin.py b/src/flantier/_commands_admin.py index 96a00ee..8d84f6a 100644 --- a/src/flantier/_commands_admin.py +++ b/src/flantier/_commands_admin.py @@ -4,14 +4,12 @@ from logging import getLogger from telegram import ( - ForceReply, Update, ) from telegram.ext import ( CallbackContext, ) -from flantier import _keyboards from flantier._roulette import Roulette from flantier._settings import SettingsManager from flantier._users import UserManager @@ -79,9 +77,44 @@ def close_registrations(update: Update, context: CallbackContext) -> None: ) -# bot.delete_message( -# chat_id=message.chat_id, message_id=message.message_id, *args, **kwargs -# ) +def process(update: Update, context: CallbackContext) -> None: + """Lance le tirage au sort et envoie les réponses en message privé.""" + if not is_admin(update, context): + return + + roulette = Roulette() + + if not roulette.is_ready(): + context.bot.send_message( + chat_id=update.message.chat_id, + text="⚠️ Les inscriptions ne sont pas encore terminées. ⚠️", + ) + return + + if roulette.tirage() != 0: + context.bot.send_message( + chat_id=update.message.chat_id, + text="⚠️ Le tirage au sort n'a pas pu être effectué. ⚠️", + ) + return + + # send results to everyone as private message + user_manager = UserManager() + for user in user_manager.users: + if not user.registered: + pass + + giftee = user_manager.get_user(user.giftee) + logger.info("send result to %s: giftee is %d", user.name, giftee.tg_id) + + context.bot.send_message( + user.tg_id, + text=f"🎅 Youpi tu offres à {giftee.name} 🎁\n", + ) + + +# LEGACY +######### def add_spouse(update: Update, context: CallbackContext) -> None: @@ -169,39 +202,3 @@ def add_spouse(update: Update, context: CallbackContext) -> None: ), ) logger.info("set spouse %s for %s", context.args[0], context.args[1]) # type: ignore - - -def process(update: Update, context: CallbackContext) -> None: - """Lance le tirage au sort et envoie les réponses en message privé.""" - if not is_admin(update, context): - return - - roulette = Roulette() - - if not roulette.is_ready(): - context.bot.send_message( - chat_id=update.message.chat_id, - text="⚠️ Les inscriptions ne sont pas encore terminées. ⚠️", - ) - return - - if roulette.tirage() != 0: - context.bot.send_message( - chat_id=update.message.chat_id, - text="⚠️ Le tirage au sort n'a pas pu être effectué. ⚠️", - ) - return - - # send results to everyone as private message - user_manager = UserManager() - for user in user_manager.users: - if not user.registered: - pass - - giftee = user_manager.get_user(user.giftee) - logger.info("send result to %s: giftee is %d", user.name, giftee.tg_id) - - context.bot.send_message( - user.tg_id, - text=f"🎅 Youpi tu offres à {giftee.name} 🎁\n", - ) From 3060c54003c864c9af152dca55d2f38913b204f9 Mon Sep 17 00:00:00 2001 From: Perceval ARENOU Date: Thu, 16 Nov 2023 15:45:24 +0000 Subject: [PATCH 2/4] try to record comments in user json as wish dataclass --- src/flantier/_commands_santa.py | 24 ++++++++---------------- src/flantier/_keyboards.py | 3 +++ src/flantier/_santa.py | 28 ++++++++++++++++++++++++++-- src/flantier/_users.py | 27 ++++++++++++++++++++------- 4 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/flantier/_commands_santa.py b/src/flantier/_commands_santa.py index 8565540..57990b3 100644 --- a/src/flantier/_commands_santa.py +++ b/src/flantier/_commands_santa.py @@ -26,6 +26,14 @@ def wishes(update: Update, _: CallbackContext) -> None: ) +def comments(update: Update, _: CallbackContext) -> None: + """Affiche la liste de cadeaux et les commentaires associés d'une personne.""" + keyboard = build_people_inline_kb("comments") + update.message.reply_text( + "🤷 De qui veux tu consulter la liste de souhaits? 🤷", reply_markup=keyboard + ) + + def update_wishes_list(update: Update, context: CallbackContext) -> None: """Met à jour la liste des cadeaux.""" _santa.create_missing_users() @@ -39,22 +47,6 @@ def update_wishes_list(update: Update, context: CallbackContext) -> None: ######### -def comments(update: Update, context: CallbackContext) -> None: - """Affiche la liste de cadeaux et les commentaires associés d'une personne.""" - if len(update.message.text.split(" ")) > 1: - name = update.message.text.split(" ")[1] - - reply_del_kb = ReplyKeyboardRemove() - context.bot.send_message( - chat_id=update.message.chat_id, - text=_santa.find_wishes(update.message.from_user.id, name), - reply_markup=reply_del_kb, - ) - - else: - _keyboards.build_people_keyboard("/commentaires") - - def add_gifter(tg_id: int, message: list) -> str: """Ajoute un offrant à un cadeau. vérifie que la personne existe et la disponiblité du cadeau diff --git a/src/flantier/_keyboards.py b/src/flantier/_keyboards.py index 0e6a70d..f09d270 100644 --- a/src/flantier/_keyboards.py +++ b/src/flantier/_keyboards.py @@ -90,6 +90,9 @@ def user_button(update: Update, _: CallbackContext) -> None: if command == "wishes": text = user_wishes_message(user_name) + if command == "comments": + text = user_comments_message(user_name) + # TODO "/offrir" text = "À qui veux-tu offrir ?" # TODO "/commentaires, /exclude" logger.info("response: %s", text) diff --git a/src/flantier/_santa.py b/src/flantier/_santa.py index 02b87d6..d2ebcad 100644 --- a/src/flantier/_santa.py +++ b/src/flantier/_santa.py @@ -10,7 +10,7 @@ from apiclient.discovery import build from flantier._settings import SettingsManager -from flantier._users import User, UserManager +from flantier._users import User, UserManager, Wish logger = getLogger("flantier") @@ -62,12 +62,22 @@ def update_wishes_list() -> None: for column in range(0, len(values), 2): name = values[column][0] gifts = values[column][1:] + comments = values[column + 1][1:] logger.debug("mise à jour des cadeaux de %s", name) user = user_manager.search_user(name) if not user: pass - user.wishes = gifts + + # user.wishes = list(zip(gifts, comments)) + + wishes = [] + for i, j in zip(gifts, comments): + logger.info("adding wish %s and comment %s", i, j) + wishes.append(Wish(wish=i, comment=j)) + + user.wishes = wishes + logger.info(user.wishes) user_manager.update_user(user) @@ -76,6 +86,11 @@ def get_wish_list(user: User) -> str: return "\n".join(w for w in user.wishes) +def get_comment_list(user: User) -> str: + """Récupère la liste des commentaires d'un participant avec son nom.""" + return "\n".join(w for w in user.comments) + + # called by the people inline keyboard def user_wishes_message(user_name: str) -> str: wishes = get_wish_list(UserManager().search_user(user_name)) @@ -86,6 +101,15 @@ def user_wishes_message(user_name: str) -> str: return text +def user_comments_message(user_name: str) -> str: + wishes = get_wish_list(UserManager().search_user(user_name)) + text = f"🎅 {user_name} voudrait pour Noël:\n" + wishes + if not wishes: + text = f"🎅 {user_name} ne veut rien pour Noël 🫥" + + return text + + def update_gifts_background_task(interval_sec: int = 600) -> None: """Update gifts list in background. Function to be run in a thread""" ticker = threading.Event() diff --git a/src/flantier/_users.py b/src/flantier/_users.py index 2a5d60d..5df99eb 100644 --- a/src/flantier/_users.py +++ b/src/flantier/_users.py @@ -1,5 +1,7 @@ #!/usr/bin/python3 """Gère les utilisateurs stockés dans le fichier de configuration users.json +We are using dataclass to represent Users and wishes (gifts) +source https://www.delftstack.com/howto/python/dataclass-to-json-in-python/ """ import json @@ -12,11 +14,21 @@ logger = getLogger("flantier") -# @dataclass -# class Wish: -# wish: str # cadeaux qui viennent du google doc -# comment: str # commentaires qui viennent du google doc -# giver: str # la personne qui offre ce cadeau +@dataclass +class Wish: + """Represents a wish from a user.""" + + wish: str # cadeaux qui viennent du google doc + comment: str # commentaires qui viennent du google doc + giver: int = 0 # la personne qui offre ce cadeau + + @property + def __dict__(self): + return asdict(self) + + @property + def json(self): + return json.dumps(self.__dict__) @dataclass @@ -29,8 +41,9 @@ class User: giftee: int = 0 # telegram id of the person to offer a gift last_giftee: int = 0 # telegram id of the person who recieved the gift last year registered: bool = False # is the user registered for secret santa - # TODO use Wish dataclass instead of dict - wishes: list = field(default_factory=list) # list of wishes as tuple (wish, comment) + wishes: list[Wish] = field( + default_factory=list[Wish] + ) # list of wishes as Wish objects class UserJSONEncoder(json.JSONEncoder): From c815fdd26c371415e4406a852c1b9d4835686c25 Mon Sep 17 00:00:00 2001 From: Perceval ARENOU Date: Sun, 19 Nov 2023 15:27:13 +0000 Subject: [PATCH 3/4] new wish format: handle comments and giver --- src/flantier/_santa.py | 3 +-- src/flantier/_users.py | 18 ++++++++++++------ src/flantier/settings_template.toml | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/flantier/_santa.py b/src/flantier/_santa.py index d2ebcad..880b972 100644 --- a/src/flantier/_santa.py +++ b/src/flantier/_santa.py @@ -73,11 +73,10 @@ def update_wishes_list() -> None: wishes = [] for i, j in zip(gifts, comments): - logger.info("adding wish %s and comment %s", i, j) + logger.info("adding wish \"%s\" with comment \"%s\"", i, j) wishes.append(Wish(wish=i, comment=j)) user.wishes = wishes - logger.info(user.wishes) user_manager.update_user(user) diff --git a/src/flantier/_users.py b/src/flantier/_users.py index 5df99eb..8776f62 100644 --- a/src/flantier/_users.py +++ b/src/flantier/_users.py @@ -22,13 +22,11 @@ class Wish: comment: str # commentaires qui viennent du google doc giver: int = 0 # la personne qui offre ce cadeau - @property def __dict__(self): return asdict(self) - @property - def json(self): - return json.dumps(self.__dict__) + def __str__(self): + return json.dumps(self.__dict__, ensure_ascii=False) @dataclass @@ -55,6 +53,13 @@ def default(self, o): return super().default(o) +def UserJSONDecoder(jsonDict): + if "tg_id" in jsonDict: + return User(**jsonDict) + if "wish" in jsonDict: + return Wish(**jsonDict) + + def user_list_to_json(users: list) -> str: """Convertit la liste des utilisateurs en JSON.""" return json.dumps(users, cls=UserJSONEncoder, indent=4, ensure_ascii=False) @@ -62,7 +67,8 @@ def user_list_to_json(users: list) -> str: def json_to_user_list(data: str) -> list: """Convertit le JSON en liste d'utilisateurs.""" - return json.loads(data, object_hook=lambda d: User(**d)) + # return json.loads(data, object_hook=lambda d: User(**d)) + return json.loads(data, object_hook=UserJSONDecoder) class UserManager: @@ -123,7 +129,7 @@ def add_user(self, tg_id: int, name: str) -> bool: logger.info("updating user %s: %d", name, tg_id) user.tg_id = tg_id else: - logger.info("Aadding user %s: %d", name, tg_id) + logger.info("adding user %s: %d", name, tg_id) self.users.append(User(tg_id, name)) logger.debug("users: %s", self.users) diff --git a/src/flantier/settings_template.toml b/src/flantier/settings_template.toml index a5d2d4a..95cd574 100644 --- a/src/flantier/settings_template.toml +++ b/src/flantier/settings_template.toml @@ -6,4 +6,4 @@ administrator = 0 # Telegram user id of the bot administrator api_key = '' # Google API Token to access Google Sheets API for gift list spreadsheet_id = '' sheet_id = '' -data_range = 'A1:AB30' # select the area where to search for whishes in sheet +data_range = 'A1:AK30' # select the area where to search for whishes in sheet From 603c7b2f68d6538088f235d947c957602b2b59b2 Mon Sep 17 00:00:00 2001 From: Perceval ARENOU Date: Sun, 19 Nov 2023 15:54:50 +0000 Subject: [PATCH 4/4] fix check in pipeline --- .github/workflows/pylint.yml | 1 - src/flantier/_commands_santa.py | 2 +- src/flantier/_keyboards.py | 8 ++++---- src/flantier/_santa.py | 10 ++++++++-- src/flantier/_users.py | 18 ++++++++++-------- src/oss117audio/download.py | 4 +--- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 436d25d..5e08de9 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -24,4 +24,3 @@ jobs: - name: Analysing code typing with mypy run: | mypy --install-types --non-interactive $(git ls-files '*.py') - mypy $(git ls-files '*.py') diff --git a/src/flantier/_commands_santa.py b/src/flantier/_commands_santa.py index 57990b3..fa7cce6 100644 --- a/src/flantier/_commands_santa.py +++ b/src/flantier/_commands_santa.py @@ -56,7 +56,7 @@ def add_gifter(tg_id: int, message: list) -> str: # trouve le destinataire dans la liste des participants if any(qqun.name == name for qqun in participants): - _wishes = _santa.find_wishes(tg_id, name, table=True) + _wishes = UserManager().get_user(qqun.tg_id).wishes if len(_wishes) > 0 and len(_wishes) >= cadeau_index: receiver_index = next( diff --git a/src/flantier/_keyboards.py b/src/flantier/_keyboards.py index f09d270..ee02178 100644 --- a/src/flantier/_keyboards.py +++ b/src/flantier/_keyboards.py @@ -14,7 +14,7 @@ CallbackContext, ) -from flantier._santa import user_wishes_message +from flantier._santa import user_wishes_message,user_comments_message from flantier._users import UserManager logger = getLogger("flantier") @@ -34,7 +34,7 @@ def build_people_inline_kb( Créer le clavier avec les noms des participants. Ajoute la commande en prefix /offrir, /cadeaux, /commentaires, /exclude """ - keyboard = [ + tkeyboard = [ InlineKeyboardButton( user.name, callback_data=command + " " + str(user.tg_id) + " " + str(user.name), @@ -42,9 +42,9 @@ def build_people_inline_kb( for user in UserManager().users if (not filter_registered or user.registered) ] - keyboard.append(InlineKeyboardButton("Annuler", callback_data="cancel 0 cancel")) + tkeyboard.append(InlineKeyboardButton("Annuler", callback_data="cancel 0 cancel")) # split keyboard in two columns - keyboard = [keyboard[i : i + COLUMNS] for i in range(0, len(keyboard), COLUMNS)] + keyboard = [tkeyboard[i : i + COLUMNS] for i in range(0, len(tkeyboard), COLUMNS)] return InlineKeyboardMarkup(keyboard) diff --git a/src/flantier/_santa.py b/src/flantier/_santa.py index 880b972..6151000 100644 --- a/src/flantier/_santa.py +++ b/src/flantier/_santa.py @@ -82,16 +82,19 @@ def update_wishes_list() -> None: def get_wish_list(user: User) -> str: """Récupère la liste des souhaits d'un participant avec son nom.""" - return "\n".join(w for w in user.wishes) + return "\n".join(w.wish for w in user.wishes) def get_comment_list(user: User) -> str: """Récupère la liste des commentaires d'un participant avec son nom.""" - return "\n".join(w for w in user.comments) + return "\n".join(w.comment for w in user.wishes) # called by the people inline keyboard def user_wishes_message(user_name: str) -> str: + """Generates the text to send as message with all wishes + from the given user + """ wishes = get_wish_list(UserManager().search_user(user_name)) text = f"🎅 {user_name} voudrait pour Noël:\n" + wishes if not wishes: @@ -101,6 +104,9 @@ def user_wishes_message(user_name: str) -> str: def user_comments_message(user_name: str) -> str: + """Generates the text to send as message with all wishes and associated comments + from the given user + """ wishes = get_wish_list(UserManager().search_user(user_name)) text = f"🎅 {user_name} voudrait pour Noël:\n" + wishes if not wishes: diff --git a/src/flantier/_users.py b/src/flantier/_users.py index 8776f62..b19c7d3 100644 --- a/src/flantier/_users.py +++ b/src/flantier/_users.py @@ -8,6 +8,7 @@ from dataclasses import asdict, dataclass, field, is_dataclass from logging import getLogger from pathlib import Path +from typing import Any DEFAULT_USERS_DB = Path.home() / ".cache/flantier/users.json" @@ -45,23 +46,24 @@ class User: class UserJSONEncoder(json.JSONEncoder): - """JSON encoder for User class.""" + """JSON encoder for User and Wish classes.""" def default(self, o): if is_dataclass(o): return asdict(o) return super().default(o) - -def UserJSONDecoder(jsonDict): - if "tg_id" in jsonDict: - return User(**jsonDict) - if "wish" in jsonDict: - return Wish(**jsonDict) +# pylint: disable=C0103,R1710 +def UserJSONDecoder(json_dict: dict) -> Any: + """JSON decoder function for User and Wish classes.""" + if "tg_id" in json_dict: + return User(**json_dict) + if "wish" in json_dict: + return Wish(**json_dict) def user_list_to_json(users: list) -> str: - """Convertit la liste des utilisateurs en JSON.""" + """Convert """ return json.dumps(users, cls=UserJSONEncoder, indent=4, ensure_ascii=False) diff --git a/src/oss117audio/download.py b/src/oss117audio/download.py index 444c391..baacc42 100644 --- a/src/oss117audio/download.py +++ b/src/oss117audio/download.py @@ -11,9 +11,7 @@ SITE = "https://zonesons.com" # pylint: disable=C0301 OSS1 = "/repliques-cultes-de-films-d-espionnage/phrases-cultes-de-oss-117-le-caire-nid-d-espions" -OSS2 = ( - "/repliques-cultes-de-films-d-espionnage/phrases-cultes-de-oss-117-rio-ne-repond-plus" -) +OSS2 = "/repliques-cultes-de-films-d-espionnage/phrases-cultes-de-oss-117-rio-ne-repond-plus" FILMS = [OSS1, OSS2] AUDIO_BASE_FOLDER = Path.home() / ".cache/flantier/"