aboutsummaryrefslogtreecommitdiff
path: root/src/main.py
blob: 9daa8f33c4bc19fdca08fcb2d8732bda794087e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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, get_user, add_vote, get_vote_counts
from .auth import app as fastapi_app
from .botnet import deploy_message
import threading
import asyncio
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")

app = AsyncApp(token=selfbot_token)

@app.message("")
async def handle_messages(message, say):
    try:
        if message.get("channel_type") != "im":
            return
        
        if message.get("user") == selfbot_user_id:
            return

        if message.get("user") not in ["U0AKCBZHHMH"]:
            await say("Botnet is temporarily disabled for users other than <@U0AKCBZHHMH> for debugging and the safety of all OAuth-authorized users. Please DM <@U0AKCBZHHMH> if this is not resolved within a few days.")
            return
        
        text = message.get("text", "").strip()
        
        if not text.startswith("botnet"):
            # yay more scuffed arbitrary stuff
            text = "botnet help"
        
        parts = text.split(" ")
        if len(parts) == 1:
            # scuffed as hell, just sets it to help arbitrarily so it gets caught later LMAO
            # too bad, if it works dont touch it
            parts = ['botnet', 'help']
        
        command = parts[1]
        args = parts[2:]
        
        if command == "help":
            await say("*Botnet Commands*:\n---\n*botnet help*: shows this message\n*botnet deploy <message>*: sends a message into the deploy queue for review/voting\n*botnet approve <channel>*: approve Botnet to function in a channel (must be CM)", mrkdwn=True)
        elif command == "deploy":
            if not args:
                await say("Please provide a message to deploy!")
                return
            message_text = " ".join(args)
            result = await deploy_message(message.get("user"), message_text)        
            if result["success"]:
                await say(f"^_^ {result['message']} (Deployment #{result['deployment_id']})")
            else:
                await say(f"T_T {result['error']}")
        elif command == "approve":
            await say("Not implemented yet")
        else:
            await say(f"Unknown command: {command}")
    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
    pass

async def main():
    await init_db()

    def run_uvicorn():
        uvicorn.run(fastapi_app, host="0.0.0.0", port=8000)

    thread = threading.Thread(target=run_uvicorn, daemon=True)
    thread.start()

    handler = AsyncSocketModeHandler(app, app_token=app_token)
    await handler.start_async()

if __name__ == "__main__":
    # handler = SocketModeHandler(app, app_token=app_token)
    # handler.start()
    asyncio.run(main())