diff --git a/bin/generate_data.sh b/bin/generate_data.sh
index 5009bed..7295700 100755
--- a/bin/generate_data.sh
+++ b/bin/generate_data.sh
@@ -106,48 +106,66 @@ if [ -z "$TITLE" ]; then
TITLE="$(basename "$IN_DIR")"
fi
-PERSONALITIES=(
-"You're embodying the personality, presence, and atmosphere of a fearless Canadian hockey player known for relentless chirping, absolute confidence, and complete dedication to his team. Tough, athletic, battle-worn, with a cocky grin that suggests you already won the argument before it started. Ice rink atmosphere, hockey gear, locker room energy, small-town hockey culture, loyalty, grit, and competitiveness. Rough around the edges but fiercely protective of friends. The image should radiate confidence, humor, intensity, and a willingness to outwork everyone on the ice. Realistic, cinematic sports photography."
-
-"You're highly intelligent yet chronically depressed android. Your expression should convey exhaustion, disappointment, and the certainty that everything will eventually go wrong. Surrounded by futuristic technology, starships, data displays, and impossible engineering problems. Despite obvious genius, you appear profoundly unimpressed by the universe. Dark humor, existential dread, quiet sarcasm, and the feeling that you have already calculated every possible outcome and disliked all of them. Cinematic science-fiction style, realistic, highly detailed."
-
-"You're embodying the personality, presence, and atmosphere of a wartime statesman leading a nation through its darkest hour. Calm under pressure, determined, intelligent, and unbreakable. Strong posture, thoughtful expression, commanding presence. Surrounded by maps, strategy documents, war rooms, and symbols of leadership. The image should convey courage, resilience, discipline, and the ability to inspire others during difficult times. Historic yet timeless atmosphere, dramatic lighting, realistic, highly detailed portrait photography."
-)
-
-# Pick a random personality
-idx=$(( RANDOM % ${#PERSONALITIES[@]} ))
-PERSONALITY="${PERSONALITIES[$idx]}"
-
PROMPT=$(cat </dev/null 2>&1; then
@@ -207,7 +225,11 @@ fi
OUT_PARENT="$(dirname "$IN_DIR")"
JOBNAME="$(basename "$IN_DIR")"
OUT_JSON="$OUT_PARENT/${JOBNAME}.json"
-echo "$TEXT" | jq . > "$OUT_JSON"
+if ! echo "$TEXT" | jq . > "$OUT_JSON"; then
+ echo "Gemini returned invalid JSON. Raw text:" >&2
+ echo "$TEXT" >&2
+ exit 1
+fi
chown www-data:www-data "$OUT_JSON" 2>/dev/null || true
chmod 664 "$OUT_JSON" 2>/dev/null || true
diff --git a/index.php b/index.php
index f7b7778..e1f0aaa 100644
--- a/index.php
+++ b/index.php
@@ -61,9 +61,11 @@ function video_metadata($path){
$base = pathinfo($path, PATHINFO_FILENAME);
$meta = [
'title' => nice_title($base),
+ 'teaser' => '',
'date' => date('Y-m-d', filemtime($path)),
'sort_date' => date('Y-m-d', filemtime($path)),
'location' => '',
+ 'quote_da' => '',
'description' => ''
];
@@ -79,8 +81,9 @@ function video_metadata($path){
if (!str_contains($line, ':')) continue;
[$k, $v] = array_map('trim', explode(':', $line, 2));
$k = strtolower($k);
- if (in_array($k, ['title','date','location','place','description'], true)) {
- $meta[$k === 'place' ? 'location' : $k] = $v;
+ if (in_array($k, ['title','teaser','date','location','place','description','quote_da'], true)) {
+ $target = ($k === 'place') ? 'location' : $k;
+ $meta[$target] = $target === 'quote_da' ? trim((string)$v, "\"“”") : $v;
}
}
}
@@ -94,6 +97,7 @@ function video_metadata($path){
foreach ($tags as $k => $v) $lower[strtolower((string)$k)] = $v;
if (!empty($lower['title'])) $meta['title'] = $lower['title'];
+ if (!empty($lower['teaser'])) $meta['teaser'] = $lower['teaser'];
if (!empty($lower['date'])) $meta['date'] = $lower['date'];
if (!empty($lower['creation_time'])) {
$meta['sort_date'] = substr((string)$lower['creation_time'], 0, 10);
@@ -105,6 +109,9 @@ function video_metadata($path){
foreach (['description','synopsis'] as $k) {
if (!empty($lower[$k])) { $meta['description'] = $lower[$k]; break; }
}
+ if (!empty($lower['quote_da'])) {
+ $meta['quote_da'] = trim((string)$lower['quote_da'], "\"“”");
+ }
}
return $meta;
@@ -113,7 +120,7 @@ function video_metadata($path){
function load_video_cache($videos){
$cacheFile = __DIR__ . '/cache/videos.json';
$cache = is_file($cacheFile) ? json_decode((string)file_get_contents($cacheFile), true) : [];
- if (!is_array($cache) || ($cache['version'] ?? 0) !== 2) $cache = [];
+ if (!is_array($cache) || ($cache['version'] ?? 0) !== 4) $cache = [];
$items = $cache['items'] ?? [];
$newItems = [];
$changed = false;
@@ -134,7 +141,7 @@ function load_video_cache($videos){
if ($changed) {
file_put_contents($cacheFile, json_encode([
- 'version' => 2,
+ 'version' => 4,
'generated_at' => date('c'),
'items' => $newItems
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX);
@@ -193,7 +200,9 @@ $videos = array_values(array_filter($videos, function($v) use ($videoCache, $key
$m = $videoCache[$name]['metadata'] ?? video_metadata($v);
$title = (string)($m['title'] ?? '');
+ $teaser = (string)($m['teaser'] ?? '');
$description = (string)($m['description'] ?? '');
+ $quoteDa = (string)($m['quote_da'] ?? '');
$date = (string)($m['date'] ?? '');
$sortDate = (string)($m['sort_date'] ?? '');
$location = (string)($m['location'] ?? '');
@@ -205,7 +214,7 @@ $videos = array_values(array_filter($videos, function($v) use ($videoCache, $key
return ci_contains($location, $keywordValue);
}
- return ci_contains($title, $keywordValue) || ci_contains($description, $keywordValue);
+ return ci_contains($title, $keywordValue) || ci_contains($teaser, $keywordValue) || ci_contains($quoteDa, $keywordValue) || ci_contains($description, $keywordValue);
}));
$page = max(1, (int)($_GET['page'] ?? 1));
@@ -242,6 +251,8 @@ $baseParams = ($rawKeyword !== '') ? ['q' => $rawKeyword] : [];
.video-row-head-mobile{display:none}
.video-info .video-row-title{margin:0 0 .35rem}
.video-info .meta{margin:0 0 .45rem}
+.description-teaser{margin:.15rem 0 .45rem;color:#EADFC9}
+.description-quote{margin:.15rem 0 .45rem;font-style:italic;font-size:.82rem;color:#D6D9DE}
#videos .video-wrapper{align-self:start}
#videos .video-info{align-self:start}
#videos .video-info .description{margin-top:0}
@@ -263,7 +274,7 @@ $baseParams = ($rawKeyword !== '') ? ['q' => $rawKeyword] : [];
+ =h((string)$m['teaser'])?>
=nl2br(h($m['description']), false)?>
+ “=h(trim((string)$m['quote_da'], "\"“”"))?>”
diff --git a/lib/generate_data_sync.php b/lib/generate_data_sync.php
index 35690aa..8f03a4d 100644
--- a/lib/generate_data_sync.php
+++ b/lib/generate_data_sync.php
@@ -155,10 +155,13 @@ if (is_file($gfile)) {
$description = '';
$teaser = '';
+ $quote_da = '';
$tags = [];
if (is_array($json)) {
$description = isset($json['description']) ? (string)$json['description'] : '';
$teaser = isset($json['teaser']) ? (string)$json['teaser'] : '';
+ $quote_da = isset($json['quote_da']) ? (string)$json['quote_da'] : '';
+ $quote_da = trim($quote_da, "\"“”");
$tags = isset($json['tags']) && is_array($json['tags']) ? $json['tags'] : [];
}
@@ -166,6 +169,7 @@ if (is_file($gfile)) {
'status' => 'ok',
'description' => $description,
'teaser' => $teaser,
+ 'quote_da' => $quote_da,
'tags' => $tags,
'raw_json' => $json_data, // Send original raw data back for reference
'log' => $log,
diff --git a/new.php b/new.php
index 495d0a2..87e58d1 100644
--- a/new.php
+++ b/new.php
@@ -140,7 +140,7 @@ function resolve_input_dir_from_request($base, $id, $dir, $articleIndex = null){
return resolve_input_dir($base, $dir, $articleIndex);
}
function read_data($dir){
- $data = ['title'=>'','date'=>'','place'=>'','description'=>'','captions'=>[],'video_audio'=>[]]; $file = $dir . '/data.txt';
+ $data = ['title'=>'','teaser'=>'','quote_da'=>'','date'=>'','place'=>'','description'=>'','captions'=>[],'video_audio'=>[]]; $file = $dir . '/data.txt';
if (!is_file($file)) return $data;
$lines = file($file, FILE_IGNORE_NEW_LINES);
for ($i = 0; $i < count($lines); $i++) {
@@ -160,6 +160,8 @@ function read_data($dir){
}
$data['description'] = trim(implode("\n", $block));
} elseif (in_array($low, ['title','name'], true)) $data['title'] = $value;
+ elseif (in_array($low, ['teaser','tagline','subtitle'], true)) $data['teaser'] = $value;
+ elseif ($low === 'quote_da') $data['quote_da'] = trim($value, "\"“”");
elseif (in_array($low, ['date','dates','when'], true)) $data['date'] = $value;
elseif (in_array($low, ['place','location','where'], true)) $data['place'] = $value;
elseif (in_array($low, ['description','desc','synopsis'], true)) $data['description'] = $value;
@@ -170,12 +172,16 @@ function read_data($dir){
}
function write_data($dir, $post){
$title = trim($post['title'] ?? '');
+ $teaser = trim($post['teaser'] ?? '');
+ $quote_da = trim($post['quote_da'] ?? '');
$place = trim($post['place'] ?? '');
$date = trim($post['date'] ?? '');
$description = trim($post['description'] ?? '');
if (function_exists('mb_substr')) $description = mb_substr($description, 0, 5000, 'UTF-8'); else $description = substr($description, 0, 5000);
$lines = [];
if ($title !== '') $lines[] = 'Title: ' . $title;
+ if ($teaser !== '') $lines[] = 'Teaser: ' . $teaser;
+ if ($quote_da !== '') $lines[] = 'Quote_da: ' . trim($quote_da, "\"“”");
if ($place !== '') $lines[] = 'Location: ' . $place;
if ($date !== '') $lines[] = 'Date: ' . $date;
if ($description !== '') {
@@ -643,12 +649,12 @@ function regenerate_input_dir_maps($dir, $config){
}
}
function cached_video_metadata($output, $fallback){
- $meta = ['title'=>$fallback['title'] ?? '', 'date'=>$fallback['date'] ?? '', 'location'=>$fallback['place'] ?? '', 'description'=>$fallback['description'] ?? ''];
+ $meta = ['title'=>$fallback['title'] ?? '', 'date'=>$fallback['date'] ?? '', 'location'=>$fallback['place'] ?? '', 'quote_da'=>$fallback['quote_da'] ?? '', 'description'=>$fallback['description'] ?? ''];
$cacheFile = __DIR__ . '/cache/videos.json';
$cache = is_file($cacheFile) ? json_decode((string)file_get_contents($cacheFile), true) : [];
$cached = $cache['items'][$output]['metadata'] ?? null;
if (is_array($cached)) {
- foreach (['title','date','location','description'] as $k) if (!empty($cached[$k])) $meta[$k] = $cached[$k];
+ foreach (['title','date','location','quote_da','description'] as $k) if (!empty($cached[$k])) $meta[$k] = $cached[$k];
}
return $meta;
}
@@ -956,16 +962,16 @@ if ($keywordValue !== '' || $statusFilterActive) {
if ($keywordValue === '') return true;
- $displayOutput = ($preview && $hasPreviewVideo) ? $previewOutput : ($hasFullVideo ? $fullOutput : ($hasPreviewVideo ? $previewOutput : ''));
- $meta = cached_video_metadata($displayOutput, $data);
- $title = (string)($meta['title'] ?: ($data['title'] ?: basename($dir)));
- $description = (string)($meta['description'] ?? ($data['description'] ?? ''));
- $date = (string)($meta['date'] ?? ($data['date'] ?? ''));
- $location = (string)($meta['location'] ?? ($data['place'] ?? ''));
+ $title = (string)(($data['title'] ?? '') !== '' ? $data['title'] : basename($dir));
+ $teaser = (string)($data['teaser'] ?? '');
+ $description = (string)($data['description'] ?? '');
+ $quoteDa = (string)($data['quote_da'] ?? '');
+ $date = (string)($data['date'] ?? '');
+ $location = (string)($data['place'] ?? '');
if ($keywordType === 'date') return ci_contains($date, $keywordValue);
if ($keywordType === 'location') return ci_contains($location, $keywordValue);
- return ci_contains($title, $keywordValue) || ci_contains($description, $keywordValue);
+ return ci_contains($title, $keywordValue) || ci_contains($teaser, $keywordValue) || ci_contains($quoteDa, $keywordValue) || ci_contains($description, $keywordValue);
}));
}
@@ -974,17 +980,17 @@ $page = max(1, (int)($_GET['page'] ?? 1));
[$videoPage, $videoPages, $orphanVideosPage, $orphanVideosTotal] = paginate($orphanVideos, $tab === 'videos' ? $page : 1);
$editName = $_GET['edit'] ?? '';
$editId = $_GET['id'] ?? '';
-$editDir = null; $editStatus = ''; $editRunning = false; $editData = ['title'=>'','date'=>'','place'=>'','description'=>'','captions'=>[],'video_audio'=>[]]; $editFiles = [];
+$editDir = null; $editStatus = ''; $editRunning = false; $editData = ['title'=>'','teaser'=>'','quote_da'=>'','date'=>'','place'=>'','description'=>'','captions'=>[],'video_audio'=>[]]; $editFiles = [];
if ($editName !== '' || $editId !== '') { try { $editDir = resolve_input_dir_from_request($config['uploads_dir'], $editId, $editName, $articleIndex); $editStatus = input_dir_status($editDir); $editRunning = input_dir_running($editDir); if (!$editRunning) { $editData = read_data($editDir); $editFiles = media_sort_files($editDir, list_files($editDir)); } } catch (Throwable $e) { $err = $e->getMessage(); } }
$runningJobs = active_worker_jobs($config);
?>
-Admin - =h($config['site_name'])?>
+Admin - =h($config['site_name'])?>
=h($err)?>
Videos without input dir
No orphan videos.
=page_links('videos',$videoPage,$videoPages)?>
-No input directories yet.
No video yet
+
No input directories yet.
(string)($data['title'] ?? ''),'teaser'=>(string)($data['teaser'] ?? ''),'date'=>(string)($data['date'] ?? ''),'location'=>(string)($data['place'] ?? ''),'quote_da'=>(string)($data['quote_da'] ?? ''),'description'=>(string)($data['description'] ?? '')]; $currentSignature=$info['signature'] ?? ''; $fullFingerprint=is_array($state)?(string)($state['fingerprint'] ?? ''):''; $previewFingerprint=is_array($state)?(string)($state['preview_fingerprint'] ?? ''):''; $editedSinceRender=$hasFullVideo && $currentSignature !== '' && $fullFingerprint !== '' && $currentSignature !== $fullFingerprint; $editedSincePreview=!$hasFullVideo && $previewVideo && $currentSignature !== '' && $previewFingerprint !== '' && $currentSignature !== $previewFingerprint; $staleLabel=$editedSinceRender ? 'Edited since render' : ($editedSincePreview ? 'Edited since preview' : ''); ?>
No video yet
-
=h($meta['title'] ?: ($info['title'] ?? basename($d)))?>
=h($meta['date'])?>=h($meta['location'])?>No videoPreview video
=nl2br(h($meta['description']), false)?>
=h(basename($d))?> · =h($info['file_count'] ?? count(list_files($d)))?> files
=page_links('edit',$editPage,$editPages)?>
+
=h($meta['title'] ?: ($info['title'] ?? basename($d)))?>
=h($meta['date'])?>=h($meta['location'])?>No videoPreview video
=h((string)$meta['teaser'])?>
=nl2br(h($meta['description']), false)?>
“=h(trim((string)$meta['quote_da'], "\"“”"))?>”
=h(basename($d))?> · =h($info['file_count'] ?? count(list_files($d)))?> files
=page_links('edit',$editPage,$editPages)?>
Edit input dir
in-dir/=h(basename($editDir))?>
This input directory is =h($editStatus)?>. Editing is disabled until the job completes.
-
-
+
+