add video versioning
This commit is contained in:
parent
eb790eb8fc
commit
e007c0ebd3
|
|
@ -26,17 +26,30 @@ app.get('/watch', async ({ query: { v }, set, redirect, error }) => {
|
|||
return cached
|
||||
}
|
||||
|
||||
if (!v.match(/[\w\-_]{11}/)) return error(404)
|
||||
const idMatch = v.match(/^([\w\-_]{11})(?:-(\d+))?$/)
|
||||
if (!idMatch) return error(404)
|
||||
|
||||
const json = await db.selectFrom('videos')
|
||||
const baseId = idMatch[1];
|
||||
const escapeRegex = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
const allowedVersionPattern = new RegExp(`^${escapeRegex(baseId)}(?:-\\d+)?$`);
|
||||
|
||||
const videoVersions = (await db.selectFrom('videos')
|
||||
.selectAll()
|
||||
.where('id', '=', v)
|
||||
.executeTakeFirst()
|
||||
.where('id', 'like', `${baseId}%`)
|
||||
.execute())
|
||||
.filter(video => allowedVersionPattern.test(video.id))
|
||||
.sort((a, b) => {
|
||||
const aVersion = Number(a.id.slice(baseId.length + 1) || 1);
|
||||
const bVersion = Number(b.id.slice(baseId.length + 1) || 1);
|
||||
return aVersion - bVersion;
|
||||
});
|
||||
|
||||
const json = videoVersions.find(video => video.id === v) || videoVersions[0];
|
||||
|
||||
if (!json) {
|
||||
const html = await m(eta.render('./watch', {
|
||||
isMissing: true,
|
||||
id: v,
|
||||
id: baseId,
|
||||
title: 'Video Not Found | PreserveTube',
|
||||
manualAnalytics: true
|
||||
}))
|
||||
|
|
@ -45,13 +58,13 @@ app.get('/watch', async ({ query: { v }, set, redirect, error }) => {
|
|||
set.headers['content-type'] = 'text/html; charset=utf-8'
|
||||
return error(404, html)
|
||||
}
|
||||
if (json.disabled) return redirect(`/transparency/${v}`)
|
||||
if (json.disabled) return redirect(`/transparency/${json.id}`)
|
||||
|
||||
let transparency: any[] = []
|
||||
if (json.hasBeenReported) {
|
||||
transparency = await db.selectFrom('reports')
|
||||
.selectAll()
|
||||
.where('target', '=', v)
|
||||
.where('target', '=', json.id)
|
||||
.execute()
|
||||
}
|
||||
|
||||
|
|
@ -85,6 +98,11 @@ app.get('/watch', async ({ query: { v }, set, redirect, error }) => {
|
|||
|
||||
const html = await m(eta.render('./watch', {
|
||||
transparency,
|
||||
versions: videoVersions.map(video => ({
|
||||
id: video.id,
|
||||
archived: video.archived
|
||||
})),
|
||||
baseId,
|
||||
...json,
|
||||
description: DOMPurify.sanitize(json.description),
|
||||
title: `${json.title} | PreserveTube`,
|
||||
|
|
|
|||
|
|
@ -11,9 +11,27 @@
|
|||
<div class="content-wrapper">
|
||||
<div class="main-content">
|
||||
<div class="report">
|
||||
<a href="abuse">[report abuse]</a>
|
||||
<div class="space"></div>
|
||||
<a href="about">[faq]</a>
|
||||
<% if (it.versions && it.versions.length > 1) { %>
|
||||
<div class="version-picker">
|
||||
<label for="version-select">Version:</label>
|
||||
<select
|
||||
id="version-select"
|
||||
onchange="window.location.href = '/watch?v=' + this.value"
|
||||
>
|
||||
<% it.versions.forEach(function(version, index){ %>
|
||||
<option value="<%= version.id %>" <%= version.id === it.id ? 'selected' : '' %>>
|
||||
v<%= version.id.slice(it.baseId.length + 1) || '1' %> (archived <%= version.archived %>)
|
||||
</option>
|
||||
<% }) %>
|
||||
</select>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div></div>
|
||||
<% } %>
|
||||
<div class="report-links">
|
||||
<a href="abuse">[report abuse]</a>
|
||||
<a href="about">[faq]</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if (it.transparency.length != 0) { %>
|
||||
|
|
@ -76,13 +94,16 @@
|
|||
}
|
||||
|
||||
.report {
|
||||
text-align: right;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.space {
|
||||
display: inline-block;
|
||||
width: 0.5%;
|
||||
.report-links {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
video {
|
||||
|
|
@ -154,6 +175,17 @@
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
.version-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.version-picker select {
|
||||
font: inherit;
|
||||
padding: 0.2rem 0.4rem;
|
||||
}
|
||||
|
||||
.video-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
|
|
|||
Loading…
Reference in New Issue