diff --git a/database.py b/database.py index edc9afc..ab7112d 100644 --- a/database.py +++ b/database.py @@ -32,6 +32,51 @@ async def change_bet(conn: connection, user_id: str, guild_id: str, new_bet_amou cur.execute("UPDATE member SET bet_value = %s WHERE user_id=%s AND guild_id=%s", (new_bet_amount, user_id, guild_id)) + conn.commit() + cur.close() + + +async def is_last_poll_created_opened(conn: connection, creator: str): + cur: cursor = conn.cursor() + + cur.execute("select opened " + "from poll " + "where creator=%s " + "and opened=true", + (creator,) + ) + result = cur.fetchone() + cur.close() + + if result is not None: + return result[0] + return + + +async def close_poll(conn: connection, poll_id: str): + cur: cursor = conn.cursor() + + cur.execute("UPDATE poll SET opened = false WHERE poll_id=%s", + (poll_id,)) + + conn.commit() + cur.close() + + +async def get_poll_id_opened(conn: connection, creator: str): + cur: cursor = conn.cursor() + + cur.execute("select opened, poll_id, question " + "from poll " + "where creator=%s " + "and opened=true", + (creator,) + ) + result = cur.fetchone() + cur.close() + + return result + async def get_user_vote(conn: connection, user_id: str, poll_id: str): cur: cursor = conn.cursor() @@ -44,9 +89,11 @@ async def get_user_vote(conn: connection, user_id: str, poll_id: str): (user_id, poll_id) ) - conn.commit() + result = cur.fetchone() cur.close() + return result + async def bet(conn, vote_id: str, poll_id: str, user_id: str, guild_id: str): cur = conn.cursor() @@ -100,15 +147,18 @@ async def insert_guild(conn, guild_id): cur.close() -async def insert_user(conn, user_id, guild_id, global_name, avatar): +async def insert_user(conn, user_id, guild_id, username, avatar): cur = conn.cursor() cur.execute( "INSERT INTO " - "member (user_id, guild_id, global_name, avatar) " + "member (user_id, guild_id, username, avatar) " "VALUES (%s, %s, %s, %s)", - (user_id, guild_id, global_name, avatar) + (user_id, guild_id, username, avatar) ) conn.commit() cur.close() + +# nombre de vote par vote_id pour calculer l'issue du vote (et potentiellement la côte) +# select vote_id, count(distinct vote_member.user_id) from vote_member group by vote_id \ No newline at end of file diff --git a/database.sql b/database.sql index 309a050..aa41432 100644 --- a/database.sql +++ b/database.sql @@ -32,7 +32,7 @@ CREATE TABLE member ( user_id VARCHAR(255), guild_id VARCHAR(255), - global_name VARCHAR(255), + username VARCHAR(255), points bigint DEFAULT 50, bet_value bigint DEFAULT 50, avatar TEXT, diff --git a/main.py b/main.py index 1fb699a..d5a127a 100644 --- a/main.py +++ b/main.py @@ -8,7 +8,8 @@ import requests import websockets from database import (user_exists, insert_user, guild_exists, insert_guild, - insert_poll, insert_vote_options, bet, get_user_vote, change_bet) + insert_poll, insert_vote_options, bet, get_user_vote, change_bet, + is_last_poll_created_opened, get_poll_id_opened, close_poll) from enums import OpCode, EventTitle, InteractionType with open('configuration.json', 'r') as file: @@ -52,6 +53,11 @@ async def create_command(): } ] }, + { + "name": "close", + "type": 1, + "description": "Pour clôturer un sondage", + }, { # à améliorer en /profil <@user_id> "name": "me", "type": 1, @@ -92,7 +98,6 @@ async def create_poll(guild_id: str, creator_id: str, poll_created_id: str, inte if "vote" in comp["components"][0]["custom_id"] and comp["components"][0]["value"] != "": vote_text = comp["components"][0]["value"] vote_options += f"Option {index}: {vote_text}\n" - buttons.append({ "type": 2, "label": vote_text, @@ -161,90 +166,102 @@ async def identify(websocket): await websocket.send(json.dumps(payload)) -async def create_poll_form(interaction_id: str, interaction_token: str, guild_id: str): +async def create_poll_form(interaction_id: str, interaction_token: str, guild_id: str, user_id: str, username: str, + avatar: str): poll_id = uuid4() if not await guild_exists(conn=conn, guild_id=guild_id): await insert_guild(conn=conn, guild_id=guild_id) - body = { - "type": 9, - "data": { - "title": "Créer un vote", - "custom_id": str(poll_id), - "components": [ - { - "type": 1, - "components": [ - { - "type": 4, - "custom_id": "label", - "label": "Question du vote", - "placeholder": "Shy aime-t-il les robots?", - "style": 1, - "min_length": 1, - "required": True - } - ] - }, - { - "type": 1, - "components": [ - { - "type": 4, - "custom_id": "vote1", - "label": "Première option", - "placeholder": "Oui", - "style": 1, - "min_length": 1, - "required": True - } - ] - }, - { - "type": 1, - "components": [ - { - "type": 4, - "custom_id": "vote2", - "label": "Deuxième option", - "placeholder": "Non", - "style": 1, - "min_length": 1, - "required": False - } - ] - }, - { - "type": 1, - "components": [ - { - "type": 4, - "custom_id": "vote3", - "label": "Troisième option", - "placeholder": "Peut-être", - "style": 1, - "min_length": 1, - "required": False - } - ] - }, - { - "type": 1, - "components": [ - { - "type": 4, - "custom_id": "vote4", - "label": "Quatrième option", - "placeholder": "Pas du tout", - "style": 1, - "min_length": 1, - "required": False - } - ] - } - ] + if not await user_exists(conn=conn, user_id=user_id, guild_id=guild_id): + await insert_user(conn=conn, user_id=user_id, guild_id=guild_id, username=username, avatar=avatar) + if not await is_last_poll_created_opened(conn=conn, creator=user_id): + body = { + "type": 9, + "data": { + "title": "Créer un vote", + "custom_id": str(poll_id), + "components": [ + { + "type": 1, + "components": [ + { + "type": 4, + "custom_id": "label", + "label": "Question du vote", + "placeholder": "Shy aime-t-il les robots?", + "style": 1, + "min_length": 1, + "required": True + } + ] + }, + { + "type": 1, + "components": [ + { + "type": 4, + "custom_id": "vote1", + "label": "Première option", + "placeholder": "Oui", + "style": 1, + "min_length": 1, + "required": True + } + ] + }, + { + "type": 1, + "components": [ + { + "type": 4, + "custom_id": "vote2", + "label": "Deuxième option", + "placeholder": "Non", + "style": 1, + "min_length": 1, + "required": False + } + ] + }, + { + "type": 1, + "components": [ + { + "type": 4, + "custom_id": "vote3", + "label": "Troisième option", + "placeholder": "Peut-être", + "style": 1, + "min_length": 1, + "required": False + } + ] + }, + { + "type": 1, + "components": [ + { + "type": 4, + "custom_id": "vote4", + "label": "Quatrième option", + "placeholder": "Pas du tout", + "style": 1, + "min_length": 1, + "required": False + } + ] + } + ] + } + } + else: + body = { + "type": 4, + "data": { + "content": f"<@{user_id}>, il faut d'abord clôturer ton sondage avant de pouvoir en créer un nouveau. " + f"(commande: **/close**)", + "flags": 64 + } } - } - res = requests.post(f"{API_URL}/interactions/{interaction_id}/{interaction_token}/callback", json=body, headers={"Authorization": f"Bot {TOKEN}"}) if res.status_code == 400: @@ -261,9 +278,9 @@ async def heartbeat(websocket, interval): async def vote_confirmation(interaction_id: str, interaction_token: str, custom_id: str, user_id: str, guild_id: str, - avatar: str, global_name: str): + avatar: str, username: str): user_vote = await get_user_vote(conn=conn, user_id=user_id, poll_id=custom_id.split("_")[0]) - if user_vote: + if user_vote is not None: body = { "type": 4, "data": { @@ -275,9 +292,9 @@ async def vote_confirmation(interaction_id: str, interaction_token: str, custom_ if not await user_exists(conn=conn, user_id=user_id, guild_id=guild_id): if not await guild_exists(conn=conn, guild_id=guild_id): await insert_guild(conn=conn, guild_id=guild_id) - await insert_user(conn=conn, user_id=user_id, avatar=avatar, guild_id=guild_id, global_name=global_name) - await bet(conn=conn, guild_id=guild_id, user_id=user_id, vote_id=custom_id, - poll_id=custom_id.split("_")[0]) + await insert_user(conn=conn, user_id=user_id, avatar=avatar, guild_id=guild_id, username=username) + await bet(conn=conn, guild_id=guild_id, user_id=user_id, vote_id=custom_id, + poll_id=custom_id.split("_")[0]) body = { "type": 4, "data": { @@ -297,6 +314,37 @@ async def vote_confirmation(interaction_id: str, interaction_token: str, custom_ print(res) +async def close_poll_cmd(guild_id: str, user_id: str, interaction_id: str, interaction_token: str, username: str, + avatar: str): + if not await guild_exists(conn=conn, guild_id=guild_id): + await insert_guild(conn=conn, guild_id=guild_id) + if not await user_exists(conn=conn, user_id=user_id, guild_id=guild_id): + await insert_user(conn=conn, user_id=user_id, guild_id=guild_id, username=username, avatar=avatar) + poll: tuple = await get_poll_id_opened(conn=conn, creator=user_id) + if poll is not None: + await close_poll(conn=conn, poll_id=poll[1]) + body = { + "type": 4, + "data": { + "content": f'@everyone le sondage "{poll[2]}" est terminé !', + } + } + else: + body = { + "type": 4, + "data": { + "content": f"<@{user_id}>, tu n'as actuellement aucun sondage en cours.", + "flags": 64 + } + } + res = requests.post(f"{API_URL}/interactions/{interaction_id}/{interaction_token}/callback", json=body, + headers={"Authorization": f"Bot {TOKEN}"}) + if res.status_code == 400: + print(res.json()) + else: + print(res) + + async def get_event(response: Any): match response["t"]: case EventTitle.MESSAGE_CREATE: @@ -320,12 +368,23 @@ async def get_event(response: Any): user_id=user_id, guild_id=response["d"]["guild"]["id"], avatar=response["d"]["member"]["user"]["avatar"], - global_name=response["d"]["member"]["user"]["global_name"]) + username=response["d"]["member"]["user"]["username"]) elif (response["d"]["type"] == InteractionType.APPLICATION_COMMAND and response["d"]["data"]["name"] == 'poll'): await create_poll_form(interaction_id=response["d"]["id"], + user_id=response["d"]["member"]["user"]["id"], interaction_token=response["d"]["token"], - guild_id=response["d"]["guild_id"]) + guild_id=response["d"]["guild_id"], + avatar=response["d"]["member"]["user"]["avatar"], + username=response["d"]["member"]["user"]["username"]) + elif (response["d"]["type"] == InteractionType.APPLICATION_COMMAND and + response["d"]["data"]["name"] == 'close'): + await close_poll_cmd(guild_id=response["d"]["guild_id"], + user_id=response["d"]["member"]["user"]["id"], + interaction_id=response["d"]["id"], + interaction_token=response["d"]["token"], + avatar=response["d"]["member"]["user"]["avatar"], + username=response["d"]["member"]["user"]["username"]) elif (response["d"]["type"] == InteractionType.APPLICATION_COMMAND and response["d"]["data"]["name"] == 'bet'): try: