diff options
| author | sillylaird <sillyfanboy@gmail.com> | 2026-09-03 00:33:59 +0000 |
|---|---|---|
| committer | sillylaird <sillyfanboy@gmail.com> | 2026-09-03 00:33:59 +0000 |
| commit | 898b52edcb47bcb3e9d6106e74ca73e74ea01e70 (patch) | |
| tree | 85c6ee5ad58b860144551184d4cf86b560c62b91 /partials/partials_vibe.php | |
| download | www-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.tar.gz www-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.zip | |
Diffstat (limited to 'partials/partials_vibe.php')
| -rw-r--r-- | partials/partials_vibe.php | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/partials/partials_vibe.php b/partials/partials_vibe.php new file mode 100644 index 0000000..aa77598 --- /dev/null +++ b/partials/partials_vibe.php @@ -0,0 +1,212 @@ +<?php +// partials/vibe.php — renders "My Current Vibe" section +// Reads from vibe.php config, detects URL type and embeds accordingly. + +$vibe = file_exists(__DIR__ . '/../vibe.php') + ? require __DIR__ . '/../vibe.php' + : ['description' => '', 'url' => '', 'updated' => '']; + +$vibe_section_title_raw = $vibe_section_title ?? 'My Current Vibe'; +$vibe_desc_raw = trim((string)($vibe['description'] ?? '')); +$vibe_url = $vibe['url'] ?? ''; +$vibe_updated = htmlspecialchars($vibe['updated'] ?? '', ENT_QUOTES, 'UTF-8'); + +// Hide description if it is empty or duplicates the section heading +$show_desc = $vibe_desc_raw !== '' && strcasecmp($vibe_desc_raw, $vibe_section_title_raw) !== 0; +$vibe_desc = htmlspecialchars($vibe_desc_raw, ENT_QUOTES, 'UTF-8'); + +function vibe_detect_type(string $url): string { + if (empty($url)) return 'none'; + $path = strtolower(parse_url($url, PHP_URL_PATH) ?? ''); + $ext = pathinfo($path, PATHINFO_EXTENSION); + + $images = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg', 'avif']; + $videos = ['mp4', 'webm', 'ogv', 'mov']; + $audio = ['mp3', 'flac', 'wav', 'ogg', 'aac', 'opus', 'm4a']; + + if (in_array($ext, $images)) return 'image'; + if (in_array($ext, $videos)) return 'video'; + if (in_array($ext, $audio)) return 'audio'; + + if (preg_match('/(?:youtube\.com\/watch\?.*v=|youtu\.be\/|youtube\.com\/shorts\/)([A-Za-z0-9_-]{11})/', $url, $m)) + return 'youtube:' . $m[1]; + + if (preg_match('/vimeo\.com\/(?:video\/)?(\d+)/', $url, $m)) + return 'vimeo:' . $m[1]; + + // Dailymotion: dailymotion.com/video/{id} or dai.ly/{id} (id may have a _slug) + if (preg_match('#(?:dailymotion\.com/video|dai\.ly)/([A-Za-z0-9]+)#i', $url, $m)) + return 'dailymotion:' . $m[1]; + + // Bilibili: bilibili.com/video/{BVxxxx} (BV id) or /video/av{n} + if (preg_match('#bilibili\.com/video/(BV[A-Za-z0-9]+)#i', $url, $m)) + return 'bilibili:bvid:' . $m[1]; + if (preg_match('#bilibili\.com/video/av(\d+)#i', $url, $m)) + return 'bilibili:aid:' . $m[1]; + + // Niconico: nicovideo.jp/watch/{sm123} or nico.ms/{sm123} + if (preg_match('#(?:nicovideo\.jp/watch|nico\.ms)/((?:sm|nm|so)?\d+)#i', $url, $m)) + return 'niconico:' . $m[1]; + + return 'link'; +} + +// Extract ?t= / &t= / #t= start offset for YouTube (supports `90`, `1m30s`, `1h2m3s`) +function vibe_youtube_start(string $url): int { + $q = []; + parse_str((string)parse_url($url, PHP_URL_QUERY), $q); + $t = $q['t'] ?? $q['start'] ?? null; + if ($t === null) { + $frag = parse_url($url, PHP_URL_FRAGMENT) ?? ''; + if (preg_match('/(?:^|&)t=([^&]+)/', $frag, $m)) $t = $m[1]; + } + if ($t === null) return 0; + if (ctype_digit((string)$t)) return (int)$t; + if (preg_match('/^(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?$/', $t, $m)) { + return ((int)($m[1] ?? 0)) * 3600 + ((int)($m[2] ?? 0)) * 60 + ((int)($m[3] ?? 0)); + } + return 0; +} + +// Map a detected iframe-provider type to an embed URL + friendly label. +// Returns [] for non-iframe types (image/audio/video/link/none). +function vibe_provider_embed(string $type, string $url): array { + if (str_starts_with($type, 'youtube:')) { + $id = substr($type, 8); + $start = vibe_youtube_start($url); + $embed = 'https://www.youtube-nocookie.com/embed/' . rawurlencode($id) + . '?rel=0&modestbranding=1' . ($start > 0 ? '&start=' . $start : ''); + return ['embed' => $embed, 'label' => 'YouTube']; + } + if (str_starts_with($type, 'vimeo:')) { + $id = substr($type, 6); + return ['embed' => 'https://player.vimeo.com/video/' . rawurlencode($id) . '?dnt=1', 'label' => 'Vimeo']; + } + if (str_starts_with($type, 'dailymotion:')) { + $id = substr($type, 12); + return ['embed' => 'https://geo.dailymotion.com/player.html?video=' . rawurlencode($id), 'label' => 'Dailymotion']; + } + if (str_starts_with($type, 'bilibili:bvid:')) { + $id = substr($type, 14); + return ['embed' => 'https://player.bilibili.com/player.html?bvid=' . rawurlencode($id) . '&page=1&high_quality=1&danmaku=0', 'label' => 'Bilibili']; + } + if (str_starts_with($type, 'bilibili:aid:')) { + $id = substr($type, 13); + return ['embed' => 'https://player.bilibili.com/player.html?aid=' . rawurlencode($id) . '&page=1&high_quality=1&danmaku=0', 'label' => 'Bilibili']; + } + if (str_starts_with($type, 'niconico:')) { + $id = substr($type, 9); + return ['embed' => 'https://embed.nicovideo.jp/watch/' . rawurlencode($id), 'label' => 'Niconico']; + } + return []; +} + +$type = vibe_detect_type($vibe_url); +$safe_url = htmlspecialchars($vibe_url, ENT_QUOTES, 'UTF-8'); +?> + +<style> + .vibe-embed { + position: relative; + padding-top: 56.25%; + overflow: hidden; + border-radius: 6px; + background: #000; + margin: 0.5rem 0; + } + .vibe-embed > iframe, + .vibe-embed > video, + .vibe-embed > img { + position: absolute; + top: 0; left: 0; + width: 100%; height: 100%; + border: 0; + object-fit: contain; + } + .vibe-media-audio { width: 100%; margin: 0.5rem 0; } + .vibe-media-img { max-width: 100%; height: auto; border-radius: 6px; } + .vibe-caption { + margin: 0.25rem 0 0; + font-size: 0.9em; + opacity: 0.8; + } + .vibe-meta { + font-size: 0.85em; + opacity: 0.7; + margin: 0.5rem 0 0; + } +</style> + +<section id="vibe" aria-labelledby="vibe-title" class="vibe-section"> + <h2 id="vibe-title" class="section-accent-title"><?= htmlspecialchars($vibe_section_title_raw, ENT_QUOTES, 'UTF-8') ?></h2> + + <?php if ($show_desc): ?> + <p><?= $vibe_desc ?></p> + <?php endif; ?> + + <?php if ($vibe_url): ?> + <?php if ($type === 'image'): ?> + <a href="<?= $safe_url ?>" target="_blank" rel="noopener noreferrer"> + <img class="vibe-media-img" src="<?= $safe_url ?>" alt="Current vibe" loading="lazy" decoding="async"> + </a> + + <?php elseif ($type === 'video'): ?> + <div class="vibe-embed"> + <video controls preload="none"> + <source src="<?= $safe_url ?>"> + </video> + </div> + <p class="vibe-caption"> + <a href="<?= $safe_url ?>" target="_blank" rel="noopener noreferrer">Open video ↗</a> + </p> + + <?php elseif ($type === 'audio'): ?> + <audio class="vibe-media-audio" controls preload="none"> + <source src="<?= $safe_url ?>"> + Your browser does not support audio. <a href="<?= $safe_url ?>">Download it</a>. + </audio> + <p class="vibe-caption"> + <a href="<?= $safe_url ?>" target="_blank" rel="noopener noreferrer">Open audio ↗</a> + </p> + + <?php elseif ($prov = vibe_provider_embed($type, $vibe_url)): ?> + <?php + $embed = $prov['embed']; + $label = $prov['label']; + $safe_embed = htmlspecialchars($embed, ENT_QUOTES); + $safe_label = htmlspecialchars($label, ENT_QUOTES); + ?> + <div class="vibe-embed"> + <noscript> + <iframe + src="<?= $safe_embed ?>" + title="Current vibe — <?= $safe_label ?> video" + loading="lazy" + referrerpolicy="strict-origin-when-cross-origin" + allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" + allowfullscreen></iframe> + </noscript> + <button type="button" class="vibe-facade js-only" + data-embed="<?= $safe_embed ?>" + aria-label="Load and play the <?= $safe_label ?> video"> + <span class="vibe-facade-play" aria-hidden="true">▶</span> + <span class="vibe-facade-text">Load <?= $safe_label ?> video<br><small>Nothing loads from <?= $safe_label ?> until you click</small></span> + </button> + </div> + <p class="vibe-caption"> + <a href="<?= $safe_url ?>" target="_blank" rel="noopener noreferrer">Watch on <?= $safe_label ?> ↗</a> + </p> + + <?php else: ?> + <p> + <a href="<?= $safe_url ?>" target="_blank" rel="noopener noreferrer"><?= $safe_url ?></a> + </p> + <?php endif; ?> + <?php endif; ?> + + <?php if ($vibe_updated): ?> + <p class="vibe-meta">Updated <?= $vibe_updated ?></p> + <?php endif; ?> + + <?php if (!empty($vibe_section_extra)) echo $vibe_section_extra; ?> +</section> |
