diff --git a/package/secubox/secubox-app-gk2hub/files/usr/sbin/hub-generator b/package/secubox/secubox-app-gk2hub/files/usr/sbin/hub-generator index cf90f757..20b5be1c 100755 --- a/package/secubox/secubox-app-gk2hub/files/usr/sbin/hub-generator +++ b/package/secubox/secubox-app-gk2hub/files/usr/sbin/hub-generator @@ -1,5 +1,6 @@ #!/bin/sh -# SecuBox Hub Generator v6 - MetaBlogizer + Streamlit + PeerTube + NFO Support +# SecuBox Hub Generator v7 - Full NFO Integration + Capability Filters +# Enhanced with MetaBlog NFO, version display, capability filtering, audience tabs OUTPUT="/www/gk2-hub/index.html" TEMP="/tmp/hub_gen_$$.html" @@ -190,6 +191,17 @@ body{background:var(--bg);color:var(--text);font-family:'Segoe UI',system-ui,san .card-caps{display:flex;flex-wrap:wrap;gap:3px;margin-top:6px} .cap-badge{font-size:0.6rem;padding:2px 6px;background:rgba(124,58,237,0.2);color:var(--accent2);border-radius:10px;border:1px solid rgba(124,58,237,0.3)} .card-keywords{font-size:0.65rem;color:var(--muted);margin-top:4px;font-style:italic} +.card-header{display:flex;align-items:center;justify-content:space-between;gap:8px} +.card-version{font-size:0.65rem;padding:2px 6px;background:rgba(0,212,255,0.15);color:var(--accent);border-radius:4px;font-family:monospace;white-space:nowrap} +.cap-cloud{display:flex;flex-wrap:wrap;gap:6px;padding:12px 20px;background:var(--surface);border-radius:8px;margin-bottom:12px;align-items:center} +.cap-title,.audience-title{color:var(--muted);font-size:0.8rem;margin-right:8px} +.cap-filter{padding:4px 10px;background:rgba(124,58,237,0.15);border:1px solid rgba(124,58,237,0.3);color:var(--accent2);border-radius:15px;font-size:0.75rem;cursor:pointer;transition:all 0.2s} +.cap-filter:hover,.cap-filter.active{background:var(--accent2);color:#fff;border-color:var(--accent2)} +.cap-filter .count{font-size:0.65rem;opacity:0.7;margin-left:3px} +.audience-bar{display:flex;flex-wrap:wrap;gap:8px;padding:10px 20px;background:var(--surface);border-radius:8px;margin-bottom:12px;align-items:center} +.audience-btn{padding:5px 12px;background:var(--surface2);border:1px solid var(--border);border-radius:6px;font-size:0.8rem;cursor:pointer;transition:all 0.2s} +.audience-btn:hover,.audience-btn.active{background:var(--accent3);color:#fff;border-color:var(--accent3)} +.audience-btn .count{font-size:0.7rem;opacity:0.7;margin-left:4px} .lock-badge{position:absolute;top:8px;right:8px;background:rgba(0,0,0,0.7);padding:4px 8px;border-radius:4px;font-size:0.8rem} .site-card[data-protected]{display:none} .site-card[data-protected].unlocked{display:flex} @@ -199,7 +211,20 @@ body{background:var(--bg);color:var(--text);font-family:'Segoe UI',system-ui,san .login-banner a:hover{background:var(--accent);color:#000} .footer{margin-top:40px;padding:20px 0;border-top:1px solid var(--border);text-align:center;color:var(--muted);font-size:0.8rem} .footer a{color:var(--accent);text-decoration:none} -@media(max-width:768px){.header{flex-direction:column;align-items:flex-start}.view-list .site-card{flex-direction:column}.view-list .card-preview{width:100%}} +.preview-btn{position:absolute;top:8px;left:8px;width:32px;height:32px;background:rgba(0,0,0,0.8);border:1px solid var(--accent);border-radius:6px;color:var(--accent);cursor:pointer;font-size:1rem;opacity:0;transition:all 0.2s;display:flex;align-items:center;justify-content:center} +.site-card:hover .preview-btn{opacity:1} +.preview-btn:hover{background:var(--accent);color:#000} +.preview-modal{position:fixed;inset:0;background:rgba(0,0,0,0.9);z-index:1000;display:none;align-items:center;justify-content:center;padding:20px} +.preview-modal.active{display:flex} +.preview-content{width:95%;max-width:1400px;height:90vh;background:var(--surface);border-radius:12px;overflow:hidden;display:flex;flex-direction:column;border:1px solid var(--border)} +.preview-close{position:absolute;top:15px;right:20px;width:36px;height:36px;background:var(--surface2);border:1px solid var(--border);border-radius:8px;color:var(--text);cursor:pointer;font-size:1.5rem;z-index:10} +.preview-close:hover{background:var(--accent);color:#000;border-color:var(--accent)} +#previewFrame{flex:1;border:none;width:100%;background:#fff} +.preview-info{padding:12px 20px;background:var(--surface2);display:flex;justify-content:space-between;align-items:center;border-top:1px solid var(--border)} +#previewTitle{font-weight:600;font-size:1rem} +#previewLink{color:var(--accent);text-decoration:none;padding:6px 12px;border:1px solid var(--accent);border-radius:6px;font-size:0.85rem} +#previewLink:hover{background:var(--accent);color:#000} +@media(max-width:768px){.header{flex-direction:column;align-items:flex-start}.view-list .site-card{flex-direction:column}.view-list .card-preview{width:100%}.preview-content{width:100%;height:100vh;border-radius:0}}
@@ -239,7 +264,7 @@ VIDEOS_FILE="/tmp/hub_videos_$$.txt" > "$CAT_FILE" > "$VIDEOS_FILE" -# MetaBlogizer sites +# MetaBlogizer sites - now with full NFO support 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") @@ -247,13 +272,53 @@ uci show metablogizer 2>/dev/null | grep "=site$" | sed "s/metablogizer\.\(.*\)= auth_required=$(uci -q get "metablogizer.$site.auth_required") [ "$enabled" != "1" ] && continue [ -z "$domain" ] && continue - cat=$(categorize_site "$name") + + # Get full NFO metadata for MetaBlog sites + site_dir="$METABLOG_SITES_DIR/$name" + nfo_data=$(get_nfo_full "$site_dir" 2>/dev/null) + + if [ -n "$nfo_data" ]; then + nfo_cat=$(echo "$nfo_data" | cut -d'|' -f1) + nfo_desc=$(echo "$nfo_data" | cut -d'|' -f2) + nfo_keywords=$(echo "$nfo_data" | cut -d'|' -f3) + nfo_caps=$(echo "$nfo_data" | cut -d'|' -f4) + nfo_audience=$(echo "$nfo_data" | cut -d'|' -f5) + nfo_version=$(get_nfo_info "$site_dir" "identity" "version" "") + else + nfo_cat="" + nfo_desc="" + nfo_keywords="" + nfo_caps="" + nfo_audience="" + nfo_version="" + fi + + # Use NFO category or fallback to name-based categorization + if [ -n "$nfo_cat" ]; then + cat="$nfo_cat" + else + cat=$(categorize_site "$name") + fi emoji=$(get_emoji "$cat") echo "$cat" >> "$CAT_FILE" - # 7th field: protected (use - placeholder for empty thumb to fix BusyBox read) + + # Track audiences for filter tabs + [ -n "$nfo_audience" ] && echo "$nfo_audience" >> "/tmp/hub_audiences_$$.txt" + + # Track capabilities for filter + if [ -n "$nfo_caps" ]; then + for cap in $(echo "$nfo_caps" | tr ',' ' '); do + [ -n "$cap" ] && echo "$cap" >> "/tmp/hub_caps_$$.txt" + done + fi + 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" + + # Format: domain name cat emoji type thumb protected desc keywords caps version audience + printf '%s\t%s\t%s\t%s\tmeta\t-\t%s\t%s\t%s\t%s\t%s\t%s\n' \ + "$domain" "$name" "$cat" "$emoji" "$protected" \ + "${nfo_desc:--}" "${nfo_keywords:--}" "${nfo_caps:--}" "${nfo_version:--}" "${nfo_audience:--}" >> "$SITES_FILE" done # Streamlit instances @@ -274,12 +339,14 @@ uci show streamlit 2>/dev/null | grep "=instance$" | sed "s/streamlit\.\(.*\)=in nfo_keywords=$(echo "$nfo_data" | cut -d'|' -f3) nfo_caps=$(echo "$nfo_data" | cut -d'|' -f4) nfo_audience=$(echo "$nfo_data" | cut -d'|' -f5) + nfo_version=$(get_nfo_info "$app_dir" "identity" "version" "") else nfo_cat="" nfo_desc="" nfo_keywords="" nfo_caps="" nfo_audience="" + nfo_version="" fi if [ -n "$nfo_cat" ]; then @@ -289,8 +356,21 @@ uci show streamlit 2>/dev/null | grep "=instance$" | sed "s/streamlit\.\(.*\)=in fi emoji=$(get_emoji "$cat") echo "$cat" >> "$CAT_FILE" - # Format: domain name cat emoji type thumb protected desc keywords caps - printf '%s\t%s\t%s\t%s\tstreamlit\t-\t-\t%s\t%s\t%s\n' "$domain" "$name" "$cat" "$emoji" "$nfo_desc" "$nfo_keywords" "$nfo_caps" >> "$SITES_FILE" + + # Track audiences for filter tabs + [ -n "$nfo_audience" ] && echo "$nfo_audience" >> "/tmp/hub_audiences_$$.txt" + + # Track capabilities for filter + if [ -n "$nfo_caps" ]; then + for cap in $(echo "$nfo_caps" | tr ',' ' '); do + [ -n "$cap" ] && echo "$cap" >> "/tmp/hub_caps_$$.txt" + done + fi + + # Format: domain name cat emoji type thumb protected desc keywords caps version audience + printf '%s\t%s\t%s\t%s\tstreamlit\t-\t-\t%s\t%s\t%s\t%s\t%s\n' \ + "$domain" "$name" "$cat" "$emoji" \ + "${nfo_desc:--}" "${nfo_keywords:--}" "${nfo_caps:--}" "${nfo_version:--}" "${nfo_audience:--}" >> "$SITES_FILE" done # Also check streamlit-forge config @@ -313,11 +393,15 @@ uci show streamlit-forge 2>/dev/null | grep "=app$" | sed "s/streamlit-forge\.\( nfo_desc=$(echo "$nfo_data" | cut -d'|' -f2) nfo_keywords=$(echo "$nfo_data" | cut -d'|' -f3) nfo_caps=$(echo "$nfo_data" | cut -d'|' -f4) + nfo_audience=$(echo "$nfo_data" | cut -d'|' -f5) + nfo_version=$(get_nfo_info "$app_dir" "identity" "version" "") else nfo_cat="" nfo_desc="" nfo_keywords="" nfo_caps="" + nfo_audience="" + nfo_version="" fi if [ -n "$nfo_cat" ]; then @@ -327,7 +411,18 @@ uci show streamlit-forge 2>/dev/null | grep "=app$" | sed "s/streamlit-forge\.\( fi emoji=$(get_emoji "$cat") echo "$cat" >> "$CAT_FILE" - printf '%s\t%s\t%s\t%s\tstreamlit\t-\t-\t%s\t%s\t%s\n' "$domain" "$name" "$cat" "$emoji" "$nfo_desc" "$nfo_keywords" "$nfo_caps" >> "$SITES_FILE" + + # Track audiences and capabilities + [ -n "$nfo_audience" ] && echo "$nfo_audience" >> "/tmp/hub_audiences_$$.txt" + if [ -n "$nfo_caps" ]; then + for cap in $(echo "$nfo_caps" | tr ',' ' '); do + [ -n "$cap" ] && echo "$cap" >> "/tmp/hub_caps_$$.txt" + done + fi + + printf '%s\t%s\t%s\t%s\tstreamlit\t-\t-\t%s\t%s\t%s\t%s\t%s\n' \ + "$domain" "$name" "$cat" "$emoji" \ + "${nfo_desc:--}" "${nfo_keywords:--}" "${nfo_caps:--}" "${nfo_version:--}" "${nfo_audience:--}" >> "$SITES_FILE" done # PeerTube videos @@ -392,6 +487,13 @@ 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) +# Capability and audience counts +CAPS_FILE="/tmp/hub_caps_$$.txt" +AUDIENCES_FILE="/tmp/hub_audiences_$$.txt" +[ -f "$CAPS_FILE" ] && CAP_COUNTS=$(sort "$CAPS_FILE" | uniq -c | sort -rn | head -10) || CAP_COUNTS="" +[ -f "$AUDIENCES_FILE" ] && AUDIENCE_COUNTS=$(sort "$AUDIENCES_FILE" | uniq -c | sort -rn) || AUDIENCE_COUNTS="" +TOTAL_WITH_NFO=$(grep -v " - - - - -$" "$SITES_FILE" 2>/dev/null | wc -l | tr -d ' ') + # Stats bar cat >> "$TEMP" << EOF " >> "$TEMP" -# Tag cloud +# Tag cloud - categories echo '