mirror of
https://github.com/MichaByte/OnBoard-Live.git
synced 2025-12-06 06:33:40 -05:00
minor bugfixes
This commit is contained in:
parent
8f274fe1e0
commit
ffc81adb8f
5 changed files with 266 additions and 211 deletions
|
|
@ -5,3 +5,4 @@ requests
|
|||
python-dotenv
|
||||
prisma
|
||||
fastapi-utils
|
||||
httpx
|
||||
|
|
@ -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"]
|
||||
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 requests.get(
|
||||
"https://verify.hackclub.dev/api/status", json={"slack_id": user}
|
||||
not in (
|
||||
await client.request(
|
||||
url="https://verify.hackclub.dev/api/status",
|
||||
method="GET",
|
||||
content=json.dumps({"slack_id": user}),
|
||||
)
|
||||
).text
|
||||
)
|
||||
bolt.client.chat_postMessage(
|
||||
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 <https://forms.hackclub.com/eligibility?program=Onboard%20Live&slack_id={user}|the verification form>! 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,10 +266,12 @@ def handle_application_submission(ack, body):
|
|||
|
||||
|
||||
@bolt.command("/onboard-live-apply")
|
||||
def apply(ack: Ack, command):
|
||||
ack()
|
||||
async def apply(ack: AsyncAck, command):
|
||||
await ack()
|
||||
async with httpx.AsyncClient() as client:
|
||||
print(
|
||||
requests.post(
|
||||
(
|
||||
await client.post(
|
||||
"https://slack.com/api/views.open",
|
||||
headers={
|
||||
"Authorization": f"Bearer {os.environ['SLACK_TOKEN']}",
|
||||
|
|
@ -198,8 +287,16 @@ def apply(ack: Ack, command):
|
|||
"text": "OnBoard Live Application",
|
||||
"emoji": True,
|
||||
},
|
||||
"submit": {"type": "plain_text", "text": "Submit", "emoji": True},
|
||||
"close": {"type": "plain_text", "text": "Cancel", "emoji": True},
|
||||
"submit": {
|
||||
"type": "plain_text",
|
||||
"text": "Submit",
|
||||
"emoji": True,
|
||||
},
|
||||
"close": {
|
||||
"type": "plain_text",
|
||||
"text": "Cancel",
|
||||
"emoji": True,
|
||||
},
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
|
|
@ -280,65 +377,14 @@ def apply(ack: Ack, command):
|
|||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
).text
|
||||
)
|
||||
# bolt.client.modal(channel=command['channel_id'], user=command['user_id'], text="Application form for OnBoard Live", blocks=[{
|
||||
|
||||
|
||||
@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:
|
||||
|
|
|
|||
Binary file not shown.
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 6.3 KiB |
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
// import 'uno.css'
|
||||
import hls from "hls.js";
|
||||
import { onMount } from "svelte";
|
||||
let videos: { [key: string]: HTMLVideoElement } = {};
|
||||
|
|
@ -7,9 +6,9 @@
|
|||
| {
|
||||
ready: boolean;
|
||||
name: string;
|
||||
focused?: boolean;
|
||||
}[]
|
||||
| null = null;
|
||||
let activeStream: string;
|
||||
let newData:
|
||||
| {
|
||||
bytesSent: any;
|
||||
|
|
@ -22,8 +21,14 @@
|
|||
onMount(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await fetch("http://localhost:9997/v3/paths/list");
|
||||
newData = (await response.json())["items"];
|
||||
const activeStreamResponse = await fetch(
|
||||
"http://localhost:8000/api/v1/active_stream",
|
||||
);
|
||||
activeStream = await activeStreamResponse.text();
|
||||
const pathListResponse = await fetch(
|
||||
"http://localhost:9997/v3/paths/list",
|
||||
);
|
||||
newData = (await pathListResponse.json())["items"];
|
||||
if (newData) {
|
||||
for (let i = 0; i < newData.length; i++) {
|
||||
delete newData[i].readyTime;
|
||||
|
|
@ -33,7 +38,7 @@
|
|||
}
|
||||
console.log(videos);
|
||||
videos = Object.fromEntries(
|
||||
Object.entries(videos).filter(([_, v]) => v != null)
|
||||
Object.entries(videos).filter(([_, v]) => v != null),
|
||||
);
|
||||
|
||||
if (JSON.stringify(newData) !== JSON.stringify(pathData)) {
|
||||
|
|
@ -44,7 +49,7 @@
|
|||
console.log(video);
|
||||
const hlsInstance = new hls({ progressive: false });
|
||||
hlsInstance.loadSource(
|
||||
`http://localhost:8888/${video}/index.m3u8`
|
||||
`http://localhost:8888/${video}/index.m3u8`,
|
||||
);
|
||||
hlsInstance.attachMedia(videos[video]);
|
||||
}
|
||||
|
|
@ -65,7 +70,10 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<div style="width: 100vw; height: 100vw; overflow: hidden; position: absolute; top: 0; left: 0"><div class="gradient"></div>
|
||||
<div
|
||||
style="width: 100vw; height: 100vw; overflow: hidden; position: absolute; top: 0; left: 0"
|
||||
>
|
||||
<div class="gradient"></div>
|
||||
</div>
|
||||
<div class="container2">
|
||||
<h2
|
||||
|
|
@ -88,7 +96,7 @@
|
|||
autoplay
|
||||
id={path.name}
|
||||
bind:this={videos[path.name]}
|
||||
class:focused={path.focused}
|
||||
class:active={path.name === activeStream}
|
||||
class:video={Object.keys(videos).length > 1}
|
||||
class:only-video={!(Object.keys(videos).length > 1)}
|
||||
></video>
|
||||
|
|
@ -172,7 +180,7 @@
|
|||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.focused {
|
||||
.active {
|
||||
width: 75vw;
|
||||
height: 75vh;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue