diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml index 3d00af0..e29f05c 100644 --- a/.github/workflows/build_and_deploy.yml +++ b/.github/workflows/build_and_deploy.yml @@ -42,10 +42,18 @@ jobs: steps: - name: Trigger staging deployment run: | - curl --request POST \ - --form token=${{ secrets.GITLAB_CI_TOKEN }} \ - --form ref=main \ - --form "variables[docker_image_tag]=latest" \ - --form "variables[application_to_deploy]=albert-tchap" \ - --form "variables[deployment_environment]=staging" \ - "https://gitlab.com/api/v4/projects/58117805/trigger/pipeline" \ No newline at end of file + RESPONSE="$(curl --request POST \ + --form token=${{ secrets.GITLAB_CI_TOKEN }} \ + --form ref=main \ + --form 'variables[pipeline_name]=${{ github.event.repository.name }} - ${{ github.event.head_commit.message }}' \ + --form 'variables[docker_image_tag]=latest' \ + --form 'variables[application_to_deploy]=${{ github.event.repository.name }}' \ + --form 'variables[deployment_environment]=staging' \ + 'https://gitlab.com/api/v4/projects/58117805/trigger/pipeline')" + + if echo "$RESPONSE" | grep -q '"status":"created"'; then + echo $RESPONSE + else + echo $RESPONSE + exit 1 + fi diff --git a/app/bot.py b/app/bot.py index 9cd1324..36a3414 100755 --- a/app/bot.py +++ b/app/bot.py @@ -45,8 +45,9 @@ def main(): for i in range(n_tries): try: tchap_bot.run() - except Exception as err: - logger.error(f"Bot startup failed with error: {err}") + except Exception as e: + err = e + logger.error(f"Bot startup failed with error: {e}") time.sleep(3) if err: diff --git a/app/bot_msg.py b/app/bot_msg.py index 5609fd7..3a4f456 100755 --- a/app/bot_msg.py +++ b/app/bot_msg.py @@ -52,7 +52,7 @@ def help(model_url, model_short_name, cmds): def commands(cmds): msg = "Les commandes spéciales suivantes sont disponibles :\n\n" - msg += "- " + "\n- ".join(cmds) + msg += "- " + "\n- ".join(cmds) # type: ignore return msg def unknown_command(cmds_msg): diff --git a/app/commands.py b/app/commands.py index 0e2ff37..0d7decb 100755 --- a/app/commands.py +++ b/app/commands.py @@ -101,7 +101,7 @@ def _get_cmds(self, config: Config, verbose: bool = False) -> list[str]: # ================================================================================ command_registry = CommandRegistry({}, set()) -user_configs = defaultdict(lambda: Config()) +user_configs: dict[str, Config] = defaultdict(lambda: Config()) tiam = TchapIam(Config()) diff --git a/app/iam.py b/app/iam.py index 7294697..a6abfac 100755 --- a/app/iam.py +++ b/app/iam.py @@ -3,12 +3,22 @@ import re from collections import namedtuple from datetime import datetime, timedelta, timezone -from urllib.parse import urlencode import aiohttp from bot_msg import AlbertMsg +UserRecord = namedtuple( + "UserRecord", + ["id", "tchap_user", "status", "domain", "n_questions", "last_activity"], + defaults=(None,), # default apply following the rightmost parameter first. +) + + +def to_record(_id: str, data: dict) -> UserRecord: + """Dict to a grist record""" + return UserRecord(**{"id": _id, **{k: v for k, v in data.items() if k in UserRecord._fields}}) + # from grist_api import GristDocAPI => is not async class AsyncGristDocAPI: @@ -33,7 +43,7 @@ async def _request(self, method, endpoint, json_data=None): response.raise_for_status() return await response.json() - async def fetch_table(self, table_id, filters=None) -> list[namedtuple]: + async def fetch_table(self, table_id, filters=None) -> list[UserRecord]: endpoint = f"/docs/{self.doc_id}/tables/{table_id}/records" data = {} if filters: @@ -42,8 +52,7 @@ async def fetch_table(self, table_id, filters=None) -> list[namedtuple]: if not result["records"]: return [] - Record = namedtuple("Record", ["id"] + list(result["records"][0]["fields"].keys())) - records = [Record(**{"id": r["id"], **r["fields"]}) for r in result["records"]] + records = [to_record(r["id"], r["fields"]) for r in result["records"]] return records async def add_records(self, table_id, records): @@ -155,8 +164,16 @@ async def add_pending_user(self, config, username) -> bool: "tchap_user": username, "status": "pending", "domain": self.domain_from_sender(username), + "n_questions": 0, } - await self.iam_client.add_records(self.users_table_name, [record]) + results = await self.iam_client.add_records(self.users_table_name, [record]) + + # Update the {not_allowed} table + records = [to_record(results["records"][0]["id"], record)] + + for r in records: + self.users_not_allowed[r.tchap_user] = r + return True async def increment_user_question(self, username, n=1, update_last_activity=True): diff --git a/app/matrix_bot/callbacks.py b/app/matrix_bot/callbacks.py index f1deacf..e0f8718 100755 --- a/app/matrix_bot/callbacks.py +++ b/app/matrix_bot/callbacks.py @@ -65,8 +65,8 @@ class Callbacks: def __init__(self, matrix_client: MatrixClient): self.matrix_client = matrix_client - self.startup = [] - self.client_callback = [] + self.startup: list = [] + self.client_callback: list = [] def register_on_custom_event(self, func, onEvent: Event, feature: dict): @properly_fail(self.matrix_client) diff --git a/app/matrix_bot/eventparser.py b/app/matrix_bot/eventparser.py index 97a8e21..733fcbb 100755 --- a/app/matrix_bot/eventparser.py +++ b/app/matrix_bot/eventparser.py @@ -75,7 +75,7 @@ def only_on_join(self) -> None: if not self.event.source.get("content", {}).get("membership") == "invite": raise EventNotConcerned - def is_command(self): + def is_command(self, *args) -> bool: return False @@ -110,29 +110,9 @@ def parse_command(self, commands: str | list[str], prefix: str, command_name: st self.command = command def is_command(self, prefix: str) -> bool: - return self.event.body.strip().startswith(prefix) + text = self.event.body.strip() + return text.startswith(prefix) and len(text) > 1 def get_command(self) -> list[str] | None: return self.command - # @deprecated: Not used/tested - async def hl(self, consider_hl_when_direct_message=True) -> str: - """ - if the event is a hl (highlight, i.e begins with the name of the bot), - returns the text after the hl. Raise EventNotConcerned otherwise - - :param consider_hl_when_direct_message: if True, consider a direct message as an highlight. - :return: the text after the highlight - :raise EventNotConcerned: if the current event is not concerned by the command. - """ - display_name = await self.matrix_client.get_display_name() - if consider_hl_when_direct_message and self.room_is_direct_message(): - return self.get_command_line( - "", - prefix="", - body=self.event.body.removeprefix(display_name).removeprefix(": "), - command_name="mention", - ) - return self.get_command_line(display_name, prefix="", command_name="mention").removeprefix( - ": " - ) diff --git a/app/tchap_utils.py b/app/tchap_utils.py index 7c9fb88..896dbc6 100755 --- a/app/tchap_utils.py +++ b/app/tchap_utils.py @@ -38,7 +38,7 @@ async def get_thread_messages( event = ep.event # Build the conversation thread - messages = [] + messages: list = [] i = 0 while isa_reply_to(event) and i < max_rewind: messages.insert(0, event) @@ -67,7 +67,7 @@ async def get_previous_messages( direction=MessageDirection.back, message_filter={"types": ["m.room.message", "m.room.encrypted"]}, ) - messages = [] + messages: list = [] decr = 0 for i, event in enumerate(roommessages.chunk): body = event.source["content"]["body"].strip() diff --git a/scripts/send_msg_to_errors.py b/scripts/send_msg_to_errors.py index 41e2d82..3466826 100755 --- a/scripts/send_msg_to_errors.py +++ b/scripts/send_msg_to_errors.py @@ -9,10 +9,10 @@ config = { "server": os.getenv("MATRIX_HOME_SERVER"), "username": os.getenv("MATRIX_BOT_USERNAME"), - "password": os.getence("MATRIX_BOT_PASSWORD"), - "errors_room_id": os.getence("ERRORS_ROOM_ID"), + "password": os.getenv("MATRIX_BOT_PASSWORD"), + "errors_room_id": os.getenv("ERRORS_ROOM_ID"), } -Config = namedtuple("Config", config.keys()) +Config = namedtuple("Config", list(config.keys())) config = Config(**config) message = "Hi, this is a test."