-Implemented YouTube timestamp correction and added the admin Upkeeping section.
What changed: Added shared YouTube publish-date scraping helpers in [includes/db.php](/Users/tyemeclifford/Documents/GH/mediaplayer/includes/db.php). New YouTube imports now set videos.created_at to the original YouTube publish date when available. Manual Add/Edit saves now also try to correct timestamps for YouTube-backed videos. Added Admin Dashboard → Upkeeping → Correct YouTube timestamps in [admin/index.php](/Users/tyemeclifford/Documents/GH/mediaplayer/admin/index.php), with batch size control for backfilling existing records. Renamed the admin table column from Added to Date, since it may now reflect original publish date. Documented the behavior in [README.md](/Users/tyemeclifford/Documents/GH/mediaplayer/README.md).
This commit is contained in:
@@ -119,6 +119,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$db->prepare("UPDATE videos SET thumbnail=? WHERE id=?")->execute([$thumbnail, $video_id]);
|
||||
}
|
||||
}
|
||||
media_apply_youtube_timestamp($video_id);
|
||||
|
||||
header('Location: edit.php?id=' . $video_id . '&saved=1');
|
||||
exit;
|
||||
|
||||
@@ -190,6 +190,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
}
|
||||
|
||||
media_apply_youtube_timestamp($id);
|
||||
|
||||
header('Location: edit.php?id=' . $id . '&saved=1');
|
||||
exit;
|
||||
}
|
||||
|
||||
+41
-1
@@ -39,6 +39,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$db->prepare("UPDATE videos SET published=? WHERE id=?")->execute([$cur ? 0 : 1, $id]);
|
||||
$msg = 'Video ' . ($cur ? 'unpublished' : 'published') . '.';
|
||||
}
|
||||
|
||||
if ($action === 'correct_youtube_timestamps') {
|
||||
$limit = max(1, min(100, (int)($_POST['timestamp_limit'] ?? 25)));
|
||||
$result = media_correct_youtube_timestamps($limit);
|
||||
$msg = 'Upkeeping checked ' . $result['checked'] . ' YouTube video' . ($result['checked'] === 1 ? '' : 's') . ': ';
|
||||
$msg .= $result['corrected'] . ' corrected';
|
||||
if ($result['already_correct']) $msg .= ', ' . $result['already_correct'] . ' already correct';
|
||||
if ($result['not_found']) $msg .= ', ' . $result['not_found'] . ' without a readable original date';
|
||||
$msg .= '.';
|
||||
}
|
||||
}
|
||||
|
||||
// Search + pagination
|
||||
@@ -73,6 +83,7 @@ $list_stmt->bindValue(':limit', $per_page, PDO::PARAM_INT);
|
||||
$list_stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
||||
$list_stmt->execute();
|
||||
$videos = $list_stmt->fetchAll();
|
||||
$youtube_timestamp_candidates = media_youtube_timestamp_candidate_count();
|
||||
|
||||
$qs = fn($p) => '?' . http_build_query(array_filter(['q' => $search, 'page' => $p]));
|
||||
|
||||
@@ -130,6 +141,12 @@ render_head('Admin — TyClifford.com', '
|
||||
|
||||
.admin-footer-bar { display:flex; align-items:center; justify-content:space-between; gap:1rem; flex-wrap:wrap; }
|
||||
.rec-count { font-family:"Share Tech Mono",monospace; font-size:.63rem; color:var(--text-3); letter-spacing:.06em; }
|
||||
.section-heading { font-family:"Share Tech Mono",monospace; font-size:.65rem; letter-spacing:.15em; text-transform:uppercase; color:var(--text-3); margin-bottom:.75rem; }
|
||||
.hint { font-size:.72rem; color:var(--text-3); margin-top:.2rem; line-height:1.5; }
|
||||
.upkeep-row { display:flex; align-items:flex-end; justify-content:space-between; gap:1rem; flex-wrap:wrap; }
|
||||
.upkeep-copy { max-width:620px; }
|
||||
.upkeep-form { display:flex; align-items:flex-end; gap:.65rem; flex-wrap:wrap; }
|
||||
.upkeep-form .form-group { min-width:120px; }
|
||||
');
|
||||
?>
|
||||
<main class="page" role="main">
|
||||
@@ -183,6 +200,29 @@ render_head('Admin — TyClifford.com', '
|
||||
<!-- Main content -->
|
||||
<div class="admin-main">
|
||||
|
||||
<div class="card">
|
||||
<p class="section-heading">Upkeeping</p>
|
||||
<div class="upkeep-row">
|
||||
<div class="upkeep-copy">
|
||||
<h2 class="card-title">Correct YouTube timestamps</h2>
|
||||
<p class="hint">
|
||||
Fetches original YouTube publish dates and updates the database timestamp shown in the admin list and public catalogue.
|
||||
<?= $youtube_timestamp_candidates ?> YouTube-backed video<?= $youtube_timestamp_candidates === 1 ? '' : 's' ?> currently match this upkeep task.
|
||||
</p>
|
||||
</div>
|
||||
<form class="upkeep-form" method="post" action="index.php">
|
||||
<input type="hidden" name="action" value="correct_youtube_timestamps">
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="timestamp_limit">Batch Size</label>
|
||||
<input class="form-input" type="number" id="timestamp_limit" name="timestamp_limit" value="25" min="1" max="100">
|
||||
</div>
|
||||
<button class="btn btn-secondary btn-sm" type="submit">
|
||||
Correct Dates
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-toolbar">
|
||||
<form class="search-form" method="get" action="index.php">
|
||||
<input class="form-input" type="search" name="q"
|
||||
@@ -214,7 +254,7 @@ render_head('Admin — TyClifford.com', '
|
||||
<th>Duration</th>
|
||||
<th>Sources</th>
|
||||
<th>Status</th>
|
||||
<th>Added</th>
|
||||
<th>Date</th>
|
||||
<th class="actions-cell">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -486,10 +486,8 @@ function yt_import_videos(PDO $db, array $videos, array $selected_ids, bool $pub
|
||||
try {
|
||||
$slug = make_slug($video['title']);
|
||||
$thumbnail = yt_download_thumbnail($video['thumbnail_url'], $slug);
|
||||
$db->prepare("
|
||||
INSERT INTO videos (title, description, slug, thumbnail, duration, sort_order, published)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
")->execute([
|
||||
$published_at = media_youtube_publish_datetime($video['watch_url']);
|
||||
$video_params = [
|
||||
$video['title'],
|
||||
$video['description'],
|
||||
$slug,
|
||||
@@ -497,7 +495,19 @@ function yt_import_videos(PDO $db, array $videos, array $selected_ids, bool $pub
|
||||
(int)$video['duration'],
|
||||
0,
|
||||
$published ? 1 : 0,
|
||||
]);
|
||||
];
|
||||
if ($published_at !== '') {
|
||||
$video_params[] = $published_at;
|
||||
$db->prepare("
|
||||
INSERT INTO videos (title, description, slug, thumbnail, duration, sort_order, published, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
|
||||
")->execute($video_params);
|
||||
} else {
|
||||
$db->prepare("
|
||||
INSERT INTO videos (title, description, slug, thumbnail, duration, sort_order, published)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
")->execute($video_params);
|
||||
}
|
||||
$video_id = (int)$db->lastInsertId();
|
||||
$db->prepare("
|
||||
INSERT INTO video_sources (video_id, label, source_type, file_path, source_url, mime_type, quality, sort_order)
|
||||
|
||||
Reference in New Issue
Block a user