#!/bin/sh
# SecuBox Hub Generator v5 - MetaBlogizer + Streamlit + PeerTube videos
OUTPUT="/www/gk2-hub/index.html"
TEMP="/tmp/hub_gen_$$.html"
DATE=$(date "+%Y-%m-%d %H:%M")
PEERTUBE_API="http://192.168.255.1:9001/api/v1"
PEERTUBE_URL="https://tube.gk2.secubox.in"
categorize_site() {
local name=$(echo "$1" | tr '[:upper:]' '[:lower:]')
case "$name" in
*intel*|*dgse*|*osint*|*threat*|*secu*|*raid*|*confid*|*mku*|*bdgse*|*camus*) echo "Intelligence" ;;
*game*|*play*|*comic*|*virus*|*survie*) echo "Divertissement" ;;
*dev*|*code*|*git*|*sdlc*|*crt*|*fabric*|*hermes*) echo "Développement" ;;
*doc*|*manual*|*guide*|*how*|*fm*|*bgp*|*lrh*|*bcf*) echo "Documentation" ;;
*media*|*video*|*tube*|*stream*|*radio*|*lyrion*|*jellyfin*) echo "Média" ;;
*blog*|*news*|*press*|*zine*|*flash*|*pub*) echo "Actualités" ;;
*cloud*|*file*|*nextcloud*|*photo*) echo "Cloud" ;;
*admin*|*control*|*status*|*hub*|*glances*|*holo*|*console*|*evolution*) echo "Administration" ;;
*money*|*coin*|*crypto*|*cgv*|*cpi*|*apr*) echo "Finance" ;;
*geo*|*map*|*gondwana*|*earth*) echo "Géographie" ;;
*psy*|*oracle*|*yijing*|*bazi*|*equa*|*lunaquar*|*clock*|*wuyun*|*yling*|*pix*|*tam*) echo "Ésotérique" ;;
*metabol*|*osint*|*generix*|*swg*|*ftvm*|*cpf*) echo "Outils" ;;
*) echo "Projets" ;;
esac
}
get_emoji() {
case "$1" in
"Intelligence") echo "🔍" ;;
"Divertissement") echo "🎮" ;;
"Développement") echo "💻" ;;
"Documentation") echo "📚" ;;
"Média") echo "🎬" ;;
"Actualités") echo "📰" ;;
"Cloud") echo "☁️" ;;
"Administration") echo "⚙️" ;;
"Finance") echo "💰" ;;
"Géographie") echo "🌍" ;;
"Ésotérique") echo "🔮" ;;
"Outils") echo "🛠️" ;;
"Streamlit") echo "📊" ;;
"PeerTube") echo "🎥" ;;
*) echo "📄" ;;
esac
}
format_duration() {
local sec=$1
local min=$((sec / 60))
local s=$((sec % 60))
if [ $min -ge 60 ]; then
local h=$((min / 60))
min=$((min % 60))
printf "%d:%02d:%02d" $h $min $s
else
printf "%d:%02d" $min $s
fi
}
# HTML Header
cat > "$TEMP" << 'HTMLHEAD'
HTMLHEAD
# Header
cat >> "$TEMP" << EOF
🔒 Certains contenus nécessitent une authentification
Se connecter
EOF
# Collect all sites
SITES_FILE="/tmp/hub_sites_$$.txt"
CAT_FILE="/tmp/hub_cats_$$.txt"
VIDEOS_FILE="/tmp/hub_videos_$$.txt"
> "$SITES_FILE"
> "$CAT_FILE"
> "$VIDEOS_FILE"
# MetaBlogizer sites
uci show metablogizer 2>/dev/null | grep "=site$" | sed "s/metablogizer\.\(.*\)=site/\1/" | while read site; do
name=$(uci -q get "metablogizer.$site.name")
domain=$(uci -q get "metablogizer.$site.domain")
enabled=$(uci -q get "metablogizer.$site.enabled")
auth_required=$(uci -q get "metablogizer.$site.auth_required")
[ "$enabled" != "1" ] && continue
[ -z "$domain" ] && continue
cat=$(categorize_site "$name")
emoji=$(get_emoji "$cat")
echo "$cat" >> "$CAT_FILE"
# 7th field: protected (use - placeholder for empty thumb to fix BusyBox read)
protected="-"
[ "$auth_required" = "1" ] && protected="protected"
printf '%s\t%s\t%s\t%s\tmeta\t-\t%s\n' "$domain" "$name" "$cat" "$emoji" "$protected" >> "$SITES_FILE"
done
# Streamlit instances
uci show streamlit 2>/dev/null | grep "=instance$" | sed "s/streamlit\.\(.*\)=instance/\1/" | while read app; do
name=$(uci -q get "streamlit.$app.name")
domain=$(uci -q get "streamlit.$app.domain")
enabled=$(uci -q get "streamlit.$app.enabled")
[ "$enabled" != "1" ] && continue
[ -z "$domain" ] && continue
cat=$(categorize_site "$name")
emoji=$(get_emoji "$cat")
echo "$cat" >> "$CAT_FILE"
printf '%s\t%s\t%s\t%s\tstreamlit\t-\t-\n' "$domain" "$name" "$cat" "$emoji" >> "$SITES_FILE"
done
# PeerTube videos
VIDEOS_JSON=$(curl -s "${PEERTUBE_API}/videos?count=50" 2>/dev/null)
TOTAL_VIDEOS=0
if [ -n "$VIDEOS_JSON" ]; then
# Parse videos using jsonfilter
echo "$VIDEOS_JSON" | jsonfilter -e '@.data[*]' 2>/dev/null | while read -r video_line; do
# Skip if empty
[ -z "$video_line" ] && continue
uuid=$(echo "$VIDEOS_JSON" | jsonfilter -e "@.data[$TOTAL_VIDEOS].uuid" 2>/dev/null)
name=$(echo "$VIDEOS_JSON" | jsonfilter -e "@.data[$TOTAL_VIDEOS].name" 2>/dev/null)
thumb=$(echo "$VIDEOS_JSON" | jsonfilter -e "@.data[$TOTAL_VIDEOS].thumbnailPath" 2>/dev/null)
duration=$(echo "$VIDEOS_JSON" | jsonfilter -e "@.data[$TOTAL_VIDEOS].duration" 2>/dev/null)
[ -z "$uuid" ] && break
[ -z "$name" ] && continue
# Format duration
dur_fmt=$(format_duration "$duration")
# Video URL and thumbnail
video_url="${PEERTUBE_URL}/w/${uuid}"
thumb_url="${PEERTUBE_URL}${thumb}"
echo "Média" >> "$CAT_FILE"
printf '%s\t%s\tMédia\t🎥\tvideo\t%s\t%s\n' "$video_url" "$name" "$thumb_url" "$dur_fmt" >> "$VIDEOS_FILE"
TOTAL_VIDEOS=$((TOTAL_VIDEOS + 1))
done
# Alternative parsing if jsonfilter fails
if [ ! -s "$VIDEOS_FILE" ]; then
# Use simple sed/awk parsing
echo "$VIDEOS_JSON" | sed 's/},/}\n/g' | while read -r line; do
uuid=$(echo "$line" | sed -n 's/.*"uuid":"\([^"]*\)".*/\1/p')
name=$(echo "$line" | sed -n 's/.*"name":"\([^"]*\)".*/\1/p' | head -1)
thumb=$(echo "$line" | sed -n 's/.*"thumbnailPath":"\([^"]*\)".*/\1/p')
duration=$(echo "$line" | sed -n 's/.*"duration":\([0-9]*\).*/\1/p')
[ -z "$uuid" ] && continue
[ -z "$name" ] && continue
dur_fmt=$(format_duration "${duration:-0}")
video_url="${PEERTUBE_URL}/w/${uuid}"
thumb_url="${PEERTUBE_URL}${thumb}"
echo "Média" >> "$CAT_FILE"
printf '%s\t%s\tMédia\t🎥\tvideo\t%s\t%s\n' "$video_url" "$name" "$thumb_url" "$dur_fmt" >> "$VIDEOS_FILE"
done
fi
fi
# Merge videos into sites file
cat "$VIDEOS_FILE" >> "$SITES_FILE" 2>/dev/null
# Stats
TOTAL=$(wc -l < "$SITES_FILE" | tr -d ' ')
TOTAL_META=$(grep " meta " "$SITES_FILE" | wc -l | tr -d ' ')
TOTAL_STREAMLIT=$(grep " streamlit " "$SITES_FILE" | wc -l | tr -d ' ')
TOTAL_VIDEOS=$(grep " video " "$SITES_FILE" | wc -l | tr -d ' ')
CAT_COUNTS=$(grep -v "^$" "$CAT_FILE" 2>/dev/null | sort | uniq -c | sort -rn)
# Stats bar
cat >> "$TEMP" << EOF
$TOTALTotal
$TOTAL_METASites
$TOTAL_STREAMLITStreamlit
$TOTAL_VIDEOSVidéos
EOF
echo "$CAT_COUNTS" | head -3 | while read count cat; do
[ -n "$cat" ] && printf '
%s%s
\n' "$count" "$cat" >> "$TEMP"
done
echo "
" >> "$TEMP"
# Tag cloud
echo '
' >> "$TEMP"
echo 'Tous' >> "$TEMP"
echo '📝 Sites' >> "$TEMP"
echo '📊 Streamlit' >> "$TEMP"
echo '🎥 Vidéos' >> "$TEMP"
echo "$CAT_COUNTS" | while read count cat; do
[ -n "$cat" ] && printf '%s%s\n' "$cat" "$cat" "$count" >> "$TEMP"
done
echo '
' >> "$TEMP"
# Category tabs
echo '
' >> "$TEMP"
printf '
📁 Tous%s
\n' "$TOTAL" >> "$TEMP"
printf '
📝 Sites%s
\n' "$TOTAL_META" >> "$TEMP"
printf '
📊 Streamlit%s
\n' "$TOTAL_STREAMLIT" >> "$TEMP"
printf '
🎥 Vidéos%s
\n' "$TOTAL_VIDEOS" >> "$TEMP"
echo "$CAT_COUNTS" | head -6 | while read count cat; do
emoji=$(get_emoji "$cat")
[ -n "$cat" ] && printf '
%s %s%s
\n' "$cat" "$emoji" "$cat" "$count" >> "$TEMP"
done
echo '
' >> "$TEMP"
# Sites grid
echo '
' >> "$TEMP"
while IFS=' ' read -r url name cat emoji type thumb protected; do
[ -z "$url" ] && continue
# Handle placeholder values (- means empty, used for BusyBox read compatibility)
[ "$thumb" = "-" ] && thumb=""
[ "$protected" = "-" ] && protected=""
# For videos, 'thumb' is thumbnail URL and 'protected' is duration
duration=""
if [ "$type" = "video" ]; then
duration="$protected"
protected=""
fi
protected_attr=""
protected_badge=""
if [ "$protected" = "protected" ]; then
protected_attr="data-protected=\"1\""
protected_badge="
🔒"
fi
if [ "$type" = "streamlit" ]; then
card_class="site-card streamlit"
cat_class="card-cat streamlit"
preview_html="
"
elif [ "$type" = "video" ]; then
card_class="site-card video"
cat_class="card-cat video"
preview_html="
$duration"
else
card_class="site-card"
cat_class="card-cat meta"
preview_html="
"
fi
# URL handling - videos already have full URL
if [ "$type" = "video" ]; then
link_url="$url"
domain_display="tube.gk2.secubox.in"
else
link_url="https://$url/"
domain_display="$url"
fi
cat >> "$TEMP" << CARD
$preview_html
$protected_badge
$name
$domain_display
$emoji $cat
CARD
done < "$SITES_FILE"
echo '
' >> "$TEMP"
# Footer and JS
cat >> "$TEMP" << 'FOOTER'
FOOTER
rm -f "$SITES_FILE" "$CAT_FILE" "$VIDEOS_FILE"
mv "$TEMP" "$OUTPUT"
chmod 644 "$OUTPUT"
logger -t hub-generator "Hub v5: $TOTAL items ($TOTAL_META sites + $TOTAL_STREAMLIT streamlit + $TOTAL_VIDEOS videos)"