Compare commits

..

38 Commits
main ... main

Author SHA1 Message Date
64bb28b4b4 The show processing needs to be refactored #5 2025-01-17 21:58:55 +01:00
70fe1cac27 The show processing needs to be refactored #5 2025-01-17 21:57:22 +01:00
1a748c01f6 The show processing needs to be refactored #5 2025-01-16 22:00:08 +01:00
a6044e16a7 The show processing needs to be refactored #5 2025-01-14 20:22:36 +01:00
821b7ff1b6 Merge pull request 'Add link to the episode the comment is on' (#80) from I79_Add_link_to_the_comment_episode into main
Reviewed-on: HPR/hpr_hub#80
2025-01-14 16:57:13 +00:00
f959958de1 Add link to the episode the comment is on 2025-01-14 17:56:31 +01:00
eb4444ebd9 Merge pull request 'Allow head method' (#78) from I77_Allow_head_requests_for_ccdn into main
Reviewed-on: HPR/hpr_hub#78
2025-01-14 16:47:13 +00:00
7b15121b8f Allow head method 2025-01-14 17:46:28 +01:00
8f8900db97 Merge pull request 'Fix for the reserve show confirmation and missing ;' (#76) from I74_Thank_You_for_recording_hpr9999_for_release_on_1970-01-01 into main
Reviewed-on: HPR/hpr_hub#76
2025-01-14 16:36:15 +00:00
50da7ea056 Fix for the reserve show confirmation and missing ; 2025-01-14 17:35:20 +01:00
35d938019a Switched to json only posting 2024-12-27 13:19:31 +01:00
b4acb758a7 Simplified and flattened the stats to json only 2024-12-26 21:26:56 +01:00
568252ab7c Moved to tools/workflow 2024-12-24 17:56:56 +01:00
c60905e5de Support for WYSIWYG upload server side 2024-12-24 17:25:14 +01:00
a553beafd5 Support for WYSIWYG upload 2024-12-24 15:52:25 +01:00
71124ab014 Removing processing tools from hpr-hub repo to workflow 2024-12-24 13:46:17 +01:00
77cb19ddb6 Remove spaces etc from filenames on server 2024-12-24 13:17:25 +01:00
d87c9ed979 Untracked changes in hprtranscode 2024-12-24 13:13:53 +01:00
1d14028ba0 Add two untracked scripts 2024-12-24 13:12:28 +01:00
a8897cc793 The magick convert is deprecated 2024-12-24 13:02:58 +01:00
2ac5bd0e51 Various emergency fixes 2024-11-25 18:23:43 +01:00
4dcdb38d86 Changed the sort on status 2024-11-25 17:45:47 +01:00
06af0e06be Merge pull request 'Added the warning and link to feedback to the shownotes' (#59) from I52_Add_comment_link_to_the_end_of_the_shownotes_in_the_rss_feed into main
Reviewed-on: HPR/hpr_hub#59
2024-10-31 10:24:05 +00:00
297d2040db Added the warning and link to feedback to the shownotes 2024-10-31 11:21:19 +01:00
17e46fea75 irss-future is now in rss.php 2024-10-31 07:48:13 +01:00
043288e5e4 Merge pull request 'Added support to add/update metadata on multiple assets via a json file' (#56) from I226_Asset_table_management into main
Reviewed-on: HPR/hpr_hub#56
2024-10-27 12:16:27 +00:00
3fc4da18ed Added support to add/update metadata on multiple assets via a json file 2024-10-26 19:31:07 +02:00
1615626c42 Merge pull request 'Fix future feed by removing gomax and adding future switch' (#55) from I54_Future_feed_not_working_after_switching_to_ccdn into main
Reviewed-on: HPR/hpr_hub#55
2024-10-23 08:37:41 +00:00
236cd08e6f Removed gomax as it was not used and it didn't work
Added a future switch to switch before `now()` and after
Cleaned up some commented out lines
2024-10-23 10:18:52 +02:00
50945b9968 Merge pull request 'The addition of a ccdn redirector and updating the link to media to point to it' (#53) from 225_Switch_url_for_media_to_hpr_ccdn into main
Reviewed-on: HPR/hpr_hub#53
Reviewed-by: Roan Horning <rho_n@josh@anhonesthost.com>
2024-10-23 07:36:34 +00:00
b2708a2b3f The addition of a ccdn redirector and updating the link to media to point to it 2024-10-21 17:35:20 +02:00
faa14cd6da 2024-10-20_21-12-39_CEST 2024-10-20 21:12:39 +02:00
8bf6aad70b Fix stats page hpr shows with playtime 2024-10-10 11:02:03 +02:00
112f443a04 Fix stats page hpr shows 2024-10-10 10:48:23 +02:00
7fdf12df28 Added the Scheduling Guidelines to the upload page 2024-10-09 20:17:49 +02:00
f19938a0c2 2024-10-04_17-33-29Z_Friday 2024-10-04 19:33:29 +02:00
dd2c9e6382 2024-09-28_18-02-01Z_Saturday database changed 2024-09-28 20:02:01 +02:00
4b8f414d63 Merge pull request 'Added an episode counter for feed generation to determine whether or not to include show notes.' (#42) from kdmurrayhpr/hpr_hub:main into main
Reviewed-on: HPR/hpr_hub#42
2024-09-24 07:08:23 +00:00
25 changed files with 14147 additions and 2085 deletions

View File

@ -1,79 +0,0 @@
#!/bin/bash -
#
# Copied from a 'history' file on archive.org and turned into a script
#
set -o nounset # Treat unset variables as an error
SCRIPT=${0##*/}
#=== FUNCTION ================================================================
# NAME: cleanup_temp
# DESCRIPTION: Cleanup temporary files in case of a keyboard interrupt
# (SIGINT) or a termination signal (SIGTERM) and at script
# exit
# PARAMETERS: * - names of temporary files to delete
# RETURNS: Nothing
#===============================================================================
function cleanup_temp {
for tmp in "$@"; do
[ -e "$tmp" ] && rm --force "$tmp"
done
exit 0
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if [[ $# -eq 0 ]]; then
echo "Usage: $SCRIPT audio_file"
exit 1
fi
AUDIO="$1"
IMAGE="${AUDIO%.*}.png"
if [[ ! -e $AUDIO ]]; then
echo "$SCRIPT: audio file $AUDIO not found"
exit 1
fi
#
# Make a temporary file (called /tmp/XXXX.png) and set traps to delete them
#
TMP1=$(mktemp -p /tmp XXXXXXXX.png) || {
echo "$SCRIPT: creation of temporary file failed!"
exit 1
}
trap 'cleanup_temp $TMP1' SIGHUP SIGINT SIGPIPE SIGTERM EXIT
#
# Make a temporary PNG file from the audio. The original uses a 'timeout' call
# but I can't get it to work for me.
#
ffmpeg -v 0 -analyzeduration 900000000000 -probesize 200M -threads 2 -i "$AUDIO" \
-filter_complex aformat=channel_layouts=mono,showwavespic=colors=white:s=3200x800 \
-frames:v 1 -f apng - 2>/dev/null | \
convert - -background black -alpha remove -alpha off "$TMP1" 2>/dev/null | cat > /dev/null 2>&1
#
# Not clear what's being done to the image here, but it produces a useful end
# result, or seems to!
#
convert -background black "$TMP1" -gravity center -background black -transparent white - | \
convert - -gravity South -background white -splice 0x5 -background black -splice 0x5 - | \
convert - -trim - | \
convert - -gravity South -chop 0x5 - | \
convert - -gravity North -background white -splice 0x5 -background black -splice 0x5 - | \
convert - -trim - | \
convert - -gravity North -chop 0x5 - | \
convert - -resize '800x200!' "$IMAGE"
#
# The original renamed the temporary file to be the target image file, but
# that's probably becausae part of this is done in a Docker container. Doesn't
# seem appropriate here
#
# vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21

4
bin/hpr_ccdn_stats.bash Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
yesterday="$( \date -u +%Y-%m-%d -d yesterday)"
echo -e "${yesterday}\t$( grep -Ec "${yesterday}T.*Sending request to" /home/hpr/logs/naughty-ip.txt )" >> /home/hpr/hub/hpr_ccdn_stats.tsv

View File

@ -1,610 +0,0 @@
#!/usr/bin/env bash
# Copyright Ken Fallon - Released into the public domain. http://creativecommons.org/publicdomain/
#============================================================
PATH=$PATH:/home/ken/sourcecode/hpr/hpr_hub/bin/
#source /home/ken/tmp/pip3.9/bin/activate
TEMP_DIR="/var/tmp/"
CHANNELS="1"
FIXAUDIO="1"
ARTIST="EMPTY"
TITLE="EMPTY"
YEAR="EMPTY"
SLOT="EMPTY"
basedir="/var/IA"
upload_dir="${basedir}/uploads"
theme="${basedir}/theme.wav"
outro="${basedir}/2022-03-07-outro.wav"
ttsserver="http://localhost:5500"
processing_dir="/home/ken/tmp/hpr/processing"
git_image_dir="/home/ken/sourcecode/hpr/HPR_Public_Code/www/images/hosts"
acceptable_duration_difference="2" # Seconds
thedate=$(/usr/bin/date -u +%Y-%m-%d_%H-%M-%SZ_%A)
echo "Processing the next HPR Show in the queue"
if [ $( curl -s -o /dev/null -w "%{http_code}" -X 'GET' "${ttsserver}/api/voices" -H 'accept: */*' ) != "200" ]
then
echo "Please start the tts-server \"podman run -it -p 5500:5500 synesthesiam/opentts:en\""
exit
fi
function abs_diff {
echo $(($1 >= $2 ? $1 - $2 : $2 - $1))
}
function create_tts_summary {
HPR_summary="$( cat "hpr${ep_num}_summary.txt" )"
echo "INFO: Converting text \"${HPR_summary}\" to speech."
curl -X 'GET' -G --data-urlencode "voice=coqui-tts:en_ljspeech" --data-urlencode "text=${HPR_summary}" --data-urlencode "vocoder=high" --data-urlencode "denoiserStrength=0.03" --data-urlencode "cache=false" ${ttsserver}/api/tts -H 'accept: */*' --output ~hpr${ep_num}_summary.wav
}
###################
# Locate media directory
#
#
show_type=""
if [[ -f "${1}" && -n "${2}" ]]
then
echo "DEBUG: Show type is local" 1>&2
show_type="local"
mediafile="${1}"
media_dir="$( dirname "${mediafile}" )"
ep_num="${2}"
echo "The duration is \"$( \date -ud "1970-01-01 $( ffprobe -i "${mediafile}" 2>&1| awk -F ': |, ' '/Duration:/ { print $2 }' )" +%s )\"."
else
echo "DEBUG: Show type is remote" 1>&2
show_type="remote"
response=$( curl --silent --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/status.php" | \
grep 'SHOW_POSTED' | \
head -1 | \
sed 's/,/ /g' )
echo "DEBUG: Getting server response" 1>&2
if [ -z "${response}" ]
then
echo "INFO: There appear to be no more shows with the status \"SHOW_POSTED\"."
echo "Getting a list of all the reservations."
curl --silent --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/status.php"
exit 3
fi
timestamp_epoc="$( echo ${response} | awk '{print $1}' )"
ep_num="$( echo ${response} | awk '{print $2}' )"
ep_date="$( echo ${response} | awk '{print $3}' )"
key="$( echo ${response} | awk '{print $4}' )"
status="$( echo ${response} | awk '{print $5}' )"
email="$( echo ${response} | awk '{print $6}' )"
#source_dir="hpr:/home/hpr/upload/${timestamp_epoc}_${ep_num}_${ep_date}_${key}"
dest_dir="${timestamp_epoc}_${ep_num}_${ep_date}_${key}"
media_dir="${processing_dir}/${timestamp_epoc}_${ep_num}_${ep_date}_${key}"
fi
echo "DEBUG: Checking variables" 1>&2
if [ -z "${show_type}" ]
then
echo "sorry, variable \"show_type\" is not set."
exit
fi
if [ -z "${media_dir}" ]
then
echo "sorry, variable \"media_dir\" is not set."
exit
fi
if [ ! -d "${media_dir}" ]
then
echo "sorry, directory \"media_dir: ${media_dir}\" does not exist"
exit 1
fi
echo detox -v "${media_dir}/"
detox -vr "${media_dir}/"
if [[ "$( find "${media_dir}" \( -iname "hpr${ep_num}.wav" -o -iname "hpr${ep_num}.mp3" -o -iname "hpr${ep_num}.ogg" -o -iname "hpr${ep_num}.spx" -o -iname "hpr${ep_num}_summary.txt" -o -iname "hpr${ep_num}_summary.wav" -o -iname "hpr${ep_num}.wav" -o -iname "*_mez.wav" -o -iname "*_sox_norm.wav" -o -iname "*_mezzanine.wav" -o -iname "*_tmp.pcm" -o -iname "hpr${ep_num}_intro.wav" -o -iname "~hpr${ep_num}_summary.wav" -o -iname "~~hpr${ep_num}_summary.wav" -o -iname "*_tmp.log" -o -iname "silence.wav" -o -iname "hpr${ep_num}_norm.wav" \) | wc -l )" -ne 0 ]]
then
echo "Files for this episode already exist."
find "${media_dir}" \( -iname "hpr${ep_num}.wav" -o -iname "hpr${ep_num}.mp3" -o -iname "hpr${ep_num}.ogg" -o -iname "hpr${ep_num}.spx" -o -iname "hpr${ep_num}_summary.txt" -o -iname "hpr${ep_num}_summary.wav" -o -iname "hpr${ep_num}.wav" -o -iname "*_mez.wav" -o -iname "*_sox_norm.wav" -o -iname "*_mezzanine.wav" -o -iname "*_tmp.pcm" -o -iname "hpr${ep_num}_intro.wav" -o -iname "~hpr${ep_num}_summary.wav" -o -iname "~~hpr${ep_num}_summary.wav" -o -iname "*_tmp.log" -o -iname "silence.wav" -o -iname "hpr${ep_num}_norm.wav" \)
read -p "Shall I remove them ? (N|y) ? " -n 1 -r
echo # (optional) move to a new line
if [[ ! $REPLY =~ ^[yY]$ ]]
then
echo "skipping...."
exit
else
echo "Removing old files ...."
find "${media_dir}" \( -iname "hpr${ep_num}.wav" -o -iname "hpr${ep_num}.mp3" -o -iname "hpr${ep_num}.ogg" -o -iname "hpr${ep_num}.spx" -o -iname "hpr${ep_num}_summary.txt" -o -iname "hpr${ep_num}_summary.wav" -o -iname "hpr${ep_num}.wav" -o -iname "*_mez.wav" -o -iname "*_sox_norm.wav" -o -iname "*_mezzanine.wav" -o -iname "*_tmp.pcm" -o -iname "hpr${ep_num}_intro.wav" -o -iname "~hpr${ep_num}_summary.wav" -o -iname "~~hpr${ep_num}_summary.wav" -o -iname "*_tmp.log" -o -iname "silence.wav" -o -iname "hpr${ep_num}_norm.wav" \) -delete -print
fi
fi
#####################################################
# Process media
media=$( find "${media_dir}" -type f -exec file {} \; | grep -Ei 'audio|mpeg|video|MP4' | awk -F ': ' '{print $1}' )
if [ -z "${media}" ]
then
echo "ERROR: Can't find any media in \"${media_dir}/\""
find "${media_dir}/" -type f
exit 1
fi
mediafile=""
echo "Found more than one media file. Please select which one to use ?"
if [ "$( echo "${media}" | wc -l )" -ne 1 ]
then
select this_media in $( echo "${media}" )
do
echo "INFO: You selected \"${this_media}\"."
ls -al "${this_media}"
mediafile="${this_media}"
break
done
else
echo "INFO: Selecting media as \"${media}\"."
mediafile="${media}"
fi
# extract file name and extension
fname="$( basename "${mediafile%.*}" )"
ext="${mediafile/*./}"
cd "${media_dir}/"
pwd
echo "INFO: Processing hpr${ep_num} from ${email}"
echo "INFO: Working directory is \"${media_dir}/\""
echo ""
if [ -z "${mediafile}" ]
then
echo "sorry, variable \"mediafile\" is not set."
exit
fi
if [ -z "${fname}" ]
then
echo "sorry, variable \"fname\" is not set."
exit
fi
if [ -z "${ext}" ]
then
echo "sorry, variable \"ext\" is not set."
exit
fi
if [ ! -f "${mediafile}" ]
then
echo "sorry, media file \"${mediafile}\" does not exist"
exit
fi
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "File information for \"${mediafile}\"" | tee -a ${fname}_tmp.log
ffprobe ${mediafile} 2>&1 | grep Audio:
mediainfo ${mediafile}
audio2image.bash ${mediafile}
xdg-open ${mediafile%.*}.png >/dev/null 2>&1 &
unset REPLY
until [[ $REPLY =~ ^[yYnN]$ ]]
do
read -p "Source Waveform look ok ? (N|y) ? " -n 1 -r
echo ""
done
if [[ ! $REPLY =~ ^[yY]$ ]]
then
echo "skipping.... $REPLY"
exit
fi
re='^[0-9]+$'
if ! [[ $ep_num =~ $re ]]
then
echo "error: episode \"${ep_num}\" is not a number"
exit 1
fi
if [ ! -f "${outro}" ]
then
echo "sorry, file \"${outro}\" does not exist"
exit 1
fi
if [ ! -f "${theme}" ]
then
echo "sorry, file \"${theme}\" does not exist"
exit 1
fi
if [ ! -r "${mediafile}" ]
then
echo "sorry, media file \"${mediafile}\" is not readable"
exit
fi
if [ $(ffprobe "${mediafile}" 2>&1 | grep "Audio:" | wc -l ) -eq 0 ]
then
echo "sorry, media file \"${mediafile}\" has no audio track"
exit
fi
xdg-open "https://hackerpublicradio.org/eps/hpr${ep_num}/index.html" >/dev/null 2>&1 &
mpv -vo=null "${mediafile}"
unset REPLY
until [[ $REPLY =~ ^[yYnN]$ ]]
do
read -p "Is the audio ok (n|Y) ? " -n 1 -r
echo ""
done
if [[ ! $REPLY =~ ^[yY]$ ]]
then
echo "skipping.... $REPLY"
exit
fi
echo "--------------------------------------------------------------------------------"
echo "Geting metadata for hpr${ep_num}"
while read -r line
do
field=$(echo $line | awk -F ':' '{print $1}')
case $field in
"HPR_summary")
HPR_summary=$(echo $line | grep "HPR_summary: " | cut -c 14- )
continue
;;
"HPR_album")
HPR_album=$(echo $line | grep "HPR_album: " | cut -c 12- )
continue
;;
"HPR_artist")
HPR_artist=$(echo $line | grep "HPR_artist: " | cut -c 13- )
continue
;;
"HPR_comment")
HPR_comment=$(echo $line | grep "HPR_comment: " | cut -c 14- )
continue
;;
"HPR_genre")
HPR_genre=$(echo $line | grep "HPR_genre: " | cut -c 12- )
continue
;;
"HPR_title")
HPR_title=$(echo $line | grep "HPR_title: " | cut -c 12- )
continue
;;
"HPR_track")
HPR_track=$(echo $line | grep "HPR_track: " | cut -c 12- )
continue
;;
"HPR_year")
HPR_year=$(echo $line | grep "HPR_year: " | cut -c 11- )
continue
;;
"HPR_duration")
HPR_duration=$(echo $line | grep "HPR_duration: " | cut -c 15- )
continue
;;
"HPR_explicit")
HPR_explicit=$(echo $line | grep "HPR_explicit: " | cut -c 15- )
continue
;;
"HPR_license")
HPR_license=$(echo $line | grep "HPR_license: " | cut -c 14- )
continue
;;
esac
done < <( curl --silent --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/say.php?id=${ep_num}" )
if [[ -z "$HPR_album" || -z "$HPR_artist" || -z "$HPR_comment" || -z "$HPR_genre" || -z "$HPR_title" || -z "$HPR_track" || -z "$HPR_year" || -z "$HPR_summary" || -z "$HPR_duration" || -z "$HPR_explicit" || -z "$HPR_license" ]]
then
echo "Could not find information on ${ep_num}. Has the show been posted ?"
exit;
fi
echo "--------------------------------------------------------------------------------"
echo "album : $HPR_album"
echo "artist : $HPR_artist"
echo "comment : $HPR_comment"
echo "genre : $HPR_genre"
echo "title : $HPR_title"
echo "track : $HPR_track"
echo "year : $HPR_year"
echo "summary : $HPR_summary"
echo "duration : $HPR_duration"
echo "explicit : $HPR_explicit"
echo "license : $HPR_license"
echo "media_dir : ${media_dir}"
echo "mediafile : ${mediafile}"
echo "fname : ${fname}"
echo "ext : ${ext}"
if [[ $HPR_duration == "0" ]]
then
echo "The duration is set to 0. Please update the show with the correct time."
exit;
fi
#============================================================
# Preproc`s the source file
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Prepare mezzanine file" | tee -a ${fname}_tmp.log
ffmpeg -y -i ${mediafile} -ar 44100 -ac $CHANNELS ${fname}_mezzanine.wav > ${fname}_tmp.log 2>&1
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Add HPR Branding" | tee -a ${fname}_tmp.log
echo "Creating the summary" | tee -a ${fname}_tmp.log
#echo "$HPR_summary" - | text2wave -F 44100 - -o hpr${ep_num}_summary.wav #festival --tts
#echo "$HPR_summary" - | espeak -w ~hpr${ep_num}_summary.wav
echo "$HPR_summary" > "hpr${ep_num}_summary.txt"
create_tts_summary_ok="not-ok"
while [ "${create_tts_summary_ok}" != "OK" ]
do
create_tts_summary
xdg-open "hpr${ep_num}_summary.txt" 2>&1 &
mpv --speed=1.8 ~hpr${ep_num}_summary.wav
read -p "Is the text to speech correct (y|N) ? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
create_tts_summary_ok="OK"
else
echo "WARN: Please correct the text and try again."
inotifywait --event modify "hpr${ep_num}_summary.txt"
fi
done
echo "INFO: TTS complete."
ffmpeg -y -i ~hpr${ep_num}_summary.wav -ar 44100 ~~hpr${ep_num}_summary.wav >> ${fname}_tmp.log 2>&1
sox -V2 -n -r 44100 -c 1 silence.wav trim 0.0 6.0 >> ${fname}_tmp.log 2>&1
sox -V2 silence.wav ~~hpr${ep_num}_summary.wav hpr${ep_num}_summary.wav >> ${fname}_tmp.log 2>&1
echo "Adding the theme" | tee -a ${fname}_tmp.log
sox -V2 -m "hpr${ep_num}_summary.wav" "${theme}" "hpr${ep_num}_intro.wav" >> ${fname}_tmp.log 2>&1
echo "Creating the sandwitch: \"hpr${ep_num}_intro.wav\" \"${fname}_mezzanine.wav\" \"${outro}\" \"hpr${ep_num}.wav\" " | tee -a ${fname}_tmp.log
sox -V2 "hpr${ep_num}_intro.wav" "${fname}_mezzanine.wav" "${outro}" "hpr${ep_num}.wav" >> ${fname}_tmp.log 2>&1
echo "Normalizing the wav files" | tee -a ${fname}_tmp.log
#sox --temp "${TEMP_DIR}" --norm hpr${ep_num}.wav hpr${ep_num}_norm.wav
ffmpeg -y -i hpr${ep_num}.wav -af loudnorm=I=-16:LRA=11:TP=-1.5 hpr${ep_num}_norm.wav >> ${fname}_tmp.log 2>&1
mv -v hpr${ep_num}_norm.wav ${upload_dir}/hpr${ep_num}.wav >> ${fname}_tmp.log 2>&1
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "File information" | tee -a ${fname}_tmp.log
ffprobe ${upload_dir}/hpr${ep_num}.wav 2>&1 | grep Audio:
mediainfo ${upload_dir}/hpr${ep_num}.wav
audio2image.bash ${upload_dir}/hpr${ep_num}.wav
xdg-open ${upload_dir}/hpr${ep_num}.png >/dev/null 2>&1 &
read -p "Processed Waveform look ok ? (N|y) ? " -n 1 -r
echo # (optional) move to a new line
if [[ ! $REPLY =~ ^[yY]$ ]]
then
echo "skipping...."
exit
fi
rm -v ${upload_dir}/hpr${ep_num}.png
echo "--------------------------------------------------------------------------------"
echo "Geting transcript of hpr${ep_num}"
whisper --model tiny --language en --output_dir "${media_dir}" "${upload_dir}/hpr${ep_num}.wav" | tee -a ${fname}_tmp.log
ls -al "${media_dir}/hpr${ep_num}".*
xdg-open "${media_dir}/hpr${ep_num}".txt 2>&1 &
echo mpv --no-audio-display --audio-channels=stereo --speed="3.5" "${media_dir}/hpr${ep_num}".txt
unset REPLY
until [[ $REPLY =~ ^[yYnN]$ ]]
do
read -p "Processed transcript look ok ? (N|y) ? " -n 1 -r
echo ""
done
if [[ ! $REPLY =~ ^[yY]$ ]]
then
echo "skipping.... $REPLY"
exit
fi
mkdir "${upload_dir}/hpr${ep_num}" >/dev/null 2>&1
cp -v "${media_dir}/hpr${ep_num}".vtt "${upload_dir}/hpr${ep_num}/hpr${ep_num}.vtt" | tee -a ${fname}_tmp.log
cp -v "${media_dir}/hpr${ep_num}".srt "${upload_dir}/hpr${ep_num}/hpr${ep_num}.srt" | tee -a ${fname}_tmp.log
cp -v "${media_dir}/hpr${ep_num}".txt "${upload_dir}/hpr${ep_num}/hpr${ep_num}.txt" | tee -a ${fname}_tmp.log
cp -v "${media_dir}/hpr${ep_num}".tsv "${upload_dir}/hpr${ep_num}/hpr${ep_num}.tsv" | tee -a ${fname}_tmp.log
cp -v "${media_dir}/hpr${ep_num}".json "${upload_dir}/hpr${ep_num}/hpr${ep_num}.json" | tee -a ${fname}_tmp.log
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Convert to opus" | tee -a ${fname}_tmp.log
ffmpeg -y -i ${upload_dir}/hpr${ep_num}.wav ${upload_dir}/hpr${ep_num}.opus 2>> ${fname}_tmp.log 1>&2
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Convert to flac" | tee -a ${fname}_tmp.log
ffmpeg -y -i ${upload_dir}/hpr${ep_num}.wav ${upload_dir}/hpr${ep_num}.flac 2>> ${fname}_tmp.log 1>&2
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Convert to mp3" | tee -a ${fname}_tmp.log
ffmpeg -y -i ${upload_dir}/hpr${ep_num}.wav ${upload_dir}/hpr${ep_num}.mp3 2>> ${fname}_tmp.log 1>&2
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Convert to ogg" | tee -a ${fname}_tmp.log
#ffmpeg -y -i ${upload_dir}/hpr${ep_num}.wav ${upload_dir}/hpr${ep_num}.ogg 2>> ${fname}_tmp.log 1>&2
ffmpeg -y -i ${upload_dir}/hpr${ep_num}.wav -acodec libopus -f ogg ${upload_dir}/hpr${ep_num}.ogg 2>> ${fname}_tmp.log 1>&2
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Convert to spx" | tee -a ${fname}_tmp.log
ffmpeg -y -i ${upload_dir}/hpr${ep_num}.wav ${upload_dir}/hpr${ep_num}.spx 2>> ${fname}_tmp.log 1>&2
### End conversion
intro_duration="$( mediainfo --Output=XML --Full "hpr${ep_num}_intro.wav" | xmlstarlet sel -T -t -m '/_:MediaInfo/_:media/_:track[@type="Audio"]' -v '_:Duration' -n | awk -F '.' '{print $1}' )"
outro_duration="$( mediainfo --Output=XML --Full "${outro}" | xmlstarlet sel -T -t -m '/_:MediaInfo/_:media/_:track[@type="Audio"]' -v '_:Duration' -n | awk -F '.' '{print $1}' )"
source_duration="$( mediainfo --Output=XML --Full "${mediafile}" | xmlstarlet sel -T -t -m '/_:MediaInfo/_:media/_:track[@type="Audio"]' -v '_:Duration' -n | awk -F '.' '{print $1}' )"
expected_duration=$(( ${intro_duration} + ${HPR_duration} + ${outro_duration} ))
echo "Intro(${intro_duration}) + Show(${HPR_duration}) + Outro(${outro_duration}) = ${expected_duration}"
media_error="0"
for check_file in \
${upload_dir}/hpr${ep_num}.wav \
${upload_dir}/hpr${ep_num}.opus \
${upload_dir}/hpr${ep_num}.flac \
${upload_dir}/hpr${ep_num}.mp3 \
${upload_dir}/hpr${ep_num}.spx \
${upload_dir}/hpr${ep_num}.ogg
do
# ${upload_dir}/hpr${ep_num}.spx
echo "INFO: Processing the file \"${check_file}\""
if [[ ! -s "${check_file}" ]]
then
echo "ERROR: Something went wrong encoding of the file \"${check_file}\""
exit
else
mediainfo --Output=XML --Full "${check_file}" | xmlstarlet sel -T -t -m '/_:MediaInfo/_:media/_:track[@type="Audio"]' -v '_:Duration' -n | awk -F '.' '{print $1}'
this_duration=$( mediainfo --Output=XML --Full "${check_file}" | xmlstarlet sel -T -t -m '/_:MediaInfo/_:media/_:track[@type="Audio"]' -v '_:Duration' -n | awk -F '.' '{print $1}' )
if [[ $(abs_diff "${this_duration}" "${expected_duration}" ) -le "${acceptable_duration_difference}" ]]
then
echo "INFO: The file \"${check_file}\" duration of ${this_duration} () is close enough to ${expected_duration}"
else
echo "ERROR: The file \"${check_file}\" actual duration of ${this_duration} is not close enough to posted duration of ${expected_duration}."
echo " Fix or update the posted duration to ${source_duration}."
media_error="1"
fi
#${expected_duration}
fi
done
echo "Source: ${source_duration}"
if [[ "${media_error}" -eq "1" ]]
then
echo "ERROR: Media is not encoded correctly"
exit
else
echo "INFO: Media duration is correct"
fi
if [[ ! -s ${upload_dir}/hpr${ep_num}.wav ]] || [[ ! -s ${upload_dir}/hpr${ep_num}.opus ]] || [[ ! -s ${upload_dir}/hpr${ep_num}.flac ]] || [[ ! -s ${upload_dir}/hpr${ep_num}.mp3 ]] || [[ ! -s ${upload_dir}/hpr${ep_num}.ogg ]] || [[ ! -s ${upload_dir}/hpr${ep_num}.spx ]]
then
echo "ERROR: Something went wrong encoding the files"
exit 1
fi
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Fixing Tags" | tee -a ${fname}_tmp.log
fix_tags -album="$HPR_album" -artist="$HPR_artist" -comment="${HPR_comment} The license is ${HPR_license}" -genre="$HPR_genre" -title="$HPR_title" -track="$HPR_track" -year="$HPR_year" ${upload_dir}/hpr${ep_num}* 2>> ${fname}_tmp.log 1>&2
fix_tags ${upload_dir}/hpr${ep_num}*
#echo "Changing the file dates to the time of upload"
touch -r ${mediafile} hpr${ep_num}*
touch -r ${mediafile} ${upload_dir}/hpr${ep_num}*
ls -al hpr${ep_num}* ${upload_dir}/hpr${ep_num}* | tee -a ${fname}_tmp.log
# # echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
# # echo "Getting info for the asset table" | tee -a ${fname}_tmp.log
# #
# # echo "INSERT INTO assets (episode_id,filename,extension,size,sha1sum,mime_type,file_type) VALUES"
# #
# # for asset_file in \
# # ${upload_dir}/hpr${ep_num}.wav \
# # ${upload_dir}/hpr${ep_num}.opus \
# # ${upload_dir}/hpr${ep_num}.flac \
# # ${upload_dir}/hpr${ep_num}.mp3 \
# # ${upload_dir}/hpr${ep_num}.spx \
# # ${upload_dir}/hpr${ep_num}.ogg
# # do
# # size="$( ls -al "${asset_file}" | awk '{print $5}' )"
# # sha1sum="$( sha1sum "${asset_file}" | awk '{print $1}' )"
# # mime_type=$( file --dereference --brief --mime "${asset_file}" )
# # file_type=$( file --dereference --brief "${asset_file}" )
# # echo "(${ep_num},'${filename}','${extension}','${size}','${sha1sum}','${mime_type}','${file_type}'),"
# # done
echo "--------------------------------------------------------------------------------" | tee -a ${fname}_tmp.log
echo "Transferring files to Servers" | tee -a ${fname}_tmp.log
#rsync -ave ssh --partial --progress --ignore-existing ${upload_dir}/hpr${ep_num}.mp3 ${upload_dir}/hpr${ep_num}.ogg ${upload_dir}/hpr${ep_num}.spx hpr:www/eps/
#firefox "https://hackerpublicradio.org/local/hpr${ep_num}.mp3" >/dev/null 2>&1 &
#firefox "https://hackerpublicradio.org/local/hpr${ep_num}.ogg" >/dev/null 2>&1 &
firefox "file://${upload_dir}/hpr${ep_num}.mp3" >/dev/null 2>&1 &
firefox "file://${upload_dir}/hpr${ep_num}.ogg" >/dev/null 2>&1 &
#firefox "https://hackerpublicradio.org/eps.php?id=${ep_num}" >/dev/null 2>&1 &
#mpv "http://hackerpublicradio.org/local/hpr${ep_num}.spx" "http://hackerpublicradio.org/local/hpr${ep_num}.ogg" "http://hackerpublicradio.org/local/hpr${ep_num}.mp3" "file://${upload_dir}/hpr${ep_num}.spx" "file://${upload_dir}/hpr${ep_num}.opus" "file://${upload_dir}/hpr${ep_num}.ogg" "file://${upload_dir}/hpr${ep_num}.mp3" "file://${upload_dir}/hpr${ep_num}.flac"
mpv "file://${upload_dir}/hpr${ep_num}.spx" "file://${upload_dir}/hpr${ep_num}.opus" "file://${upload_dir}/hpr${ep_num}.ogg" "file://${upload_dir}/hpr${ep_num}.mp3" "file://${upload_dir}/hpr${ep_num}.flac"
read -p "Remove files for \"${fname}\" (y|N) ? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
mediafilename=$(basename "${mediafile}")
mediaextension="${mediafilename##*.}" # "
# ssh hpr -t "mkdir /home/hpr/www/eps/hpr${ep_num}" >/dev/null 2>&1
# rsync -ave ssh --partial --progress --ignore-existing "${mediafile}" hpr:www/eps/hpr${ep_num}/hpr${ep_num}_source.${mediaextension} | tee -a ${fname}_tmp.log
#
# rsync -ave ssh --partial --progress --ignore-existing "${media_dir}/hpr${ep_num}.wav".vtt hpr:www/eps/hpr${ep_num}/hpr${ep_num}.vtt | tee -a ${fname}_tmp.log
# rsync -ave ssh --partial --progress --ignore-existing "${media_dir}/hpr${ep_num}.wav".srt hpr:www/eps/hpr${ep_num}/hpr${ep_num}.srt | tee -a ${fname}_tmp.log
# rsync -ave ssh --partial --progress --ignore-existing "${media_dir}/hpr${ep_num}.wav".txt hpr:www/eps/hpr${ep_num}/hpr${ep_num}.txt | tee -a ${fname}_tmp.log
#
# ssh hpr -t "ls -al /home/hpr/www/eps/hpr${ep_num}*"
# cp -v "${mediafile}" "${upload_dir}/hpr${ep_num}_source.${mediaextension}"
#echo "Remove temp files"
rm -v ~hpr${ep_num}_summary.wav ~~hpr${ep_num}_summary.wav silence.wav
rm -v ${fname}_mezzanine.wav ${fname}_tmp*.pcm ${fname}_tmp.log ${fname}_mez.wav
#mv -v ${fname}* hpr${ep_num}* *_${ep_num}_* /var/IA/done/
# wget --timeout=0 -q "http://hackerpublicradio.org/hpr_ogg_rss.php?gomax=1" -O - | xmlstarlet val --err -
# wget --timeout=0 -q "http://hackerpublicradio.org/hpr_mp3_rss.php?gomax=1" -O - | xmlstarlet val --err -
# wget --timeout=0 -q "http://hackerpublicradio.org/hpr_spx_rss.php?gomax=1" -O - | xmlstarlet val --err -
# wget --timeout=0 -q "http://hackerpublicradio.org/rss-future.php" -O - | xmlstarlet val --err -
echo "INFO: rsync -ave ssh --partial --progress ${upload_dir}/hpr${ep_num}* borg:/data/IA/uploads/"
rsync -ave ssh --partial --progress ${upload_dir}/hpr${ep_num}* borg:/data/IA/uploads/
echo "$( ssh borg -t "ls -al /data/IA/uploads/hpr${ep_num}*" ; ls -al ${upload_dir}/hpr${ep_num}* )" | grep "hpr${ep_num}" | awk '{print $5, $NF}' | sort
if [ ${show_type} == "remote" ]
then
echo "INFO: Setting the status"
# SHOW_SUBMITTED → METADATA_PROCESSED → SHOW_POSTED → MEDIA_TRANSCODED → UPLOADED_TO_IA → UPLOADED_TO_RSYNC_NET
curl --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/status.php?ep_num=${ep_num}&status=MEDIA_TRANSCODED"
curl --silent --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/status.php"
fi
else
echo "skipping...."
echo "cp -v \"${mediafile}\" \"${upload_dir}/hpr${ep_num}_source.${mediaextension}\""
echo "rm -v ${fname}_mezzanine.wav ${fname}_tmp*.pcm ${fname}_tmp.log ${fname}_mez.wav"
#echo "mv -v ${fname}* hpr${ep_num}* *_${ep_num}_* /var/IA/done/"
echo "wget --timeout=0 -q \"http://hackerpublicradio.org/hpr_ogg_rss.php?gomax=1\" -O - | xmlstarlet val --err -"
echo "wget --timeout=0 -q \"http://hackerpublicradio.org/hpr_mp3_rss.php?gomax=1\" -O - | xmlstarlet val --err -"
echo "wget --timeout=0 -q \"http://hackerpublicradio.org/hpr_spx_rss.php?gomax=1\" -O - | xmlstarlet val --err -"
echo "rsync -ave ssh --partial --progress ${upload_dir}/ borg:/data/IA/uploads/"
fi

View File

@ -1,260 +0,0 @@
#!/usr/bin/env bash
# Copyright Ken Fallon - Released into the public domain. http://creativecommons.org/publicdomain/
#============================================================
source /home/ken/tmp/pip3.9/bin/activate
PATH=$PATH:/home/ken/sourcecode/hpr/hpr_hub/bin/
processing_dir="/home/ken/tmp/hpr/processing"
git_image_dir="/home/ken/sourcecode/hpr/HPR_Public_Code/www/images/hosts"
echo "Processing the next HPR Show in the queue"
###################
# Get the show
#
#
response=$( curl --silent --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/status.php" | \
grep 'METADATA_PROCESSED' | \
head -1 | \
sed 's/,/ /g' )
if [ -z "${response}" ]
then
echo "INFO: There appear to be no more shows with the status \"METADATA_PROCESSED\"."
echo "Getting a list of all the reservations."
curl --silent --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/status.php" | sort -n
exit 3
fi
timestamp_epoc="$( echo ${response} | awk '{print $1}' )"
ep_num="$( echo ${response} | awk '{print $2}' )"
ep_date="$( echo ${response} | awk '{print $3}' )"
key="$( echo ${response} | awk '{print $4}' )"
status="$( echo ${response} | awk '{print $5}' )"
email="$( echo ${response} | awk '{print $6}' )"
email_unpadded="$( echo $email | sed 's/.nospam@nospam./@/g' )"
upload_dir="/home/hpr/upload/${timestamp_epoc}_${ep_num}_${ep_date}_${key}"
source_dir="hpr:${upload_dir}"
dest_dir="${timestamp_epoc}_${ep_num}_${ep_date}_${key}"
ssh hpr -t "detox -v ${upload_dir}/"
echo "INFO: Downloading hpr${ep_num} from ${email_unpadded}"
echo ""
echo rsync -ave ssh --partial --progress ${source_dir}/ ${processing_dir}/${dest_dir}/
rsync -ave ssh --partial --progress ${source_dir}/ ${processing_dir}/${dest_dir}/
echo ""
echo "INFO: Working directory is \"${processing_dir}/${dest_dir}/\""
echo ""
shownotes_json="${processing_dir}/${dest_dir}/shownotes.json"
if [ ! -s "${shownotes_json}" ]
then
echo "ERROR: \"${shownotes_json}\" is missing"
exit 2
fi
if [ "$( file "${shownotes_json}" | grep -ic "text" )" -eq 0 ]
then
echo "ERROR: \"${shownotes_json}\" is not a text file"
exit 3
fi
jq '.' "${shownotes_json}" | sponge "${shownotes_json}"
###################
# Get the media
#
remote_media="$( jq --raw-output '.metadata.POST.url' "${processing_dir}/${dest_dir}/shownotes.json" )"
if [ -n "${remote_media}" ]
then
echo "INFO: Fetching remote media from \"${remote_media}\""
wget --timestamping --directory-prefix="${processing_dir}/${dest_dir}/" "${remote_media}"
if [ $? -ne 0 ]
then
echo "ERROR: Could not get the remote media"
exit 5
fi
fi
shownotes_html="${processing_dir}/${dest_dir}/shownotes.html"
if [ ! -s "${shownotes_html}" ]
then
echo "ERROR: \"${shownotes_html}\" is missing"
exit 4
fi
shownotes_txt="${processing_dir}/${dest_dir}/shownotes.txt"
if [ ! -s "${shownotes_txt}" ]
then
echo "ERROR: \"${shownotes_txt}\" is missing"
exit 7
fi
xdg-open "${shownotes_txt}" >/dev/null 2>&1 &
xdg-open "${shownotes_json}" >/dev/null 2>&1 &
xdg-open "${shownotes_html}" >/dev/null 2>&1 &
read -p "Does the metadata 'look ok ? (N|y) ? " -n 1 -r
echo # (optional) move to a new line
if [[ ! $REPLY =~ ^[yY]$ ]]
then
echo "skipping...."
exit 22
fi
media=$( find "${processing_dir}/${dest_dir}/" -type f -exec file {} \; | grep -Ei 'audio|mpeg|video|MP4' | awk -F ': ' '{print $1}' )
if [ -z "${media}" ]
then
echo "ERROR: Can't find any media in \"${processing_dir}/${dest_dir}/\""
find "${processing_dir}/${dest_dir}/" -type f
exit 1
fi
the_show_media=""
if [ "$( echo "${media}" | wc -l )" -ne 1 ]
then
echo "Multiple files found. Which one do you want to use ?"
select this_media in $( echo "${media}" )
do
echo "INFO: You selected \"${this_media}\"."
ls -al "${this_media}"
the_show_media="${this_media}"
break
done
else
echo "INFO: Selecting media as \"${media}\"."
the_show_media="${media}"
fi
duration=$( \date -ud "1970-01-01 $( ffprobe -i "${the_show_media}" 2>&1| awk -F ': |, ' '/Duration:/ { print $2 }' )" +%s )
###################
# Gather episode information
#
if [ "$( curl --silent --write-out '%{http_code}' http://hackerpublicradio.org/say.php?id=${ep_num} --output /dev/null )" == 200 ]
then
echo "ERROR: The Episode hpr${ep_num} has already been posted"
exit 6
fi
if [ "$( jq --raw-output '.metadata.Episode_Number' ${shownotes_json} )" != "${ep_num}" ]
then
echo "ERROR: The Episode_Number: \"${ep_num}\" was not found in \"${shownotes_json}\""
exit 10
fi
if [ "$( jq --raw-output '.metadata.Episode_Date' ${shownotes_json} )" != "${ep_date}" ]
then
echo "ERROR: The Episode_Date: \"${ep_date}\" was not found in \"${shownotes_json}\""
exit 8
fi
if [ "$( jq --raw-output '.host.Host_Email' ${shownotes_json} )" != "${email_unpadded}" ]
then
echo "ERROR: The Host_Email: \"${email_unpadded}\" was not found in \"${shownotes_json}\""
exit 9
fi
###################
# Assemble the components
#
# https://newbedev.com/how-to-urlencode-data-for-curl-command/
hostid="$( jq --raw-output '.host.Host_ID' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
host_name="$( jq --raw-output '.host.Host_Name' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
title=$( jq --raw-output '.episode.Title' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )
summary="$( jq --raw-output '.episode.Summary' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
series="$( jq --raw-output '.episode.Series' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
series_name="$( jq --raw-output '.episode.Series_Name' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
explicit="$( jq --raw-output '.episode.Explicit' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
episode_license="$( jq --raw-output '.episode.Show_License' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
tags="$( jq --raw-output '.episode.Tags' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
host_license=$( jq --raw-output '.host.Host_License' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )
host_profile=$( jq --raw-output '.host.Host_Profile' ${shownotes_json} | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )
# notes="$( grep -P ":\t" ${shownotes_txt} | awk -F "\t" '{print $2}' )"
notes="$( cat "${shownotes_html}" | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
if [ $# -gt 0 ]
then
declare -A hash
for argument
do
if [[ $argument =~ ^[^=]+=.*$ ]]
then
this_key="${argument%=*}" # "${} Kate format hack
this_value="${argument#*=}" # "${} Kate format hack
this_value="$( echo "${this_value}" | jq --slurp --raw-input @uri | sed -e 's/%0A"$//g' -e 's/^"//g' )"
eval "${this_key}=${this_value}"
echo "INFO: Replacing \"${this_key}\" with \"${this_value}\"."
fi
done
fi
if [ "${hostid}" == '0' ]
then
echo "ERROR: The hostid is 0. Create the host and use \"hostid=???\" to override"
exit 11
fi
# # # # has to be done here as we need to know the hostid
# # # host_photo="$( jq --raw-output '.metadata.FILES.host_photo.name' ${shownotes_json} )"
# # # if [ -n "${host_photo}" ]
# # # then
# # # host_photo="${processing_dir}/${dest_dir}/photo"
# # # host_avatar="${git_image_dir}/${hostid}.png"
# # # echo "INFO: Found host photo \"${host_photo}\""
# # # gm convert "${host_photo}" -resize x80 "${host_avatar}"
# # # xdg-open "${host_avatar}"
# # # read -p "Does the avatar 'look ok ? (N|y) ? " -n 1 -r
# # # echo # (optional) move to a new line
# # # if [[ ! $REPLY =~ ^[yY]$ ]]
# # # then
# # # echo "ERROR: Problem with avatar...."
# # # exit 12
# # # else
# # # echo "INFO: Copying avatar to the server."
# # # scp "${host_avatar}" hpr:www/images/hosts/
# # # fi
# # # fi
###################
# Post show to HPR
#
post_show="${processing_dir}/${dest_dir}/post_show.txt"
post_show_response="${processing_dir}/${dest_dir}/post_show_response.txt"
echo "key=${key}&ep_num=${ep_num}&ep_date=${ep_date}&email=${email}&title=${title}&duration=${duration}&summary=${summary}&series=${series}&series_name=${series_name}&explicit=${explicit}&episode_license=${episode_license}&tags=${tags}&hostid=${hostid}&host_name=${host_name}&host_license=${host_license}&host_profile=${host_profile}&notes=${notes}" > ${post_show}
echo "Sending:"
cat "${post_show}"
echo "key=${key}
ep_num=${ep_num}
ep_date=${ep_date}
email=${email}
title=${title}
duration=${duration}
summary=${summary}
series=${series}
series_name=${series_name}
explicit=${explicit}
episode_license=${episode_license}
tags=${tags}
hostid=${hostid}
host_name=${host_name}
host_license=${host_license}
host_profile=${host_profile}
notes=${notes}"
wget --post-file="${post_show}" "https://hub.hackerpublicradio.org/cms/add_show.php" -O - #"${post_show_response}"
# /home/ken/sourcecode/personal/bin/hpr-publish.bash
#
# xdg-open "https://hackerpublicradio.org/eps/hpr${ep_num}/index.html" >/dev/null 2>&1 &

View File

@ -1,52 +0,0 @@
#!/usr/bin/env bash
# Copyright Ken Fallon - Released into the public domain. http://creativecommons.org/publicdomain/
#============================================================
upload_dir="/home/hpr/upload"
reserve_dir="/home/hpr/reserve"
hub_dir="/home/hpr/hub"
reserve_file="${hub_dir}/reserve.txt"
while read reserve_show_dir
do
echo "Processing \"${reserve_show_dir}\""
shownotes="${reserve_show_dir}/shownotes.json"
if [ ! -s "${shownotes}" ]
then
echo "ERROR: \"${shownotes}\" not found"
exit 1
fi
host_id="$( jq --raw-output '.host.Host_ID' "${shownotes}" )"
if [ "${host_id}" -eq "0" ]
then
echo "ERROR: New host detected \"${host_id}\" post the first show to the regular queue."
exit 1
fi
metadata_url="$( jq --raw-output '.metadata.url' "${shownotes}" )"
if [ -n "${metadata_url}" ]
then
save_name=$( basename "${metadata_url}" | sed -e 's/[^A-Za-z0-9.]/_/g' -e 's/__/_/g' )
wget "${metadata_url}" -O "${reserve_show_dir}/${save_name}"
if [ ! -s "${reserve_show_dir}/${save_name}" ]
then
echo "ERROR: \"${metadata_url}\" needs to be downloaded as \"${reserve_show_dir}/${save_name}\""
exit 1
fi
fi
Host_ID="$( jq --raw-output '.host.Host_ID' "${shownotes}" )"
Host_Name="$( jq --raw-output '.host.Host_Name' "${shownotes}" | sed -e 's/[^A-Za-z0-9]/_/g' -e 's/__/_/g' )"
Key="$( jq --raw-output '.metadata.Key' "${shownotes}" )"
Timestamp="$( jq --raw-output '.metadata.Timestamp' "${shownotes}" )"
Title="$( jq --raw-output '.episode.Title' "${shownotes}" | sed -e 's/[^A-Za-z0-9]/_/g' -e 's/__/_/g')"
Timestamp_Epoch="$( \date -u +%s -d "${Timestamp}" )"
mv -v "${reserve_show_dir}" "${reserve_dir}/${Timestamp_Epoch}_${Host_ID}_${Key}_${Host_Name}_${Title}"
done < <( find "${upload_dir}" -type d -iname "*_9999_*" )
ls -1 "${reserve_dir}" | awk -F '_' '{ $2=""; $3=""; print}' | while read line
do
upload_epoch="$( echo "${line}" | awk '{print $1}' )"
upload_iso8601="$( \date -d "@${upload_epoch}" +%Y-%m-%d )"
echo "${upload_iso8601} $( echo ${line} | awk '{ $1=""; print}' )"
done > "${reserve_file}"
cat "${reserve_file}"

6
bin/run-speedtest.bash Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
# * * * * * /usr/local/bin/run-speedtest.bash >/dev/null 2>&1
speedtest-cli --json | jq '.' > /var/www/html/speedtest.json
chown apache:apache /var/www/html/speedtest.json

View File

@ -1,5 +0,0 @@
#!/usr/bin/env bash
# Copyright Ken Fallon - Released into the public domain. http://creativecommons.org/publicdomain/
#============================================================
curl --silent --netrc-file ${HOME}/.netrc "https://hub.hackerpublicradio.org/cms/status.php"

View File

@ -1,406 +0,0 @@
<?php
require "/home/hpr/php/include.php";
date_default_timezone_set('UTC');
function goback() {
header( "Location: " . $_SERVER["HTTP_REFERER"] ) ;
exit;
}
logextra( "Starting add_show.php");
if ( $_SERVER['REQUEST_METHOD'] !== 'POST' ) {
problem("ERROR: It is not a POST");
}
logextra( "It is a POST" );
if ( empty($_SERVER["REMOTE_ADDR"]) ) {
problem("ERROR: No REMOTE_ADDR");
}
else {
$ip = $_SERVER["REMOTE_ADDR"];
}
logextra( "We have a IP of $ip" );
if (count($_POST) !== 15) {
logextra( "POST is not 15" );
if (count($_POST) !== 17) {
# 19 is for mosaic
# if this reports 0 is could be that the max upload is not set correctly in php.ini.
problem("ERROR: Incorrect number of POST entries ".count($_POST) );
}
}
logextra( "Correct number of POST entries" );
if ( isset( $_POST['key'] ) and strlen( $_POST['key'] ) === 45 and strlen( htmlspecialchars( stripslashes( strip_tags( $_POST['key'] ) ) ) ) === 45 and ctype_xdigit( $_POST['key'] ) ) {
$db_key = htmlspecialchars( stripslashes( strip_tags( $_POST['key'] ) ) );
}
else {
problem("ERROR: no key");
}
logextra( "Field lengths are correct" );
$query = "SELECT * FROM reservations WHERE reservations.key = '$db_key' ";
$result = @mysqli_query($connection, $query);
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
logextra( "Getting this reservation from the db" );
if ( $db["key"] != $db_key ) {
problem("ERROR: Could not find the reservation in the db");
}
logextra( "Found this reservation from the db" );
if ( empty($_POST["title"]) or strlen($_POST["title"]) > 100 ) {
problem("ERROR: Title length is not OK");
}
logextra( "Title length is OK" );
$title = $_POST["title"];
if ( empty($_POST["summary"]) or strlen( $_POST["summary"]) > 200 or strlen(str_replace('\\', '', $_POST["summary"])) > 100 ) {
problem("ERROR: Summary length is not OK");
}
logextra( "Summary length is OK" );
$summary = $_POST["summary"];
if ( empty($_POST["explicit"]) ) {
problem("ERROR: explicit is missing");
}
logextra( "explicit exists" );
if ( strcmp($_POST["explicit"], "Yes") !== 0 ) {
logextra( "explicit is not yes" );
if ( strcmp($_POST["explicit"], "Clean") !== 0 ) {
problem("ERROR: explicit needs to be either Yes or Clean");
}
}
logextra( "explicit is either Yes or Clean" );
$explicit = $_POST["explicit"];
if ( $explicit === "Clean" ) {
$explicit = 0;
}
else {
$explicit = 1;
}
if ( empty($_POST["episode_license"]) or strlen($_POST["episode_license"]) < 4 or strlen($_POST["episode_license"]) > 11 ) {
problem("ERROR: episode_license length is not fine");
}
logextra( "episode_license length is fine" );
if ( !(
strcmp($_POST["episode_license"], "CC-BY-SA") === 0 or
strcmp($_POST["episode_license"], "CC-BY-NC-SA") === 0 or
strcmp($_POST["episode_license"], "CC-BY-NC-ND") === 0 or
strcmp($_POST["episode_license"], "CC-0") === 0 or
strcmp($_POST["episode_license"], "CC-BY-NC") === 0 or
strcmp($_POST["episode_license"], "CC-BY") === 0 or
strcmp($_POST["episode_license"], "Other") === 0 )
) {
problem("ERROR: license is not a valid value");
}
logextra( "license is a valid value" );
$episode_license = $_POST["episode_license"];
if ( empty($_POST["notes"]) or strlen($_POST["notes"]) > 40000 ) {
problem("ERROR: Notes are missing not less than max");
}
logextra( "Notes are not missing and are less than max" );
$notes = $_POST["notes"];
if ( ( empty($_POST["series"]) and ($_POST["series"] != 0 ) ) or (strlen($_POST["series"]) > 3 ) ) {
problem("ERROR: Series id is not in the correct range");
}
$series = $_POST["series"];
if ( (strval(intval($series)) != strval($series)) ){
problem("ERROR: series is not an int");
}
logextra( "series is int" );
$result_series = mysqli_query($connection, "SELECT name FROM miniseries WHERE id='$series'");
logextra( "Series id is in the correct range \"$series\"" );
if (!isset($result_series)) {
problem("ERROR: Series has not been found");
}
$db_series_name_array = mysqli_fetch_row( $result_series );
$db_series_name = $db_series_name_array[0];
if ( empty($db_series_name) ) {
problem("ERROR: Series name \"${db_series_name}\" is missing from db ");
}
logextra( "Series name has been found in db: \"$db_series_name\"" );
if ( empty($_POST["series_name"]) ) {
problem("ERROR: series_name length is not fine");
}
$series_name = $_POST["series_name"];
if ( $series_name != $db_series_name ) {
problem("ERROR: series_name \"$series_name\" and db_series_name \"$db_series_name\" don't match.");
}
logextra( "series_name checkes passed: \"$series_name\"" );
if ( !empty($_POST["tags"]) and strlen($_POST["tags"]) > 100 ) {
problem("ERROR: Tags are not the correct length");
}
logextra( "Tags are the correct length" );
$tags = $_POST["tags"];
#############
# Host checks
if ( empty($_POST["host_name"]) or strlen($_POST["host_name"]) > 40 ) {
problem("ERROR: host_name is not set and not the correct length");
}
logextra( "host_name is set and correct length" );
$host_name = $_POST["host_name"];
if ( strlen($_POST["host_profile"]) > 2000 ) {
problem("ERROR: host_profile is not the correct length");
}
logextra( "host_profile is correct length" );
$host_profile = $_POST["host_profile"];
if ( empty($_POST["host_license"]) or strlen($_POST["host_license"]) < 4 or strlen($_POST["host_license"]) > 11 ) {
problem("ERROR: host_license is not in the correct range");
}
logextra( "host_license is in the correct range" );
if ( !(
strcmp($_POST["host_license"], "CC-BY-SA") === 0 or
strcmp($_POST["host_license"], "CC-BY-NC-SA") === 0 or
strcmp($_POST["host_license"], "CC-BY-NC-ND") === 0 or
strcmp($_POST["host_license"], "CC-0") === 0 or
strcmp($_POST["host_license"], "CC-BY-NC") === 0 or
strcmp($_POST["host_license"], "CC-BY") === 0 or
strcmp($_POST["host_license"], "Other") === 0 )
) {
problem("ERROR: host_license is not a predfined value");
}
logextra( "host_license is a predfined value" );
$host_license = $_POST["host_license"];
if ( $_POST["hostid"] == 0 ) {
problem("ERROR: hostid is 0");
}
logextra( "hostid is not 0" );
if ( empty($_POST["hostid"]) ) {
problem("ERROR: hostid doesn't exists ");
}
logextra( "hostid exists " );
$result = mysqli_query($connection, 'SELECT MAX(hostid) FROM hosts;');
if (!isset($result)) {
problem("ERROR: could not get the max host from db");
}
$maxhost_array = mysqli_fetch_row( $result );
$maxhost = $maxhost_array[0];
logextra( "retrieved the max host from db" );
$hostid = $_POST["hostid"];
if ( (strval(intval($hostid)) != strval($hostid)) ){
problem("ERROR: host id is not an int");
}
logextra( "host id is int" );
if ( ( intval($hostid) < 0 ) or ( intval($hostid) > $maxhost ) ){
problem("ERROR: host id \"$hostid\" is not in the correct range \" $maxhost \"");
}
logextra( "host id is int, and in the correct range" );
$query = "SELECT * FROM `hosts` WHERE `hostid` = '$hostid' and `host` = '$host_name';";
$result = @mysqli_query($connection, $query);
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
logextra( "Getting this host from the db" );
if ( ( $db["hostid"] != $hostid ) or ( $db["host"] != $host_name ) ) {
problem("ERROR: Could not find the host \"" . $db["hostid"] ."\", \"" . $db["host"] . "\" in the db \"${hostid}\", \"${host_name}\"" . $query );
}
logextra( "Found this reservation from the db" );
if ( ( $db["profile"] != "$host_profile" ) or ( $db["license"] != "$host_license" ) ) {
logextra("The host_license is different to that in the db");
$host_profile = mysqli_real_escape_string( $connection, $host_profile );
$host_license = mysqli_real_escape_string( $connection, $host_license );
$query = "UPDATE `hosts` SET `profile` = '$host_profile', `license` = '$host_license' WHERE `hosts`.`hostid` = '$hostid';";
$result = mysqli_query($connection, $query );
if (!isset($result)) {
problem("ERROR: could not update the host profile");
} else {
logextra( "Updating the host profile" );
}
}
logextra( "The host_license is the same to that in the db" );
##############
# Episode Check
// SHOW_SUBMITTED → METADATA_PROCESSED → SHOW_POSTED → MEDIA_TRANSCODED → UPLOADED_TO_IA → UPLOADED_TO_RSYNC_NET
if ( !empty($_POST["ep_num"]) and isset( $_POST["ep_num"] ) ) {
$ep_num = intval( $_POST["ep_num"] );
}
else {
problem("ERROR: ep_num is empty");
}
// // SELECT MAX(ep_num) FROM `reservations` → 3627
// // SELECT MIN(ep_num) FROM `reservations` WHERE ep_num > 0 → 3582
//
$result = mysqli_query($connection, 'SELECT MAX(ep_num) FROM `reservations`;');
if (!isset($result)) {
problem("ERROR: Can't get max eps from reservations");
}
$max_eps_array = mysqli_fetch_row( $result );
$max_eps = $max_eps_array[0];
mysqli_free_result($result);
$result = mysqli_query($connection, 'SELECT MIN(ep_num) FROM `reservations` WHERE ep_num > 0;');
if (!isset($result)) {
problem("ERROR: Can't get min eps from reservations");
}
$min_eps_array = mysqli_fetch_row( $result );
$min_eps = $min_eps_array[0];
mysqli_free_result($result);
if ( empty( $ep_num ) ) {
problem("ERROR: ep_num is empty");
}
if ( $ep_num < $min_eps ) {
problem("ERROR: ep_num is too small");
}
if ( $ep_num > $max_eps ) {
problem("ERROR: ep_num is too big");
}
if ( intval($ep_num) === 0 ) {
problem("ERROR: ep_num is 0");
}
else {
$ep_num = intval($ep_num);
}
$result = mysqli_query($connection, "SELECT ep_num FROM reservations WHERE ep_num='$ep_num' AND status='METADATA_PROCESSED';");
if (!isset($result)) {
problem("ERROR: Cant get info from reservations db");
}
$db_ep_num_array = mysqli_fetch_row( $result );
$db_ep_num = $db_ep_num_array[0];
mysqli_free_result($result);
if ( $db_ep_num != $ep_num ){
problem("ERROR: Cant find $ep_num with status of METADATA_PROCESSED");
}
$result = mysqli_query($connection, "SELECT `id` FROM `eps` WHERE `id` = '$ep_num';");
if (!isset($result)) {
problem("ERROR: The show $ep_num is already in the eps db");
}
$db_ep_num_array = mysqli_fetch_row( $result );
$db_ep_num = $db_ep_num_array[0];
mysqli_free_result($result);
if ( !empty( $db_ep_num ) ) {
problem("ERROR: $ep_num is already in the eps table");
}
if ( intval($db_ep_num) === $ep_num ) {
problem("ERROR: $ep_num is already in the eps table");
}
logextra( "ep_num checkes passed: $ep_num" );
if ( !preg_match("/^\d{4}-\d{2}-\d{2}$/", $_POST["ep_date"]) ) {
problem("ERROR: ep_date fails the regex match ");
}
else {
$ep_date = $_POST["ep_date"];
}
if ( strtotime($ep_date) === false ) {
problem("ERROR: ep_date didn't convert to date");
}
else {
$ep_date_epoch = strtotime($ep_date);
}
logextra( "ep_date checkes passed: $ep_date" );
if ( !empty($_POST["duration"]) and isset( $_POST["duration"] ) ) {
$duration = intval( $_POST["duration"] );
}
else {
problem("ERROR: duration is empty");
}
if ( empty( $duration ) ) {
problem("ERROR: duration is empty");
}
if ( $duration < 50 ) {
problem("ERROR: duration is too small");
}
if ( $duration > 26830 ) {
problem("ERROR: duration is too big");
}
if ( intval($duration) === 0 ) {
problem("ERROR: duration is 0");
}
else {
$duration = intval($duration);
}
logextra( "duration checkes passed: $duration" );
$title = mysqli_real_escape_string( $connection, $title );
$summary = mysqli_real_escape_string( $connection, $summary );
$notes = mysqli_real_escape_string( $connection, $notes );
$tags = mysqli_real_escape_string( $connection, $tags );
$query_add = "INSERT INTO eps VALUES ('$ep_num', '{$ep_date}', '{$title}', '{$duration}', '{$summary}', '{$notes}', '{$hostid}', '{$series}', '{$explicit}', '{$episode_license}', '{$tags}', '0', '0', '0')";
$result = mysqli_query($connection, $query_add );
if(!$result) {
problem("ERROR: DB problem - The show $ep_num was not added to the eps db.");
}
if (mysqli_errno( $connection )) {
$error = "MySQL error ".mysqli_errno( $connection ).": ".mysqli_error()."\n";
problem("ERROR: MySQL error- The show $ep_num was not added to the eps db.\n$error");
}
$result = mysqli_query($connection, "SELECT `id` FROM `eps` WHERE `id` = '$ep_num';");
if (!isset($result)) {
problem("ERROR: DB problem - The show $ep_num has not been added to the eps db");
}
$db_ep_num_array = mysqli_fetch_row( $result );
$db_ep_num = $db_ep_num_array[0];
mysqli_free_result($result);
if (mysqli_errno( $connection )) {
$error = "MySQL error ".mysqli_errno( $connection ).": ".mysqli_error()."\n";
problem("ERROR: MySQL error- The show $ep_num was not added to the eps db.\n$error");
}
$result = mysqli_query($connection, "UPDATE reservations SET `status` = 'SHOW_POSTED' WHERE `ep_num` = '$ep_num' AND status='METADATA_PROCESSED';" );
if (!isset($result)) {
problem("ERROR: DB problem - The show $ep_num has not been added to the eps db");
}
if (mysqli_errno( $connection )) {
$error = "MySQL error ".mysqli_errno( $connection ).": ".mysqli_error()."\n";
problem("ERROR: Could not update the show reservation to SHOW_POSTED in the db");
}
logextra( "Finished $ep_num ." );
?>

577
cms/add_show_json.php Normal file
View File

@ -0,0 +1,577 @@
<?php
require "/home/hpr/php/include.php";
date_default_timezone_set('UTC');
// executed by postshow.bash
// curl --netrc-file $HOME/.netrc --verbose --request POST https://hub.hackerpublicradio.org/cms/add_show_json.php --data-ascii @post_show.json --header "Content-Type: application/json"
logextra( "Starting add_show_json.php");
//Make sure that it is a POST request.
if(strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') != 0){
throw new Exception('Request method must be POST!');
}
//Make sure that the content type of the POST request has been set to application/json
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
if(strcasecmp($contentType, 'application/json') != 0){
throw new Exception('Content type must be: application/json');
}
//Receive the RAW post data.
$content = trim(file_get_contents("php://input"));
//Attempt to decode the incoming RAW post data from JSON.
$decoded_json = json_decode($content, true);
//If json_decode failed, the JSON is invalid.
if(!is_array($decoded_json)){
problem( "Received content contained invalid JSON!" );
}
if ( empty($_SERVER["REMOTE_ADDR"]) ) {
problem("No REMOTE_ADDR");
}
else {
$ip = $_SERVER["REMOTE_ADDR"];
}
logextra( "We have a IP of $ip" );
// Check the key
$provided_key = $decoded_json['key'];
if ( isset( $provided_key ) and strlen( $provided_key ) === 45 and strlen( htmlspecialchars( stripslashes( strip_tags( $provided_key ) ) ) ) === 45 and ctype_xdigit( $provided_key ) ) {
$db_key = htmlspecialchars( stripslashes( strip_tags( $provided_key ) ) );
}
else {
problem("no valid key found");
}
logextra( "Found Valid \$key: $db_key" );
// Check if this is a known reservation
$query = "SELECT * FROM reservations WHERE reservations.key = '$db_key' ";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
logextra( "Getting this reservation from the db" );
if ( $db["key"] != $db_key ) {
problem("Could not find the reservation in the db");
}
logextra( "Found this reservation from the db" );
// Check title
$provided_title = urldecode( $decoded_json["title"] );
if ( empty($provided_title) or strlen($provided_title) > 100 ) {
problem("Title length is not OK");
}
logextra( "Title length is OK" );
$title = $provided_title;
// Check summary
$provided_summary = urldecode( $decoded_json["summary"] );
if ( empty($provided_summary) or strlen( $provided_summary) > 200 or strlen(str_replace('\\', '', $provided_summary)) > 100 ) {
problem("Summary length is not OK");
}
logextra( "Summary length is OK" );
$summary = $provided_summary;
// Check Adult flag
$provided_explicit = urldecode( $decoded_json["explicit"] );
if ( empty($provided_explicit) ) {
problem("explicit is missing");
}
logextra( "explicit exists" );
if ( strcmp($provided_explicit, "Yes") !== 0 ) {
logextra( "explicit is not yes" );
if ( strcmp($provided_explicit, "Clean") !== 0 ) {
problem("explicit needs to be either Yes or Clean");
}
}
logextra( "explicit is either Yes or Clean" );
$explicit = $provided_explicit;
if ( $explicit === "Clean" ) {
$explicit = 0;
}
else {
$explicit = 1;
}
// Check notes
$provided_notes = urldecode( $decoded_json["notes"] );
if ( empty($provided_notes) or strlen($provided_notes) > 100000 ) {
problem("Notes are missing not less than max");
}
logextra( "Notes are present and are under the max length" );
$notes = $provided_notes;
// Check episode Lisence
$provided_episode_license = urldecode( $decoded_json["episode_license"] );
if ( empty($provided_episode_license) or strlen($provided_episode_license) < 4 or strlen($provided_episode_license) > 11 ) {
problem("episode_license length is not fine");
}
logextra( "episode_license length is fine" );
$query = "SELECT short_name FROM licenses WHERE short_name = '$provided_episode_license'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["short_name"]) ) {
problem( "No result returned for this short_name:\"${provided_episode_license}\"" );
}
}
$episode_license = $provided_episode_license;
logextra( "episode_license is a valid value \"${episode_license}\"" );
// Check Series ID
$provided_series_id = urldecode( $decoded_json["series_id"] );
if ( ( empty($provided_series_id) and ($provided_series_id != 0 ) ) or (strlen($provided_series_id) > 3 ) ) {
problem("Series id is not in the correct range");
}
logextra( "series length is fine" );
if ( (strval(intval($provided_series_id)) != strval($provided_series_id)) ){
problem("series is not an int");
}
logextra( "series is int" );
$query = "SELECT COUNT(id) AS count_id FROM miniseries WHERE id='$provided_series_id'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["count_id"]) ) {
problem( "No result count returned for this miniseries:\"${provided_series_id}\"" );
}
$count_id = $db["count_id"];
if ( $count_id === 0 ) {
problem( "No result returned for this query \"$query\"" );
}
}
$series_id = $provided_series_id;
logextra( "Series ID was found \"$series_id\"" );
// Check Series Name
$provided_series_name = urldecode( $decoded_json["series_name"] );
if ( empty( $provided_series_name ) or strlen( $provided_series_name ) < 3 or strlen( $provided_series_name ) > 50 ) {
problem("series_name length is not correct");
}
$query = "SELECT name FROM miniseries WHERE id='$series_id'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["name"]) ) {
problem( "No result name returned for this miniseries:\"${series_id}\"" );
}
$db_series_name = $db["name"];
}
logextra( "Series name has been found in db: \"$db_series_name\"" );
if ( $provided_series_name != $db_series_name ) {
problem("Provided series_name \"$provided_series_name\" and db_series_name \"$db_series_name\" don't match.");
}
$series_name = $provided_series_name;
logextra( "Series Name was found \"$series_name\"" );
// Check Tags
$provided_tags = urldecode( $decoded_json["tags"] );
if ( empty( $provided_tags ) or strlen( $provided_tags ) < 3 or strlen( $provided_tags ) > 100 ) {
problem("Tags are not the correct length");
}
logextra( "Tags are the correct length" );
$tags = $provided_tags;
// Check Host ID
$provided_hostid = urldecode( $decoded_json["hostid"] );
if ( empty( $provided_hostid ) or ( $provided_hostid === 0 ) or ( $provided_hostid > 999 ) or ( strlen( $provided_hostid ) > 3 ) or ( strval( intval( $provided_hostid ) ) != strval( $provided_hostid ) ) ) {
problem("Host id is not in the correct range \"${provided_hostid}\"");
}
logextra( "host id length is fine" );
$query = "SELECT COUNT(hostid) AS count_hostid FROM hosts WHERE hostid='$provided_hostid'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["count_hostid"]) ) {
problem( "No result count returned for this hostid:\"${provided_hostid}\"" );
}
$count_hostid = $db["count_hostid"];
if ( $count_hostid === 0 ) {
problem( "No result returned for this query \"$query\"" );
}
}
$host_id = $provided_hostid;
logextra( "Host ID was found \"$host_id\"" );
// Check Host Name
$provided_host_name = urldecode( $decoded_json["host_name"] );
if ( empty( $provided_host_name ) or strlen( $provided_host_name ) < 3 or strlen( $provided_host_name ) > 50 ) {
problem("host_name length is not correct");
}
$query = "SELECT host FROM hosts WHERE hostid='$host_id'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["host"]) ) {
problem( "No result host name returned for this host_id:\"${host_id}\"" );
}
$db_host_name = $db["host"];
}
logextra( "Host name has been found in db: \"$db_host_name\"" );
if ( $provided_host_name != $db_host_name ) {
problem("Provided host_name \"$provided_host_name\" and db_host_name \"$db_host_name\" don't match.");
}
$host_name = $provided_host_name;
logextra( "Host ID was found \"$host_name\"" );
// Check Host Lisence
$provided_host_license = urldecode( $decoded_json["host_license"] );
if ( empty($provided_host_license) or strlen($provided_host_license) < 4 or strlen($provided_host_license) > 11 ) {
problem("host_license length is not fine");
}
logextra( "host_license length is fine" );
$query = "SELECT short_name FROM licenses WHERE short_name = '$provided_host_license'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["short_name"]) ) {
problem( "No result returned for this short_name:\"${provided_host_license}\"" );
}
}
$host_license = $provided_host_license;
logextra( "host_license is a valid value \"${host_license}\"" );
// Check Episode Date
$provided_ep_date = urldecode( $decoded_json["ep_date"] );
if ( !preg_match( "/^\d{4}-\d{2}-\d{2}$/", $provided_ep_date ) ) {
problem("ep_date fails the regex match \"${provided_ep_date}\"");
}
if ( strtotime( $provided_ep_date ) === false ) {
problem("ep_date didn't convert to date \"${provided_ep_date}\"");
}
$ep_date_epoch = strtotime( $provided_ep_date );
$ep_date = $provided_ep_date;
logextra( "ep_date checkes passed: $ep_date, $ep_date_epoch" );
// Check Host Profile
$provided_host_profile = urldecode( $decoded_json["host_profile"] );
if ( strlen( $provided_host_profile ) > 2000 ) {
problem("host_profile is not the correct length");
}
logextra( "host_profile is correct length" );
$host_profile = $provided_host_profile;
// Check Host email
$provided_email = urldecode( $decoded_json["email"] );
if ( empty( $provided_email ) or ( strlen( $provided_email ) > 100 ) ) {
problem("Host email is not in the correct length \"${provided_email}\"");
}
logextra( "host email length is fine" );
if (!filter_var($provided_email, FILTER_VALIDATE_EMAIL)) {
problem("Host email is not in the correct format. \"${provided_email}\"");
}
logextra( "host email passes validation $provided_email" );
$query = "SELECT COUNT(email) AS count_email FROM hosts WHERE email='$provided_email'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["count_email"]) ) {
problem( "The email address is not in the database:\"${provided_email}\"" );
}
$count_email = $db["count_email"];
if ( $count_email === 0 ) {
problem( "No result returned for this query \"$query\"" );
}
}
$email = $provided_email;
logextra( "Host email was found in the database \"$email\"" );
// Confirm the provided Host ID, hostname and email match in the db.
$query = "SELECT COUNT(hostid) AS count_hostid FROM hosts WHERE hostid='$host_id' AND host = '$host_name' AND email='$provided_email'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["count_hostid"]) ) {
problem( "The email address is not in the database:\"${provided_email}\"" );
}
$count_hostid = $db["count_hostid"];
if ( $count_hostid === 0 ) {
problem( "No result returned for this query \"$query\"" );
}
}
logextra( "Host email and host id were found in the database \"$host_id\", \"$host_name\", \"$email\", " );
// Check Duration
$provided_duration = urldecode( $decoded_json["duration"] );
if ( empty( $provided_duration ) or $provided_duration < 120 or $provided_duration > 43200 ) {
problem("Duration id is not in the correct range");
}
logextra( "Duration length is fine" );
$duration = $provided_duration;
logextra( "Duration was found \"$duration\"" );
// Check Episode Number
$provided_ep_num = intval( urldecode( $decoded_json["ep_num"] ) );
if ( !isset( $provided_ep_num ) ) {
problem("ep_num is not set ");
}
if ( empty( $provided_ep_num ) ) {
problem("ep_num is empty ");
}
// SELECT MAX(ep_num) FROM `reservations` → 3627
// SELECT MIN(ep_num) FROM `reservations` WHERE ep_num > 0 → 3582
$result = mysqli_query($connection, 'SELECT MAX(ep_num) FROM `reservations`;');
if (!isset($result)) {
problem("Can't get max eps from reservations");
}
$max_eps_array = mysqli_fetch_row( $result );
$max_eps = $max_eps_array[0];
mysqli_free_result($result);
$result = mysqli_query($connection, 'SELECT MIN(ep_num) FROM `reservations` WHERE ep_num > 0;');
if (!isset($result)) {
problem("Can't get min eps from reservations");
}
$min_eps_array = mysqli_fetch_row( $result );
$min_eps = $min_eps_array[0];
mysqli_free_result($result);
if ( $provided_ep_num < $min_eps ) {
problem("ep_num is too small");
}
if ( $provided_ep_num > $max_eps ) {
problem("ep_num is too big");
}
if ( intval($provided_ep_num) === 9999 ) {
problem("ep_num is a reserved show 9999");
}
if ( intval($provided_ep_num) === 0 ) {
problem("ep_num is 0");
}
$ep_num = intval($provided_ep_num);
// Workflow Check
// SHOW_SUBMITTED → SHOW_POSTED → MEDIA_TRANSCODED → UPLOADED_TO_IA → UPLOADED_TO_RSYNC_NET
$result = mysqli_query($connection, "SELECT ep_num FROM reservations WHERE ep_num='$ep_num' AND status='SHOW_SUBMITTED';");
if (!isset($result)) {
problem("Cant get info from reservations db");
}
$db_ep_num_array = mysqli_fetch_row( $result );
$db_ep_num = $db_ep_num_array[0];
mysqli_free_result($result);
if ( $db_ep_num != $ep_num ){
problem("Cant find $ep_num with status of SHOW_SUBMITTED");
}
$query = "SELECT COUNT(id) AS count_id FROM eps WHERE id = '$ep_num'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
$count_id = $db["count_id"];
if ( $count_id != 0 ) {
problem( "$count_id An existing episode has been posted with this episode id:\"${ep_num}\"" );
}
}
logextra( "The episode ID \"$ep_num\" has not already been assigned" );
/////////////////////////////////////////////////////////////////////////
// Update database - Actual Changes
// Update host_profile
$query = "SELECT profile FROM hosts WHERE hostid = '$host_id' and host = '$host_name'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( $db["profile"] != "$host_profile" ) {
logextra("The host_profile is different to that in the db");
$host_profile = mysqli_real_escape_string( $connection, $host_profile );
$query = "UPDATE `hosts` SET `profile` = '$host_profile' WHERE `hosts`.`hostid` = '$host_id';";
$result = mysqli_query($connection, $query );
if (!isset($result)) {
problem("could not update the host profile");
} else {
logextra( "Updating the host profile" );
}
}
logextra( "The profile is the same to that in the db" );
// Update license
$query = "SELECT license FROM hosts WHERE hostid = '$host_id' and host = '$host_name'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "No result returned for this query \"$query\"" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty( $db["license"] ) ) {
problem( "No result returned for this license:\"${provided_episode_license}\"" );
}
}
$db_license = $db["license"];
if ( strcmp( $host_license, $db_license ) !== 0 ) {
logextra("The host_license \"$host_license\" is not the same to that in the db \"$db_license\"");
$host_license = mysqli_real_escape_string( $connection, $host_license );
$query = "UPDATE `hosts` SET `license` = '$host_license' WHERE `hosts`.`hostid` = '$host_id';";
$result = mysqli_query($connection, $query );
if (!isset($result)) {
problem("could not update the host license");
} else {
logextra( "Updating the host license" );
}
}
else {
logextra( "The host_license is the same to that in the db \"$host_license\"" );
}
$title = mysqli_real_escape_string( $connection, $title );
$summary = mysqli_real_escape_string( $connection, $summary );
$notes = mysqli_real_escape_string( $connection, $notes );
$tags = mysqli_real_escape_string( $connection, $tags );
$query_add = "INSERT INTO eps VALUES ('$ep_num', '{$ep_date}', '{$title}', '{$duration}', '{$summary}', '{$notes}', '{$host_id}', '{$series_id}', '{$explicit}', '{$episode_license}', '{$tags}', '0', '0', '0')";
$result = mysqli_query($connection, $query_add );
if(!$result) {
problem("DB problem - The show $ep_num was not added to the eps db.");
}
if (mysqli_errno( $connection )) {
$error = "MySQL error ".mysqli_errno( $connection ).": ".mysqli_error()."\n";
problem("MySQL error- The show $ep_num was not added to the eps db.\n$error");
}
logextra( "Added the entry: $query_add" );
$result = mysqli_query($connection, "SELECT `id` FROM `eps` WHERE `id` = '$ep_num';");
if (!isset($result)) {
problem("DB problem - The show $ep_num has not been added to the eps db");
}
$db_ep_num_array = mysqli_fetch_row( $result );
$db_ep_num = $db_ep_num_array[0];
mysqli_free_result($result);
if (mysqli_errno( $connection )) {
$error = "MySQL error ".mysqli_errno( $connection ).": ".mysqli_error()."\n";
problem("MySQL error- The show $ep_num was not added to the eps db.\n$error");
}
$result = mysqli_query($connection, "UPDATE reservations SET `status` = 'SHOW_POSTED' WHERE `ep_num` = '$ep_num' AND status='SHOW_SUBMITTED';" );
if (!isset($result)) {
problem("DB problem - The show $ep_num has not been added to the eps db");
}
if (mysqli_errno( $connection )) {
$error = "MySQL error ".mysqli_errno( $connection ).": ".mysqli_error()."\n";
problem("Could not update the show status to SHOW_POSTED in the db");
}
logextra( "Finished $ep_num ." );
?>

443
cms/assets.php Normal file
View File

@ -0,0 +1,443 @@
<?php
## Recent Changes
# $allowed_content_type moved to include.php
require "/home/hpr/php/include.php";
date_default_timezone_set('UTC');
// curl --netrc-file $HOME/.netrc --verbose --request POST https://hub.hackerpublicradio.org/cms/assets.php --data-ascii @assets.json --header "Content-Type: application/json"
//Make sure that it is a POST request.
if ( strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') != 0 && strcasecmp($_SERVER['REQUEST_METHOD'], 'GET') != 0 ){
throw new Exception('Request method must be POST!');
}
if ( strcasecmp($_SERVER['REQUEST_METHOD'], 'GET') == 0 ){
executeGET();
}
if ( strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') == 0 ){
executePOST();
}
function executeGET() {
global $connection;
$asset_array = array ();
if (isset($_GET['id'])) {
$id = $_GET['id'];
$result = mysqli_query($connection, 'SELECT MAX(id) FROM eps;');
if (!isset($result)) {
logextra( "unable to execute SELECT MAX(id) FROM eps;" );
problem( "2f1497d7734f5dc7ce04e1a343cbd4cb" );
die('Could not query:' . mysqli_error());
}
$maxhost_array = mysqli_fetch_row( $result );
$maxhost = $maxhost_array[0];
$num_get_args=0;
foreach($_GET as $k => $v) {
++$num_get_args;
}
if ( (strval(intval($id)) != strval($id)) OR ( intval($id) <= 0 ) OR ( intval($id) > $maxhost ) OR ( $num_get_args > 1 ) ){
logextra( "The id \"$id\" is not valid." );
problem( "6b070390632e12a962338d2e31464f9f" );
exit;
}
$query = "SELECT id FROM eps WHERE id = '$id'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
logextra( "Cud not run SELECT id FROM eps WHERE id = $id" );
problem( "568dff032398640456d749135358a88b" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["id"]) ) {
logextra( "The \"$id\" is not in the database" );
http_response_code(404);
die();
}
}
$ep_retrieve = "SELECT episode_id, filename, extension, `size`, sha1sum, mime_type
FROM assets
WHERE episode_id = '$id'
ORDER BY episode_id ASC;";
}
else {
$ep_retrieve = "SELECT episode_id, filename, extension, `size`, sha1sum, mime_type
FROM assets
ORDER BY episode_id ASC;";
}
if ($result = mysqli_query($connection, $ep_retrieve)) {
while ($row = mysqli_fetch_array($result)) {
$episode_id = $row['episode_id'];
$filename = $row['filename'];
$extension = $row['extension'];
$size = $row['size'];
$sha1sum = $row['sha1sum'];
$mime_type = $row['mime_type'];
$asset_array["hpr$episode_id"][$filename] = array (
"episode_id" => $episode_id,
"filename" => $filename,
"extension" => $extension,
"size" => $size,
"sha1sum" => $sha1sum,
"mime_type" => $mime_type
);
}
}
header('Content-Type: application/json');
header("Content-disposition: inline; filename=hpr_stats.json");
echo json_encode($asset_array);
}
function executePOST() {
global $connection, $allowed_extensions, $allowed_content_type;
//Make sure that the content type of the POST request has been set to application/json
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
if(strcasecmp($contentType, 'application/json') != 0){
throw new Exception('Content type must be: application/json');
}
//Receive the RAW post data.
$content = trim(file_get_contents("php://input"));
//Attempt to decode the incoming RAW post data from JSON.
$decoded = json_decode($content, true);
//If json_decode failed, the JSON is invalid.
if(!is_array($decoded)){
logextra( "Received content contained invalid JSON!" );
problem( "0e0e69415750c96f19d234f83270fdea" );
}
foreach($decoded['assets'] as $asset) {
// Check episode_id
if ( isset( $asset['episode_id'] ) ) {
$provided_episode_id = $asset['episode_id'];
$provided_episode_id = filter_var($provided_episode_id, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
$result = mysqli_query($connection, 'SELECT MAX(id) FROM eps;');
if (!isset($result)) {
logextra( "Can't connect to db" );
problem( "4c85d7b9e1d2eb741cdb60fd9f97b852" );
die('Could not query:' . mysqli_error());
}
$maxhost_array = mysqli_fetch_row( $result );
$maxhost = $maxhost_array[0];
$num_get_args=0;
foreach($_GET as $k => $v) {
++$num_get_args;
}
if (strval(intval($provided_episode_id)) != strval($provided_episode_id)) {
logextra( "ID is not a valid number because strval(intval($provided_episode_id)) != strval($provided_episode_id))" );
problem( "b2babb5bebde79e08ddf3c780c56615d" );
}
if ( intval($provided_episode_id) <= 0 ){
logextra( "ID is not a valid number because intval($provided_episode_id) <= 0" );
problem( "b245522d0582e61612e8b7dcdb0e0f4c" );
}
if ( intval($provided_episode_id) > $maxhost ){
logextra( "ID is not a valid number because intval($provided_episode_id) > $maxhost" );
problem( "c6feadcf0b6eda204cbfba6824aa2c7a" );
}
if ( $num_get_args > 1 ){
logextra( "ID is not a valid number because \$num_get_args: $num_get_args > 1" );
problem( "ba22518c5ced567cd0b855206985f036" );
}
$query = "SELECT id FROM eps WHERE id = '$provided_episode_id'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
logextra( "No result returned for this query \"SELECT id FROM eps WHERE id = '$provided_episode_id'\"" );
problem( "fa0778750519cb140b4076c844b3ec78" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["id"]) ) {
logextra( "No result returned for this id:\"${id}\"" );
problem( "1e09df9f3896da3e80507ea4538a4aca" );
}
}
$episode_id = $provided_episode_id;
logextra( "Found Valid \$episode_id: $episode_id" );
}
else {
logextra( "No episode_id provided" );
problem( "eae535cc88680a5bdab4e7bb4e54d83e" );
exit;
}
// Check filename
if ( isset( $asset['filename'] ) ) {
$provided_filename = $asset['filename'];
$provided_filename = filter_var($provided_filename, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
$this_dirname = dirname("$provided_filename", 2);
if ( empty($this_dirname) ) {
logextra( "no dirname" );
problem("b23ed28377cf4cf36cbf01931377ddc7");
}
if ( $this_dirname === "/" ) {
logextra( "dirname is root" );
problem("b90228a9c4d008eab57304bd36b75a08");
}
$this_basename = basename($provided_filename);
if ( empty($this_basename) ) {
logextra( "Cound not extract basename from filename: $provided_filename" );
problem("44b5022e3a32605c6b0afdf7699ed153");
}
if ( $this_basename !== $provided_filename ) {
logextra( "filename: $provided_filename does not match name:$this_basename" );
problem("832f0283544692bd6691e3802e67099c");
}
$this_ext = pathinfo($provided_filename, PATHINFO_EXTENSION);
if ( empty($this_ext) ) {
logextra( "The extension for \"$provided_filename\" is empty" );
problem("63166ba6572ac51b47804d9787152903");
}
$this_prefix =pathinfo($provided_filename, PATHINFO_FILENAME);
if ( empty($this_prefix) ) {
logextra( "The prefix for \"$provided_filename\" is empty" );
problem("9ad9a6b9e47e6960ff30442c3c808609");
}
if ( strlen($provided_filename) < 5 ) {
logextra( "The length of \"$provided_filename\" is less than 5" );
problem("e131ae01530f4098c299aaca0a6ee8e1");
}
if ( strlen($provided_filename) > 60 ) {
logextra( "The length of \"$provided_filename\" is greater than 60" );
problem("d90560ef4cac05954c93523d529ed20e");
}
if (!in_array( $this_ext, $allowed_extensions, true )) {
logextra( "This extension $this_ext, is not in the list of allowed_extensions" );
problem("dd98c84719083fb80fecbd0405504038 $this_ext");
}
$filename = $provided_filename;
logextra( "Found Valid \$filename: $filename" );
}
else {
logextra( "No filename provided" );
problem( "1edd3bcd2a16c152f0a97106372862f9" );
exit;
}
// Check extension
if ( isset( $asset['extension'] ) ) {
$provided_extension = $asset['extension'];
$provided_extension = filter_var($provided_extension, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
if ( $provided_extension !== $this_ext ) {
logextra( "The extensions provided \"$provided_extension\" and in the filename dont match \"$provided_filename\"" );
problem("ed58e1493aa56e0eaf50362cc6f64425");
}
if (!in_array( $provided_extension, $allowed_extensions, true )) {
logextra( "This extension $this_ext, is not in the list of allowed_extensions" );
problem("dc406b9151871e38ac69c2bf44fa74da");
}
$extension = $provided_extension;
logextra( "Found Valid \$extension: $extension" );
}
else {
logextra( "No extension provided" );
problem( "04b53ecd0ffa3faa68db1e541554903d" );
exit;
}
// Check size
if ( isset( $asset['size'] ) ) {
$provided_size = $asset['size'];
$provided_size = filter_var($provided_size, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
if (strval(intval($provided_size)) != strval($provided_size)) {
logextra( "The provided size is not a valid number because strval(intval($provided_size)) != strval($provided_size))" );
problem( "cc349935f0d80b40d5593b0fd54eaf58" );
}
if ( intval($provided_size) <= 0 ){
logextra( "The provided size is not a valid number because intval($provided_size) <= 0" );
problem( "91c54771bcf68f974c9aa8959f953dd8" );
}
if ( intval($provided_size) > 3000000000 ){
logextra( "The provided size is not a valid number because it's a lot larger than any show so far" );
problem( "8c085ec045b062e3a864e6fc22fceee4" );
}
$size = $provided_size;
logextra( "Found Valid \$size: $size" );
}
else {
logextra( "No size provided" );
problem( "a6d661c483c6d62d4df1df88a64118ce" );
exit;
}
// Check sha1sum
if ( isset( $asset['sha1sum'] ) ) {
$provided_sha1sum = $asset['sha1sum'];
$provided_sha1sum = filter_var($provided_sha1sum, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
if ( !preg_match('/^[0-9a-f]{40}$/i', $provided_sha1sum) ) {
logextra( "The format of the sha1sum is invalid $provided_sha1sum" );
problem( "e30c8db8a7e07ba69ef18f957f3e8843" );
}
$sha1sum = $provided_sha1sum;
logextra( "Found Valid \$sha1sum: $sha1sum" );
}
else {
logextra( "No sha1sum provided" );
problem( "cd3d303dbefec08016d567080116ef77" );
exit;
}
// Check mime_type
if ( isset( $asset['mime_type'] ) ) {
$provided_mime_type = $asset['mime_type'];
$provided_mime_type = filter_var($provided_mime_type, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
if ( !preg_match('/^[\w-]+\/[\w-]+(?:;\s*[\w-]+=[\w-]+)*$/i', $provided_mime_type) ) {
logextra( "The format of the mime_type is invalid \"$provided_mime_type\"" );
problem( "b36041a7d959730a9a541404db3b5025" );
}
list($content_type, $charset_type) = explode('; charset=', $provided_mime_type);
if ( !isset( $content_type ) ) {
logextra( "Can't find content_type in \"$provided_mime_type\"" );
problem( "c28ac580f5281ab2d97cbf052c92a25c" );
}
if ( empty( $content_type ) ) {
logextra( "Empty content_type in \"$provided_mime_type\"" );
problem( "fcec6e4039bc60daede3434e24c97a9f" );
}
if (!in_array( $content_type, $allowed_content_type, true )) {
logextra( "This content_type \"$content_type\", is not in the list of allowed_extensions" );
problem("4f29dcd2b3ef7efc5c4bc65be7a787ca");
}
if ( !isset( $charset_type ) ) {
logextra( "Can't find charset_type in \"$provided_mime_type\"" );
problem( "" );
}
if ( empty( $charset_type ) ) {
logextra( "Empty charset_type in \"$provided_mime_type\"" );
problem( "" );
}
$allowed_charset_type = array( "binary", "us-ascii", "utf-8");
if (!in_array( $charset_type, $allowed_charset_type, true )) {
logextra( "This charset_type \"$charset_type\", is not in the list of allowed_extensions" );
problem("");
}
$mime_type = $provided_mime_type;
logextra( "Found Valid \$mime_type: $mime_type" );
}
else {
logextra( "No mime_type provided" );
problem( "0c85eb982665a4978fea8f85611fbe88" );
exit;
}
// Check file_type
if ( isset( $asset['file_type'] ) ) {
$provided_file_type = $asset['file_type'];
$provided_file_type = filter_var($provided_file_type, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
if ( strlen($provided_file_type) < 5 ) {
logextra( "The length of \"$provided_file_type\" is less than 5" );
problem("60839aaddc82e0fbe4f5da269c361cf6");
}
if ( strlen($provided_file_type) > 140 ) {
logextra( "The length of \"$provided_file_type\" is greater than 140" );
problem("cafbb1b0c9955b92303fe34102890fa3");
}
$file_type = $provided_file_type;
logextra( "Found Valid \$file_type: $file_type" );
}
else {
logextra( "No file_type provided" );
problem( "a1b6a02d68533f9749da16164cbe704e" );
exit;
}
// Write values to db
//$episode_id is a number
$filename = mysqli_real_escape_string( $connection, $filename );
$extension = mysqli_real_escape_string( $connection, $extension );
//$size is a number
$sha1sum = mysqli_real_escape_string( $connection, $sha1sum );
$mime_type = mysqli_real_escape_string( $connection, $mime_type );
$file_type = mysqli_real_escape_string( $connection, $file_type );
$query_replace = "REPLACE INTO assets VALUES ('$episode_id','{$filename}','{$extension}','$size','{$sha1sum}','{$mime_type}','{$file_type}')";
$result = mysqli_query($connection, $query_replace );
if(!$result) {
problem("ERROR: DB problem - The asset for \"$episode_id\" with filename of \"$filename\" was not added to the eps db.");
}
else{
logextra( "mysql_query.result: \"$result\"\n" );
}
if (mysqli_errno( $connection )) {
$error = "MySQL error ".mysqli_errno( $connection ).": ".mysqli_error()."\n";
problem("ERROR: MySQL error- The asset for \"$episode_id\" with filename of \"$filename\" was not added to the eps db.\n$error");
}
logextra( "Finished ." );
}
http_response_code(200);
}
?>

View File

@ -1,11 +1,14 @@
<?php
require "/home/hpr/php/include.php";
date_default_timezone_set('UTC');
if (isset($_GET['id'])) {
$id = $_GET['id'];
$result = mysqli_query($connection, 'SELECT MAX(id) FROM eps;');
if (!isset($result)) {
die('Could not query:' . mysqli_error());
problem( "45f606ad99fe4fca7430b7b5bba1c681" );
die('Could not query:' . mysqli_error());
}
$maxhost_array = mysqli_fetch_row( $result );
$maxhost = $maxhost_array[0];
@ -14,26 +17,25 @@ if (isset($_GET['id'])) {
++$num_get_args;
}
if ( (strval(intval($id)) != strval($id)) OR ( intval($id) <= 0 ) OR ( intval($id) > $maxhost ) OR ( $num_get_args > 1 ) ){
exit;
problem( "ea860134910fecd136229e45262709d7" );
exit;
}
$query = "SELECT id FROM eps WHERE id = '$id'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
call412( "a9564ebc3289b7a14551baf8ad5ec60a" );
problem( "dc5b8dae7ea2a7e70ac0b7ea65ce2d12" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["id"]) ) {
call412( "a9564ebc3289b7a14551baf8ad5ec60a" );
problem( "2b6462ff2389405a796066dfc73ccf55" );
}
}
}
else {
call412( "a9564ebc3289b7a14551baf8ad5ec60a" );
problem( "ae1f3471af22d32d3bf2efc9130a00ae" );
exit;
}
Header('Content-type: text/tab-separated-values');
header("Content-disposition: inline; filename=say.txt");
$ep_retrieve = "SELECT
UNIX_TIMESTAMP(eps.date) AS timestamp,
@ -88,42 +90,62 @@ if ($result = mysqli_query($connection, $ep_retrieve)) {
}
}
}
$HPR_summary = "This is Hacker Public Radio episode $id for " . date("l", $date) . " the " . date("jS", $date) . " of " . date("F Y", $date) . ". Todays show is entitled. ${title}.";
else {
http_response_code(404);
die();
}
$synopsis = "This is Hacker Public Radio episode $id for " . date("l", $date) . " the " . date("jS", $date) . " of " . date("F Y", $date) . ". Todays show is entitled. ${title}.";
if ($series > "0"){
$series_query = mysqli_query($connection, "SELECT name, description FROM miniseries WHERE id = '$series'");
$series_result = mysqli_fetch_array($series_query);
$series_title = $series_result['name'];
$desc = $series_result['description'];
$HPR_summary = "${HPR_summary} It is part of the series \"$series_title\"";
$synopsis = "${synopsis} It is part of the series \"$series_title\"";
}
$HPR_summary = "${HPR_summary} ${host_notes} and is about " . round($duration/60) . " minutes long. It carries ";
$synopsis = "${synopsis} ${host_notes} and is about " . round($duration/60) . " minutes long. It carries ";
if ($explicit == 0) {
$HPR_summary = "${HPR_summary} a clean flag. ";
$synopsis = "${synopsis} a clean flag. ";
$explicit = "Clean";
}
else{
$HPR_summary = "${HPR_summary} an explicit flag. ";
$synopsis = "${synopsis} an explicit flag. ";
$explicit = "Explicit";
}
if ( !empty( $summary ) ) {
$HPR_summary = "${HPR_summary}. The summary is. $summary";
$synopsis = "${synopsis}. The summary is. $summary";
}
if (strcmp($license, "CC-BY-SA" ) !== 0) {
$HPR_summary = "${HPR_summary}. Todays show is licensed under a $license_long_name license.";
$synopsis = "${synopsis}. Todays show is licensed under a $license_long_name license.";
}
$HPR_summary = str_replace($host,$espeak_name,$HPR_summary);
$synopsis = str_replace($host,$espeak_name,$synopsis);
echo "HPR_summary: ${HPR_summary}\n";
echo "HPR_album: Hacker Public Radio\n";
echo "HPR_artist: ${host}\n";
echo "HPR_hostid: ${hostid}\n";
echo "HPR_comment: https://hackerpublicradio.org ${explicit}; $summary\n";
echo "HPR_genre: Podcast\n";
echo "HPR_license: ${license}\n";
echo "HPR_title: ${title}\n";
echo "HPR_track: $id\n";
echo "HPR_year: " . date("Y", $date) . "\n";
echo "HPR_duration: ${duration}\n";
echo "HPR_explicit: ${explicit}\n";
?>
// --------------------------------------------
// Display the results
$arr = array(
'genre' => "Podcast",
'album' => "Hacker Public Radio",
'track' => "$id",
'year' => date("Y", $date),
'date' => date("Y-m-d", $date),
'artist' => "${host}",
'hostid' => "${hostid}",
'title' => "${title}",
'duration' => "${duration}",
'license' => "${license}",
'explicit' => "${explicit}",
'summary' => "${summary}",
'comment' => "https://hackerpublicradio.org ${explicit}; $summary",
'synopsis' => "${synopsis}"
);
header('Content-Type: application/json');
header("Content-disposition: inline; filename=hpr_stats.json");
echo json_encode($arr);
mysqli_close($connection);

View File

@ -42,7 +42,7 @@ $current_episode_number = $current_episode_array[1];
// Populate array with future shows and reservations
$show_array = array ();
// REQUEST_UNVERIFIED → SHOW_SUBMITTED → METADATA_PROCESSED → SHOW_POSTED → MEDIA_TRANSCODED → UPLOADED_TO_IA → UPLOADED_TO_RSYNC_NET
// REQUEST_UNVERIFIED → SHOW_SUBMITTED → METADATA_PROCESSED → SHOW_POSTED → MEDIA_TRANSCODED → UPLOADED_TO_IA → UPLOADED_TO_CCDN
$ep_retrieve = "SELECT hosts.host, eps.id, eps.title, eps.date FROM eps, hosts WHERE eps.valid=1 AND eps.hostid = hosts.hostid AND eps.date >= '$current_episode_date' ORDER BY date DESC";
$ep_retrieve = "SELECT
@ -76,11 +76,12 @@ if ($result = mysqli_query($connection, $ep_retrieve)) {
$show_array[$id] = array ( "date" => date('Y-m-d', strtotime($date) ),
"title" => $title,
"host" => $host,
"status" => $status
"status" => $status,
"workflow" => $status
);
}
}
// REQUEST_UNVERIFIED → SHOW_SUBMITTED → METADATA_PROCESSED → SHOW_POSTED → MEDIA_TRANSCODED → UPLOADED_TO_IA → UPLOADED_TO_RSYNC_NET
// REQUEST_UNVERIFIED → SHOW_SUBMITTED → METADATA_PROCESSED → SHOW_POSTED → MEDIA_TRANSCODED → UPLOADED_TO_IA → UPLOADED_TO_CCDN
// Populate array with currently processing shows EMAIL_LINK_CLICKED
$ep_retrieve = "
@ -104,7 +105,8 @@ if ($result = mysqli_query($connection, $ep_retrieve)) {
$show_array[$id] = array ( "date" => date('Y-m-d', strtotime($date) ),
"title" => $status,
"host" => "Unverified",
"status" => "Processing"
"status" => "Processing",
"workflow" => $status
);
}
}
@ -122,7 +124,8 @@ if ($result = mysqli_query($connection, $ep_retrieve)) {
$show_array[$id] = array ( "date" => date('Y-m-d', strtotime($date) ),
"title" => " Available again in $minutes minutes",
"host" => "Unverified",
"status" => "Locked"
"status" => "Locked",
"workflow" => "Locked"
);
}
}
@ -153,7 +156,8 @@ if ($result = mysqli_query($connection, $ep_retrieve)) {
$show_array[$id] = array ( "date" => date('Y-m-d', strtotime($date) ),
"title" => $title,
"host" => $host,
"status" => "Finished"
"status" => "Finished",
"workflow" => "Finished"
);
}
}

126
cms/shownotes.php Normal file
View File

@ -0,0 +1,126 @@
<?php
require "/home/hpr/php/include.php";
date_default_timezone_set('UTC');
if (isset($_GET['id'])) {
$id = $_GET['id'];
$result = mysqli_query($connection, 'SELECT MAX(id) FROM eps;');
if (!isset($result)) {
problem( "d7f47a123af3ea10628ce44d2146b40e" );
die('Could not query:' . mysqli_error());
}
$maxhost_array = mysqli_fetch_row( $result );
$maxhost = $maxhost_array[0];
$num_get_args=0;
foreach($_GET as $k => $v) {
++$num_get_args;
}
if ( (strval(intval($id)) != strval($id)) OR ( intval($id) <= 0 ) OR ( intval($id) > $maxhost ) OR ( $num_get_args > 1 ) ){
problem( "5d45cb79dd9426e7e4ab5595ac647a62" );
exit;
}
$query = "SELECT id FROM eps WHERE id = '$id'";
$result = @mysqli_query($connection, $query);
if($result === FALSE) {
problem( "b26e5cea3779b66c76bf1c3c266e1a51" );
}
else {
$db = mysqli_fetch_array($result, MYSQLI_ASSOC);
if ( empty($db["id"]) ) {
problem( "a5d5eab30290ba4460ceb337add11821" );
}
}
}
else {
problem( "39122c23e90fcf5cb9ca9e03a5c5a3c5" );
exit;
}
$ep_retrieve = "SELECT
UNIX_TIMESTAMP(eps.date) AS timestamp,
eps.title,
eps.duration,
eps.summary,
eps.tags,
hosts.host,
hosts.email,
hosts.license as host_license,
hosts.profile,
eps.hostid,
eps.series,
eps.notes,
miniseries.name as series_name,
eps.license as show_license,
eps.explicit
FROM
eps
LEFT JOIN hosts ON eps.hostid = hosts.hostid
LEFT JOIN miniseries ON miniseries.id = eps.series
WHERE
hosts.valid = '1'
AND eps.id = '$id'";
if ($result = mysqli_query($connection, $ep_retrieve)) {
while ($row = mysqli_fetch_array($result)) {
$date = $row['timestamp'];
$title = $row['title'];
$duration = $row['duration'];
$summary = $row['summary'];
$host = $row['host'];
$hostid = $row['hostid'];
$host_email = $row['email'];
$host_license = $row['host_license'];
$host_profile = $row['profile'];
$series = $row['series'];
$series_name = $row['series_name'];
$show_license = $row['show_license'];
$explicit = $row['explicit'];
$tags = $row['tags'];
$notes = $row['notes'];
}
}
else {
http_response_code(404);
die();
}
if ($explicit == 0) {
$explicit = "Clean";
}
else{
$explicit = "Explicit";
}
// --------------------------------------------
// Display the results
$arr = array(
'host' => array (
'Host_ID' => "${hostid}",
'Host_Name' => "${host}",
'Host_Email' => "${host_email}",
'Host_License' => "${host_license}",
'Host_Profile' => "${host_profile}"
),
'episode' => array (
'Title' => "${title}",
'Summary' => "${summary}",
'Explicit' => "${explicit}",
'Show_License' => "${show_license}",
'Series' => "${series}",
'Series_Name' => "${series_name}",
'Tags' => "${tags}",
'Show_Notes' => "${notes}"
),
'metadata' => array (
'Episode_Number' => "${id}",
'Episode_Date' => date("Y-m-d", $date)
)
);
header('Content-Type: application/json');
header("Content-disposition: inline; filename=hpr_stats.json");
echo json_encode($arr);
mysqli_close($connection);

View File

@ -1,325 +1,133 @@
<?php
require "/home/hpr/php/include.php";
$format="json";
date_default_timezone_set('UTC');
if (isset($_GET['format'])){
if ($_GET['format'] === "txt") {
$format="txt";
}
if ($_GET['format'] === "json") {
$format="json";
}
if ($_GET['format'] === "xml") {
$format="xml";
}
if ($_GET['format'] === "csv") {
$format="csv";
}
$current_time = time();
$total_twt_shows = 300;
$twt_duration = 232812;
$start_date_twt = "2005-09-19";
$rename_date_hpr = "2007-12-31";
// --------------------------------------------
// Get the number of published shows
$ep_retrieve = "SELECT max(date) as latest_episode_release_date, max(id) as latest_episode_id from eps WHERE eps.date <= UTC_DATE();";
if ($result = mysqli_query($connection, $ep_retrieve)) {
$data=mysqli_fetch_assoc($result);
$latest_episode_release_date = $data['latest_episode_release_date'];
$latest_episode_id = intval( $data['latest_episode_id'] );
}
$twat_startdate = abs(strtotime(date("c")) - strtotime("2005-09-19T00:00:00Z"));
$twat_years = floor($twat_startdate / (365*60*60*24));
$twat_months = floor(($twat_startdate - $twat_years * 365*60*60*24) / (30*60*60*24));
$twat_days = floor(($twat_startdate - $twat_years * 365*60*60*24 - $twat_months*30*60*60*24)/ (60*60*24));
$agetwat = $twat_startdate;
// --------------------------------------------
// Shows in the Future Feed
$hpr_startdate = abs(strtotime(date("c")) - strtotime("2007-12-31T00:00:00Z"));
$hpr_years = floor($hpr_startdate / (365*60*60*24));
$hpr_months = floor(($hpr_startdate - $hpr_years * 365*60*60*24) / (30*60*60*24));
$hpr_days = floor(($hpr_startdate - $hpr_years * 365*60*60*24 - $hpr_months*30*60*60*24)/ (60*60*24));
$agehpr = $hpr_startdate;
$ep_retrieve = "SELECT COUNT( DISTINCT id ) as num_future_shows FROM eps WHERE eps.date > UTC_DATE() AND duration <> 0";
if ($result = mysqli_query($connection, $ep_retrieve)) {
$data=mysqli_fetch_assoc($result);
$num_future_shows = intval( $data['num_future_shows'] );
}
// --------------------------------------------
// Shows in the Reserve Queue
$last_show = mysqli_query($connection, "SELECT max(date), max(id) from eps");
$last_show_date = mysqli_fetch_row($last_show);
$totalshows=$last_show_date[1]+300;
$totalhpr=$last_show_date[1];
$ep_retrieve = "SELECT COUNT(*) as num_reserve_shows FROM reservations WHERE status='RESERVE_SHOW_SUBMITTED'";
if ($result = mysqli_query($connection, $ep_retrieve)) {
$data=mysqli_fetch_assoc($result);
$num_reserve_shows = intval( $data['num_reserve_shows'] );
}
// --------------------------------------------
// Get the number of hosts
$ep_retrieve = "SELECT hostid FROM hosts WHERE valid = '1' ORDER BY hostid ASC";
$num_of_hosts = "1";
$ep_retrieve = "SELECT COUNT( DISTINCT hostid ) as num_hosts FROM hosts WHERE valid = '1'";
if ($result = mysqli_query($connection, $ep_retrieve)) {
while ($row = mysqli_fetch_array($result)) {
$hostid = $row['hostid'];
$last_show = mysqli_query($connection, "SELECT max(date) from eps WHERE hostid='$hostid' AND valid = '1'");
$last_show_date = mysqli_fetch_row($last_show);
if (!empty($last_show_date[0])) {
$num_of_hosts++;
}
}
$data=mysqli_fetch_assoc($result);
$num_hosts = intval( $data['num_hosts'] );
}
// --------------------------------------------
// Get first free slot
// Get the next free slot
$query = mysqli_query($connection, "SELECT id + 1 FROM eps mo
WHERE NOT EXISTS
(
SELECT NULL
FROM eps mi
WHERE mi.id = mo.id + 1
)
ORDER BY
id
LIMIT 1");
$next_show_num_array = mysqli_fetch_row($query);
$next_show_num = $next_show_num_array[0];
$next_free_slot = "https://repo.anhonesthost.net/HPR/hpr_hub/issues/71";
// --------------------------------------------
// Get latest published show
$query = mysqli_query($connection, "SELECT max(date), max(id) from eps WHERE eps.date <= UTC_DATE()");
$current_episode_array = mysqli_fetch_row($query);
$current_episode_date = $current_episode_array[0];
$current_episode_number = $current_episode_array[1];
// --------------------------------------------
// Populate array with future shows
$un_delivered = -1;
$days_to_undelivered = 0;
$show_array = array ();
$ep_retrieve = "SELECT hosts.host, eps.id, eps.title, eps.date FROM eps, hosts WHERE eps.valid=1 AND eps.hostid = hosts.hostid AND eps.date >= '$current_episode_date' ORDER BY date DESC";
// playtime
$ep_retrieve = "SELECT SUM(duration) as total_playtime_all_hpr_shows_seconds FROM `eps`";
if ($result = mysqli_query($connection, $ep_retrieve)) {
while ($row = mysqli_fetch_array($result)) {
$id = $row['id'];
$id = fixid($id);
$date = $row['date'];
$title = $row['title'];
$host = $row['host'];
if ( file_exists("./eps/hpr$id.ogg") and file_exists("./eps/hpr$id.spx") and file_exists("./eps/hpr$id.mp3") ) {
$delivered = 1;
if ($un_delivered === -1 ) {
$days_to_undelivered++;
}
}
else {
$delivered = 0;
$un_delivered = $days_to_undelivered;
}
$show_array[$id] = array ( "date" => $date,
"title" => $title,
"host" => $host,
"delivered" => $delivered
);
}
$data=mysqli_fetch_assoc($result);
$total_playtime_all_hpr_shows_seconds = intval( $data['total_playtime_all_hpr_shows_seconds'] );
$total_playtime_all_shows_seconds = $twt_duration + $total_playtime_all_hpr_shows_seconds;
}
// --------------------------------------------
// Calculate the time to the next show
$next_show_date = date('Y-m-d', strtotime($show_array[$next_show_num - 1 ]["date"] . ' + 1 weekday'));
$days_to_wait = floor((strtotime($next_show_date) - strtotime(gmdate('Y-m-d')))/(60*60*24));
$total_playtime_all_shows_human_readable = convertSecToTime( $total_playtime_all_shows_seconds );
// --------------------------------------------
// Future Hosts
$ep_retrieve = "SELECT DISTINCT hostid FROM eps WHERE eps.date > UTC_DATE()";
// Comments
// $ep_retrieve = "SELECT id, type, date, title, notes, host, hostid FROM eps WHERE valid = '1' ORDER BY id DESC LIMIT 10";
if ($result = mysqli_query($connection, $ep_retrieve)) {
$num_future_hosts = mysqli_num_rows($result);
}
// --------------------------------------------
// Shows in the Queue
$ep_retrieve = "SELECT DISTINCT id FROM eps WHERE eps.date > UTC_DATE() AND duration <> 0";
// $ep_retrieve = "SELECT id, type, date, title, notes, host, hostid FROM eps WHERE valid = '1' ORDER BY id DESC LIMIT 10";
if ($result = mysqli_query($connection, $ep_retrieve)) {
$num_future_shows = mysqli_num_rows($result);
}
// --------------------------------------------
// Shows in the Queue
$result=mysqli_query($connection, "SELECT count(*) as total FROM `reservations` WHERE `status` LIKE 'SHOW_SUBMITTED' ORDER BY `ip` ASC ");
$data=mysqli_fetch_assoc($result);
$num_submitted_shows = $data['total'];
// --------------------------------------------
// Duration of all shows
$result=mysqli_query($connection, "SELECT SUM(duration) as total_duration FROM `eps`");
$data=mysqli_fetch_assoc($result);
$total_duration = $data['total_duration'];
$human_total_duration = convertSecToTime($total_duration);
// --------------------------------------------
// Reserve Shows
$result = mysqli_query($connection, 'SELECT COUNT(*) FROM reservations WHERE status="RESERVE_SHOW_SUBMITTED";');
if (!isset($result)) {
naughty("cac33babd8a24edd138087ef7e4280f6");
}
$reserve_array = mysqli_fetch_row( $result );
$reserve_shows = $reserve_array[0];
mysqli_free_result($result);
// --------------------------------------------
// workflow
$ep_retrieve = "SELECT status, COUNT(*) AS total FROM reservations WHERE status != 'RESERVE_SHOW_SUBMITTED' GROUP BY status;";
$workflow="\"workflow\": {";
if ($result = mysqli_query($connection, $ep_retrieve)) {
while ($row = mysqli_fetch_array($result)) {
$status = $row['status'];
$total = $row['total'];
$workflow=$workflow."
\"$status\": \"$total\",";
}
}
$workflow=$workflow."
\"RESERVE_SHOW_SUBMITTED\": \"$reserve_shows\"
},";
// --------------------------------------------
// duration
$result=mysqli_query($connection, "SELECT SUM(duration) as total_duration FROM `eps`");
$data=mysqli_fetch_assoc($result);
$total_duration = $data['total_duration'];
$human_total_duration = convertSecToTime($total_duration);
// --------------------------------------------
// Unprocessed comments
$comment_directory = "/home/hpr/comments";
$unprocessed_comments = iterator_count(new FilesystemIterator("$comment_directory", FilesystemIterator::SKIP_DOTS));
// --------------------------------------------
// Shows on the FTP server
// Calculations
$new_shows=0;
if ($handle = opendir('/home/hpr/upload')) {
while (false !== ($entry = readdir($handle))) {
if ( $entry != "." && $entry != "..") {
$new_shows++;
}
$total_released_shows = $latest_episode_id + $total_twt_shows;
$total_submitted_shows = $latest_episode_id + $total_twt_shows + $num_future_shows + $num_reserve_shows;
$project_age_seconds = strtotime( $start_date_twt ) - $current_time;
$project_age = convertSecToTime( $project_age_seconds );
// --------------------------------------------
// Display the workflow
$workflow = array();
$ep_retrieve = "SELECT status, COUNT(*) AS total FROM reservations WHERE status != 'RESERVE_SHOW_SUBMITTED' GROUP BY status;";
if ($result = mysqli_query($connection, $ep_retrieve)) {
while ($row = mysqli_fetch_array($result)) {
$workflow[ $row['status'] ] = $row['total'];
}
closedir($handle);
}
// --------------------------------------------
// Produce output
// Shows in the Reserve Queue
$current_time = time();
$ep_retrieve = "SELECT COUNT(*) AS num_unprocessed_shows FROM reservations WHERE status!='RESERVE_SHOW_SUBMITTED' AND status!='REQUEST_UNVERIFIED'";
if ($result = mysqli_query($connection, $ep_retrieve)) {
$data=mysqli_fetch_assoc($result);
$num_unprocessed_shows = intval( $data['num_unprocessed_shows'] );
}
// --------------------------------------------
// Display the results
$arr = array(
'stats_generated' => $current_time,
'start_date_twt' => $start_date_twt,
'rename_date_hpr' => $rename_date_hpr,
'latest_episode_release_date' => $latest_episode_release_date,
'project_age' => $project_age,
'latest_episode_id' => $latest_episode_id,
'total_twt_shows' => $total_twt_shows,
'total_released_shows' => $total_released_shows,
'num_future_shows' => $num_future_shows,
'num_reserve_shows' => $num_reserve_shows,
'total_submitted_shows' => $total_submitted_shows,
'num_hosts' => $num_hosts,
'days_to_next_free_slot' => "todo",
'total_playtime_all_shows_seconds' => $total_playtime_all_shows_seconds,
'total_playtime_all_shows_human_readable' => $total_playtime_all_shows_human_readable,
'next_free_slot' => $next_free_slot,
'unprocessed_comments' => $unprocessed_comments,
'num_unprocessed_shows' => $num_unprocessed_shows,
'show_processing_workflow' => $workflow
);
header('Content-Type: application/json');
header("Content-disposition: inline; filename=hpr_stats.json");
echo json_encode($arr);
if ($format === "json") {
header('Content-Type: application/json');
header("Content-disposition: inline; filename=hpr_stats.json");
echo "{
\"stats_generated\": ".$current_time.",
\"age\": {
\"start\": \"2005-09-19T00:00:00Z\",
\"rename\": \"2007-12-31T00:00:00Z\",
\"since_start\": {
\"total_seconds\": ".$agetwat.",
\"years\": ".$twat_years.",
\"months\": ".$twat_months.",
\"days\": ".$twat_days."
},
\"since_rename\": {
\"total_seconds\": ".$agehpr.",
\"years\": ".$hpr_years.",
\"months\": ".$hpr_months.",
\"days\": ".$hpr_days."
}
},
\"shows\": {
\"total\": ".$totalshows.",
\"twat\": 300,
\"hpr\": ".$totalhpr.",
\"duration\": ".$total_duration.",
\"human_duration\": \"".$human_total_duration."\"
},
\"hosts\": ".$num_of_hosts.",
\"slot\": {
\"next_free\": ".$days_to_wait.",
\"no_media\": ".$un_delivered."
},
$workflow
\"queue\": {
\"number_future_hosts\": ".$num_future_hosts.",
\"number_future_shows\": ".$num_future_shows.",
\"unprocessed_comments\": ".$unprocessed_comments.",
\"submitted_shows\": ".$num_submitted_shows.",
\"shows_in_workflow\": ".$new_shows.",
\"reserve\": ".$reserve_shows."
}
}
";
}
elseif ($format === "xml") {
header("Content-type: application/xml");
header("Content-disposition: inline; filename=hpr_stats.xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
<stats>
<stats_generated>".$current_time."</stats_generated>
<age>
<start>2005-09-19T00:00:00Z</start>
<rename>2007-12-31T00:00:00Z</rename>
<since_start>
<total_seconds>".$agetwat."</total_seconds>
<years>". $twat_years."</years>
<months>".$twat_months."</months>
<days>".$twat_days."</days>
</since_start>
<since_rename>
<total_seconds>".$agehpr."</total_seconds>
<years>".$hpr_years."</years>
<months>".$hpr_months."</months>
<days>".$hpr_days."</days>
</since_rename>
</age>
<shows>
<total>".$totalshows."</total>
<twat>300</twat>
<hpr>".$totalhpr."</hpr>
<duration>".$total_duration."</duration>
<human_duration>".$human_total_duration."</human_duration>
</shows>
<hosts>".$num_of_hosts."</hosts>
<slot>
<next_free>".$days_to_wait."</next_free>
<no_media>".$un_delivered."</no_media>
</slot>
<queue>
<number_future_hosts>".$num_future_hosts."</number_future_hosts>
<number_future_shows>".$num_future_shows."</number_future_shows>
<unprocessed_comments>".$unprocessed_comments."</unprocessed_comments>
<submitted_shows>".$num_submitted_shows."</submitted_shows>
<shows_in_workflow>".$new_shows."</shows_in_workflow>
<reserve>".$reserve_shows."</reserve>
</queue>
</stats>";
}
elseif ($format === "csv") {
header("Content-type: text/csv");
header("Content-disposition: inline; filename=hpr_stats.csv");
print "stats_generated,age_start,age_rename,age_since_start_total_seconds,age_since_start_years,age_since_start_months,age_since_start_days,age_since_rename_total_seconds,age_since_rename_years,age_since_rename_months,age_since_rename_days,shows_total,shows_twat,shows_hpr,hosts,slot_next_free,slot_no_media,number_future_hosts,number_future_shows,unprocessed_comments,shows_in_workflow,queue_reserve,duration\n";
print "${current_time},2005-09-19T00:00:00Z,2007-12-31T00:00:00Z,${agetwat},${twat_years},${twat_months},${twat_days},${agehpr},${hpr_years},${hpr_months},${hpr_days},${totalshows},300,${totalhpr},${num_of_hosts},${days_to_wait},${un_delivered},${num_future_hosts},${num_future_shows},${unprocessed_comments},${new_shows},${reserve_shows},${total_duration}\n";
}
else {
Header('Content-type: text/tab-separated-values');
header("Content-disposition: inline; filename=hpr_stats.txt");
printf("Started:\t%d years, %d months, %d days ago (2005-09-19)\n", $twat_years, $twat_months, $twat_days);
printf("Renamed HPR:\t%d years, %d months, %d days ago (2007-12-31)\n", $hpr_years, $hpr_months, $hpr_days);
echo "Total Shows:\t" . $totalshows . "\n";
echo "Total TWAT:\t300\n";
echo "Total HPR:\t" . $totalhpr . "\n";
echo "Duration:\t" . $total_duration . "\n";
echo "Human Duration:\t" . $human_total_duration . "\n";
echo "HPR Hosts:\t${num_of_hosts}\n";
echo "Days to next free slot:\t${days_to_wait}\n";
echo "Hosts in Queue:\t$num_future_hosts\n";
echo "Shows in Queue:\t$num_future_shows\n";
echo "Comments waiting approval:\t$unprocessed_comments\n";
echo "Files on the FTP Server:\t$new_shows\n";
echo "Number of Reserve Shows:\t$reserve_shows\n";
echo "Days until show without media:\t$un_delivered\n";
print "$current_time,$agetwat,$agehpr,$totalshows,300,$totalhpr,$num_of_hosts,$days_to_wait,$num_future_hosts,$num_future_shows,$unprocessed_comments,$new_shows,$reserve_shows,$un_delivered";
// print_r($show_array);
}
mysqli_close($connection);
?>

View File

@ -267,6 +267,17 @@ There are only <strong><?php echo "${days_to_wait}"; ?></strong> days to wait un
<li>Then <a aria-label="Help on Adding an episode" href="<?php echo "${baseurl}about.html#adding_an_episode"; ?>">fill in a form</a>.</li>
</ol>
<h2 id="scheduling_guidelines">Scheduling Guidelines</h2>
<ol>
<li>You must have your audio recording ready to upload <strong>before</strong> you pick a slot.</li>
<li>New hosts, Interviews, and other time critical shows should use the first free slot.</li>
<li>Always try and fill any free slots that are available in the <strong>upcoming two weeks</strong>.</li>
<li>When the queue is filling up then leave some slots free for new contributors.</li>
<li>Post non urgent shows into the first empty week.</li>
<li>If you are uploading a series of shows then post them one every two weeks.</li>
<li>If you have a non urgent show that is timeless, then add it to the <a href="https://hackerpublicradio.org/about.html#reserve_queue">Reserve Queue</a>.</li>
</ol>
<h2 id="reserve_queue">Add to the Reserve Queue ?</h2>
<p>

106
hub/ccdn.php Normal file
View File

@ -0,0 +1,106 @@
<?php
# request.php > request_confirm.php > upload.php > upload_confirm.php
## Recent Changes
# Support multiple mirrors
require "/home/hpr/php/include.php";
$ip = $_SERVER["REMOTE_ADDR"];
if ( $_SERVER['REQUEST_METHOD'] !== 'GET' && $_SERVER['REQUEST_METHOD'] !== 'HEAD' ) {
naughty("34522f7b9ba88b319afa9f063b98905c");
}
if ( empty($_SERVER["REMOTE_ADDR"]) ) {
naughty("021dbd5f91f40918ea68fd0ca1a2e381");
}
if ( count($_GET) !== 1 ) {
naughty("f5df1c0d9accb7868e601b60cf2f5c06");
}
if ( isset($_GET["filename"]) ) {
$filename = $_GET["filename"];
if ( empty($filename) ) {
naughty("ef50f1353583f371903daba3abc9b3a4");
}
$filename = filter_var($filename, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
$dirname = dirname("$filename", 2);
if ( empty($dirname) ) {
naughty("71b6b14eef459e0404311257dad8ffe4");
}
if ( $dirname === "/" ) {
naughty("9e342e30b911e1ac3c5e831a6da6116b");
}
if ( !(
strcmp($dirname, "/correspondents") === 0 or
strcmp($dirname, "/eps") === 0 or
strcmp($dirname, "/series") === 0 )
) {
naughty("f157a8f5fedc7282c7a6469931223dbf");
}
$name = basename($filename); // To get file name
if ( empty($name) ) {
naughty("27ece7c2dba5caa5885ef40737270fd3");
}
$ext = pathinfo($filename, PATHINFO_EXTENSION); // To get extension
if ( empty($ext) ) {
naughty("c6a4329fe2f3c2c739ec666e956c2c5f");
}
$prefix = pathinfo($filename, PATHINFO_FILENAME); // File name without extension
if ( empty($prefix) ) {
naughty("f398399ec10ec9ab4b5b23ae43f21b01");
}
if ( strlen($filename) < 5 ) {
naughty("f78bf180af9239fc7fcf5fbc2b13b59b");
}
if ( strlen($filename) > 60 ) {
naughty("38e9a0cf7f650ac62e75c08269c9d913");
}
if (!in_array( $ext, $allowed_extensions, true )) {
logextra( "This extension $this_ext, is not in the list of allowed_extensions" );
naughty("545e49f7ac913863c6c3db40670ebb9d");
}
}
else {
naughty("0b78322e1c5010ba289c20250ca1fb1f");
}
if (
strcmp($dirname, "/eps") === 0 and
in_array( $ext, $allowed_extensions_common, true )
) {
$mirrors = array_merge($ccdn_hosts_common, $ccdn_hosts_complete);
}
else {
$mirrors = $ccdn_hosts_complete;
}
$mirror = 'https://' . $mirrors[ array_rand($mirrors, 1) ];
$pos = strpos($mirror, 'archive.org');
if ($pos !== false) {
$path = $mirror . '/download/' . $prefix . '/' . $name;
} else {
$path = $mirror . $filename;
}
logextra( "Sending request to ${path}" );
header("location:${path}");
?>

View File

@ -25,8 +25,6 @@ if (strcasecmp('public', $_POST["anti_spam_question"]) !== 0) {
naughty("6aef421ce05e3ac34f4cd91ae3248a45");
}
$comment_directory = "/home/hpr/comments";
if ( ! file_exists( $comment_directory ) ) {
# Looks like the comments directory has not been created
naughty("d5342ea497f701656433e81fb5eed064");
@ -273,7 +271,7 @@ $mailer->addBCC('admin@hobbypublicradio.org');
$mailer->AddAddress('comments@hackerpublicradio.org');
$mailer->isHTML(false);
$mailer->Subject = "New Comment for show hpr${eps_id} on ${ep_date} ${key}";
$mailer->MsgHTML("<p>hpr${eps_id} on ${ep_date} by ${host} with the title <strong>${title}</strong> \"${summary}\"</p>
$mailer->MsgHTML("<p><a href=\"https://hackerpublicradio.org/eps/hpr${eps_id}\">hpr${eps_id}</a> on ${ep_date} by ${host} with the title <strong>${title}</strong> \"${summary}\"</p>
<p>
See attachment for the json comment file.
</p>
@ -318,6 +316,8 @@ $justification
);
$mailer->AltBody = "hpr${eps_id} on ${ep_date} by ${host} with the title ${title} \"${summary}\"</p>
https://hackerpublicradio.org/eps/hpr${eps_id}
See attachment for the json comment file.
There are now ${unprocessed_comments} unprocessed comments.

11596
hub/quill.js Normal file

File diff suppressed because it is too large Load Diff

980
hub/quill.snow.css Normal file
View File

@ -0,0 +1,980 @@
/*!
* Quill Editor v1.3.7
* https://quilljs.com/
* Copyright (c) 2014, Jason Chen
* Copyright (c) 2013, salesforce.com
*
*
*/
/*
Copyright (c) 2017-2024, Slab
Copyright (c) 2014, Jason Chen
Copyright (c) 2013, salesforce.com
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
.ql-container {
box-sizing: border-box;
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
height: 100%;
margin: 0px;
position: relative;
}
.ql-container.ql-disabled .ql-tooltip {
visibility: hidden;
}
.ql-container.ql-disabled .ql-editor ul[data-checked] > li::before {
pointer-events: none;
}
.ql-clipboard {
left: -100000px;
height: 1px;
overflow-y: hidden;
position: absolute;
top: 50%;
}
.ql-clipboard p {
margin: 0;
padding: 0;
}
.ql-editor {
box-sizing: border-box;
line-height: 1.42;
height: 100%;
outline: none;
overflow-y: auto;
padding: 12px 15px;
tab-size: 4;
-moz-tab-size: 4;
text-align: left;
white-space: pre-wrap;
word-wrap: break-word;
}
.ql-editor > * {
cursor: text;
}
.ql-editor p,
.ql-editor ol,
.ql-editor ul,
.ql-editor pre,
.ql-editor blockquote,
.ql-editor h1,
.ql-editor h2,
.ql-editor h3,
.ql-editor h4,
.ql-editor h5,
.ql-editor h6 {
margin: 0;
padding: 0;
counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol,
.ql-editor ul {
padding-left: 1.5em;
}
.ql-editor ol > li,
.ql-editor ul > li {
list-style-type: none;
}
.ql-editor ul > li::before {
content: '\2022';
}
.ql-editor ul[data-checked=true],
.ql-editor ul[data-checked=false] {
pointer-events: none;
}
.ql-editor ul[data-checked=true] > li *,
.ql-editor ul[data-checked=false] > li * {
pointer-events: all;
}
.ql-editor ul[data-checked=true] > li::before,
.ql-editor ul[data-checked=false] > li::before {
color: #777;
cursor: pointer;
pointer-events: all;
}
.ql-editor ul[data-checked=true] > li::before {
content: '\2611';
}
.ql-editor ul[data-checked=false] > li::before {
content: '\2610';
}
.ql-editor li::before {
display: inline-block;
white-space: nowrap;
width: 1.2em;
}
.ql-editor li:not(.ql-direction-rtl)::before {
margin-left: -1.5em;
margin-right: 0.3em;
text-align: right;
}
.ql-editor li.ql-direction-rtl::before {
margin-left: 0.3em;
margin-right: -1.5em;
}
.ql-editor ol li:not(.ql-direction-rtl),
.ql-editor ul li:not(.ql-direction-rtl) {
padding-left: 1.5em;
}
.ql-editor ol li.ql-direction-rtl,
.ql-editor ul li.ql-direction-rtl {
padding-right: 1.5em;
}
.ql-editor ol li {
counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
counter-increment: list-0;
}
.ql-editor ol li:before {
content: counter(list-0, decimal) '. ';
}
.ql-editor ol li.ql-indent-1 {
counter-increment: list-1;
}
.ql-editor ol li.ql-indent-1:before {
content: counter(list-1, lower-alpha) '. ';
}
.ql-editor ol li.ql-indent-1 {
counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-2 {
counter-increment: list-2;
}
.ql-editor ol li.ql-indent-2:before {
content: counter(list-2, lower-roman) '. ';
}
.ql-editor ol li.ql-indent-2 {
counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-3 {
counter-increment: list-3;
}
.ql-editor ol li.ql-indent-3:before {
content: counter(list-3, decimal) '. ';
}
.ql-editor ol li.ql-indent-3 {
counter-reset: list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-4 {
counter-increment: list-4;
}
.ql-editor ol li.ql-indent-4:before {
content: counter(list-4, lower-alpha) '. ';
}
.ql-editor ol li.ql-indent-4 {
counter-reset: list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-5 {
counter-increment: list-5;
}
.ql-editor ol li.ql-indent-5:before {
content: counter(list-5, lower-roman) '. ';
}
.ql-editor ol li.ql-indent-5 {
counter-reset: list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-6 {
counter-increment: list-6;
}
.ql-editor ol li.ql-indent-6:before {
content: counter(list-6, decimal) '. ';
}
.ql-editor ol li.ql-indent-6 {
counter-reset: list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-7 {
counter-increment: list-7;
}
.ql-editor ol li.ql-indent-7:before {
content: counter(list-7, lower-alpha) '. ';
}
.ql-editor ol li.ql-indent-7 {
counter-reset: list-8 list-9;
}
.ql-editor ol li.ql-indent-8 {
counter-increment: list-8;
}
.ql-editor ol li.ql-indent-8:before {
content: counter(list-8, lower-roman) '. ';
}
.ql-editor ol li.ql-indent-8 {
counter-reset: list-9;
}
.ql-editor ol li.ql-indent-9 {
counter-increment: list-9;
}
.ql-editor ol li.ql-indent-9:before {
content: counter(list-9, decimal) '. ';
}
.ql-editor .ql-indent-1:not(.ql-direction-rtl) {
padding-left: 3em;
}
.ql-editor li.ql-indent-1:not(.ql-direction-rtl) {
padding-left: 4.5em;
}
.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right {
padding-right: 3em;
}
.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right {
padding-right: 4.5em;
}
.ql-editor .ql-indent-2:not(.ql-direction-rtl) {
padding-left: 6em;
}
.ql-editor li.ql-indent-2:not(.ql-direction-rtl) {
padding-left: 7.5em;
}
.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right {
padding-right: 6em;
}
.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right {
padding-right: 7.5em;
}
.ql-editor .ql-indent-3:not(.ql-direction-rtl) {
padding-left: 9em;
}
.ql-editor li.ql-indent-3:not(.ql-direction-rtl) {
padding-left: 10.5em;
}
.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right {
padding-right: 9em;
}
.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right {
padding-right: 10.5em;
}
.ql-editor .ql-indent-4:not(.ql-direction-rtl) {
padding-left: 12em;
}
.ql-editor li.ql-indent-4:not(.ql-direction-rtl) {
padding-left: 13.5em;
}
.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right {
padding-right: 12em;
}
.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right {
padding-right: 13.5em;
}
.ql-editor .ql-indent-5:not(.ql-direction-rtl) {
padding-left: 15em;
}
.ql-editor li.ql-indent-5:not(.ql-direction-rtl) {
padding-left: 16.5em;
}
.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right {
padding-right: 15em;
}
.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right {
padding-right: 16.5em;
}
.ql-editor .ql-indent-6:not(.ql-direction-rtl) {
padding-left: 18em;
}
.ql-editor li.ql-indent-6:not(.ql-direction-rtl) {
padding-left: 19.5em;
}
.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right {
padding-right: 18em;
}
.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right {
padding-right: 19.5em;
}
.ql-editor .ql-indent-7:not(.ql-direction-rtl) {
padding-left: 21em;
}
.ql-editor li.ql-indent-7:not(.ql-direction-rtl) {
padding-left: 22.5em;
}
.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right {
padding-right: 21em;
}
.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right {
padding-right: 22.5em;
}
.ql-editor .ql-indent-8:not(.ql-direction-rtl) {
padding-left: 24em;
}
.ql-editor li.ql-indent-8:not(.ql-direction-rtl) {
padding-left: 25.5em;
}
.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right {
padding-right: 24em;
}
.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right {
padding-right: 25.5em;
}
.ql-editor .ql-indent-9:not(.ql-direction-rtl) {
padding-left: 27em;
}
.ql-editor li.ql-indent-9:not(.ql-direction-rtl) {
padding-left: 28.5em;
}
.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right {
padding-right: 27em;
}
.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right {
padding-right: 28.5em;
}
.ql-editor .ql-video {
display: block;
max-width: 100%;
}
.ql-editor .ql-video.ql-align-center {
margin: 0 auto;
}
.ql-editor .ql-video.ql-align-right {
margin: 0 0 0 auto;
}
.ql-editor .ql-bg-black {
background-color: #000;
}
.ql-editor .ql-bg-red {
background-color: #e60000;
}
.ql-editor .ql-bg-orange {
background-color: #f90;
}
.ql-editor .ql-bg-yellow {
background-color: #ff0;
}
.ql-editor .ql-bg-green {
background-color: #008a00;
}
.ql-editor .ql-bg-blue {
background-color: #06c;
}
.ql-editor .ql-bg-purple {
background-color: #93f;
}
.ql-editor .ql-color-white {
color: #fff;
}
.ql-editor .ql-color-red {
color: #e60000;
}
.ql-editor .ql-color-orange {
color: #f90;
}
.ql-editor .ql-color-yellow {
color: #ff0;
}
.ql-editor .ql-color-green {
color: #008a00;
}
.ql-editor .ql-color-blue {
color: #06c;
}
.ql-editor .ql-color-purple {
color: #93f;
}
.ql-editor .ql-font-serif {
font-family: Georgia, Times New Roman, serif;
}
.ql-editor .ql-font-monospace {
font-family: Monaco, Courier New, monospace;
}
.ql-editor .ql-size-small {
font-size: 0.75em;
}
.ql-editor .ql-size-large {
font-size: 1.5em;
}
.ql-editor .ql-size-huge {
font-size: 2.5em;
}
.ql-editor .ql-direction-rtl {
direction: rtl;
text-align: inherit;
}
.ql-editor .ql-align-center {
text-align: center;
}
.ql-editor .ql-align-justify {
text-align: justify;
}
.ql-editor .ql-align-right {
text-align: right;
}
.ql-editor.ql-blank::before {
color: rgba(0,0,0,0.6);
content: attr(data-placeholder);
font-style: italic;
left: 15px;
pointer-events: none;
position: absolute;
right: 15px;
}
.ql-snow.ql-toolbar:after,
.ql-snow .ql-toolbar:after {
clear: both;
content: '';
display: table;
}
.ql-snow.ql-toolbar button,
.ql-snow .ql-toolbar button {
background: none;
border: none;
cursor: pointer;
display: inline-block;
float: left;
height: 24px;
padding: 3px 5px;
width: 28px;
}
.ql-snow.ql-toolbar button svg,
.ql-snow .ql-toolbar button svg {
float: left;
height: 100%;
}
.ql-snow.ql-toolbar button:active:hover,
.ql-snow .ql-toolbar button:active:hover {
outline: none;
}
.ql-snow.ql-toolbar input.ql-image[type=file],
.ql-snow .ql-toolbar input.ql-image[type=file] {
display: none;
}
.ql-snow.ql-toolbar button:hover,
.ql-snow .ql-toolbar button:hover,
.ql-snow.ql-toolbar button:focus,
.ql-snow .ql-toolbar button:focus,
.ql-snow.ql-toolbar button.ql-active,
.ql-snow .ql-toolbar button.ql-active,
.ql-snow.ql-toolbar .ql-picker-label:hover,
.ql-snow .ql-toolbar .ql-picker-label:hover,
.ql-snow.ql-toolbar .ql-picker-label.ql-active,
.ql-snow .ql-toolbar .ql-picker-label.ql-active,
.ql-snow.ql-toolbar .ql-picker-item:hover,
.ql-snow .ql-toolbar .ql-picker-item:hover,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected {
color: #06c;
}
.ql-snow.ql-toolbar button:hover .ql-fill,
.ql-snow .ql-toolbar button:hover .ql-fill,
.ql-snow.ql-toolbar button:focus .ql-fill,
.ql-snow .ql-toolbar button:focus .ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill {
fill: #06c;
}
.ql-snow.ql-toolbar button:hover .ql-stroke,
.ql-snow .ql-toolbar button:hover .ql-stroke,
.ql-snow.ql-toolbar button:focus .ql-stroke,
.ql-snow .ql-toolbar button:focus .ql-stroke,
.ql-snow.ql-toolbar button.ql-active .ql-stroke,
.ql-snow .ql-toolbar button.ql-active .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow.ql-toolbar button:hover .ql-stroke-miter,
.ql-snow .ql-toolbar button:hover .ql-stroke-miter,
.ql-snow.ql-toolbar button:focus .ql-stroke-miter,
.ql-snow .ql-toolbar button:focus .ql-stroke-miter,
.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter {
stroke: #06c;
}
@media (pointer: coarse) {
.ql-snow.ql-toolbar button:hover:not(.ql-active),
.ql-snow .ql-toolbar button:hover:not(.ql-active) {
color: #444;
}
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill {
fill: #444;
}
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter {
stroke: #444;
}
}
.ql-snow {
box-sizing: border-box;
}
.ql-snow * {
box-sizing: border-box;
}
.ql-snow .ql-hidden {
display: none;
}
.ql-snow .ql-out-bottom,
.ql-snow .ql-out-top {
visibility: hidden;
}
.ql-snow .ql-tooltip {
position: absolute;
transform: translateY(10px);
}
.ql-snow .ql-tooltip a {
cursor: pointer;
text-decoration: none;
}
.ql-snow .ql-tooltip.ql-flip {
transform: translateY(-10px);
}
.ql-snow .ql-formats {
display: inline-block;
vertical-align: middle;
}
.ql-snow .ql-formats:after {
clear: both;
content: '';
display: table;
}
.ql-snow .ql-stroke {
fill: none;
stroke: #444;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2;
}
.ql-snow .ql-stroke-miter {
fill: none;
stroke: #444;
stroke-miterlimit: 10;
stroke-width: 2;
}
.ql-snow .ql-fill,
.ql-snow .ql-stroke.ql-fill {
fill: #444;
}
.ql-snow .ql-empty {
fill: none;
}
.ql-snow .ql-even {
fill-rule: evenodd;
}
.ql-snow .ql-thin,
.ql-snow .ql-stroke.ql-thin {
stroke-width: 1;
}
.ql-snow .ql-transparent {
opacity: 0.4;
}
.ql-snow .ql-direction svg:last-child {
display: none;
}
.ql-snow .ql-direction.ql-active svg:last-child {
display: inline;
}
.ql-snow .ql-direction.ql-active svg:first-child {
display: none;
}
.ql-snow .ql-editor h1 {
font-size: 2em;
}
.ql-snow .ql-editor h2 {
font-size: 1.5em;
}
.ql-snow .ql-editor h3 {
font-size: 1.17em;
}
.ql-snow .ql-editor h4 {
font-size: 1em;
}
.ql-snow .ql-editor h5 {
font-size: 0.83em;
}
.ql-snow .ql-editor h6 {
font-size: 0.67em;
}
.ql-snow .ql-editor a {
text-decoration: underline;
}
.ql-snow .ql-editor blockquote {
border-left: 4px solid #ccc;
margin-bottom: 5px;
margin-top: 5px;
padding-left: 16px;
}
.ql-snow .ql-editor code,
.ql-snow .ql-editor pre {
background-color: #f0f0f0;
border-radius: 3px;
}
.ql-snow .ql-editor pre {
white-space: pre-wrap;
margin-bottom: 5px;
margin-top: 5px;
padding: 5px 10px;
}
.ql-snow .ql-editor code {
font-size: 85%;
padding: 2px 4px;
}
.ql-snow .ql-editor pre.ql-syntax {
background-color: #23241f;
color: #f8f8f2;
overflow: visible;
}
.ql-snow .ql-editor img {
max-width: 100%;
}
.ql-snow .ql-picker {
color: #444;
display: inline-block;
float: left;
font-size: 14px;
font-weight: 500;
height: 24px;
position: relative;
vertical-align: middle;
}
.ql-snow .ql-picker-label {
cursor: pointer;
display: inline-block;
height: 100%;
padding-left: 8px;
padding-right: 2px;
position: relative;
width: 100%;
}
.ql-snow .ql-picker-label::before {
display: inline-block;
line-height: 22px;
}
.ql-snow .ql-picker-options {
background-color: #fff;
display: none;
min-width: 100%;
padding: 4px 8px;
position: absolute;
white-space: nowrap;
}
.ql-snow .ql-picker-options .ql-picker-item {
cursor: pointer;
display: block;
padding-bottom: 5px;
padding-top: 5px;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label {
color: #ccc;
z-index: 2;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill {
fill: #ccc;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke {
stroke: #ccc;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-options {
display: block;
margin-top: -1px;
top: 100%;
z-index: 1;
}
.ql-snow .ql-color-picker,
.ql-snow .ql-icon-picker {
width: 28px;
}
.ql-snow .ql-color-picker .ql-picker-label,
.ql-snow .ql-icon-picker .ql-picker-label {
padding: 2px 4px;
}
.ql-snow .ql-color-picker .ql-picker-label svg,
.ql-snow .ql-icon-picker .ql-picker-label svg {
right: 4px;
}
.ql-snow .ql-icon-picker .ql-picker-options {
padding: 4px 0px;
}
.ql-snow .ql-icon-picker .ql-picker-item {
height: 24px;
width: 24px;
padding: 2px 4px;
}
.ql-snow .ql-color-picker .ql-picker-options {
padding: 3px 5px;
width: 152px;
}
.ql-snow .ql-color-picker .ql-picker-item {
border: 1px solid transparent;
float: left;
height: 16px;
margin: 2px;
padding: 0px;
width: 16px;
}
.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg {
position: absolute;
margin-top: -9px;
right: 0;
top: 50%;
width: 18px;
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before,
.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before,
.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before {
content: attr(data-label);
}
.ql-snow .ql-picker.ql-header {
width: 98px;
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: 'Normal';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: 'Heading 1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: 'Heading 2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: 'Heading 3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: 'Heading 4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: 'Heading 5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: 'Heading 6';
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
font-size: 2em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
font-size: 1.5em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
font-size: 1.17em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
font-size: 1em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
font-size: 0.83em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
font-size: 0.67em;
}
.ql-snow .ql-picker.ql-font {
width: 108px;
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: 'Sans Serif';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
content: 'Serif';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
content: 'Monospace';
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
font-family: Georgia, Times New Roman, serif;
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
font-family: Monaco, Courier New, monospace;
}
.ql-snow .ql-picker.ql-size {
width: 98px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: 'Normal';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
content: 'Small';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
content: 'Large';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
content: 'Huge';
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
font-size: 10px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
font-size: 18px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
font-size: 32px;
}
.ql-snow .ql-color-picker.ql-background .ql-picker-item {
background-color: #fff;
}
.ql-snow .ql-color-picker.ql-color .ql-picker-item {
background-color: #000;
}
.ql-toolbar.ql-snow {
border: 1px solid #ccc;
box-sizing: border-box;
font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
padding: 8px;
}
.ql-toolbar.ql-snow .ql-formats {
margin-right: 15px;
}
.ql-toolbar.ql-snow .ql-picker-label {
border: 1px solid transparent;
}
.ql-toolbar.ql-snow .ql-picker-options {
border: 1px solid transparent;
box-shadow: rgba(0,0,0,0.2) 0 2px 8px;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
border-color: #ccc;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
border-color: #ccc;
}
.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,
.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover {
border-color: #000;
}
.ql-toolbar.ql-snow + .ql-container.ql-snow {
border-top: 0px;
}
.ql-snow .ql-tooltip {
background-color: #fff;
border: 1px solid #ccc;
box-shadow: 0px 0px 5px #ddd;
color: #444;
padding: 5px 12px;
white-space: nowrap;
}
.ql-snow .ql-tooltip::before {
content: "Visit URL:";
line-height: 26px;
margin-right: 8px;
}
.ql-snow .ql-tooltip input[type=text] {
display: none;
border: 1px solid #ccc;
font-size: 13px;
height: 26px;
margin: 0px;
padding: 3px 5px;
width: 170px;
}
.ql-snow .ql-tooltip a.ql-preview {
display: inline-block;
max-width: 200px;
overflow-x: hidden;
text-overflow: ellipsis;
vertical-align: top;
}
.ql-snow .ql-tooltip a.ql-action::after {
border-right: 1px solid #ccc;
content: 'Edit';
margin-left: 16px;
padding-right: 8px;
}
.ql-snow .ql-tooltip a.ql-remove::before {
content: 'Remove';
margin-left: 8px;
}
.ql-snow .ql-tooltip a {
line-height: 26px;
}
.ql-snow .ql-tooltip.ql-editing a.ql-preview,
.ql-snow .ql-tooltip.ql-editing a.ql-remove {
display: none;
}
.ql-snow .ql-tooltip.ql-editing input[type=text] {
display: inline-block;
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: 'Save';
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode=link]::before {
content: "Enter link:";
}
.ql-snow .ql-tooltip[data-mode=formula]::before {
content: "Enter formula:";
}
.ql-snow .ql-tooltip[data-mode=video]::before {
content: "Enter video:";
}
.ql-snow a {
color: #06c;
}
.ql-container.ql-snow {
border: 1px solid #ccc;
}

7
hub/redirect.php Normal file
View File

@ -0,0 +1,7 @@
<?php
# request.php > request_confirm.php > upload.php > upload_confirm.php
#require "/home/hpr/php/include.php";
?>
<?php
header('location:https://hub.hackerpublicradio.org/calendar.php');
?>

View File

@ -1,5 +1,9 @@
<?php
# request.php > request_confirm.php > upload.php > upload_confirm.php
## Recent Change
# Support for WYSIWYG https://github.com/slab/quill BSD-3-Clause license
require "/home/hpr/php/include.php";
if ( $_SERVER['REQUEST_METHOD'] !== 'GET' and empty($_SERVER["REMOTE_ADDR"]) and count($_GET) !== 1 ) {
@ -100,20 +104,23 @@ if ( !file_exists( $image_url )) {
// Main
$body="give";
// $body="give";
//$body="index_full";
include 'header.html';
?>
<body>
<link href="quill.snow.css" rel="stylesheet">
<script src="quill.js"></script>
<main id="maincontent">
<hr />
<?php
if ( $ep_num == 9999 ) {
echo "<h1>Uploading to the Reserve Queue.</h1>\n";
echo "<h2>Uploading to the Reserve Queue.</h2>\n";
}
else {
echo "<h1>Uploading hpr${ep_num} for release on ${ep_date}</h1>\n";
echo "<h2>Uploading hpr${ep_num} for release on ${ep_date}</h2>\n";
}
?>
<p>
@ -162,8 +169,12 @@ include 'header.html';
</tr>
<tr>
<td style="vertical-align:top;">Profile: (<a href="<?php echo "${baseurl}about.html#Profile"; ?>" target="_blank">?</a>)</td>
<!-- TODO https://xing.github.io/wysihtml5/ -->
<td><textarea name="host_profile" maxlength="2000" rows="10" cols="50" placeholder="Enter some text about yourself with links to your blog or other online presence."><?php echo htmlspecialchars($profile) ?></textarea></td>
<td>
<noscript>
<textarea name="host_profile" maxlength="2000" rows="10" cols="50" placeholder="Enter some text about yourself with links to your blog or other online presence."><?php echo htmlspecialchars($profile) ?></textarea>
</noscript>
<div id="editor_profile" name="host_profile"></div>
</td>
</tr>
</table>
<h2>Please fill in some information about this episode</h2>
@ -176,12 +187,6 @@ include 'header.html';
<td><strong>Summary(*) (<a href="<?php echo "${baseurl}about.html#Short_Summary"; ?>" target="_blank">?</a>):</strong></td>
<td><input required type="text" name="summary" size="70" maxlength="100" placeholder="This is a short 100 character summary of what your show is about."></td>
</tr>
<tr>
<td style="vertical-align:top;"><strong>Theme: (<a href="<?php echo "${baseurl}about.html#Theme"; ?>" target="_blank">?</a>)</strong></td>
<td>
Please <strong>do not</strong> add a theme to your show: <small>See <a href="https://lists.hackerpublicradio.com/pipermail/hpr/2021-November/004328.html">Policy Decision</a> for more information.</small><br />
</td>
</tr>
<tr>
<td><strong>Explicit: (<a href="<?php echo "${baseurl}about.html#Explicit"; ?>" target="_blank">?</a>)</strong></td>
<td>
@ -208,22 +213,29 @@ include 'header.html';
</tr>
<tr>
<td><strong>Notes(*) (<a href="<?php echo "${baseurl}about.html#show_notes"; ?>" target="_blank">?</a>):</strong></td>
<td><textarea required name="notes" maxlength="40000" rows="20" cols="70" placeholder="Please add your show notes here." ></textarea></td>
</tr>
<tr>
<td>Format: (<a href="<?php echo "${baseurl}about.html#shownotes_format"; ?>" target="_blank">?</a>)</td>
<td>
<small>What format if any did you just use in the show notes above ?</small><br />
<select name="shownotes_format">
<option value="plain_text" selected>Plain text</option>
<option value="html5">HTML5 (Preferred)</option>
<option value="Markdown_GitHub">Markdown (GitHub flavoured)</option>
<option value="Markdown_Pandoc">Markdown (Pandoc flavoured)</option>
<option value="restructured_text">RestructuredText</option>
<option value="txt2tags">txt2tags</option>
</select>
<noscript>
<textarea required name="notes" maxlength="40000" rows="20" cols="70" placeholder="Please add your show notes here." ></textarea>
</noscript>
<div id="editor_notes" name="notes"></div>
</td>
</tr>
<noscript>
<tr>
<td>Format: (<a href="<?php echo "${baseurl}about.html#shownotes_format"; ?>" target="_blank">?</a>)</td>
<td>
<small>What format if any did you just use in the show notes above ?</small><br />
<select name="shownotes_format">
<option value="plain_text" selected>Plain text</option>
<option value="html5">HTML5 (Preferred)</option>
<option value="Markdown_GitHub">Markdown (GitHub flavoured)</option>
<option value="Markdown_Pandoc">Markdown (Pandoc flavoured)</option>
<option value="restructured_text">RestructuredText</option>
<option value="txt2tags">txt2tags</option>
</select>
</td>
</tr>
</noscript>
<tr>
<td>Series: (<a href="<?php echo "${baseurl}about.html#series"; ?>" target="_blank">?</a>)</td>
<td>
@ -259,24 +271,14 @@ include 'header.html';
Please avoid services that require login or downloading via a browser.<br />
<input type="url" size="30" name="url" placeholder="https://example.com/hpr9999.flac">
</p>
<p>
<strong>3. Upload via an alternative method</strong>:
If you wish to send a show using another method then please discuss it with the HPR Volunteer at admin@hackerpublicradio.org.
</p>
<p>
<strong>4. Reserve a slot</strong>:
Leave upload option 1 and 2 empty if you have received prior approval for a reservation from the Community via the <a href="/mailman/listinfo/hpr_hackerpublicradio.org">HPR Mailing List</a> to either:
</p>
<ul>
<li>Reserve the show now and upload media later.</li>
<li>Send physical media by the postal service or deliver in person.<br />
<em>Make sure you plan in enough time to deliver your media.</em></li>
</ul>
</td>
</tr>
</table>
<?php echo "<input type=\"hidden\" name=\"hostid\" value=\"$hostid\">"; ?>
<?php echo "<input type=\"hidden\" name=\"key\" value=\"$key\">"; ?>
<script>
document.write(`<?php echo "<input type=\"hidden\" name=\"shownotes_format\" value=\"html5\">"; ?>`);
</script>
<br />
<input type="submit" name="submit_edit" value="Submit"> This will take a <strong>long time</strong>, leave the browser running. You will get an email once the upload is complete.
<?php
@ -290,10 +292,49 @@ include 'header.html';
?>
<div id="progressbar">
<div></div>
</div>
<script>
const toolbarOptions = [
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
['link', 'image'],
['clean'] // remove formatting button
];
const quill_profile = new Quill('#editor_profile', {
modules: {
toolbar: toolbarOptions
},
placeholder: 'Enter your personal profile here...',
theme: 'snow'
});
const form_profile = document.querySelector("form");
quill_profile.root.innerHTML = `<?php echo $profile ?>` .replace(/(<ul>|<ol>|<\/li>)(?:[\s]+)(<li>|<\/ul>|<\/ol>)/g, '$1$2');
form_profile.addEventListener("formdata", (event) => {
event.formData.append("host_profile", quill_profile.root.innerHTML);
});
const quill = new Quill('#editor_notes', {
modules: {
toolbar: toolbarOptions
},
placeholder: 'Enter your show notes here...',
theme: 'snow'
});
const form = document.querySelector("form");
form.addEventListener("formdata", (event) => {
event.formData.append("notes", quill.root.innerHTML);
});
</script>
</form>
</main>
<?php
include 'footer.html';
?>

View File

@ -1,6 +1,12 @@
<?php
# request.php > request_confirm.php > upload.php > upload_confirm.php
## Recent Changes
# TODO disabled the max notes check. We need to re-enable after we get a feel for the max length
# Removed support for the txt file
# Removde the POST duplication from the json file
# No longer logs the post to log file
require "/home/hpr/php/include.php";
function goback() {
@ -148,10 +154,14 @@ if ( !(
}
logextra( "license is a valid value" );
if ( empty($_POST["notes"]) or strlen($_POST["notes"]) > 40000 ) {
naughty("5860799406a323209b902d5104fe7bae");
}
logextra( "Notes are less than max" );
// TODO re-enable after we get a feel for the max length
// if ( empty($_POST["notes"]) or strlen($_POST["notes"]) > 100000 ) {
// naughty("5860799406a323209b902d5104fe7bae");
// }
// logextra( "Notes are less than max" );
$notes_length = strlen($_POST["notes"]);
logextra( "Notes are $notes_length long." );
if ( ( empty($_POST["series"]) and ($_POST["series"] != 0 ) ) or (strlen($_POST["series"]) > 3 ) ) {
naughty("f1c83b57821d562f66246d975ef28994");
@ -247,12 +257,6 @@ if (!mkdir($dir_structure, 0777, true)) {
naughty("804c4be123ca0327840b76bf4f8eb19e");
}
$shownote_file = "${dir_structure}/shownotes.txt";
if ( file_exists( $shownote_file ) ) {
naughty("33370d1c5c19a6ca4ef3f3ce59158e57");
}
logextra( "The shownotes txt file exists $shownote_file" );
$shownote_file_json = "${dir_structure}/shownotes.json";
if ( file_exists( $shownote_file_json ) ) {
naughty("85c8df74d172794c49233c1a94c299fd");
@ -264,40 +268,6 @@ $this_file = print_r($_FILES, true);
logextra( "Received $this_post, $this_file" );
$show_data = "------------------------------------------------------------";
$show_data = $show_data . "\nEpisode_Number:\t" . $ep_num;
$show_data = $show_data . "\nEpisode_Date:\t" . $ep_date;
$show_data = $show_data . "\nTimestamp:\t" . $db_timestamp;
$show_data = $show_data . "\nKey:\t" . $_POST['key'];
$show_data = $show_data . "\nHost_IP:\t" . $db_ip;
$show_data = $show_data . "\n------------------------------------------------------------";
$show_data = $show_data . "\nHost_ID:\t" . $_POST['hostid'];
$show_data = $show_data . "\nHost_Name:\t" . $_POST['host_name'];
$show_data = $show_data . "\nHost_Email:\t" . $db_email;
$show_data = $show_data . "\nHost_License:\t" . $_POST['host_license'];
$show_data = $show_data . "\nHost_Profile:\n" . $_POST['host_profile'];
$show_data = $show_data . "\n------------------------------------------------------------";
$show_data = $show_data . "\nTitle:\t" . $_POST['title'];
$show_data = $show_data . "\nSummary:\t" . $_POST['summary'];
$show_data = $show_data . "\nShownotes_Format:\t" . $_POST['shownotes_format'];
$show_data = $show_data . "\nExplicit:\t" . $_POST['explicit'];
$show_data = $show_data . "\nShow_License:\t" . $_POST['license'];
$show_data = $show_data . "\nSeries:\t" . $series;
$show_data = $show_data . "\nSeries_Name:\t" . $series_name;
$show_data = $show_data . "\nTags:\t" . $_POST['tags'];
$show_data = $show_data . "\nurl:\t" . $_POST['url'];
$show_data = $show_data . "\n------------------------------------------------------------";
$show_data = $show_data . "\nShow_Notes:\n" . $_POST['notes'];
$show_data = $show_data . "\n------------------------------------------------------------";
$show_data = $show_data . "\nPOST:\n" . $this_post;
$show_data = $show_data . "\n------------------------------------------------------------";
$show_data = $show_data . "\nFILES:\n" . $this_file;
$show_data = $show_data . "\n------------------------------------------------------------\n";
file_put_contents($shownote_file, stripslashes($show_data) );
logextra( "Wrote the $shownote_file" );
$show_data_json = array(
"host" => array(
"Host_ID" => $_POST['hostid'],
@ -322,28 +292,24 @@ $show_data_json = array(
"Timestamp" => $db_timestamp,
"Key" => $_POST['key'],
"Host_IP" => $db_ip,
"POST" => $_POST,
"FILES" => $_FILES,
"url" => $_POST['url'],
"Shownotes_Format" => $_POST['shownotes_format'],
)
);
file_put_contents($shownote_file_json, json_encode($show_data_json) );
logextra( "Wrote the $shownote_file_json" );
file_put_contents($shownote_file_json, json_encode( $show_data_json ) );
$shownote_file_json_length = strlen( json_encode( $show_data_json ) );
logextra( "Wrote the shownotes which are $shownote_file_json_length long" );
if ( !file_exists( $dir_structure ) ) {
naughty("a1534e6d525352dce7183a2e22862049");
}
logextra( "The dir_structure still exists" );
if ( !file_exists( "$dir_structure/shownotes.txt" ) ) {
naughty("ab8051b531c120b8bffd2a5b25a19cc3");
}
logextra( "shownotes.txt still exists" );
if ( !file_exists( "$dir_structure/shownotes.json" ) ) {
naughty("a9564ebc3289b7a14551baf8ad5ec60a");
naughty("3eb02d6b9ea801d4c5909b4fac0ccd96");
}
logextra( "shownotes.json still exists" );
@ -494,7 +460,7 @@ $mailer->addBCC('admin@hackerpublicradio.org');
$mailer->addBCC('admin@hobbypublicradio.org');
$mailer->AddAddress("$db_email");
$mailer->isHTML(false);
if ( $ep_num === 9999 ) {
if ( $ep_num == "9999" ) {
$mailer->Subject = "Thank you for uploading to the Reserve Queue";
$mailer->MsgHTML("<p><em>This email is an automatic reply. If you have not made this request then please ignore this email.</em></p>
<p>Thank You for recording an episode for the Reserve Queue.</p>
@ -510,20 +476,20 @@ if ( $ep_num === 9999 ) {
else {
$mailer->Subject = "Thank you for uploading hpr${ep_num}::${ep_date}";
$mailer->MsgHTML("<p><em>This email is an automatic reply. If you have not made this request then please ignore this email.</em></p>
<p>Thank You for recording hpr${ep_num} for release on ${ep_date}.</p>
<p>Thank you for recording hpr${ep_num} for release on ${ep_date}.</p>
<pre>
$message
</pre>
<p>
Your show will now be processed by a HPR Volunteer.<br />
Thanks,<br />
HPR Bot
HPR Bot.
</p>");
}
$mailer->AltBody = "This email is an automatic reply. If you have not made this request then please ignore this email.
Thank You for recording hpr${ep_num} for release on ${ep_date}.
Thank you for recording hpr${ep_num}, for release on ${ep_date}.
$message

View File

@ -17,8 +17,6 @@ if ( ! $pos === false) {
date_default_timezone_set("UTC");
if (!($connection = @ mysqli_connect("$databaseHostName", "$databaseUsername", "$databasePassword")))
die("Could not connect to database");
@ -334,4 +332,18 @@ if ($pos !== false) {
$HPR_Names = "Hackers";
}
// General allowed Settings
$allowed_content_type = array( "application/json", "application/octet-stream", "application/ogg", "application/x-subrip", "audio/flac", "audio/mpeg", "audio/ogg", "audio/x-flac", "audio/x-wav", "image/jpeg", "image/png", "image/webp", "text/plain", "text/x-c" );
$allowed_extensions = array("wav", "flac", "opus", "ogg", "mp3", "jpg", "jpeg", "png", "webp", "srt", "txt" );
$allowed_extensions_common = array("opus", "ogg", "mp3", "jpg", "jpeg", "png", "webp", "srt", "txt" );
#$ccdn_hosts_common = array("alpha.nl.eu.mirror.hackerpublicradio.org", "hpr.nyc3.cdn.digitaloceanspaces.com" );
$ccdn_hosts_common = array("alpha.nl.eu.mirror.hackerpublicradio.org", "hpr.nyc3.cdn.digitaloceanspaces.com" );
#$ccdn_hosts_common = array( "hpr.nyc3.cdn.digitaloceanspaces.com" );
$ccdn_hosts_complete = array( "archive.org" );
?>

View File

@ -1,213 +0,0 @@
<?php
// TODO
// lisence
// filter by date
// if rss.php then use switches
// host out of eps
// explicit from db
#
$mimetype = "audio/ogg";
$format = "ogg";
require "/home/hpr/php/include.php";
$query = "SELECT hosts.host, eps.id, eps.series, eps.title, eps.notes, eps.date, hosts.email, eps.hostid, eps.explicit, eps.version, eps.valid, eps.duration, assets.size
FROM eps, hosts, assets
WHERE eps.valid=1
AND eps.hostid = hosts.hostid
AND eps.id = assets.episode_id
AND eps.duration > 0
AND eps.date >= UTC_DATE()";
if (isset($_GET['format'])) {
$this_format = $_GET['format'];
if ( $this_format === "mp3" ) {
$format = "mp3";
}
if ( $this_format === "ogg" ) {
$format = "ogg";
}
if ( $this_format === "spx" ) {
$format = "spx";
}
}
$query = "${query}\nAND assets.filename REGEXP \"^hpr[0-9]+.$format\"";
$query = "${query}\nAND assets.extension = '$format'";
$html = 1;
if (isset($_GET['html'])) {
$html = $_GET['html'];
if ( $html === "0" ) {
$html = 0;
}
}
$full = "1";
if (isset($_GET['full'])) {
$full = $_GET['full'];
if ( $full === "1" ) {
$feed = "total";
}
if ( $full === "0" ) {
$feed = "tenday";
}
}
if (isset($_GET['hostid'])) {
$hostid = $_GET['hostid'];
$hostid = intval($hostid);
if (is_int(intval($hostid))) {
$query = "$query AND hosts.hostid = '$hostid'";
}
}
if (isset($_GET['series'])) {
$series = $_GET['series'];
$series = intval($series);
if (is_int(intval($series))) {
$query = "$query AND eps.series = '$series'";
}
}
$query = "$query ORDER BY id DESC ";
if (isset($_GET['limit'])) {
$this_limit = $_GET['limit'];
$this_limit = intval($this_limit);
if (is_int(intval($this_limit))) {
$limit = $this_limit;
}
}
header("Content-type: application/xml");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
date_default_timezone_set('UTC');
print '<?xml version="1.0" encoding="UTF-8" ?>' . "\n";
?>
<rss version="2.0" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" >
<channel>
<title>Hacker Public Radio - Future Feed</title>
<link><?php print "${baseurl}"; ?>about.html</link>
<itunes:subtitle>A daily show hosted the community on topics that are of interest to hackers and hobbyists.</itunes:subtitle>
<description>Hacker Public Radio is an podcast that releases shows every weekday Monday through Friday. Our shows are produced by the community (you) and can be on any topic that are of interest to hackers and hobbyists. This is the shows that are in the future feed.</description>
<language>en-us</language>
<itunes:category text="Technology">
<itunes:category text="Tech News"/>
</itunes:category>
<itunes:category text="Education">
<itunes:category text="Training"/>
</itunes:category>
<itunes:image href="<?php print "${baseurl}"; ?>images/hpr_feed_itunes.png"/>
<itunes:explicit>yes</itunes:explicit>
<itunes:author>Hacker Public Radio</itunes:author>
<itunes:keywords>Community Radio, Tech Interviews, Linux, Open, Hobby, Software Freedom</itunes:keywords>
<copyright>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License</copyright>
<managingEditor>feedback@NOSPAM-hackerpublicradio.org (HPR Feedback)</managingEditor>
<!-- <author>feedback@NOSPAM-hackerpublicradio.org (HPR Feedback)</author> -->
<itunes:owner>
<itunes:name>HPR Volunteer</itunes:name>
<itunes:email>admin@hackerpublicradio.org</itunes:email>
</itunes:owner>
<webMaster>admin@hackerpublicradio.org (HPR Volunteer)</webMaster>
<generator>kate</generator>
<docs>http://www.rssboard.org/rss-specification</docs>
<ttl>720</ttl>
<skipDays>
<day>Saturday</day>
<day>Sunday</day>
</skipDays>
<image>
<url><?php print "${baseurl}"; ?>images/hpr_feed_small.png</url>
<title>Hacker Public Radio</title>
<link><?php print "${baseurl}"; ?>about.html</link>
<description>The Hacker Public Radio Old Microphone Logo</description>
<height>164</height>
<width>144</width>
</image>
<googleplay:author>HPR Volunteer</googleplay:author>
<googleplay:description>Hacker Public Radio is an podcast that releases shows every weekday Monday through Friday. Our shows are produced by the community (you) and can be on any topic that are of interest to hackers and hobbyists.</googleplay:description>
<googleplay:email>admin@hackerpublicradio.org</googleplay:email>
<googleplay:image href="<?php print "${baseurl}"; ?>images/hpr_feed_itunes.png"/>
<googleplay:category text="Technology"/>
<?php
print " <atom:link href=\"${baseurl}". str_replace('&', '&amp;', $_SERVER["REQUEST_URI"]) ."\" rel=\"self\" type=\"application/rss+xml\" />\n";
print " <pubDate>".date(DATE_RFC1123, strtotime(date('Y-m-d')))."</pubDate>\n";
//Set $r to SQL query for execution agains the table
if ($result = mysqli_query($connection, $query)) {
while ($row = mysqli_fetch_array($result)) {
$id = fixid(stripslashes($row['id']));
$version = $row['version'];
if ( $version === "0" ) {
$version = "";
}
else {
$version = ".${version}";
}
$episode_explicit = $row['explicit'];
if ($episode_explicit == 0) {
$episode_explicit = "Clean";
}
else{
$episode_explicit = "Explicit";
}
$url="${baseurl}eps/hpr${id}${version}";
if (isset($_GET['hostidinfilename'])) {
$hostidinfilename = $_GET['hostidinfilename'];
if ( $hostidinfilename === "1" ) {
$url = $url . "_host-" . htmlspecialchars(stripslashes(strip_tags($row["hostid"])));
}
}
if ( isset($_GET['seriesidinfilename']) ) {
$seriesidinfilename = $_GET['seriesidinfilename'];
if ( $seriesidinfilename === "1" ) {
$url = $url . "_series-" . htmlspecialchars(stripslashes(strip_tags($row["series"])));
}
}
$url = $url . "." . $format;
$itunes_summary = htmlspecialchars(stripslashes(strip_tags(substr($row["notes"],0,4000))));
$show_notes = $row["notes"];
$warning = "<p>This show has been flagged as $episode_explicit by the host.</p>\n";
$show_notes = $show_notes . utf8_encode ( $warning );
echo " <item>\n";
if ( $episode_explicit === "Clean" ) {
echo " <itunes:explicit>no</itunes:explicit>\n";
echo " <googleplay:explicit>No</googleplay:explicit>\n";
}
else {
echo " <itunes:explicit>yes</itunes:explicit>\n";
echo " <googleplay:explicit>Yes</googleplay:explicit>\n";
}
echo " <title>HPR$id: " . htmlspecialchars(stripslashes(strip_tags($row["title"]))) . "</title>\n";
// echo "<description> " . ($row["title"]) . "</description>\n";
$email_padded = formatemail($row['email']);
echo " <author>". $email_padded . " (" . htmlspecialchars(stripslashes(strip_tags($row["host"]))) .")</author>\n";
echo " <googleplay:author>". $email_padded . " (" . htmlspecialchars(stripslashes(strip_tags($row["host"]))) .")</googleplay:author>\n";
echo " <itunes:author>". $email_padded . " (" . htmlspecialchars(stripslashes(strip_tags($row["host"]))) .")</itunes:author>\n";
echo " <googleplay:image href=\"${baseurl}images/hpr_feed_itunes.png\"/>\n";
echo " <link>${baseurl}eps/hpr".$id."/index.html</link>\n";
echo " <description><![CDATA[" . $show_notes . "]]>\n</description>\n";
// echo " <googleplay:description><![CDATA[" . $show_notes . "]]>\n</googleplay:description>\n";
echo " <itunes:summary><![CDATA[" . $itunes_summary . "]]>\n</itunes:summary>\n";
echo " <pubDate>" .date(DATE_RFC1123, strtotime($row['date'])) . "</pubDate>\n";
$length = $row['size'];
echo " <enclosure url=\"$url\" length=\"$length\" type=\"$mimetype\"/>\n";
echo " <guid>" . $url . "</guid>\n";
echo " </item>\n";
}
}
//Display non-connection errors
//Close sql connection
mysqli_close($connection);
echo " </channel>
</rss>
";
?>

View File

@ -35,6 +35,12 @@ switch ($atomurl) {
$mimetype = "audio/mpeg";
$feed = "total";
break;
case "/rss-future.php":
$format = "mp3";
$mimetype = "audio/mpeg";
$feed = "future";
$limit = 100;
break;
case "/hpr_ogg_rss.php":
$format = "ogg";
$mimetype = "audio/ogg";
@ -60,11 +66,6 @@ switch ($atomurl) {
$mimetype = "audio/mpeg";
$feed = "tenday";
break;
case "/rss1.php":
$format = "spx";
$mimetype = "audio/ogg";
$feed = "tenday";
break;
}
require "/home/hpr/php/include.php";
@ -121,15 +122,11 @@ if (isset($_GET['full'])) {
}
}
$gomax = "0";
if (isset($_GET['gomax'])) {
$gomax = $_GET['gomax'];
if ( $gomax === "1" ) {
$gomax = "1";
}
if ( $feed === "future" ) {
$query = "${query}\nAND eps.date >= UTC_DATE() ";
}
if ( $gomax === "0" ) {
$query = "${query}\nAND eps.date <= UTC_DATE() ";
else {
$query = "${query}\nAND eps.date <= UTC_DATE() ";
}
if (isset($_GET['hostid'])) {
@ -189,7 +186,6 @@ print '<?xml version="1.0" encoding="UTF-8" ?>' . "\n";
<itunes:keywords>Community Radio, Tech Interviews, Linux, Open, Hobby, Software Freedom</itunes:keywords>
<copyright>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License</copyright>
<managingEditor>feedback@NOSPAM-hackerpublicradio.org (HPR Feedback)</managingEditor>
<!-- <author>feedback@NOSPAM-hackerpublicradio.org (HPR Feedback)</author> -->
<itunes:owner>
<itunes:name>HPR Volunteer</itunes:name>
<itunes:email>admin@hackerpublicradio.org</itunes:email>
@ -237,34 +233,19 @@ if ($result = mysqli_query($connection, $query)) {
else{
$episode_explicit = "Explicit";
}
$url="http://hackerpublicradio.org/eps/hpr${id}${version}";
if (isset($_GET['hostidinfilename'])) {
$hostidinfilename = $_GET['hostidinfilename'];
if ( $hostidinfilename === "1" ) {
$url = $url . "_host-" . htmlspecialchars(stripslashes(strip_tags($row["hostid"])));
}
}
if ( isset($_GET['seriesidinfilename']) ) {
$seriesidinfilename = $_GET['seriesidinfilename'];
if ( $seriesidinfilename === "1" ) {
$url = $url . "_series-" . htmlspecialchars(stripslashes(strip_tags($row["series"])));
}
}
$url = $url . "." . $format;
$url="https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr${id}/hpr${id}.${format}";
$itunes_summary = htmlspecialchars(stripslashes(strip_tags(substr($row["notes"],0,4000))));
if ( $html == 1 ) {
# $show_notes = "<p>This show has been flagged as $episode_explicit by the host.</p>\n" . $row["notes"];
$show_notes = $row["notes"];
$warning = "<p>This show has been flagged as $episode_explicit by the host.</p>\n";
$show_notes = "<p>This show has been flagged as $episode_explicit by the host.</p>\n";
$show_notes = $show_notes . $row["notes"];
$show_notes = $show_notes . "<p><a href=\"https://hackerpublicradio.org/eps/hpr${id}/index.html#comments\">Provide <strong>feedback</strong> on this episode</a>.</p>";
}
else {
# $show_notes = "This show has been flagged as $episode_explicit by the host.\n" . htmlspecialchars(stripslashes(strip_tags($row["notes"]))) ;
$show_notes = htmlspecialchars(stripslashes(strip_tags($row["notes"]))) ;
$warning = "This show has been flagged as $episode_explicit by the host.\n";
$show_notes = "This show has been flagged as $episode_explicit by the host.\n";
$show_notes = $show_notes . htmlspecialchars(stripslashes(strip_tags($row["notes"]))) ;
}
# $show_notes = utf8_encode ( $show_notes );
$warning = utf8_encode ( $warning );
echo " <item>\n";
if ( $episode_explicit === "Clean" ) {
echo " <itunes:explicit>no</itunes:explicit>\n";
@ -289,7 +270,6 @@ if ($result = mysqli_query($connection, $query)) {
else {
echo " <description><![CDATA[" . $show_notes . "]]>\n</description>\n";
}
// echo " <googleplay:description><![CDATA[" . $show_notes . "]]>\n</googleplay:description>\n";
echo " <itunes:summary><![CDATA[" . $itunes_summary . "]]>\n</itunes:summary>\n";
echo " <pubDate>" .date(DATE_RFC1123, strtotime($row['date'])) . "</pubDate>\n";
$length = $row['size'];
@ -301,8 +281,6 @@ if ($result = mysqli_query($connection, $query)) {
}
}
//Display non-connection errors
//Close sql connection
mysqli_close($connection);
echo " </channel>
</rss>