From ffc81adb8f15257e714eb883aa25ddfe1a2f2a0a Mon Sep 17 00:00:00 2001 From: Micha Albert Date: Sun, 28 Jul 2024 21:24:45 +0000 Subject: [PATCH] minor bugfixes --- requirements.txt | 3 +- stream/backend/main.py | 427 ++++++++++-------- stream/tiling-frontend/bun.lockb | Bin 104718 -> 104718 bytes .../public/flag-orpheus-left.svg | 1 - stream/tiling-frontend/src/App.svelte | 46 +- 5 files changed, 266 insertions(+), 211 deletions(-) delete mode 100644 stream/tiling-frontend/public/flag-orpheus-left.svg diff --git a/requirements.txt b/requirements.txt index 926494c..b5a1063 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ slack-bolt requests python-dotenv prisma -fastapi-utils \ No newline at end of file +fastapi-utils +httpx \ No newline at end of file diff --git a/stream/backend/main.py b/stream/backend/main.py index 7b9b3dd..0f81ed3 100644 --- a/stream/backend/main.py +++ b/stream/backend/main.py @@ -1,25 +1,52 @@ -from random import choice -from fastapi import FastAPI, Request, Response -from prisma import Prisma -from secrets import token_hex -from slack_bolt import Ack, App -from fastapi_utils.tasks import repeat_every -from slack_bolt.adapter.fastapi import SlackRequestHandler -from dotenv import load_dotenv +import json import os -import requests +from contextlib import asynccontextmanager +from random import choice +from secrets import token_hex + +import httpx +import uvicorn +from dotenv import load_dotenv +from fastapi import FastAPI, Request, Response +from fastapi.middleware.cors import CORSMiddleware +from fastapi_utils.tasks import repeat_every +from prisma import Prisma +from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler +from slack_bolt.async_app import AsyncAck, AsyncApp load_dotenv() -api = FastAPI() + +@asynccontextmanager +async def lifespan(app: FastAPI): + await db.connect() + async with httpx.AsyncClient() as client: + for stream in await db.stream.find_many(): + await client.post( + "http://127.0.0.1:9997/v3/config/paths/add/" + stream.key, + json={"name": stream.key}, + ) + yield + await db.disconnect() + + +api = FastAPI(lifespan=lifespan) + +api.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_methods=["*"], + allow_headers=["*"], +) db = Prisma() -bolt = App( + +bolt = AsyncApp( token=os.environ["SLACK_TOKEN"], signing_secret=os.environ["SLACK_SIGNING_SECRET"] ) -bolt_handler = SlackRequestHandler(bolt) +bolt_handler = AsyncSlackRequestHandler(bolt) active_stream = None @@ -42,9 +69,14 @@ async def get_user_by_id(user_id: str): return user if user else Response(status_code=404, content="404: User not found") +@api.get("/api/v1/active_stream") +async def get_active_stream(): + return active_stream + + @bolt.event("app_home_opened") -def handle_app_home_opened_events(body, logger, event, client): - client.views_publish( +async def handle_app_home_opened_events(body, logger, event, client): + await client.views_publish( user_id=event["user"], # the view object that appears in the app home view={ @@ -64,45 +96,100 @@ def handle_app_home_opened_events(body, logger, event, client): ) -@bolt.action("approve") -def approve(ack, body): - ack() +@bolt.action("deny") +async def deny(ack, body): + await ack() message = body["message"] - applicant_slack_id = message["blocks"][len(message) - 3]["text"]["text"].split(": ")[1] # I hate it. You hate it. We all hate it. Carry on. - applicant_name = message["blocks"][len(message) - 6]["text"]["text"] - print(applicant_slack_id, applicant_name) - # new_user = await db.user.create( - # {"slack_id": applicant_slack_id, "name": user["name"]} - # ) - # print(new_user.id) - # new_stream = await db.stream.create( - # {"user": {"connect": {"id": new_user.id}}, "key": token_hex(16)} - # ) - # print(new_user, new_stream) + applicant_slack_id = message["blocks"][len(message) - 3]["text"]["text"].split( + ": " + )[ + 1 + ] # I hate it. You hate it. We all hate it. Carry on. + applicant_name = message["blocks"][len(message) - 7]["text"]["text"].split( + "Name: " + )[ + 1 + ] # oops i did it again + await bolt.client.chat_delete( + channel=body["container"]["channel_id"], ts=message["ts"] + ) + await bolt.client.chat_postMessage( + channel=body["container"]["channel_id"], + text=f"{applicant_name}'s application has been denied! Remember to reach out to them if this is a fixable issue. Their username is <@{applicant_slack_id}>.", + ) + + +@bolt.action("approve") +async def approve(ack, body): + await ack() + await db.connect() + message = body["message"] + applicant_slack_id = message["blocks"][len(message) - 3]["text"]["text"].split( + ": " + )[ + 1 + ] # I hate it. You hate it. We all hate it. Carry on. + applicant_name = message["blocks"][len(message) - 7]["text"]["text"].split( + "Name: " + )[ + 1 + ] # oops i did it again + await bolt.client.chat_delete( + channel=body["container"]["channel_id"], ts=message["ts"] + ) + await bolt.client.chat_postMessage( + channel=body["container"]["channel_id"], + text=f"{applicant_name}'s application has been approved! Their username is <@{applicant_slack_id}>.", + ) + if applicant_slack_id in [d.slack_id for d in await db.user.find_many()]: # type: ignore + return + new_user = await db.user.create( + {"slack_id": applicant_slack_id, "name": applicant_name} + ) + new_stream = await db.stream.create( + {"user": {"connect": {"id": new_user.id}}, "key": token_hex(16)} + ) + sumbitter_convo = await bolt.client.conversations_open( + users=applicant_slack_id, return_im=True + ) + await bolt.client.chat_postMessage( + channel=sumbitter_convo["channel"]["id"], + text=f"Your application has been approved! Your stream key is `{new_stream.key}`. Keep this safe and do not share it with anyone!", + ) @bolt.view("apply") -def handle_application_submission(ack, body): - ack() +async def handle_application_submission(ack, body): + await ack() user = body["user"]["id"] - sumbitter_convo = bolt.client.conversations_open(users=user, return_im=True) - user_real_name = bolt.client.users_info(user=user)["user"]["real_name"] - user_verified = ( - "Eligible L" - not in requests.get( - "https://verify.hackclub.dev/api/status", json={"slack_id": user} - ).text - ) - bolt.client.chat_postMessage( + sumbitter_convo = await bolt.client.conversations_open(users=user, return_im=True) + user_real_name = (await bolt.client.users_info(user=user))["user"]["real_name"] + user_verified = "" + async with httpx.AsyncClient() as client: + user_verified = ( + "Eligible L" + not in ( + await client.request( + url="https://verify.hackclub.dev/api/status", + method="GET", + content=json.dumps({"slack_id": user}), + ) + ).text + ) + await bolt.client.chat_postMessage( channel=sumbitter_convo["channel"]["id"], text=f"Your application has been submitted! We will review it shortly. Please do not send another application - If you haven't heard back in over 48 hours, or you forgot something in your application, please message <@{os.environ['ADMIN_SLACK_ID']}>! Here's a copy of your responses for your reference:\nSome info on your project(s): {body['view']['state']['values']['project-info']['project-info-body']['value']}{f'\nPlease fill out ! We can only approve your application once this is done.' if not user_verified else ''}", ) - admin_convo = bolt.client.conversations_open( + admin_convo = await bolt.client.conversations_open( users=os.environ["ADMIN_SLACK_ID"], return_im=True ) - bolt.client.chat_postMessage( + will_behave = False + boxes = body['view']['state']['values']['c+wGI']['checkboxes']['selected_options'] + if len(boxes) == 1 and boxes[0]["value"] == 'value-1': + will_behave = True + await bolt.client.chat_postMessage( channel=admin_convo["channel"]["id"], - text=":siren-real: New OnBoard Live application! :siren-real:", + text="New OnBoard Live application!", blocks=[ { "type": "section", @@ -139,7 +226,7 @@ def handle_application_submission(ack, body): "type": "section", "text": { "type": "plain_text", - "text": f":pray: Will behave on stream: Yes", + "text": f":pray: Will behave on stream: {will_behave}", "emoji": True, }, }, @@ -179,166 +266,125 @@ def handle_application_submission(ack, body): @bolt.command("/onboard-live-apply") -def apply(ack: Ack, command): - ack() - print( - requests.post( - "https://slack.com/api/views.open", - headers={ - "Authorization": f"Bearer {os.environ['SLACK_TOKEN']}", - "Content-type": "application/json; charset=utf-8", - }, - json={ - "trigger_id": command["trigger_id"], - "view": { - "type": "modal", - "callback_id": "apply", - "title": { - "type": "plain_text", - "text": "OnBoard Live Application", - "emoji": True, +async def apply(ack: AsyncAck, command): + await ack() + async with httpx.AsyncClient() as client: + print( + ( + await client.post( + "https://slack.com/api/views.open", + headers={ + "Authorization": f"Bearer {os.environ['SLACK_TOKEN']}", + "Content-type": "application/json; charset=utf-8", }, - "submit": {"type": "plain_text", "text": "Submit", "emoji": True}, - "close": {"type": "plain_text", "text": "Cancel", "emoji": True}, - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Welcome to OnBoard Live!\n\n*Please make sure to read this form thoroughly.*\n\nWe can't wait to see what you make!\n\n_Depending on your screen, you might need to scroll down to see the whole form._", - }, - }, - {"type": "divider"}, - { - "type": "input", - "block_id": "project-info", - "element": { - "action_id": "project-info-body", - "type": "plain_text_input", - "multiline": True, - "placeholder": { - "type": "plain_text", - "text": "I want to make...", - }, - }, - "label": { + json={ + "trigger_id": command["trigger_id"], + "view": { + "type": "modal", + "callback_id": "apply", + "title": { "type": "plain_text", - "text": "What do you plan on making?\n\nNote that you can make whatever you want, this is just so we know what level you're at!", + "text": "OnBoard Live Application", "emoji": True, }, - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Examples of unacceptable behavior include (but are not limited to) streaming inappropriate content or content that is unrelated to PCB design, sharing your stream key with others, trying to abuse the system, streaming work that you did not do or is not actually live (i.e. pre-recorded). Inappropriate behavior may result in removal from the Hack Club Slack or other consequences, as stated in the . Any use of your stream key is your responsibilty, so don't share it with anyone for any reason. Admins will never ask for your stream key. Please report any urgent rule violations by messaging <@U05C64XMMHV>. If they do not respond in 5 minutes, please ping .", - }, - }, - { - "type": "section", - "text": { + "submit": { "type": "plain_text", - "text": "Confirm that you have read the above by following these instructions:", + "text": "Submit", + "emoji": True, }, - "accessory": { - "type": "checkboxes", - "options": [ - { - "text": { - "type": "plain_text", - "text": "To agree that you will be well-behaved while you're live, DO NOT check this box. Instead, check the one below.", - "emoji": True, - }, - "description": { - "type": "mrkdwn", - "text": "This is to make sure you're paying attention!", - }, - "value": "value-0", - }, - { - "text": { - "type": "plain_text", - "text": "To agree that you will be well-behaved while you're live, check this box.", - "emoji": True, - }, - "value": "value-1", - }, - ], - "action_id": "checkboxes", + "close": { + "type": "plain_text", + "text": "Cancel", + "emoji": True, }, - }, - {"type": "divider"}, - { - "type": "context", - "elements": [ + "blocks": [ { - "type": "mrkdwn", - "text": "Please ask <@U05C64XMMHV> for help if you need it!", - } + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Welcome to OnBoard Live!\n\n*Please make sure to read this form thoroughly.*\n\nWe can't wait to see what you make!\n\n_Depending on your screen, you might need to scroll down to see the whole form._", + }, + }, + {"type": "divider"}, + { + "type": "input", + "block_id": "project-info", + "element": { + "action_id": "project-info-body", + "type": "plain_text_input", + "multiline": True, + "placeholder": { + "type": "plain_text", + "text": "I want to make...", + }, + }, + "label": { + "type": "plain_text", + "text": "What do you plan on making?\n\nNote that you can make whatever you want, this is just so we know what level you're at!", + "emoji": True, + }, + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Examples of unacceptable behavior include (but are not limited to) streaming inappropriate content or content that is unrelated to PCB design, sharing your stream key with others, trying to abuse the system, streaming work that you did not do or is not actually live (i.e. pre-recorded). Inappropriate behavior may result in removal from the Hack Club Slack or other consequences, as stated in the . Any use of your stream key is your responsibilty, so don't share it with anyone for any reason. Admins will never ask for your stream key. Please report any urgent rule violations by messaging <@U05C64XMMHV>. If they do not respond in 5 minutes, please ping .", + }, + }, + { + "type": "section", + "text": { + "type": "plain_text", + "text": "Confirm that you have read the above by following these instructions:", + }, + "accessory": { + "type": "checkboxes", + "options": [ + { + "text": { + "type": "plain_text", + "text": "To agree that you will be well-behaved while you're live, DO NOT check this box. Instead, check the one below.", + "emoji": True, + }, + "description": { + "type": "mrkdwn", + "text": "This is to make sure you're paying attention!", + }, + "value": "value-0", + }, + { + "text": { + "type": "plain_text", + "text": "To agree that you will be well-behaved while you're live, check this box.", + "emoji": True, + }, + "value": "value-1", + }, + ], + "action_id": "checkboxes", + }, + }, + {"type": "divider"}, + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": "Please ask <@U05C64XMMHV> for help if you need it!", + } + ], + }, ], }, - ], - }, - }, - ).text - ) - # bolt.client.modal(channel=command['channel_id'], user=command['user_id'], text="Application form for OnBoard Live", blocks=[{ + }, + ) + ).text + ) @bolt.action("checkboxes") -def handle_some_action(ack): - ack() - - -# "type": "header", -# "text": { -# "type": "plain_text", -# "text": "Welcome to OnBoard Live!", -# } -# }, -# { -# "type": "section", -# "text": { -# "type": "mrkdwn", -# "text": "Before you can get designing, we need a little bit of info from you. All fields are required!" -# } -# }, -# { -# "type": "divider" -# }, -# { -# "type": "input", -# "element": { -# "type": "plain_text_input", -# "multiline": True, -# "action_id": "project_ideas_input-action", -# "placeholder": { -# "type": "plain_text", -# "text": "I want to make a..." -# } -# }, -# "label": { -# "type": "plain_text", -# "text": "What do you plan to make with OnBoard Live?\nThis can be changed anytime!", -# } -# }, -# { -# "type": "divider" -# }, -# { -# "type": "actions", -# "elements": [ -# { -# "type": "button", -# "text": { -# "type": "plain_text", -# "text": "Apply!", -# }, -# "value": "apply", -# "style": "primary", -# "action_id": "actionId-0" - -# }]}]) +async def handle_some_action(ack): + await ack() @api.post("/slack/events") @@ -350,6 +396,7 @@ async def slack_event_endpoint(req: Request): async def change_active_stream(): global active_stream streams = [] + await db.connect() for stream in await db.stream.find_many(): streams.append(stream.id) if len(streams) == 0: diff --git a/stream/tiling-frontend/bun.lockb b/stream/tiling-frontend/bun.lockb index e0a9e9a2a72831ce8eb9cd97ab1f99cc1931b86e..ac9ea20925231ff24fecce59b7419adf4bbe9919 100755 GIT binary patch delta 26 hcmeC%#MZZotzipey$}auoS~kno}uyfb|J?0HUM_~2tEJ+ delta 26 dcmeC%#MZZotzipey$}Zz0|abu7h-I00{~}X2D< \ No newline at end of file diff --git a/stream/tiling-frontend/src/App.svelte b/stream/tiling-frontend/src/App.svelte index 272c917..10704c6 100644 --- a/stream/tiling-frontend/src/App.svelte +++ b/stream/tiling-frontend/src/App.svelte @@ -1,5 +1,4 @@ -
+
+

1} class:only-video={!(Object.keys(videos).length > 1)} > @@ -127,11 +135,11 @@ background-color: transparent; } .gradient { - width: 100vw; + width: 100vw; height: 100vh; - position: absolute; - transform-origin: center; - overflow: hidden; + position: absolute; + transform-origin: center; + overflow: hidden; background: linear-gradient( 45deg, rgba(236, 55, 80, 1) 0%, @@ -147,15 +155,15 @@ 0% { transform: scale(1) rotate(0deg); } - 25% { - transform: scale(2) rotate(-35deg); - } + 25% { + transform: scale(2) rotate(-35deg); + } 50% { transform: scale(3) rotate(90deg); } - 75% { - transform: scale(2) rotate(-35deg); - } + 75% { + transform: scale(2) rotate(-35deg); + } 100% { transform: scale(1) rotate(0deg); } @@ -172,7 +180,7 @@ padding-left: 10px; padding-right: 10px; } - .focused { + .active { width: 75vw; height: 75vh; }