IT WORKS!!!111!!!1 (too many changes)

This commit is contained in:
Micha Albert 2024-08-01 01:34:55 +00:00
parent 0a523a06d2
commit 77a2bd103e
2 changed files with 150 additions and 137 deletions

View file

@ -1,16 +1,15 @@
import json import json
import logging
import os import os
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from random import choice from random import choice
from secrets import token_hex from secrets import token_hex
from typing import Dict, List
import httpx import httpx
import uvicorn
from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.interval import IntervalTrigger
from dotenv import load_dotenv from dotenv import load_dotenv
from fastapi import Depends, FastAPI, Request, Response from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from prisma import Prisma from prisma import Prisma
from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler
@ -18,11 +17,12 @@ from slack_bolt.async_app import AsyncAck, AsyncApp
load_dotenv() load_dotenv()
active_stream = {} active_stream: Dict[str, str | bool] = {}
active_streams = [] active_streams: List[Dict[str, str | bool]] = []
scheduler = AsyncIOScheduler() scheduler = AsyncIOScheduler()
async def update_active(): async def update_active():
global active_stream global active_stream
global active_streams global active_streams
@ -37,26 +37,38 @@ async def update_active():
if stream["ready"] and stream not in active_streams: if stream["ready"] and stream not in active_streams:
active_streams.append(stream) active_streams.append(stream)
print(active_streams) print(active_streams)
try:
if len(active_streams) == 0: if len(active_streams) == 0:
print("No active streams") print("No active streams")
return return
if active_stream == {}: if active_stream == {}:
active_stream = choice(active_streams)["name"] print("No current active stream, picking new one...")
new_stream = choice(active_streams)["name"] active_stream = choice(active_streams)
return
if len(active_streams) == 1: if len(active_streams) == 1:
return return
while new_stream == active_stream: print(
new_stream = choice(active_streams)["name"] f"starting to pick new active stream (switching away from {active_stream['name']})"
)
new_stream = choice(active_streams)
while new_stream["name"] == active_stream["name"]:
print(
f"re-attemppting to pick active stream since we picked {new_stream} again"
)
new_stream = choice(active_streams)
print(f"found new stream to make active: {new_stream}")
try:
await db.connect() await db.connect()
old_active_stream_user = await db.user.find_first(where={"id": (await db.stream.find_first(where={"key": active_stream})).user_id}) # type: ignore except Exception as e:
print(e)
print(f"trying to find user associated with stream {active_stream['name']}")
print(await db.stream.find_many())
old_active_stream_user = await db.user.find_first(where={"id": (await db.stream.find_first(where={"key": str(active_stream["name"])})).user_id}) # type: ignore
await bolt.client.chat_postMessage(channel="C07ERCGG989", text=f"Hey <@{old_active_stream_user.slack_id}>, you're no longer in focus!") # type: ignore await bolt.client.chat_postMessage(channel="C07ERCGG989", text=f"Hey <@{old_active_stream_user.slack_id}>, you're no longer in focus!") # type: ignore
active_stream = new_stream active_stream = new_stream
active_stream_user = await db.user.find_first(where={"id": (await db.stream.find_first(where={"key": active_stream})).user_id}) # type: ignore active_stream_user = await db.user.find_first(where={"id": (await db.stream.find_first(where={"key": str(active_stream["name"])})).user_id}) # type: ignore
await bolt.client.chat_postMessage(channel="C07ERCGG989", text=f"Hey <@{active_stream_user.slack_id}>, you're in focus! Make sure to tell us what you're working on!") # type: ignore await bolt.client.chat_postMessage(channel="C07ERCGG989", text=f"Hey <@{active_stream_user.slack_id}>, you're in focus! Make sure to tell us what you're working on!") # type: ignore
await db.disconnect() await db.disconnect()
except Exception:
return
async def check_for_new(): async def check_for_new():
global active_stream global active_stream
@ -65,40 +77,58 @@ async def check_for_new():
streams_raw = (await client.get("http://localhost:9997/v3/paths/list")).json()[ streams_raw = (await client.get("http://localhost:9997/v3/paths/list")).json()[
"items" "items"
] ]
streams_have_changed = False streams_simple = []
streams = []
for stream in streams_raw: for stream in streams_raw:
streams.append({"name": stream["name"], "ready": stream["ready"]}) if stream["ready"]:
for stream in streams: streams_simple.append(stream["name"])
for active_stream in active_streams: active_streams_simple = []
if stream["name"] == active_stream["name"] and not stream["ready"]: for i in active_streams:
active_streams.remove(active_stream) active_streams_simple.append(i["name"])
streams_have_changed = True if active_stream == {}:
for active_stream in active_streams: active_stream = {"name": i["name"], "ready": True}
if stream["name"] == active_stream["name"] and not stream["ready"]: for stream in active_streams_simple:
active_streams.remove(active_stream) if stream not in streams_simple:
streams_have_changed = True active_streams.remove(
if stream["ready"] and [s["name"] for s in streams] not in [s["name"] for s in active_streams]: next(item for item in active_streams if item["name"] == stream)
streams_have_changed = True )
active_streams.append(stream) active_stream = choice(active_streams)
new_active_streams = [] for stream in streams_simple:
[new_active_streams.append(x) for x in active_streams if x not in new_active_streams] if stream not in active_streams_simple:
active_streams = new_active_streams active_streams.append({"name": stream, "ready": True})
if streams_have_changed: # for stream in streams:
print("Streams have changed!") # for i in active_streams:
streams_have_changed = False # if stream["name"] == i["name"] and not i["ready"]:
await update_active() # print(f"removing stream that is no longer ready: {i["name"]}")
return # active_streams.remove(i)
# active_stream = choice(active_streams)
# for i in active_streams:
# if stream["name"] == i["name"] and not stream["ready"]:
# active_streams.remove(i)
# if active_stream == stream["name"]:
# active_stream = choice(active_streams)
# active_streams_simple = []
# for i in active_streams:
# active_streams_simple.append(i["name"])
# if stream["ready"] and stream["name"] not in active_streams_simple:
# active_streams.append(stream)
# new_active_streams = []
# [new_active_streams.append(x) for x in active_streams if x not in new_active_streams]
# active_streams = new_active_streams
if len(active_streams) == 0: if len(active_streams) == 0:
print("No active streams") print("No active streams")
active_stream = {} active_stream = {}
@asynccontextmanager @asynccontextmanager
async def lifespan(app: FastAPI): async def lifespan(app: FastAPI):
await update_active() await update_active()
scheduler.start() scheduler.start()
scheduler.add_job(update_active, IntervalTrigger(minutes=5)) scheduler.add_job(update_active, IntervalTrigger(seconds=5 * 60))
scheduler.add_job(check_for_new, IntervalTrigger(seconds=3)) scheduler.add_job(check_for_new, IntervalTrigger(seconds=3))
try:
await db.connect() await db.connect()
except Exception:
pass
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
for stream in await db.stream.find_many(): for stream in await db.stream.find_many():
await client.post( await client.post(
@ -173,13 +203,6 @@ async def handle_app_home_opened_events(body, logger, event, client):
) )
@bolt.event("message")
async def handle_message(event):
if event["channel"] == "C07ERCGG989":
print(event)
await bolt.client.chat_delete(channel="C07ERCGG989", ts=event["ts"])
@bolt.action("deny") @bolt.action("deny")
async def deny(ack, body): async def deny(ack, body):
await ack() await ack()
@ -206,7 +229,10 @@ async def deny(ack, body):
@bolt.action("approve") @bolt.action("approve")
async def approve(ack, body): async def approve(ack, body):
await ack() await ack()
try:
await db.connect() await db.connect()
except Exception:
pass
message = body["message"] message = body["message"]
applicant_slack_id = message["blocks"][len(message) - 3]["text"]["text"].split( applicant_slack_id = message["blocks"][len(message) - 3]["text"]["text"].split(
": " ": "
@ -236,18 +262,14 @@ async def approve(ack, body):
sumbitter_convo = await bolt.client.conversations_open( sumbitter_convo = await bolt.client.conversations_open(
users=applicant_slack_id, return_im=True users=applicant_slack_id, return_im=True
) )
async with httpx.AsyncClient() as client:
await client.post(
"http://127.0.0.1:9997/v3/config/paths/add/" + new_stream.key,
json={"name": new_stream.key},
)
await bolt.client.chat_postMessage( await bolt.client.chat_postMessage(
channel=sumbitter_convo["channel"]["id"], channel=sumbitter_convo["channel"]["id"],
blocks=[ text=f"Welcome to OnBoard Live! Your stream key is {new_stream.key}. To use your stream key the easy way, go to <https://live.onboard.hackclub.com/{new_stream.key}/publish|this link>. You can also use it in OBS with the server URL of rtmp://live.onboard.hackclub.com:1935",
{
"type": "section",
"text": {
"type": "plain_text",
"text": f"Welcome to OnBoard Live! Your stream key is {new_stream.key}. To use your stream key the easy way, go to <https://live.onboard.hackclub.com/{new_stream.key}/publish|this link>. You can also use it in OBS with the server URL of rtmp://live.onboard.hackclub.com:1935",
"emoji": True,
},
}
],
) )
await db.disconnect() await db.disconnect()

View file

@ -8,17 +8,13 @@
name: string; name: string;
}[] }[]
| null = null; | null = null;
let activeStream: string; $: activeStream = "";
let oldActiveStream: string | null = null; $: oldActiveStream = "";
let newData: let newData: {
| {
bytesSent: any;
bytesReceived: any;
readyTime: any;
ready: boolean; ready: boolean;
name: string; name: string;
}[] isActive: boolean;
| null = null; }[] = [];
let activePaths: string[] = []; let activePaths: string[] = [];
onMount(() => { onMount(() => {
const fetchData = async () => { const fetchData = async () => {
@ -27,33 +23,32 @@
"http://localhost:8000/api/v1/active_stream", "http://localhost:8000/api/v1/active_stream",
); );
activeStream = (await activeStreamResponse.text()).replaceAll('"', ""); activeStream = (await activeStreamResponse.text()).replaceAll('"', "");
if (oldActiveStream !== null && oldActiveStream !== activeStream) { // if (oldActiveStream !== null && oldActiveStream !== activeStream) {
window.location.reload(); // window.location.reload();
} // }
oldActiveStream = activeStream; oldActiveStream = activeStream;
const pathListResponse = await fetch( const pathListResponse = await (
"http://localhost:9997/v3/paths/list", await fetch("http://localhost:9997/v3/paths/list")
); ).json();
newData = (await pathListResponse.json())["items"]; console.log(pathListResponse);
if (newData) { newData = [];
for (let i = 0; i < newData.length; i++) { for (let i = 0; i < pathListResponse["items"].length; i++) {
delete newData[i].readyTime; if (pathListResponse["items"][i]["ready"] === false) {
delete newData[i].bytesReceived;
delete newData[i].bytesSent;
} }
newData.push({
name: pathListResponse["items"][i]["name"],
ready: pathListResponse["items"][i]["ready"],
isActive: pathListResponse["items"][i]["name"] === activeStream,
});
} }
console.log(newData);
videos = Object.fromEntries( videos = Object.fromEntries(
Object.entries(videos).filter(([_, v]) => v != null), Object.entries(videos).filter(([_, v]) => v != null),
); );
console.log(newData);
if (JSON.stringify(newData) !== JSON.stringify(pathData)) { if (JSON.stringify(newData) !== JSON.stringify(pathData)) {
console.log("Data changed"); console.log("Data changed");
pathData = newData; pathData = newData;
for (let pathIdx = 0; pathIdx < pathData?.length! - 1; pathIdx++) {
if (pathData![pathIdx].ready) {
activePaths.push(pathData![pathIdx].name);
}
}
setTimeout(() => { setTimeout(() => {
for (const video in videos) { for (const video in videos) {
const hlsInstance = new hls({ progressive: false }); const hlsInstance = new hls({ progressive: false });
@ -80,26 +75,19 @@
</script> </script>
<div <div
style="width: 100vw; height: 100vw; overflow: hidden; position: absolute; top: 0; left: 0" style="width: 100vw; height: 100vh; overflow: hidden; position: absolute; top: 0; left: 0"
> >
<div class="gradient"></div> <div class="gradient"></div>
</div> </div>
<div <h2 class="text-4xl text-center">OnBoard Live Design Stream</h2>
class="flex w-screen h-screen justify-items-center bg-transparent absolute top-0 left-0 overflow-hidden" <img
>
<h2 class="text-4xl text-center w-screen absolute top-4">
OnBoard Live Design Stream
</h2>
<img
class="absolute top-0 left-0 w-48" class="absolute top-0 left-0 w-48"
src="https://assets.hackclub.com/flag-orpheus-left.svg" src="https://assets.hackclub.com/flag-orpheus-left.svg"
alt="Hack Club" alt="Hack Club"
/> />
<div class="grid w-screen grid-rows-2 grid-cols-1 h-[90vh] justify-items-center bg-transparent mt-0">
{#if pathData?.map((path) => path.ready).includes(true)} {#if pathData?.map((path) => path.ready).includes(true)}
{#if activePaths.length == 1} {#if activePaths.length == 1}
<div
class="flex justify-center items-center w-screen h-3/4 absolute top-20"
>
<!-- svelte-ignore a11y-media-has-caption --> <!-- svelte-ignore a11y-media-has-caption -->
<video <video
controls controls
@ -108,33 +96,35 @@
bind:this={videos[activeStream]} bind:this={videos[activeStream]}
class="h-full w-auto" class="h-full w-auto"
></video> ></video>
</div>
{:else} {:else}
<div <div class="flex justify-center items-center w-auto h-[65vh] mt-5">
class="flex justify-center items-center w-screen h-1/2 absolute top-20" {#each newData as path}
> {#if path.ready && path.name === activeStream}
<!-- svelte-ignore a11y-media-has-caption --> <!-- svelte-ignore a11y-media-has-caption -->
<video <video
controls controls
autoplay autoplay
id={activeStream} id={path.name}
bind:this={videos[activeStream]} bind:this={videos[path.name]}
class="h-full w-auto" class="max-h-[65vh] w-auto bg-red-500"
></video> ></video>
{/if}
{/each}
</div> </div>
<div <div
class="flex justify-center items-center w-screen h-1/4 absolute bottom-10" class="flex items-center justify-center justify-items-center w-screen h-[25vh] bottom-12 absolute"
> >
{#each activePaths as path} {#each newData as path}
{#if path !== activeStream} {#if path.name !== activeStream && path.ready}
<!-- svelte-ignore a11y-media-has-caption --> <!-- svelte-ignore a11y-media-has-caption -->
<video <video
controls controls
autoplay autoplay
muted muted
id={path} id={path.name}
bind:this={videos[path]} bind:this={videos[path.name]}
class="h-[20vh] w-auto mx-10" class="max-h-[25vh] mx-10"
></video> ></video>
{/if} {/if}
{/each} {/each}
@ -163,6 +153,7 @@
position: absolute; position: absolute;
transform-origin: center; transform-origin: center;
overflow: hidden; overflow: hidden;
z-index: -999;
background: linear-gradient( background: linear-gradient(
45deg, 45deg,
rgba(236, 55, 80, 1) 0%, rgba(236, 55, 80, 1) 0%,