157 lines
3.7 KiB
Bash
Executable File
157 lines
3.7 KiB
Bash
Executable File
#!/bin/sh
|
||
|
||
# © DJ Chase, 2024. Licensed under the Academic Free License version 3.0.
|
||
|
||
readonly HTTP_FOUND='302 Found'
|
||
readonly HTTP_BAD_REQUEST='400 Bad Request'
|
||
readonly HTTP_NOT_FOUND='404 Not Found'
|
||
readonly HTTP_METHOD_NOT_ALLOWED='405 Method Not Allowed'
|
||
# SC2155 is about munging return codes, which is fine here
|
||
# shellcheck disable=SC2155
|
||
readonly HTML_PAGE_START="$(
|
||
dirname "${DOCUMENT_ROOT}${SCRIPT_NAME}"
|
||
)/.page-start.html"
|
||
# shellcheck disable=SC2155
|
||
readonly HTML_PAGE_END="$(
|
||
dirname "${DOCUMENT_ROOT}${SCRIPT_NAME}"
|
||
)/.page-end.html"
|
||
|
||
percentDecode() \
|
||
{
|
||
# usage: foo | percentDecode
|
||
|
||
# shellcheck disable=SC2059
|
||
printf "$(sed 's/+/ /g; s/%/\\x/g' | tr -d '\r')"
|
||
}
|
||
|
||
htmlEncode() \
|
||
{
|
||
# usage: foo | htmlEncode
|
||
|
||
sed "
|
||
s_&_&\;_g;
|
||
s_'_'\;_g;
|
||
s_\"_"\;_g;
|
||
s_<_<\;_g;
|
||
s_>_>\;_g
|
||
"
|
||
}
|
||
|
||
error() \
|
||
{
|
||
# usage: error <status_code> [<message>]
|
||
|
||
printf 'Status: %s\n' "$1"
|
||
|
||
if [ "$2" ]
|
||
then
|
||
printf 'Content-type: text/plain; charset=utf-8\n\n'
|
||
|
||
[ "$REQUEST_METHOD" = 'HEAD' ] && exit 0
|
||
|
||
printf '%s\n\n' "$1" "$2"
|
||
else
|
||
printf '\n'
|
||
fi
|
||
|
||
# exit 0 so that the webserver doesn't return "Internal Server Error"
|
||
exit 0
|
||
}
|
||
|
||
|
||
if [ "$REQUEST_METHOD" = 'GET' ] || [ "$REQUEST_METHOD" = 'HEAD' ]
|
||
then
|
||
if [ "$QUERY_STRING" ]
|
||
then
|
||
format="$(
|
||
printf '%s\n' "$QUERY_STRING" \
|
||
| sed 's/&/\n/g' \
|
||
| grep '^format=' \
|
||
| cut -d = -f 2- \
|
||
| percentDecode
|
||
)"
|
||
: "${format:=best}"
|
||
pageURL="$(
|
||
printf '%s\n' "$QUERY_STRING" \
|
||
| sed 's/&/\n/g' \
|
||
| grep '^url=' \
|
||
| cut -d = -f 2- \
|
||
| percentDecode
|
||
)"
|
||
|
||
[ "$pageURL" ] \
|
||
|| error "$HTTP_BAD_REQUEST" \
|
||
'You need to include the `url` parameter'
|
||
|
||
ytdlOutput="$(
|
||
youtube-dl --format "$format" --get-url -- "$pageURL" \
|
||
2>&1
|
||
)"
|
||
|
||
# shellcheck disable=SC2181
|
||
if [ "$?" -eq 0 ]
|
||
then
|
||
printf 'Status: %s\n' "$HTTP_FOUND"
|
||
|
||
# `head -n 1` in case someone sets a format of
|
||
# 'bestaudio+bestvideo' or similar, since we can only
|
||
# redirect to one URL at a time
|
||
printf 'Location: %s\n\n' "$(
|
||
printf '%s\n' "$ytdlOutput" \
|
||
| sed '/^$/d' \
|
||
| head -n 1
|
||
)"
|
||
else
|
||
error "$HTTP_NOT_FOUND" "$ytdlOutput"
|
||
fi
|
||
else
|
||
printf 'Content-Type: text/html; charset=utf-8\n\n'
|
||
|
||
[ "$REQUEST_METHOD" = 'HEAD' ] && exit 0
|
||
|
||
cat "$HTML_PAGE_START" "$HTML_PAGE_END"
|
||
fi
|
||
|
||
elif [ "$REQUEST_METHOD" = 'POST' ]
|
||
then
|
||
postBody="$(tr -d '\r' | sed 's/&/\n/g')"
|
||
url="$(
|
||
# field is already percent encoded
|
||
printf '%s' "$postBody" \
|
||
| grep '^url=' \
|
||
| cut -d = -f 2- \
|
||
| htmlEncode
|
||
)"
|
||
scriptURL="$(
|
||
printf 'https://%s%s' "$SERVER_NAME" "$SCRIPT_NAME" \
|
||
| htmlEncode
|
||
)"
|
||
|
||
printf 'Content-Type: text/html; charset=utf-8\n\n'
|
||
cat "$HTML_PAGE_START" - "$HTML_PAGE_END" <<EOF
|
||
<hr/>
|
||
|
||
<p>Use this code to embed the video:</p>
|
||
|
||
<pre><code><video controls>
|
||
<source media="(prefers-reduced-data: reduce)" src="$scriptURL?format=worst&url=$url">
|
||
<source src="$scriptURL?url=$url">
|
||
<track src="https://example.com/captions.vtt" kind="captions" srclang="en" label="English">
|
||
<p>It looks like your browser doesn’t support HTML video. You can still
|
||
<a href="$scriptURL?url=$url">download
|
||
the video</a> and watch it locally. You can also
|
||
<a href="https://example.com/captions.vtt">download the captions
|
||
file</a> if your video player can import it.
|
||
</p>
|
||
</video></code></pre>
|
||
|
||
<p>Remember to replace <code>https://example.com/captions.vtt</code> with the
|
||
link to your captions file (WebVTT). See
|
||
<a href="https://dj-chase.com/unlisted/vtt-embed-example-cc.vtt">the demo
|
||
caption file</a> if you’d like an example of what that looks like.</p>
|
||
EOF
|
||
else
|
||
printf 'Status: %s\n' "$HTTP_METHOD_NOT_ALLOWED"
|
||
printf 'Allow: GET, POST, HEAD\n\n'
|
||
fi
|