From c2a74e7472beace631fcab24986d83326e4c5dd7 Mon Sep 17 00:00:00 2001 From: Arslaan Pathan Date: Thu, 16 Jul 2026 19:37:14 +1200 Subject: Almost done with voting!! --- src/botnet.py | 42 ++---------------------------------------- src/db.py | 8 ++++++++ src/main.py | 41 ++++++++++++++++++++++++++++++++++++++++- src/utils.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 src/utils.py (limited to 'src') diff --git a/src/botnet.py b/src/botnet.py index 086d01f..377c0c2 100644 --- a/src/botnet.py +++ b/src/botnet.py @@ -1,4 +1,5 @@ from .db import create_deployment, get_daily_user_deployment_count, get_deployment, update_deployment_status, get_active_users, get_user, add_deployment_message, get_deployment_messages +from .utils import generate_voting_blocks from slack_sdk.web.async_client import AsyncWebClient import os from dotenv import load_dotenv @@ -90,46 +91,7 @@ async def deploy_message(user_id: str, message: str): deployment_id = await create_deployment(user_id, message) - blocks = [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": f"Voting | Deployment #{deployment_id}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": f"*Message:*\n> {message}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": f"*Votes:*\n> Approve: 0\n> Reject: 0" - } - }, - { - "type": "actions", - "elements": [ - { - "type": "button", - "text": {"type": "plain_text", "text": "Approve ^_^"}, - "style": "primary", - "action_id": f"vote_approve_{deployment_id}" - }, - { - "type": "button", - "text": {"type": "plain_text", "text": "Reject T_T"}, - "style": "danger", - "action_id": f"vote_reject_{deployment_id}" - } - ] - } - ] + blocks = generate_voting_blocks(deployment_id, message, 0, 0, True) client = AsyncWebClient(token=selfbot_token) response = await client.chat_postMessage( diff --git a/src/db.py b/src/db.py index b971a13..f1ae4f6 100644 --- a/src/db.py +++ b/src/db.py @@ -168,3 +168,11 @@ async def get_user_vote(deployment_id: int, voter_id: str): async def get_vote_counts(deployment_id: int): votes = await get_votes(deployment_id) return len(votes["approve"]), len(votes["reject"]) + +async def update_voting_message_ts(deployment_id: int, message_ts: str): + async with aiosqlite.connect(DB_PATH) as db: + await db.execute( + "UPDATE Deployments SET voting_message_ts = ? WHERE id = ?", + (message_ts, deployment_id) + ) + await db.commit() diff --git a/src/main.py b/src/main.py index 1c43240..9daa8f3 100644 --- a/src/main.py +++ b/src/main.py @@ -1,8 +1,9 @@ import os +import re from slack_bolt.app.async_app import AsyncApp from slack_bolt.adapter.socket_mode.async_handler import AsyncSocketModeHandler from dotenv import load_dotenv -from .db import init_db +from .db import init_db, get_user, add_vote, get_vote_counts from .auth import app as fastapi_app from .botnet import deploy_message import threading @@ -11,6 +12,8 @@ import uvicorn load_dotenv() +VOTE_PATTERN = re.compile(r"^vote_(approve|reject)_(\d+)$") + selfbot_token = os.environ.get("SLACK_SELFBOT_OAUTH_XOXP") app_token = os.environ.get("SLACK_APP_TOKEN") selfbot_user_id = os.environ.get("SELFBOT_USER_ID") @@ -64,6 +67,42 @@ async def handle_messages(message, say): except Exception as e: print(f"something broke, good luck LMAO {e}") +@app.action(VOTE_PATTERN) +async def handle_vote(ack, respond, logger, context, body, client): + await ack() + + action_id = body["actions"][0]["action_id"] + match = VOTE_PATTERN.match(action_id) + + if not match: + return + + vote_type = match.group(1) + deployment_id = int(match.group(2)) + + user_id = body["user"]["id"] + channel_id = body["channel"]["id"] + user = await get_user(user_id) + if not user: + # await respond(f"You must join the botnet first!", response_type="ephemeral") + await client.chat_postEphemeral(channel=channel_id, user=user_id, text="You must join the botnet first!") + return + + # await respond("Not implemented yet", response_type="ephemeral") + # await client.chat_postEphemeral(channel=channel_id, user=user_id, text="Not implemented yet") + + existing_vote = await get_user_vote(deployment_id, user_id) + if existing_vote: + await client.chat_postEphemeral(channel=channel_id, user=user_id, text=f"You already voted {existing_vote} on this deployment!") + + await add_vote(deployment, user_id, vote_type) + + approve_count, reject_count = await get_vote_counts(deployment_id) + + THRESHOLD = 3 # FIXME: DYNAMICALLY CALCULATE THIS!! + deployment = await get_deployment(deployment_id) + + @app.event("message") async def shut_up_slack_bolt(): # shut up that annoying debug warning that this event is unhandled diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..1efc693 --- /dev/null +++ b/src/utils.py @@ -0,0 +1,45 @@ +def generate_voting_blocks(deployment_id: int, message: str, approve_count: int, reject_count: int, voting_enabled: bool): + blocks = [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": f"Voting | Deployment #{deployment_id}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": f"*Message:*\n> {message}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": f"*Votes:*\n> Approve: {approve_count}\n> Reject: {reject_count}" + } + }, + ] + + if voting_enabled: + blocks.append({ + "type": "actions", + "elements": [ + { + "type": "button", + "text": {"type": "plain_text", "text": "Approve ^_^"}, + "style": "primary", + "action_id": f"vote_approve_{deployment_id}" + }, + { + "type": "button", + "text": {"type": "plain_text", "text": "Reject T_T"}, + "style": "danger", + "action_id": f"vote_reject_{deployment_id}" + } + ] + }) + + return blocks -- cgit v1.2.3