Points management and functional '/bet' command

This commit is contained in:
guams 2025-03-30 18:31:18 +02:00
parent fb38a74013
commit d7bb8aa270
4 changed files with 143 additions and 36 deletions

View File

@ -24,3 +24,7 @@ Readme in progress...
\] \]
## TODO
- [ ] corriger le problème de seuil
- [ ] changer la bet_value après un vote perdant (on se retrouve parfois avec un bet_value > points)

View File

@ -95,6 +95,25 @@ async def get_user_vote(conn: connection, user_id: str, poll_id: str):
return result return result
async def get_user_points(conn: connection, user_id: str, guild_id: str):
cur: cursor = conn.cursor()
cur.execute(""
"SELECT points "
"FROM member "
"WHERE user_id=%s "
"AND member.guild_id=%s",
(user_id, guild_id)
)
result = cur.fetchone()
cur.close()
if result is not None:
return result[0]
return
async def get_bet_value(conn: connection, user_id: str, guild_id: str): async def get_bet_value(conn: connection, user_id: str, guild_id: str):
cur: cursor = conn.cursor() cur: cursor = conn.cursor()
@ -219,5 +238,47 @@ async def insert_user(conn, user_id, guild_id, username, avatar):
conn.commit() conn.commit()
cur.close() cur.close()
async def get_users_by_vote_id_and_poll_id():
pass async def get_users_and_bet_value_by_vote_id(conn: connection, vote_id: str):
cur = conn.cursor()
cur.execute("SELECT user_id, bet_value FROM vote_member "
"WHERE vote_id=%s",
(vote_id,)
)
result = cur.fetchall()
cur.close()
return result
async def add_user_points(conn: connection, user_id: str, bet_value: int):
cur = conn.cursor()
cur.execute(
"UPDATE member "
"SET points = points + %s "
"WHERE user_id=%s",
(bet_value, user_id)
)
conn.commit()
cur.close()
async def minus_user_points(conn: connection, user_id: str, bet_value: int):
try:
cur = conn.cursor()
cur.execute(
"UPDATE member "
"SET points = points - %s "
"WHERE user_id=%s",
(bet_value, user_id)
)
conn.commit()
cur.close()
except Exception:
conn.rollback()

View File

@ -35,7 +35,7 @@ CREATE TABLE member
user_id VARCHAR(255), user_id VARCHAR(255),
guild_id VARCHAR(255), guild_id VARCHAR(255),
username VARCHAR(255), username VARCHAR(255),
points bigint DEFAULT 50, points bigint DEFAULT 50 NOT NULL CHECK (points >= 50),
bet_value bigint DEFAULT 50, bet_value bigint DEFAULT 50,
avatar TEXT, avatar TEXT,
PRIMARY KEY (user_id), PRIMARY KEY (user_id),

108
main.py
View File

@ -10,7 +10,8 @@ import websockets
from database import (user_exists, insert_user, guild_exists, insert_guild, 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, get_bet_value, is_last_poll_created_opened, get_poll_id_opened, close_poll, get_bet_value,
get_bet_value_multipliers, get_vote_id_by_vote_option_and_poll_id) get_bet_value_multipliers, get_vote_id_by_vote_option_and_poll_id,
get_users_and_bet_value_by_vote_id, add_user_points, minus_user_points, get_user_points)
from enums import OpCode, EventTitle, InteractionType from enums import OpCode, EventTitle, InteractionType
with open('configuration.json', 'r') as file: with open('configuration.json', 'r') as file:
@ -286,7 +287,14 @@ async def create_poll_form(interaction_id: str, interaction_token: str, guild_id
async def heartbeat(websocket, interval): async def heartbeat(websocket, interval):
while True: while True:
await asyncio.sleep(interval / 1000) await asyncio.sleep(interval / 1000)
await websocket.send(json.dumps({"op": OpCode.HEARTBEAT, "d": None})) try:
await websocket.send(json.dumps({"op": OpCode.HEARTBEAT, "d": None}))
except websockets.exceptions.ConnectionClosed:
print("WebSocket fermé")
break
except Exception as e:
print(f"Erreur lors du heartbeat : {e}")
break
async def vote_confirmation(interaction_id: str, interaction_token: str, custom_id: str, user_id: str, async def vote_confirmation(interaction_id: str, interaction_token: str, custom_id: str, user_id: str,
@ -309,10 +317,11 @@ async def vote_confirmation(interaction_id: str, interaction_token: str, custom_
bet_value = await get_bet_value(conn=conn, user_id=user_id, guild_id=guild_id) bet_value = await get_bet_value(conn=conn, user_id=user_id, guild_id=guild_id)
await bet(conn=conn, guild_id=guild_id, user_id=user_id, vote_id=custom_id, await bet(conn=conn, guild_id=guild_id, user_id=user_id, vote_id=custom_id,
poll_id=custom_id.split("_")[0], bet_value=bet_value) poll_id=custom_id.split("_")[0], bet_value=bet_value)
await minus_user_points(conn=conn, user_id=user_id, bet_value=bet_value)
body = { body = {
"type": 4, "type": 4,
"data": { "data": {
"content": f"<@{user_id}>, tu as misé 50 sur l'option **{custom_id.split('_')[1]}** ! 🎉", "content": f"<@{user_id}>, tu as misé {bet_value} sur l'option **{custom_id.split('_')[1]}** ! 🎉",
"flags": 64 "flags": 64
} }
} }
@ -343,22 +352,24 @@ async def close_poll_cmd(guild_id: str, user_id: str, interaction_id: str, issue
values = await get_bet_value_multipliers(conn=conn, poll_id=poll[1]) values = await get_bet_value_multipliers(conn=conn, poll_id=poll[1])
for value in values: for value in values:
vote_id = value[0] vote_id = value[0]
users_with_bet_values = await get_users_and_bet_value_by_vote_id(conn=conn, vote_id=vote_id)
if vote_id == winner_id: if vote_id == winner_id:
winner_cote = value[1] winner_cote = value[1]
# get users where vote_id for user_with_bet_value in users_with_bet_values:
# users.points + (value[1] * users.vote.bet_value) print(int(user_with_bet_value[1] * winner_cote))
pass await add_user_points(conn=conn,
else: user_id=user_with_bet_value[0],
# get users where vote_id bet_value=int(user_with_bet_value[1] * winner_cote))
# users.points - users.vote.bet_value
pass
await close_poll(conn=conn, poll_id=poll[1]) await close_poll(conn=conn, poll_id=poll[1])
if winner_cote is not None:
out = (round(winner_cote, 2) - 1) * 100
else:
out = 0.0
body = { body = {
"type": 4, "type": 4,
"data": { "data": {
"content": f'@everyone le sondage **{poll[2]}** est terminé ! L\'issue gagnante est **{issue}** ' "content": f'@everyone le sondage **{poll[2]}** est terminé ! L\'issue gagnante est **{issue}** '
f'avec une côte de {(round(winner_cote, 2) - 1) * 100}%' f'avec une côte de {out}%'
} }
} }
else: else:
@ -387,8 +398,7 @@ async def close_poll_cmd(guild_id: str, user_id: str, interaction_id: str, issue
async def get_event(response: Any): async def get_event(response: Any):
match response["t"]: match response["t"]:
case EventTitle.MESSAGE_CREATE: # case EventTitle.MESSAGE_CREATE:
print(f'{response["d"]["author"]["username"]}: {response["d"]["content"]}')
case EventTitle.INTERACTION_CREATE: case EventTitle.INTERACTION_CREATE:
if response["d"]["type"] == InteractionType.MODAL_SUBMIT: if response["d"]["type"] == InteractionType.MODAL_SUBMIT:
await create_poll( await create_poll(
@ -428,27 +438,50 @@ async def get_event(response: Any):
username=response["d"]["member"]["user"]["username"]) username=response["d"]["member"]["user"]["username"])
elif (response["d"]["type"] == InteractionType.APPLICATION_COMMAND and elif (response["d"]["type"] == InteractionType.APPLICATION_COMMAND and
response["d"]["data"]["name"] == 'bet'): response["d"]["data"]["name"] == 'bet'):
try: command_option: int = response["d"]["data"]["options"][0]["value"]
command_option: str = response["d"]["data"]["options"][0]["value"] await change_bet_cmd(guild_id=response["d"]["guild_id"],
if await guild_exists(conn=conn, guild_id=response["d"]["guild_id"]): command_option=command_option,
if command_option.isnumeric() and await user_exists(conn=conn, user_id=response["d"]["member"]["user"]["id"],
user_id=response["d"]["member"]["user"][ username=response["d"]["member"]["user"]["username"],
"id"], avatar=response["d"]["member"]["user"]["avatar"],
guild_id=response["d"]["guild_id"]): interaction_id=response["d"]["id"],
await change_bet(conn=conn, interaction_token=response["d"]["token"])
guild_id=response["d"]["guild_id"],
user_id=response["d"]["member"]["user"]["id"],
new_bet_amount=response["d"]["data"]["name"])
else:
await bet_error_message("Vous devez rentrer un nombre")
except Exception:
await bet_error_message("Vous avez oublié de donner une somme !")
case _: case _:
print(response) print(response)
async def bet_error_message(message: str): async def change_bet_cmd(guild_id: str, command_option: int, user_id: str, username: str, avatar: str,
print(message) interaction_id: str, interaction_token: str):
if not await guild_exists(conn=conn, guild_id=guild_id):
await insert_user(conn=conn, guild_id=guild_id, user_id=user_id, username=username, avatar=avatar)
if not await user_exists(conn=conn, user_id=user_id, guild_id=guild_id):
await insert_guild(conn=conn, guild_id=guild_id)
if await get_user_points(conn=conn, user_id=user_id, guild_id=guild_id) >= command_option:
await change_bet(conn=conn, guild_id=guild_id, user_id=user_id, new_bet_amount=command_option)
body = {
"type": 4,
"data": {
"content": f"<@{user_id}>, ton prochain pari vaudra **{command_option}**.",
"flags": 64
}
}
else:
body = {
"type": 4,
"data": {
"content": f"<@{user_id}>, solde insuffisant !",
"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 connect(): async def connect():
@ -460,13 +493,22 @@ async def connect():
await identify(websocket) await identify(websocket)
while True: connected = True
while connected:
response = json.loads(await websocket.recv()) response = json.loads(await websocket.recv())
match response["op"]: match response["op"]:
case OpCode.DISPATCH: case OpCode.DISPATCH:
await get_event(response) await get_event(response)
case OpCode.RECONNECT:
print("Reconnexion...")
connected = False
case _: case _:
print(response) pass
# Reconnexion
await websocket.close()
await asyncio.sleep(5)
await connect()
async def main(): async def main():