- Reversed Imgur support.
Removed the Imgur-specific provider handling from [includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php), removed the admin upkeep Imgur counter/copy from [admin/index.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/index.php), updated the upload hint in [admin/add.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/add.php), cleaned the README mentions, and deleted provider_embed.php.
This commit is contained in:
@@ -77,9 +77,7 @@ Styled to match the existing `gate.php` / `index.php` dark theme exactly.
|
|||||||
6. Set quality labels (1080p, 720p, 480p, etc.)
|
6. Set quality labels (1080p, 720p, 480p, etc.)
|
||||||
7. Save — Video.js will use the stored source location and auto-select the best format the browser supports
|
7. Save — Video.js will use the stored source location and auto-select the best format the browser supports
|
||||||
|
|
||||||
External URLs must use `http://` or `https://`. Uploaded files and remote URLs can be mixed on the same video. Recognized provider URLs such as YouTube, Vimeo, Dailymotion, Imgur, Twitch, Facebook, TikTok, Instagram, X/Twitter, SoundCloud, Spotify, Google Drive, Wistia, Streamable, and Loom render through their embed players.
|
External URLs must use `http://` or `https://`. Uploaded files and remote URLs can be mixed on the same video. Recognized provider URLs such as YouTube, Vimeo, Dailymotion, Twitch, Facebook, TikTok, Instagram, X/Twitter, SoundCloud, Spotify, Google Drive, Wistia, Streamable, and Loom render through their embed players.
|
||||||
|
|
||||||
Imgur links use the official Imgur embed script inside a local wrapper, so album, gallery, image, GIF, GIFV, and video URLs can render without direct iframe blocking.
|
|
||||||
|
|
||||||
When adding an external URL, the admin form can fetch title, description, duration, thumbnail metadata, and readable provider view counts through oEmbed, page metadata, and JSON-LD. The save action repeats the metadata lookup as a fallback, so blank titles can be filled from supported external pages even if the browser autofill was not used.
|
When adding an external URL, the admin form can fetch title, description, duration, thumbnail metadata, and readable provider view counts through oEmbed, page metadata, and JSON-LD. The save action repeats the metadata lookup as a fallback, so blank titles can be filled from supported external pages even if the browser autofill was not used.
|
||||||
|
|
||||||
@@ -105,7 +103,7 @@ The public display is configurable in **Admin → Settings → Public Display**:
|
|||||||
- show or hide the total public view count
|
- show or hide the total public view count
|
||||||
- show or hide public page statistics on the homepage and catalogue
|
- show or hide public page statistics on the homepage and catalogue
|
||||||
|
|
||||||
The admin dashboard also includes **Upkeeping → Correct external view counts**. It checks existing remote-source videos in batches, scrapes readable provider counts when available, and adds those provider totals to the media-site totals without double-counting local plays. YouTube and Imgur have dedicated handling, and generic metadata patterns cover readable Vimeo, Dailymotion, and similar provider pages when they expose counts. Unsupported providers and local-only uploads can still be corrected manually on the edit screen.
|
The admin dashboard also includes **Upkeeping → Correct external view counts**. It checks existing remote-source videos in batches, scrapes readable provider counts when available, and adds those provider totals to the media-site totals without double-counting local plays. YouTube has dedicated handling, and generic metadata patterns cover readable Vimeo, Dailymotion, and similar provider pages when they expose counts. Unsupported providers and local-only uploads can still be corrected manually on the edit screen.
|
||||||
|
|
||||||
### Public Search
|
### Public Search
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -308,7 +308,7 @@ render_head('Add Video — Admin', '
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<p class="section-heading">Video Sources</p>
|
<p class="section-heading">Video Sources</p>
|
||||||
<p class="hint" style="margin-bottom:1rem;">
|
<p class="hint" style="margin-bottom:1rem;">
|
||||||
Upload a video file, link a direct media file, or paste a provider page URL such as YouTube, Vimeo, or Imgur. The player will use a provider embed when the URL supports it.
|
Upload a video file, link a direct media file, or paste a provider page URL such as YouTube or Vimeo. The player will use a provider embed when the URL supports it.
|
||||||
Uploaded files: <strong>MP4, WebM, OGV, MOV, MKV, AVI</strong>. Remote URLs must use <strong>http://</strong> or <strong>https://</strong>.
|
Uploaded files: <strong>MP4, WebM, OGV, MOV, MKV, AVI</strong>. Remote URLs must use <strong>http://</strong> or <strong>https://</strong>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -95,7 +95,6 @@ $list_stmt->execute();
|
|||||||
$videos = $list_stmt->fetchAll();
|
$videos = $list_stmt->fetchAll();
|
||||||
$youtube_timestamp_candidates = media_youtube_timestamp_candidate_count();
|
$youtube_timestamp_candidates = media_youtube_timestamp_candidate_count();
|
||||||
$external_view_candidates = media_external_view_count_candidate_count();
|
$external_view_candidates = media_external_view_count_candidate_count();
|
||||||
$imgur_view_candidates = media_imgur_view_count_candidate_count();
|
|
||||||
$admin_total_views = total_video_views(false);
|
$admin_total_views = total_video_views(false);
|
||||||
|
|
||||||
$qs = fn($p) => '?' . http_build_query(array_filter(['q' => $search, 'page' => $p]));
|
$qs = fn($p) => '?' . http_build_query(array_filter(['q' => $search, 'page' => $p]));
|
||||||
@@ -242,8 +241,7 @@ render_head('Admin — TyClifford.com', '
|
|||||||
<h2 class="card-title">Correct external view counts</h2>
|
<h2 class="card-title">Correct external view counts</h2>
|
||||||
<p class="hint">
|
<p class="hint">
|
||||||
Scrapes readable counts from supported providers and adds them to the media-site totals alongside local plays.
|
Scrapes readable counts from supported providers and adds them to the media-site totals alongside local plays.
|
||||||
<?= $external_view_candidates ?> external video<?= $external_view_candidates === 1 ? '' : 's' ?> can be checked,
|
<?= $external_view_candidates ?> external video<?= $external_view_candidates === 1 ? '' : 's' ?> can be checked.
|
||||||
including <?= $imgur_view_candidates ?> Imgur-backed item<?= $imgur_view_candidates === 1 ? '' : 's' ?>.
|
|
||||||
Current database total: <?= h(view_count_label((int)$admin_total_views)) ?>.
|
Current database total: <?= h(view_count_label((int)$admin_total_views)) ?>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
-105
@@ -512,45 +512,6 @@ function media_youtube_id_from_url(string $url): string {
|
|||||||
return media_clean_token($id);
|
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 {
|
|
||||||
$path = media_imgur_path_from_url($url);
|
|
||||||
if ($path === '') return '';
|
|
||||||
return media_append_query(public_url_path('/provider_embed.php'), [
|
|
||||||
'provider' => 'imgur',
|
|
||||||
'id' => $path,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function media_normalize_datetime(string $value): string {
|
function media_normalize_datetime(string $value): string {
|
||||||
$value = trim(html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
|
$value = trim(html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
|
||||||
if ($value === '') return '';
|
if ($value === '') return '';
|
||||||
@@ -681,26 +642,6 @@ function media_view_count_from_html(string $html): int {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function media_imgur_view_count_from_html(string $html): int {
|
|
||||||
$count = media_view_count_from_html($html);
|
|
||||||
if ($count > 0) return $count;
|
|
||||||
|
|
||||||
$html = html_entity_decode($html, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
||||||
$patterns = [
|
|
||||||
'/\bviews?\b[^0-9]{0,80}([0-9][0-9,.\s]*\s*[KMBkmb]?)/i',
|
|
||||||
'/([0-9][0-9,.\s]*\s*[KMBkmb]?)\s+\bviews?\b/i',
|
|
||||||
'/"views_count"\s*:\s*"?(\d+)"?/i',
|
|
||||||
'/"viewsCount"\s*:\s*"?(\d+)"?/i',
|
|
||||||
];
|
|
||||||
foreach ($patterns as $pattern) {
|
|
||||||
if (!preg_match($pattern, $html, $match)) continue;
|
|
||||||
$count = media_count_from_text($match[1]);
|
|
||||||
if ($count > 0) return $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function media_youtube_view_count_from_html(string $html): int {
|
function media_youtube_view_count_from_html(string $html): int {
|
||||||
return media_view_count_from_html($html);
|
return media_view_count_from_html($html);
|
||||||
}
|
}
|
||||||
@@ -724,18 +665,9 @@ 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')) {
|
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);
|
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');
|
$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;
|
if ($fetch['body'] === '' || $fetch['error'] !== '') return 0;
|
||||||
|
|
||||||
if (media_host_matches($host, 'imgur.com') || media_host_matches($host, 'i.imgur.com')) {
|
|
||||||
return media_imgur_view_count_from_html($fetch['body']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return media_view_count_from_html($fetch['body']);
|
return media_view_count_from_html($fetch['body']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,19 +744,6 @@ function media_external_view_count_candidate_count(): int {
|
|||||||
")->fetchColumn();
|
")->fetchColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
function media_imgur_view_count_candidate_count(): int {
|
|
||||||
return (int)get_db()->query("
|
|
||||||
SELECT COUNT(DISTINCT v.id)
|
|
||||||
FROM videos v
|
|
||||||
INNER JOIN video_sources vs ON vs.video_id = v.id
|
|
||||||
WHERE vs.source_type='remote'
|
|
||||||
AND (
|
|
||||||
vs.source_url LIKE '%imgur.com%'
|
|
||||||
OR vs.source_url LIKE '%i.imgur.com%'
|
|
||||||
)
|
|
||||||
")->fetchColumn();
|
|
||||||
}
|
|
||||||
|
|
||||||
function media_restore_external_view_counts(int $limit = 25): array {
|
function media_restore_external_view_counts(int $limit = 25): array {
|
||||||
$result = [
|
$result = [
|
||||||
'checked' => 0,
|
'checked' => 0,
|
||||||
@@ -951,10 +870,6 @@ function media_provider_oembed_endpoint(string $url, string $host): string {
|
|||||||
if (media_host_matches($host, 'dailymotion.com') || media_host_matches($host, 'dai.ly')) {
|
if (media_host_matches($host, 'dailymotion.com') || media_host_matches($host, 'dai.ly')) {
|
||||||
return 'https://www.dailymotion.com/services/oembed?url=' . rawurlencode($url);
|
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')) {
|
if (media_host_matches($host, 'tiktok.com')) {
|
||||||
return 'https://www.tiktok.com/oembed?url=' . rawurlencode($url);
|
return 'https://www.tiktok.com/oembed?url=' . rawurlencode($url);
|
||||||
}
|
}
|
||||||
@@ -1086,14 +1001,6 @@ function media_external_metadata(string $url): array {
|
|||||||
if ($url === '') return $metadata;
|
if ($url === '') return $metadata;
|
||||||
|
|
||||||
$host = strtolower((string)(parse_url($url, PHP_URL_HOST) ?? ''));
|
$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);
|
$provider = media_provider_embed($url);
|
||||||
$metadata['provider'] = $provider['provider'] ?? '';
|
$metadata['provider'] = $provider['provider'] ?? '';
|
||||||
|
|
||||||
@@ -1168,13 +1075,6 @@ function media_provider_thumbnail_url(string $url): string {
|
|||||||
if ($id !== '') return 'https://www.dailymotion.com/thumbnail/video/' . rawurlencode($id);
|
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);
|
return media_oembed_thumbnail_url($url, $host);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1310,11 +1210,6 @@ function media_provider_embed(string $url): ?array {
|
|||||||
if ($id !== '') return ['provider' => 'dailymotion', 'embed' => 'https://www.dailymotion.com/embed/video/' . rawurlencode($id)];
|
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')) {
|
if (media_host_matches($host, 'twitch.tv')) {
|
||||||
$parent = media_twitch_parent_host();
|
$parent = media_twitch_parent_host();
|
||||||
if (preg_match('#/videos/(\d+)#', $path, $m)) {
|
if (preg_match('#/videos/(\d+)#', $path, $m)) {
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once __DIR__ . '/includes/db.php';
|
|
||||||
|
|
||||||
$provider = strtolower(trim((string)($_GET['provider'] ?? '')));
|
|
||||||
$id = trim((string)($_GET['id'] ?? ''));
|
|
||||||
|
|
||||||
if ($provider !== 'imgur') {
|
|
||||||
http_response_code(404);
|
|
||||||
exit('Unsupported provider.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$parts = array_values(array_filter(explode('/', $id), 'strlen'));
|
|
||||||
$data_id = '';
|
|
||||||
if (isset($parts[0], $parts[1]) && in_array($parts[0], ['a', 'gallery'], true)) {
|
|
||||||
$clean = media_clean_token($parts[1]);
|
|
||||||
if ($clean !== '') $data_id = $parts[0] . '/' . $clean;
|
|
||||||
} elseif (isset($parts[0])) {
|
|
||||||
$clean = media_clean_token($parts[0]);
|
|
||||||
if ($clean !== '') $data_id = $clean;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($data_id === '') {
|
|
||||||
http_response_code(400);
|
|
||||||
exit('Invalid Imgur item.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$imgur_url = 'https://imgur.com/' . $data_id;
|
|
||||||
$title = 'Imgur media';
|
|
||||||
?>
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="referrer" content="no-referrer-when-downgrade">
|
|
||||||
<title><?= h($title) ?></title>
|
|
||||||
<style>
|
|
||||||
html, body {
|
|
||||||
margin:0;
|
|
||||||
width:100%;
|
|
||||||
min-height:100%;
|
|
||||||
background:#000;
|
|
||||||
color:#fff;
|
|
||||||
font-family:Inter, system-ui, sans-serif;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
display:flex;
|
|
||||||
align-items:center;
|
|
||||||
justify-content:center;
|
|
||||||
overflow:auto;
|
|
||||||
}
|
|
||||||
.imgur-embed-pub {
|
|
||||||
width:100%;
|
|
||||||
max-width:100%;
|
|
||||||
margin:0 auto !important;
|
|
||||||
}
|
|
||||||
.imgur-embed-pub iframe {
|
|
||||||
max-width:100% !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<blockquote class="imgur-embed-pub" lang="en" data-id="<?= h($data_id) ?>">
|
|
||||||
<a href="<?= h($imgur_url) ?>" target="_blank" rel="noopener">View on Imgur</a>
|
|
||||||
</blockquote>
|
|
||||||
<script async src="https://s.imgur.com/min/embed.js" charset="utf-8"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user