Reinitialize repo to remove private data
10,000 hours mucking with `git filter-repo` and no reasonable use-case found. On the plus side, anyone looking at this and curious what I nuked isn't missing much. This lived in a monorepo up until about a week ago.
This commit is contained in:
parent
8c03023aac
commit
c83acbdcfe
19 changed files with 1133 additions and 1 deletions
124
admission.py
Normal file
124
admission.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import cherrypy
|
||||
import requests
|
||||
|
||||
import config
|
||||
import ovenapi
|
||||
|
||||
|
||||
def check_webhook_throttle() -> bool:
|
||||
now = time.time()
|
||||
|
||||
# Clean up notification list to recent notifications
|
||||
while config.NOTIFICATIONS and now - config.NOTIFICATIONS[0] > 60:
|
||||
config.NOTIFICATIONS.pop(0)
|
||||
|
||||
config.NOTIFICATIONS.append(now)
|
||||
|
||||
return not len(config.NOTIFICATIONS) > config.NOTIFICATION_THROTTLE
|
||||
|
||||
|
||||
def webhook_online(stream) -> None:
|
||||
if not config.is_webhook_ready():
|
||||
return
|
||||
|
||||
data = {"username": f"{config.WEBHOOK_NAME} Online", "content": config.WEBHOOK_ONLINE}
|
||||
|
||||
if config.is_avatar_ready():
|
||||
target_av = f"{stream[1]}/{stream[2]}.png"
|
||||
avatar = target_av if Path(config.WEBHOOK_AVATAR_PATH, target_av).is_file() else "default.png"
|
||||
data["avatar_url"] = f"{config.WEBHOOK_AVATAR_URL}/{avatar}"
|
||||
|
||||
requests.post(config.WEBHOOK_URL, timeout=10, json=data, headers=config.WEBHOOK_HEADERS)
|
||||
|
||||
|
||||
def webhook_offline() -> None:
|
||||
if not config.is_webhook_ready():
|
||||
return
|
||||
|
||||
data = {"username": f"{config.WEBHOOK_NAME} Offline", "content": config.WEBHOOK_OFFLINE}
|
||||
|
||||
if config.WEBHOOK_AVATAR_PATH and config.WEBHOOK_AVATAR_URL:
|
||||
data["avatar_url"] = f"{config.WEBHOOK_AVATAR_URL}/offline.png"
|
||||
|
||||
requests.post(config.WEBHOOK_URL, timeout=10, json=data, headers=config.WEBHOOK_HEADERS)
|
||||
|
||||
|
||||
def check_authorized(host, app, stream, source) -> bool:
|
||||
# Are we globally disabled?
|
||||
if config.DISABLED:
|
||||
return False
|
||||
# IP Banned?
|
||||
if source in config.BLOCKED_IPS:
|
||||
return False
|
||||
# Nothing in the Oven API maps a domain to "default" vhost
|
||||
# So here we fudge checking default vhost for all apps/streams
|
||||
if f"default:{app}:{stream}" in config.DISABLED_KEYS:
|
||||
return False
|
||||
# Finally check the provided vhost app/stream
|
||||
return f"{host}:{app}:{stream}" not in config.DISABLED_KEYS
|
||||
|
||||
|
||||
@cherrypy.tools.register("on_end_request")
|
||||
def handle_notify() -> None:
|
||||
# If we don't have API creds we can't do this, abort
|
||||
if not (config.API_USER and config.API_PASS):
|
||||
return
|
||||
|
||||
# Get stream list from API
|
||||
# Unfortunately Oven doesn't reflect the new stream fast enough so we have to wait :(
|
||||
time.sleep(1)
|
||||
stream_list = ovenapi.OvenAPI(config.API_USER, config.API_PASS).get_stream_list()
|
||||
|
||||
# If we haven't gone empty->active or active->empty we need to do nothing
|
||||
if bool(stream_list) != bool(config.LAST_STREAM_LIST):
|
||||
if not check_webhook_throttle():
|
||||
cherrypy.log("Webhook throttle limit hit, ignoring")
|
||||
return
|
||||
|
||||
# Dispatch the appropriate webhook
|
||||
webhook_online(stream_list[0]) if stream_list else webhook_offline()
|
||||
|
||||
# Save our stream list into a durable value
|
||||
config.LAST_STREAM_LIST = stream_list.copy()
|
||||
|
||||
|
||||
class Admission:
|
||||
# /admission to control/trigger sessions
|
||||
@cherrypy.expose
|
||||
@cherrypy.tools.json_in()
|
||||
@cherrypy.tools.json_out()
|
||||
@cherrypy.tools.handle_notify()
|
||||
def default(self) -> dict:
|
||||
# Fast fail if we have no json payload
|
||||
try:
|
||||
input_json = cherrypy.request.json
|
||||
except AttributeError:
|
||||
cherrypy.response.status = 400
|
||||
return {}
|
||||
|
||||
# If this is a viewer, allow it with no processing
|
||||
# This should never happen since we won't enable webhooks for viewing
|
||||
if input_json["request"]["direction"] == "outgoing":
|
||||
return {"allowed": True}
|
||||
|
||||
# Figure out scheme, host, app and stream name for recording who is live
|
||||
_, _, host, app, path = input_json["request"]["url"].split("/")[:5]
|
||||
stream = path.split("?")[0]
|
||||
|
||||
# If we are closing, return a fast 200
|
||||
if input_json["request"]["status"] == "closing":
|
||||
return {}
|
||||
|
||||
# Get client IP for ACL checking
|
||||
ip = input_json["client"]["real_ip"]
|
||||
|
||||
# Check if stream is authorized
|
||||
if not check_authorized(host, app, stream, ip):
|
||||
cherrypy.log(f"Unauthorized stream key: {app}/{stream}")
|
||||
return {"allowed": False}
|
||||
|
||||
# Compile and dispatch our response
|
||||
return {"allowed": True}
|
Loading…
Add table
Add a link
Reference in a new issue