- Live homepage:

Added default Live settings in 
[includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php) 
using https://stream.place/embed/tyclifford.com.
Added Admin → Settings → Live Section controls in 
[admin/settings.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/settings.php): 
enable/disable, live title, and embed URL/iframe input.
Added a homepage Videos / Live toggle in 
[index.php](/Users/tyemeclifford/Documents/GH/mediaplayer/index.php). 
Videos remains the default view, so the homepage behaves normally until 
Live is selected.
Imgur:
Added Imgur URL normalization, embed support, oEmbed/thumbnail hooks, 
and external view count scraping support in 
[includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php).
Supports imgur.com, albums/galleries, and direct i.imgur.com 
photos/GIFs/videos by routing them through Imgur embeds.
Imgur external views now flow into external_view_count, so per-item and 
overall site totals include readable Imgur provider counts.
Updated the add-video hint and README docs.
This commit is contained in:
Ty Clifford
2026-06-25 07:38:19 -04:00
parent 08caf98fa5
commit a3aa51c4e2
5 changed files with 187 additions and 5 deletions
+90
View File
@@ -74,6 +74,9 @@ function get_db(): PDO {
'public_show_video_views' => '1',
'public_show_total_views' => '1',
'public_show_page_stats' => '1',
'live_enabled' => '1',
'live_title' => 'Ty Clifford live stream',
'live_embed' => 'https://stream.place/embed/tyclifford.com',
];
$ins = $pdo->prepare("INSERT OR IGNORE INTO settings (key, value) VALUES (?, ?)");
foreach ($defaults as $k => $v) $ins->execute([$k, $v]);
@@ -171,6 +174,30 @@ function public_page_stats(): array {
];
}
function media_iframe_src_from_input(string $value): string {
$value = trim($value);
if ($value === '') return '';
if (stripos($value, '<iframe') !== false && preg_match('/\ssrc=["\']([^"\']+)["\']/i', $value, $match)) {
$value = html_entity_decode($match[1], ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
return normalize_media_url($value);
}
function live_embed_url(): string {
return media_iframe_src_from_input(setting('live_embed', 'https://stream.place/embed/tyclifford.com'));
}
function live_embed_title(): string {
$title = trim(setting('live_title', 'Ty Clifford live stream'));
return $title !== '' ? $title : 'Live stream';
}
function live_enabled(): bool {
return setting_bool('live_enabled', true) && live_embed_url() !== '';
}
function url_rewrite_mode(): string {
$mode = strtolower(setting('url_rewrite_mode', 'pretty'));
return in_array($mode, ['pretty', 'query'], true) ? $mode : 'pretty';
@@ -485,6 +512,41 @@ function media_youtube_id_from_url(string $url): string {
return media_clean_token($id);
}
function media_imgur_path_from_url(string $url): string {
$url = normalize_media_url($url);
if ($url === '') return '';
$host = strtolower((string)(parse_url($url, PHP_URL_HOST) ?? ''));
$segments = media_path_segments($url);
if (!$segments) return '';
if (media_host_matches($host, 'i.imgur.com')) {
$id = pathinfo($segments[0], PATHINFO_FILENAME);
$id = media_clean_token($id);
return $id !== '' ? $id : '';
}
if (!media_host_matches($host, 'imgur.com')) return '';
if (in_array($segments[0], ['a', 'gallery'], true) && isset($segments[1])) {
$id = media_clean_token($segments[1]);
return $id !== '' ? $segments[0] . '/' . $id : '';
}
$id = media_clean_token($segments[0]);
return $id !== '' ? $id : '';
}
function media_imgur_page_url(string $url): string {
$path = media_imgur_path_from_url($url);
return $path !== '' ? 'https://imgur.com/' . $path : '';
}
function media_imgur_embed_url(string $url): string {
$page = media_imgur_page_url($url);
return $page !== '' ? rtrim($page, '/') . '/embed' : '';
}
function media_normalize_datetime(string $value): string {
$value = trim(html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
if ($value === '') return '';
@@ -638,6 +700,10 @@ function media_external_view_count_from_url(string $url): int {
if (media_host_matches($host, 'youtube.com') || media_host_matches($host, 'youtu.be') || media_host_matches($host, 'youtube-nocookie.com')) {
return media_youtube_view_count($url);
}
if (media_host_matches($host, 'imgur.com') || media_host_matches($host, 'i.imgur.com')) {
$imgur_page = media_imgur_page_url($url);
if ($imgur_page !== '') $url = $imgur_page;
}
$fetch = media_http_get($url, 15, 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
if ($fetch['body'] === '' || $fetch['error'] !== '') return 0;
@@ -844,6 +910,10 @@ function media_provider_oembed_endpoint(string $url, string $host): string {
if (media_host_matches($host, 'dailymotion.com') || media_host_matches($host, 'dai.ly')) {
return 'https://www.dailymotion.com/services/oembed?url=' . rawurlencode($url);
}
if (media_host_matches($host, 'imgur.com') || media_host_matches($host, 'i.imgur.com')) {
$imgur_page = media_imgur_page_url($url);
if ($imgur_page !== '') return 'https://api.imgur.com/oembed.json?url=' . rawurlencode($imgur_page);
}
if (media_host_matches($host, 'tiktok.com')) {
return 'https://www.tiktok.com/oembed?url=' . rawurlencode($url);
}
@@ -975,6 +1045,14 @@ function media_external_metadata(string $url): array {
if ($url === '') return $metadata;
$host = strtolower((string)(parse_url($url, PHP_URL_HOST) ?? ''));
if (media_host_matches($host, 'imgur.com') || media_host_matches($host, 'i.imgur.com')) {
$imgur_page = media_imgur_page_url($url);
if ($imgur_page !== '') {
$url = $imgur_page;
$metadata['url'] = $url;
$host = strtolower((string)(parse_url($url, PHP_URL_HOST) ?? ''));
}
}
$provider = media_provider_embed($url);
$metadata['provider'] = $provider['provider'] ?? '';
@@ -1049,6 +1127,13 @@ function media_provider_thumbnail_url(string $url): string {
if ($id !== '') return 'https://www.dailymotion.com/thumbnail/video/' . rawurlencode($id);
}
if (media_host_matches($host, 'imgur.com') || media_host_matches($host, 'i.imgur.com')) {
$imgur_path = media_imgur_path_from_url($url);
if ($imgur_path !== '' && !str_contains($imgur_path, '/')) {
return 'https://i.imgur.com/' . rawurlencode($imgur_path) . 'h.jpg';
}
}
return media_oembed_thumbnail_url($url, $host);
}
@@ -1184,6 +1269,11 @@ function media_provider_embed(string $url): ?array {
if ($id !== '') return ['provider' => 'dailymotion', 'embed' => 'https://www.dailymotion.com/embed/video/' . rawurlencode($id)];
}
if (media_host_matches($host, 'imgur.com') || media_host_matches($host, 'i.imgur.com')) {
$embed = media_imgur_embed_url($url);
if ($embed !== '') return ['provider' => 'imgur', 'embed' => $embed];
}
if (media_host_matches($host, 'twitch.tv')) {
$parent = media_twitch_parent_host();
if (preg_match('#/videos/(\d+)#', $path, $m)) {