Skip to content

Commit

Permalink
Merge branch 'main' into issue-1771/video-recording-lost-typecast
Browse files Browse the repository at this point in the history
  • Loading branch information
russss authored Sep 1, 2024
2 parents 37f301c + 2d909d2 commit e84d7be
Show file tree
Hide file tree
Showing 2 changed files with 658 additions and 3 deletions.
104 changes: 101 additions & 3 deletions apps/api/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from . import api
from main import db
from models import event_year
from models.cfp import Proposal
from models.ical import CalendarEvent
from models.admin_message import AdminMessage
Expand All @@ -16,6 +17,9 @@
def _require_video_api_key(func):
@wraps(func)
def wrapper(*args, **kwargs):
if not app.config.get("VIDEO_API_KEY"):
abort(401)

auth_header = request.headers.get("authorization", None)
if not auth_header or not auth_header.startswith("Bearer "):
abort(401)
Expand Down Expand Up @@ -147,9 +151,7 @@ def post(self, proposal_type):

current_tickets = {
t.id: t
for t in EventTicket.query.filter_by(
state="entered-lottery", user_id=current_user.id
).all()
for t in EventTicket.query.filter_by(state="entered-lottery", user_id=current_user.id).all()
if t.proposal.type == proposal_type
}

Expand All @@ -169,6 +171,101 @@ def post(self, proposal_type):
return [t.id for t in res]


class ProposalC3VOCPublishingWebhook(Resource):
method_decorators = {"post": [_require_video_api_key]}

def post(self):
if not request.is_json:
abort(415)

payload = request.get_json()

try:
conference = payload["fahrplan"]["conference"]
proposal_id = payload["fahrplan"]["id"]

if not payload["is_master"]:
# c3voc *should* only send us information about the master
# encoding getting published. Aborting early ensures we don't
# accidentially delete video information from the database.
abort(403, message="The request referenced a non-master video edit, and has been denied.")

if conference != f"emf{event_year()}":
abort(
422,
message="The request did not reference the current event year, and has not been processed.",
)

proposal = Proposal.query.get_or_404(proposal_id)

if payload["voctoweb"]["enabled"]:
if payload["voctoweb"]["frontend_url"]:
c3voc_url = payload["voctoweb"]["frontend_url"]
if not c3voc_url.startswith("https://media.ccc.de/"):
abort(406, message="voctoweb frontend_url must start with https://media.ccc.de/")
app.logger.info(f"C3VOC webhook set c3voc_url for {proposal.id=} to {c3voc_url}")
proposal.c3voc_url = c3voc_url
proposal.video_recording_lost = False
else:
# This allows c3voc to notify us if videos got depublished
# as well. We do not explicitely set 'video_recording_lost'
# here because the video might only need fixing audio or
# such.
app.logger.warning(
f"C3VOC webhook cleared c3voc_url for {proposal.id=}, was {proposal.c3voc_url}"
)
proposal.c3voc_url = None

if payload["voctoweb"]["thumb_path"]:
path = payload["voctoweb"]["thumb_path"]
if path.startswith("/static.media.ccc.de"):
path = "https://static.media.ccc.de/media" + path[len("/static.media.ccc.de"):]
if not path.startswith("https://"):
abort(406, message="voctoweb thumb_path must start with https:// or /static.media.ccc.de")
app.logger.info(f"C3VOC webhook set thumbnail_url for {proposal.id=} to {path}")
proposal.thumbnail_url = path
else:
app.logger.warning(
f"C3VOC webhook cleared thumbnail_url for {proposal.id=}, was {proposal.thumbnail_url}"
)
proposal.thumbnail_url = None

if payload["youtube"]["enabled"]:
if payload["youtube"]["urls"]:
# Please do not overwrite existing youtube urls
youtube_url = payload["youtube"]["urls"][0]
if not youtube_url.startswith("https://www.youtube.com/watch"):
abort(406, message="youtube url must start with https://www.youtube.com/watch")
if not proposal.youtube_url:
# c3voc will send us a list, even though we only have one
# video.
app.logger.info(f"C3VOC webhook set youtube_url for {proposal.id=} to {youtube_url}")
proposal.youtube_url = youtube_url
proposal.video_recording_lost = False
elif proposal.youtube_url not in payload["youtube"]["urls"]:
# c3voc sent us some urls, but none of them are matching
# the url we have in our database.
app.logger.warning(
"C3VOC webhook sent youtube urls update without referencing the previously stored value. Ignoring."
)
app.logger.debug(
f"{proposal.id=} {payload['youtube']['urls']=} {proposal.youtube_url=}"
)
else:
# see comment at c3voc_url above
app.logger.warning(
f"C3VOC webhook cleared youtube_url for {proposal.id=}, was {proposal.youtube_url}"
)
proposal.youtube_url = None

db.session.add(proposal)
db.session.commit()
except KeyError as e:
abort(400, message=f"Missing required field: {e}")

return "OK", 204


def renderScheduleMessage(message):
return {"id": message.id, "body": message.message}

Expand All @@ -186,3 +283,4 @@ def get(self):
api.add_resource(FavouriteExternal, "/external/<int:event_id>/favourite")
api.add_resource(ScheduleMessage, "/schedule_messages")
api.add_resource(UpdateLotteryPreferences, "/schedule/tickets/<proposal_type>/preferences")
api.add_resource(ProposalC3VOCPublishingWebhook, "/proposal/c3voc-publishing-webhook")
Loading

0 comments on commit e84d7be

Please sign in to comment.