#!/bin/bash ################################################################################ # Author: Fred (support@qo-op.com) # Version: 0.1 # License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) ################################################################################ mkdir -p ~/.zen/bunkerbox # BunkerBOX temp directory # Fred MadeInZion, [20/03/2022 23:03] # Script qui capture et transfert dans IPFS le flux des nouvelles vidéos de https://crowdbunker.com/ # le resultat est inscrit dans une chaine video accessible localement ou publiée au travers de qo-op # ou du TestNET astrXbian, videoclub entre amis d'amis... MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized ME="${0##*/}" TS=$(date -u +%s%N | cut -b1-13) [[ ! $(which ipfs) ]] && echo "EXIT. Vous devez avoir installé ipfs CLI sur votre ordinateur" && echo "RDV sur https://dist.ipfs.io/#go-ipfs" && exit 1 YOU=$(ps auxf --sort=+utime | grep -w ipfs | grep -v -E 'color=auto|grep' | tail -n 1 | cut -d " " -f 1) || echo " warning ipfs daemon not running" isLAN=$(hostname -I | awk '{print $1}' | head -n 1 | cut -f3 -d '/' | grep -E "(^127\.)|(^192\.168\.)|(^fd42\:)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])/") IPFSNGW="https://tube.copylaradio.com" IPFSNGW="http://127.0.0.1:8080" [[ ! $isLAN ]] && IPFSNGW="https://$(hostname)" echo "IPFS GATEWAY $IPFSNGW" ## GET LATEST VIDEOS VWALLURL="https://api.crowdbunker.com/post/all" curl -s $VWALLURL -H "Accept: application/json" > ~/.zen/bunkerbox/crowd.json [[ ! -f ~/.zen/bunkerbox/crowd.json ]] && echo "ERROR GET VIDEO SOURCE LIST FROM $VWALLURL" && exit 1 ## LOOP THROUGH (REVERSE LIST) cat ~/.zen/bunkerbox/crowd.json | jq -r '.posts | .[] | .video.id' > /tmp/vuid.list # Reverse list to start with older videos for VUID in $(tac /tmp/vuid.list); do [[ "$VUID" == "null" ]] && echo "MESSAGE... Bypassing..." && echo && continue echo "=====================================================" echo "Bunker BOX : Adding $VUID" mkdir -p ~/.zen/bunkerbox/$VUID/media URL="https://api.crowdbunker.com/post/$VUID/details" # echo "WISHING TO EXPLORE $URL ?"; read TEST; [[ "$TEST" != "" ]] && echo && continue curl -s $URL -H "Accept: application/json" -o ~/.zen/bunkerbox/$VUID/media/$VUID.json # STREAMING LIVE ? echo ">>> Extracting video caracteristics from ~/.zen/bunkerbox/$VUID/media/$VUID.json" ISLIVE=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .video.isLiveType)&& [[ "$ISLIVE" == "true" ]] && echo "LIVE... " LIVE=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .video.isLiveActive) && [[ "$LIVE" == "true" ]] && echo "STREAMING... Bypassing..." && echo && continue DURATION=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .video.duration) && [[ $DURATION == 0 ]] && echo "NOT STARTED YET" && echo && continue TITLE=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .video.title | sed "s/'/ /g" | sed 's/"/ /g') # Remove quote CHANNEL=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .channel.organization.uid) ## GET MORE DATA... CORRECT IT for each JSON ORGUID=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .organization.uid) ORGNAME=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .organization.name) ORGBANNER=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .organization.banner.url) HLS=$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r .video.hlsManifest.url) MEDIASOURCE=$(echo $HLS | rev | cut -d '/' -f 2- | rev) echo "$TITLE ($DURATION s)" ## NO choice made, so ask to continue each loop [[ ! $(cat ~/.zen/bunkerbox/choice 2>/dev/null) ]] && echo "READY TO PROCESS ? ENTER. Any character sent means next." && read TEST && [[ "$TEST" != "" ]] && echo && continue ## NO CHOICE MADE echo "$HLS" ## Download HLS source m3u8 (contains video & audio) curl -s $HLS -o ~/.zen/bunkerbox/$VUID/$VUID.m3u8 [[ ! $(cat ~/.zen/bunkerbox/choice 2>/dev/null) ]] && cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 # DEBUG echo ">>>>>>>>>>>>>>>> Downloading VIDEO" # Choose 360p or 480p or 720p or 240p VSIZE=360 && VIDEOHEAD=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep -B1 ${VSIZE}p | head -n 1) && VIDEOSRC=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep ${VSIZE}p | tail -n 1 | cut -f 1 -d '.') [[ "$VIDEOSRC" == "" ]] && VSIZE=480 && VIDEOHEAD=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep -B1 ${VSIZE}p | head -n 1) && VIDEOSRC=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep ${VSIZE}p | tail -n 1 | cut -f 1 -d '.') [[ "$VIDEOSRC" == "" ]] && VSIZE=720 && VIDEOHEAD=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep -B1 ${VSIZE}p | head -n 1) && VIDEOSRC=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep ${VSIZE}p | tail -n 1 | cut -f 1 -d '.') [[ "$VIDEOSRC" == "" ]] && VSIZE=240 &&VIDEOHEAD=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep -B1 ${VSIZE}p | head -n 1) && VIDEOSRC=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep ${VSIZE}p | tail -n 1 | cut -f 1 -d '.') ## NO VIDEO ? [[ "$VIDEOSRC" == "" ]] && echo "NO COMPATIBLE RESOLUTION VIDEO FOUND." && cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 && continue # THUMBNAIL VTHUMB="$(cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq -r --arg VSIZE "$VSIZE" '.video.thumbnails[] | select(.height == $VSIZE) | .url')" echo ">>>>>>>>>>>>>>>> Downloading $VSIZE Thumbnail" [[ ! -f ~/.zen/bunkerbox/$VUID/media/$VUID.jpg ]] && curl -s $VTHUMB -o ~/.zen/bunkerbox/$VUID/media/$VUID.jpg [[ ! -f ~/.zen/bunkerbox/$VUID/media/$VUID.jpg ]] && cp ${MY_PATH}/images/astroport.jpg ~/.zen/bunkerbox/$VUID/media/$VUID.jpg # CORRECT MISSING THUMB echo "VIDEOSRC=$MEDIASOURCE/$VIDEOSRC" # Downloading Video m3u8 and Video [[ ! -f ~/.zen/bunkerbox/$VUID/media/$VIDEOSRC.m3u8 ]] && curl -s $MEDIASOURCE/$VIDEOSRC.m3u8 -o ~/.zen/bunkerbox/$VUID/media/$VIDEOSRC.m3u8 [[ ! -f ~/.zen/bunkerbox/$VUID/media/$VIDEOSRC ]] && curl $MEDIASOURCE/$VIDEOSRC -o ~/.zen/bunkerbox/$VUID/media/$VIDEOSRC echo ">>>>>>>>>>>>>>>> Downloading AUDIO" AUDIOLINE=$(cat ~/.zen/bunkerbox/$VUID/$VUID.m3u8 | grep '=AUDIO') AUDIOFILE=$(echo $AUDIOLINE | rev | cut -d '.' -f 2- | cut -d '"' -f 1 | rev) echo "AUDIO=$MEDIASOURCE/$AUDIOFILE" # Downloading Audio m3u8 and Audio [[ ! -f ~/.zen/bunkerbox/$VUID/media/$AUDIOFILE.m3u8 ]] && curl -s $MEDIASOURCE/$AUDIOFILE.m3u8 -o ~/.zen/bunkerbox/$VUID/media/$AUDIOFILE.m3u8 [[ ! -f ~/.zen/bunkerbox/$VUID/media/$AUDIOFILE ]] && curl $MEDIASOURCE/$AUDIOFILE -o ~/.zen/bunkerbox/$VUID/media/$AUDIOFILE echo ">>>>>>>>>>>>>>>> CREATING $VSIZE M3U8" echo "#EXTM3U #EXT-X-VERSION:6 #EXT-X-INDEPENDENT-SEGMENTS $AUDIOLINE $VIDEOHEAD $VIDEOSRC.m3u8 " > ~/.zen/bunkerbox/$VUID/media/$VUID.m3u8 ls ~/.zen/bunkerbox/$VUID/media/ # SHOW ALL COLLECTED MEDIA ########################################################################## ########################################################################## start=`date +%s` echo "##########################################################################" echo ">>>>>>>>>>>>>>>> ADDING index.html" # COPY index, style, js AND data cp -R ${MY_PATH}/templates/styles ~/.zen/bunkerbox/$VUID/media/ cp -R ${MY_PATH}/templates/js ~/.zen/bunkerbox/$VUID/media/ cp ${MY_PATH}/templates/videojs.html ~/.zen/bunkerbox/$VUID/media/index.html cp ${MY_PATH}/images/astroport.jpg ~/.zen/bunkerbox/$VUID/media/ ## NO OR EMPTY HISTORY? COPY from TEMPLATE (PROGRAM START) [[ ! -f ~/.zen/bunkerbox/history.json || $(cat ~/.zen/bunkerbox/history.json 2>/dev/null) == "" ]] && cp ${MY_PATH}/templates/data/history.json ~/.zen/bunkerbox/history.json # qo-op get latest history.json if [[ "$(cat ~/.zen/bunkerbox/choice 2>/dev/null)" == "qo-op" ]]; then IPNSL="/ipns/$(cat ~/.zen/bunkerbox/qo-op)" ipfs get -o ~/.zen/bunkerbox/history.qo-op.json $IPNSL/history.json # Get actual IPNS qo-op history.json [[ $(cat ~/.zen/bunkerbox/history.qo-op.json | jq .Videos[].link | grep $VUID) ]] && echo "VIDEO DEJA DANS IPFS... CONTINUE" && echo && cp ~/.zen/bunkerbox/history.qo-op.json ~/.zen/bunkerbox/history.json && continue # JSON FUSION jq -s '.[0] * .[1]' ~/.zen/bunkerbox/history.qo-op.json ~/.zen/bunkerbox/history.json | jq -M '.Videos |= unique_by(.link)' > ~/.zen/bunkerbox/history.fusion.json mv ~/.zen/bunkerbox/history.fusion.json ~/.zen/bunkerbox/history.json ## REPLACE LOCAL HISTORY CACHE else IPNSL="./" fi # Add previous CHANNEL History [[ -f ~/.zen/bunkerbox/history.${CHANNEL}.json ]] && cp ~/.zen/bunkerbox/history.${CHANNEL}.json ~/.zen/bunkerbox/$VUID/media/ # Add current/latest reversed history to media echo '{ "Videos":' > ~/.zen/bunkerbox/$VUID/media/history.json cat ~/.zen/bunkerbox/history.json | jq '.[] | reverse' >> ~/.zen/bunkerbox/$VUID/media/history.json echo '}' >> ~/.zen/bunkerbox/$VUID/media/history.json # COPY videojs.html TEMPLATE & Updating links sed "s/_IPFSROOT_/./g" ${MY_PATH}/templates/videojs.html > ~/.zen/bunkerbox/$VUID/media/index.html sed -i "s/_VUID_/$VUID/g" ~/.zen/bunkerbox/$VUID/media/index.html # sed -i s/_DATE_/$(date -u "+%Y-%m-%d#%H:%M:%S")/g ~/.zen/bunkerbox/$VUID/media/index.html # !! Different Copy Makes Different Chains ! sed -i "s~_TITLE_~$TITLE~g" ~/.zen/bunkerbox/$VUID/media/index.html sed -i "s~_CHANNEL_~$CHANNEL~g" ~/.zen/bunkerbox/$VUID/media/index.html sed -i "s~_IPNSL_~$IPNSL~g" ~/.zen/bunkerbox/$VUID/media/index.html #MAJ IPNS link echo ">>>>> ADDING MEDIA TO IPFS : ipfs add -rwH ~/.zen/bunkerbox/$VUID/media/* " echo ################################################################# # IPFS WRITING. All that is prepared above in ~/.zen/bunkerbox/$VUID/media/ will become permanent ! ################################################################# IPFSROOT=$(ipfs add -rwHq ~/.zen/bunkerbox/$VUID/media/* | tail -n 1) INDEX="/ipfs/$IPFSROOT" ################################################################# # IPFS WRITING DONE. Doing after is to UPDATE local history(s).json in ~/.zen/bunkerbox/ # Then publishing on IPNS 'qo-op' all dynamic data needed by above 'index.html' ################################################################# ################# # Take care about CHANNEL history echo "++ MANAGE $CHANNEL HISTORY" [[ ! -f ~/.zen/bunkerbox/history.${CHANNEL}.json || $(cat ~/.zen/bunkerbox/history.${CHANNEL}.json 2>/dev/null) == "" ]] && cp ${MY_PATH}/templates/data/history.json ~/.zen/bunkerbox/history.${CHANNEL}.json if [[ ! $(cat ~/.zen/bunkerbox/history.${CHANNEL}.json | jq .Videos[].link | grep $VUID) ]]; then echo "ADD ~/.zen/bunkerbox/history.${CHANNEL}.json" # Bad characters breaks this command !! # cat ~/.zen/bunkerbox/history.${CHANNEL}.json | jq --arg INDEX "$INDEX" --arg TITLE "$TITLE" --arg VUID "$VUID" --arg TSVUID "TSVUID" '.Videos += [{"link": "
'''$TITLE''' "}]' > ~/.zen/tmp/history.${CHANNEL}.json cat ~/.zen/bunkerbox/history.${CHANNEL}.json | jq '.Videos += [{"link": "
'"'_TITLE_'"'"}]' > ~/.zen/bunkerbox/$VUID/media/history.${CHANNEL}.json sed -i "s~_INDEX_~$INDEX~g" ~/.zen/bunkerbox/$VUID/media/history.${CHANNEL}.json sed -i "s~_VUID_~$VUID~g" ~/.zen/bunkerbox/$VUID/media/history.${CHANNEL}.json sed -i "s~_TITLE_~$TITLE~g" ~/.zen/bunkerbox/$VUID/media/history.${CHANNEL}.json [[ "$(cat ~/.zen/bunkerbox/$VUID/media/history.${CHANNEL}.json)" == "" ]] && echo "NO history.${CHANNEL}.json FATAL ERROR" && exit 1 cp ~/.zen/bunkerbox/$VUID/media/history.${CHANNEL}.json ~/.zen/bunkerbox/history.${CHANNEL}.json fi ################# ## UPDATE GLOCAL HISTORY ? IsThere=$(cat ~/.zen/bunkerbox/history.json | jq .Videos[].link | grep $VUID) if [[ ! $IsThere ]]; then echo "Add $INDEX to ~/.zen/bunkerbox/$VUID/media/history.json" ## history.json Videos.link is the HTML code displayed in index.html with pagination.js (related to) cat ~/.zen/bunkerbox/history.json | jq '.Videos += [{"link": "
'"'_TITLE_'"'"}]' > ~/.zen/bunkerbox/$VUID/media/history.json # sed -i "s~_TSVUID_~$TS$VUID~g" ~/.zen/bunkerbox/$VUID/media/history.json # Makes different chain for each creator !! sed -i "s~_INDEX_~$INDEX~g" ~/.zen/bunkerbox/$VUID/media/history.json sed -i "s~_VUID_~$VUID~g" ~/.zen/bunkerbox/$VUID/media/history.json sed -i "s~_TITLE_~$TITLE~g" ~/.zen/bunkerbox/$VUID/media/history.json # COULD BE DONE LIKE THAT # cat ~/.zen/bunkerbox/$VUID/media/history.json | jq --arg INDEX "$INDEX" --arg TITLE "$TITLE" '.Videos += [{"link": "'''$TITLE'''"}]' > ~/.zen/bunkerbox/history.json echo "MISE A JOUR ~/.zen/bunkerbox/history.json" [[ "$(cat ~/.zen/bunkerbox/$VUID/media/history.json)" == "" ]] && echo "NO $VUID/media/history.json FATAL ERROR" && exit 1 # Upgrade local history.json with reverse new one if [[ -f ~/.zen/bunkerbox/$VUID/media/history.json ]]; then echo '{ "Videos":' > ~/.zen/bunkerbox/history.json cat ~/.zen/bunkerbox/$VUID/media/history.json | jq '.[] | reverse' >> ~/.zen/bunkerbox/history.json echo '}' >> ~/.zen/bunkerbox/history.json fi fi ################# VMAIN="/ipfs/$IPFSROOT/$VUID.m3u8" # UPDATING original JSON - TODO inform crowdbunker that IPFS copy is available. cat ~/.zen/bunkerbox/$VUID/media/$VUID.json | jq ".video.hlsManifest.url = \"$VMAIN\"" > ~/.zen/bunkerbox/$VUID/$VUID.json echo "TODO: CALL BACK SOURCE ... New HLS = $IPFSNGW$VMAIN" ################# # Create local index.html simple redirect to current IPFS video echo "" > ~/.zen/bunkerbox/index.html echo "===== INDEX ===== $IPFSNGW/ipfs/$IPFSROOT" echo "HISTORY : $IPFSNGW/ipfs/$IPFSROOT/history.json" ################# ################# ################# PS3="Comment voulez-vous publier votre collecte ? " choices=("debug" "local" "qo-op" "astrXbian") fav=$(cat ~/.zen/bunkerbox/choice 2>/dev/null) [[ ! $fav ]] && select fav in "${choices[@]}"; do [[ $fav ]] && break; done case $fav in "local") echo 'local' > ~/.zen/bunkerbox/choice echo "MODE 'local'" continue ;; "astrXbian") echo "MODE 'astrXbian' (DEV ZONE)" [[ ! -d ~/.zen/astrXbian ]] && echo "DEV ZONE - Installez astrXbian SVP ... P2P VideoClub DEMO - DEV ZONE !" && exit 1 [[ ! $IPFSNODEID ]] && echo "Missing IPFSNODEID. Exit" && exit 1 echo 'astrXbian' > ~/.zen/bunkerbox/choice mkdir -p ~/.zen/ipfs/.$IPFSNODEID/astroport/bunkerbox echo "" > ~/.zen/ipfs/.$IPFSNODEID/astroport/bunkerbox/index.html cp ~/.zen/bunkerbox/history.json ~/.zen/ipfs/.$IPFSNODEID/astroport/bunkerbox/ echo "BALISE Station :: $IPFSNGW/ipns/$IPFSNODEID/.$IPFSNODEID/astroport/bunkerbox/" echo "Propagation lors du prochain cycle astrXbian" continue ;; "qo-op") echo "MODE 'qo-op'" if [[ ! $(ipfs key list | grep 'qo-op') ]]; then echo "Clef qo-op manquante! (Missing qo-op key!)" echo "Récupérez la auprès de votre meilleur ami. Et ne brisez pas la chaine de confiance!" echo "(Get it from your best friend and do not break confidence ring!)" sleep 2 echo echo "Envoyez un email pour obtenir assistance. (Contact support@qo-op.com) ? HELP !" sleep 1 echo echo "Utiliser la clef 'qo-op' par défaut ? ENTRER pour OUI. Saisissez un caractère avant si NON." read KDEV if [[ "$KDEV" != "" ]]; then echo "La confiance est dans la CLEF (Confidence is in the KEY)." echo "Génération de la votre (here is yours): " publishkey=$(ipfs key gen qo-op) echo "~/.ipfs/keystore/key_ofxs233q" echo "Partagez cette clef avec vos amis pour créer votre chaine video en commun..." echo "$IPFSNGW/ipns/$publishkey" echo echo "$publishkey" > ~/.zen/bunkerbox/qo-op echo 'qo-op' > ~/.zen/bunkerbox/choice else ## USE DEV KEY echo "Activation clef 'qo-op' par défaut." echo "k51qzi5uqu5djt17zonkpg1cb8hrxhahpesybusz8q57j4ocqm0qlc6s99z60x" > ~/.zen/bunkerbox/qo-op cp ${MY_PATH}/key_ofxs233q ~/.ipfs/keystore/ fi else ## qo-op KEY IS ALREADY THERE. WRITE 'qo-op' IPNS key # Refreshing actual 'qo-op' key ipfs key list -l | grep 'qo-op' | cut -f 1 -d ' ' > ~/.zen/bunkerbox/qo-op fi echo 'qo-op' > ~/.zen/bunkerbox/choice IPNS=$(cat ~/.zen/bunkerbox/qo-op) echo echo "Chaine Vidéo 'qo-op' => $IPFSNGW/ipns/$IPNS" echo ##### NEW HOMEPAGE / NEW DYNAMIC DATA ###### HERE TIMESTAMPING IS OK InHere=$(cat ~/.zen/bunkerbox/history.qo-op.json | jq .Videos[].link | grep $VUID) if [[ ! $InHere ]]; then echo "BunkerBOX - NOUVELLE VIDEO - Mise à jour homepage & dynamic history(s).json" mkdir -p ~/.zen/bunkerbox/qo-op/ ## This is the welcome page of your qo-op channel. # Could be redirect, or ... Your homepage is introduced there !! # echo "" > ~/.zen/bunkerbox/qo-op/index.html # echo "" > ~/.zen/bunkerbox/qo-op/index.html cp -R ${MY_PATH}/templates/styles ~/.zen/bunkerbox/qo-op/ cp -R ${MY_PATH}/templates/js ~/.zen/bunkerbox/qo-op/ cp ${MY_PATH}/templates/homepage.html ~/.zen/bunkerbox/qo-op/index.html cp ${MY_PATH}/templates/crowbunkerbox.png ~/.zen/bunkerbox/qo-op/ sed -i "s~_IPNSL_~$IPNSL~g" ~/.zen/bunkerbox/qo-op/index.html cp ~/.zen/bunkerbox/history.json ~/.zen/bunkerbox/qo-op/history.json cp ~/.zen/bunkerbox/history.${CHANNEL}.json ~/.zen/bunkerbox/qo-op/history.${CHANNEL}.json echo "$TS" > ~/.zen/bunkerbox/qo-op/ts # TimeStamping echo "Adding ~/.zen/bunkerbox/qo-op/* to IPFS " VROOT=$(ipfs add -rwHq ~/.zen/bunkerbox/qo-op/* | tail -n 1) echo "'qo-op' update with /ipfs/$VROOT" ipfs name publish --key=qo-op /ipfs/$VROOT echo "HOME : $IPFSNGW/ipns/$IPNS/" echo "HISTORY : $IPFSNGW/ipns/$IPNS/history.json" fi continue ;; "debug") echo "debug" > ~/.zen/bunkerbox/choice continue ;; esac end=`date +%s`; echo ___Duration `expr $end - $start` seconds___ done