Compare commits

...

4 Commits

Author SHA1 Message Date
Icedream 5d76411416
Update streamserver to nginx 1.20.1. 2021-07-09 11:42:34 +02:00
Icedream 40cbd2ed6e
Add new slug property for videos.
These will in the future hold pre-generated slugs since some runs can have the
same title and slugs are generated based on those titles.

This also implements a default for when no slugs are set (as is the case for all
videos right now) where the slug is still generated based on the title but a
counter suffix is added for dupe titles.
2021-07-09 11:42:33 +02:00
Icedream 5781966b91
s/'/"/g 2021-07-09 11:42:33 +02:00
Icedream e45a883a3e
Update translations. 2021-07-09 11:42:33 +02:00
10 changed files with 93 additions and 68 deletions

View File

@ -89,6 +89,7 @@ class VideoList extends React.Component<VideoListProps, VideoListState> {
duration, duration,
fileName, fileName,
title, title,
slug,
sourceVideoStart, sourceVideoStart,
sourceVideoEnd, sourceVideoEnd,
}, },
@ -100,6 +101,7 @@ class VideoList extends React.Component<VideoListProps, VideoListState> {
id={id} id={id}
thumbnailServerURL={thumbnailServerURL} thumbnailServerURL={thumbnailServerURL}
fileName={fileName} fileName={fileName}
slug={slug}
title={title} title={title}
sourceVideoStart={sourceVideoStart} sourceVideoStart={sourceVideoStart}
sourceVideoEnd={sourceVideoEnd} sourceVideoEnd={sourceVideoEnd}

View File

@ -39,6 +39,7 @@ export default function VideoListItem({
duration, duration,
id, id,
fileName, fileName,
slug,
title, title,
sourceVideoStart, sourceVideoStart,
sourceVideoEnd, sourceVideoEnd,
@ -47,6 +48,7 @@ export default function VideoListItem({
duration: number | string, duration: number | string,
id: string, id: string,
fileName: string, fileName: string,
slug: string,
title: string, title: string,
sourceVideoStart: number | string, sourceVideoStart: number | string,
sourceVideoEnd: number | string, sourceVideoEnd: number | string,
@ -77,7 +79,6 @@ export default function VideoListItem({
} }
displayDuration = videoEnd - videoStart; displayDuration = videoEnd - videoStart;
} }
const titleUrlSlug = sanitizeTitle(title);
const listGroupItem = ( const listGroupItem = (
<ListGroup.Item action> <ListGroup.Item action>
<Media> <Media>
@ -131,7 +132,7 @@ export default function VideoListItem({
); );
if (fileName) { if (fileName) {
return ( return (
<Link passHref href="/[id]/[vslug]" as={`/${id}/${titleUrlSlug}`}> <Link passHref href="/[id]/[vslug]" as={`/${id}/${slug}`}>
{listGroupItem} {listGroupItem}
</Link> </Link>
); );

View File

@ -23,7 +23,7 @@
"defaultMessage": "Greife sofort auf deine Lieblings-Runs von GDQ zu!" "defaultMessage": "Greife sofort auf deine Lieblings-Runs von GDQ zu!"
}, },
"Home.introText2": { "Home.introText2": {
"defaultMessage": "Diese Website sammelt Icedreams Clips der Runs von Games Done Quick." "defaultMessage": "Diese Website sammelt Clips der Runs von Games Done Quick."
}, },
"LocaleSwitcher.screenReaderText": { "LocaleSwitcher.screenReaderText": {
"defaultMessage": "Sprache ändern", "defaultMessage": "Sprache ändern",

View File

@ -39,7 +39,7 @@
"defaultMessage": "Type something to search here…" "defaultMessage": "Type something to search here…"
}, },
"VideoListPage.updatedLastAgo": { "VideoListPage.updatedLastAgo": {
"defaultMessage": "Updated last {time}", "defaultMessage": "Last updated {time}",
"description": "Text below the video list on the video list page that says in relative time when the list was last updated" "description": "Text below the video list on the video list page that says in relative time when the list was last updated"
}, },
"VideoPlayerPage.tab.mirrorPlayer": { "VideoPlayerPage.tab.mirrorPlayer": {

View File

@ -115,7 +115,7 @@ const getProps = withSession(async (req, _res, { id, vslug }: VideoPlayerPagePar
redirect: true, redirect: true,
id, id,
video, video,
vslug: sanitizeTitle(video.title), vslug: video.slug,
}, },
}; };
} }
@ -132,13 +132,13 @@ const getProps = withSession(async (req, _res, { id, vslug }: VideoPlayerPagePar
redirect: true, redirect: true,
id, id,
video: realVIndex, video: realVIndex,
vslug: sanitizeTitle(video.title), vslug: video.slug,
}, },
}; };
} }
// Check if we can find any video with matching vslug // Check if we can find any video with matching vslug
const video = videos.find(({ title }: { title: string }) => sanitizeTitle(title) === vslug); const video = videos.find(({ slug }: VideoEntry) => slug === vslug);
if (!video) { if (!video) {
return { props: {} }; return { props: {} };
} }

View File

@ -19,45 +19,45 @@
* BOOTSTRAP * BOOTSTRAP
*/ */
@import '~bootstrap/scss/functions'; @import "~bootstrap/scss/functions";
@import '~bootstrap/scss/variables'; @import "~bootstrap/scss/variables";
@import '~bootstrap/scss/mixins'; @import "~bootstrap/scss/mixins";
@import '~@forevolve/bootstrap-dark/scss/dark-mixins'; @import "~@forevolve/bootstrap-dark/scss/dark-mixins";
html:not([data-enable-dark='true']) { html:not([data-enable-dark="true"]) {
@import '~bootstrap/scss/root'; @import "~bootstrap/scss/root";
@import '~bootstrap/scss/reboot'; @import "~bootstrap/scss/reboot";
@import '~bootstrap/scss/type'; @import "~bootstrap/scss/type";
@import '~bootstrap/scss/images'; @import "~bootstrap/scss/images";
// @import '~bootstrap/scss/code'; // @import '~bootstrap/scss/code';
@import '~bootstrap/scss/grid'; @import "~bootstrap/scss/grid";
// @import '~bootstrap/scss/tables'; // @import '~bootstrap/scss/tables';
@import '~bootstrap/scss/forms'; @import "~bootstrap/scss/forms";
@import '~bootstrap/scss/buttons'; @import "~bootstrap/scss/buttons";
@import '~bootstrap/scss/transitions'; @import "~bootstrap/scss/transitions";
@import '~bootstrap/scss/dropdown'; @import "~bootstrap/scss/dropdown";
@import '~bootstrap/scss/button-group'; @import "~bootstrap/scss/button-group";
@import '~bootstrap/scss/input-group'; @import "~bootstrap/scss/input-group";
// @import '~bootstrap/scss/custom-forms'; // @import '~bootstrap/scss/custom-forms';
@import '~bootstrap/scss/nav'; @import "~bootstrap/scss/nav";
@import '~bootstrap/scss/navbar'; @import "~bootstrap/scss/navbar";
// @import '~bootstrap/scss/card'; // @import '~bootstrap/scss/card';
@import '~bootstrap/scss/breadcrumb'; @import "~bootstrap/scss/breadcrumb";
// @import '~bootstrap/scss/pagination'; // @import '~bootstrap/scss/pagination';
// @import '~bootstrap/scss/badge'; // @import '~bootstrap/scss/badge';
// @import '~bootstrap/scss/jumbotron'; // @import '~bootstrap/scss/jumbotron';
// @import '~bootstrap/scss/alert'; // @import '~bootstrap/scss/alert';
// @import '~bootstrap/scss/progress'; // @import '~bootstrap/scss/progress';
@import '~bootstrap/scss/media'; @import "~bootstrap/scss/media";
@import '~bootstrap/scss/list-group'; @import "~bootstrap/scss/list-group";
@import '~bootstrap/scss/close'; @import "~bootstrap/scss/close";
// @import '~bootstrap/scss/toasts'; // @import '~bootstrap/scss/toasts';
// @import '~bootstrap/scss/modal'; // @import '~bootstrap/scss/modal';
@import '~bootstrap/scss/tooltip'; @import "~bootstrap/scss/tooltip";
@import '~bootstrap/scss/popover'; @import "~bootstrap/scss/popover";
// @import '~bootstrap/scss/carousel'; // @import '~bootstrap/scss/carousel';
@import '~bootstrap/scss/spinners'; @import "~bootstrap/scss/spinners";
@import '~bootstrap/scss/utilities'; @import "~bootstrap/scss/utilities";
// @import '~bootstrap/scss/print'; // @import '~bootstrap/scss/print';
} }
@ -65,45 +65,45 @@ html:not([data-enable-dark='true']) {
* BOOTSTRAP DARK * BOOTSTRAP DARK
*/ */
html[data-enable-dark='true'] { html[data-enable-dark="true"] {
@import '~@forevolve/bootstrap-dark/scss/dark-variables'; @import "~@forevolve/bootstrap-dark/scss/dark-variables";
@import '~bootstrap/scss/root'; @import "~bootstrap/scss/root";
@import '~bootstrap/scss/reboot'; @import "~bootstrap/scss/reboot";
@import '~bootstrap/scss/type'; @import "~bootstrap/scss/type";
@import '~bootstrap/scss/images'; @import "~bootstrap/scss/images";
// @import '~bootstrap/scss/code'; // @import '~bootstrap/scss/code';
@import '~bootstrap/scss/grid'; @import "~bootstrap/scss/grid";
// @import '~bootstrap/scss/tables'; // @import '~bootstrap/scss/tables';
// @import '~@forevolve/bootstrap-dark/scss/dark-tables'; // @import '~@forevolve/bootstrap-dark/scss/dark-tables';
@import '~bootstrap/scss/forms'; @import "~bootstrap/scss/forms";
@import '~bootstrap/scss/buttons'; @import "~bootstrap/scss/buttons";
@import '~bootstrap/scss/transitions'; @import "~bootstrap/scss/transitions";
@import '~bootstrap/scss/dropdown'; @import "~bootstrap/scss/dropdown";
@import '~bootstrap/scss/button-group'; @import "~bootstrap/scss/button-group";
@import '~bootstrap/scss/input-group'; @import "~bootstrap/scss/input-group";
@import '~@forevolve/bootstrap-dark/scss/dark-input-group'; @import "~@forevolve/bootstrap-dark/scss/dark-input-group";
// @import '~bootstrap/scss/custom-forms'; // @import '~bootstrap/scss/custom-forms';
@import '~bootstrap/scss/nav'; @import "~bootstrap/scss/nav";
@import '~bootstrap/scss/navbar'; @import "~bootstrap/scss/navbar";
// @import '~bootstrap/scss/card'; // @import '~bootstrap/scss/card';
@import '~bootstrap/scss/breadcrumb'; @import "~bootstrap/scss/breadcrumb";
// @import '~bootstrap/scss/pagination'; // @import '~bootstrap/scss/pagination';
// @import '~bootstrap/scss/badge'; // @import '~bootstrap/scss/badge';
// @import '~bootstrap/scss/jumbotron'; // @import '~bootstrap/scss/jumbotron';
// @import '~bootstrap/scss/alert'; // @import '~bootstrap/scss/alert';
// @import '~bootstrap/scss/progress'; // @import '~bootstrap/scss/progress';
@import '~bootstrap/scss/media'; @import "~bootstrap/scss/media";
@import '~bootstrap/scss/list-group'; @import "~bootstrap/scss/list-group";
@import '~bootstrap/scss/close'; @import "~bootstrap/scss/close";
// @import '~bootstrap/scss/toasts'; // @import '~bootstrap/scss/toasts';
// @import '~bootstrap/scss/modal'; // @import '~bootstrap/scss/modal';
@import '~bootstrap/scss/tooltip'; @import "~bootstrap/scss/tooltip";
@import '~bootstrap/scss/popover'; @import "~bootstrap/scss/popover";
// @import '~bootstrap/scss/carousel'; // @import '~bootstrap/scss/carousel';
@import '~bootstrap/scss/spinners'; @import "~bootstrap/scss/spinners";
@import '~bootstrap/scss/utilities'; @import "~bootstrap/scss/utilities";
// @import '~bootstrap/scss/print'; // @import '~bootstrap/scss/print';
@import '~@forevolve/bootstrap-dark/scss/dark-styles'; @import "~@forevolve/bootstrap-dark/scss/dark-styles";
} }
.breadcrumb { .breadcrumb {

View File

@ -15,13 +15,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@import '~video.js/src/css/video-js'; @import "~video.js/src/css/video-js";
@import 'bootstrap'; @import "bootstrap";
$colorTransitionFunction: ease-out; $colorTransitionFunction: ease-out;
$colorTransitionDuration: 1s; $colorTransitionDuration: 1s;
html[data-toggled-dark='true'] * { html[data-toggled-dark="true"] * {
transition: background-color $colorTransitionDuration $colorTransitionFunction, transition: background-color $colorTransitionDuration $colorTransitionFunction,
color $colorTransitionDuration $colorTransitionFunction, color $colorTransitionDuration $colorTransitionFunction,
border-color $colorTransitionDuration $colorTransitionFunction !important; border-color $colorTransitionDuration $colorTransitionFunction !important;

View File

@ -15,8 +15,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { VideoList } from './datatypes/VideoList'; import { VideoEntry, VideoList } from './datatypes/VideoList';
import { VideoOnDemandIndex } from './datatypes/VideoOnDemandIdentifier'; import { VideoOnDemandIndex } from './datatypes/VideoOnDemandIdentifier';
import sanitizeTitle from './sanitizeTitle';
const upstreamURL = process.env.UPSTREAM_URL; const upstreamURL = process.env.UPSTREAM_URL;
const upstreamDirectURL = process.env.UPSTREAM_DIRECT_URL || upstreamURL; const upstreamDirectURL = process.env.UPSTREAM_DIRECT_URL || upstreamURL;
@ -73,7 +74,26 @@ export async function getIndex(): Promise<VideoOnDemandIndex> {
} }
export async function getVideos(id: string): Promise<VideoList> { export async function getVideos(id: string): Promise<VideoList> {
return getDirect(`videos/${id}.json`); const result: VideoList = await getDirect(`videos/${id}.json`);
result.videos = result.videos.reduce((all: Array<VideoEntry>, {
slug,
title,
...video
}: VideoEntry) => [
...all,
{
...video,
title,
slug: typeof slug === 'string'
? slug
: sanitizeTitle(title + (
all.find(v => v.title === title)
? ` ${all.filter(v => v.title === title).length + 1}`
: ''
)),
},
], [])
return result;
} }
export function getDownloadURL(id: string, fileName: string): string { export function getDownloadURL(id: string, fileName: string): string {

View File

@ -19,6 +19,7 @@ export interface VideoEntry {
fileName:string fileName:string
title: string title: string
duration?: number | string, duration?: number | string,
slug: string,
sourceVideoURL: string sourceVideoURL: string
sourceVideoStart: number | string sourceVideoStart: number | string
sourceVideoEnd: number | string sourceVideoEnd: number | string

View File

@ -1,4 +1,6 @@
ARG NGINX_VERSION=1.19.2 ARG NGINX_VERSION=1.20.1
FROM icedream/nginx as icedream-nginx
FROM nginx:${NGINX_VERSION}-alpine AS ffmpeg-build FROM nginx:${NGINX_VERSION}-alpine AS ffmpeg-build
@ -46,12 +48,11 @@ FROM nginx:${NGINX_VERSION}-alpine
RUN \ RUN \
export DEBIAN_FRONTEND=noninteractive &&\ export DEBIAN_FRONTEND=noninteractive &&\
if command -v apk >/dev/null 2>/dev/null; then apk add --no-cache gnupg; else apt-get update && apt-get install -y gnupg wget ca-certificates && apt-get clean; fi if command -v apk >/dev/null 2>/dev/null; then apk add --no-cache gnupg; else apt-get update && apt-get install -y gnupg wget ca-certificates && apt-get clean; fi
COPY nginx/rootfs/ / COPY --from=icedream-nginx /usr/local/bin/docker-* /usr/local/bin/
RUN chmod +x /usr/local/bin/*
COPY --from=module-source /usr/src/ /usr/src/nginx-modules/ COPY --from=module-source /usr/src/ /usr/src/nginx-modules/
COPY --from=0 /usr/src/packages/ /packages/ COPY --from=ffmpeg-build /usr/src/packages/ /packages/
COPY --from=0 /etc/apk/keys/ /etc/apk/keys/ COPY --from=ffmpeg-build /etc/apk/keys/ /etc/apk/keys/
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN sed -i '1s#^#/packages/community\n#' /etc/apk/repositories RUN sed -i '1s#^#/packages/community\n#' /etc/apk/repositories
RUN cat /etc/apk/repositories RUN cat /etc/apk/repositories