mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-03-08 04:20:08 +03:00
Compare commits
1 Commits
db-bug-fix
...
GlassedSil
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51512a60da |
27
.github/workflows/docker-pr.yml
vendored
27
.github/workflows/docker-pr.yml
vendored
@@ -1,27 +0,0 @@
|
||||
name: docker-pr
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Set hash
|
||||
id: vars
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
|
||||
- name: create-json
|
||||
id: create-json
|
||||
uses: jsdaniell/create-json@1.1.2
|
||||
with:
|
||||
name: "version.json"
|
||||
json: '{"type": "docker", "tag": "nightly", "commit": "${{ steps.vars.outputs.sha_short }}", "date": "${{ steps.date.outputs.date }}"}'
|
||||
dir: 'backend/'
|
||||
- name: Build docker images
|
||||
run: docker build . -t tzahi12345/youtubedl-material:nightly-pr
|
||||
18
.github/workflows/docker.yml
vendored
18
.github/workflows/docker.yml
vendored
@@ -3,16 +3,6 @@ name: docker
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths-ignore:
|
||||
- '.github/**'
|
||||
- '.vscode/**'
|
||||
- 'chrome-extension/**'
|
||||
- 'releases/**'
|
||||
- '**/**.md'
|
||||
- '**.crx'
|
||||
- '**.pem'
|
||||
- '.dockerignore'
|
||||
- '.gitignore'
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
@@ -31,7 +21,7 @@ jobs:
|
||||
uses: jsdaniell/create-json@1.1.2
|
||||
with:
|
||||
name: "version.json"
|
||||
json: '{"type": "docker", "tag": "${{secrets.DOCKERHUB_MASTER_TAG}}", "commit": "${{ steps.vars.outputs.sha_short }}", "date": "${{ steps.date.outputs.date }}"}'
|
||||
json: '{"type": "docker", "tag": "nightly", "commit": "${{ steps.vars.outputs.sha_short }}", "date": "${{ steps.date.outputs.date }}"}'
|
||||
dir: 'backend/'
|
||||
- name: setup platform emulator
|
||||
uses: docker/setup-qemu-action@v1
|
||||
@@ -49,8 +39,4 @@ jobs:
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm,linux/arm64/v8
|
||||
push: true
|
||||
# Defaults:
|
||||
# DOCKERHUB_USERNAME : tzahi12345
|
||||
# DOCKERHUB_REPO : youtubedl-material
|
||||
# DOCKERHUB_MASTER_TAG: nightly
|
||||
tags: ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:${{secrets.DOCKERHUB_MASTER_TAG}}
|
||||
tags: tzahi12345/youtubedl-material:nightly
|
||||
|
||||
54
Dockerfile
54
Dockerfile
@@ -1,26 +1,18 @@
|
||||
FROM ubuntu:22.04 AS ffmpeg
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
FROM ubuntu:20.04 AS ffmpeg
|
||||
|
||||
RUN apt-get update && apt-get -y install curl xz-utils
|
||||
COPY docker-build.sh .
|
||||
RUN sh ./docker-build.sh
|
||||
|
||||
#--------------# Stage 2
|
||||
|
||||
FROM ubuntu:22.04 as frontend
|
||||
FROM ubuntu:20.04 as frontend
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && apt-get -y install \
|
||||
curl \
|
||||
gnupg \
|
||||
# Ubuntu 22.04 ships Node.JS 12 by default :)
|
||||
nodejs \
|
||||
# needed on 21.10 and before, maybe not on 22.04 YARN: brings along npm, solves dependency conflicts,
|
||||
# spares us this spaghetti approach: https://stackoverflow.com/a/60547197
|
||||
npm && \
|
||||
apt-get install -f && \
|
||||
npm config set strict-ssl false && \
|
||||
npm install -g @angular/cli
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install curl gnupg
|
||||
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
|
||||
RUN apt-get -y install nodejs
|
||||
|
||||
RUN npm install -g @angular/cli
|
||||
|
||||
WORKDIR /build
|
||||
COPY [ "package.json", "package-lock.json", "/build/" ]
|
||||
@@ -30,43 +22,37 @@ COPY [ "angular.json", "tsconfig.json", "/build/" ]
|
||||
COPY [ "src/", "/build/src/" ]
|
||||
RUN npm run build
|
||||
|
||||
#--------------# Final Stage
|
||||
#--------------#
|
||||
|
||||
FROM ubuntu:22.04
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ENV UID=1000 \
|
||||
GID=1000 \
|
||||
USER=youtube \
|
||||
NO_UPDATE_NOTIFIER=true
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN groupadd -g $GID $USER && useradd --system -g $USER --uid $UID $USER
|
||||
|
||||
RUN apt-get update && apt-get -y install curl
|
||||
|
||||
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
|
||||
RUN apt-get update && apt-get -y install \
|
||||
npm \
|
||||
nodejs \
|
||||
python2 \
|
||||
python3 \
|
||||
gosu \
|
||||
atomicparsley && \
|
||||
apt-get install -f && \
|
||||
apt-get autoremove --purge && \
|
||||
apt-get autoremove && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt
|
||||
atomicparsley
|
||||
|
||||
WORKDIR /app
|
||||
COPY --chown=$UID:$GID --from=ffmpeg [ "/usr/local/bin/ffmpeg", "/usr/local/bin/ffmpeg" ]
|
||||
COPY --chown=$UID:$GID --from=ffmpeg [ "/usr/local/bin/ffprobe", "/usr/local/bin/ffprobe" ]
|
||||
COPY --from=ffmpeg /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
|
||||
COPY --from=ffmpeg /usr/local/bin/ffprobe /usr/local/bin/ffprobe
|
||||
COPY --chown=$UID:$GID [ "backend/package.json", "backend/package-lock.json", "/app/" ]
|
||||
ENV PM2_HOME=/app/pm2
|
||||
RUN npm config set strict-ssl false && \
|
||||
npm install pm2 -g && \
|
||||
RUN npm install pm2 -g && \
|
||||
npm install && chown -R $UID:$GID ./
|
||||
|
||||
COPY --chown=$UID:$GID --from=frontend [ "/build/backend/public/", "/app/public/" ]
|
||||
COPY --chown=$UID:$GID [ "/backend/", "/app/" ]
|
||||
|
||||
EXPOSE 17442
|
||||
ENTRYPOINT [ "/app/entrypoint.sh" ]
|
||||
# ENTRYPOINT [ "/app/entrypoint.sh" ]
|
||||
CMD [ "pm2-runtime", "pm2.config.js" ]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[](https://github.com/Tzahi12345/YoutubeDL-Material/issues)
|
||||
[](https://github.com/Tzahi12345/YoutubeDL-Material/blob/master/LICENSE.md)
|
||||
|
||||
YoutubeDL-Material is a Material Design frontend for [youtube-dl](https://rg3.github.io/youtube-dl/). It's coded using [Angular 13](https://angular.io/) for the frontend, and [Node.js](https://nodejs.org/) on the backend.
|
||||
YoutubeDL-Material is a Material Design frontend for [youtube-dl](https://rg3.github.io/youtube-dl/). It's coded using [Angular 11](https://angular.io/) for the frontend, and [Node.js](https://nodejs.org/) on the backend.
|
||||
|
||||
Now with [Docker](#Docker) support!
|
||||
|
||||
|
||||
49
armhf.Dockerfile
Normal file
49
armhf.Dockerfile
Normal file
@@ -0,0 +1,49 @@
|
||||
FROM alpine:3.12 as frontend
|
||||
|
||||
RUN apk add --no-cache \
|
||||
npm \
|
||||
curl
|
||||
|
||||
RUN npm install -g @angular/cli
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
RUN curl -L https://github.com/balena-io/qemu/releases/download/v3.0.0%2Bresin/qemu-3.0.0+resin-arm.tar.gz | tar zxvf - -C . && mv qemu-3.0.0+resin-arm/qemu-arm-static .
|
||||
|
||||
COPY [ "package.json", "package-lock.json", "/build/" ]
|
||||
RUN npm install
|
||||
|
||||
COPY [ "angular.json", "tsconfig.json", "/build/" ]
|
||||
COPY [ "src/", "/build/src/" ]
|
||||
RUN ng build --prod
|
||||
|
||||
#--------------#
|
||||
|
||||
FROM arm32v7/alpine:3.12
|
||||
|
||||
COPY --from=frontend /build/qemu-arm-static /usr/bin
|
||||
|
||||
ENV UID=1000 \
|
||||
GID=1000 \
|
||||
USER=youtube
|
||||
|
||||
RUN addgroup -S $USER -g $GID && adduser -D -S $USER -G $USER -u $UID
|
||||
|
||||
RUN apk add --no-cache \
|
||||
ffmpeg \
|
||||
npm \
|
||||
python2 \
|
||||
su-exec \
|
||||
&& apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing/ \
|
||||
atomicparsley
|
||||
|
||||
WORKDIR /app
|
||||
COPY --chown=$UID:$GID [ "backend/package.json", "backend/package-lock.json", "/app/" ]
|
||||
RUN npm install && chown -R $UID:$GID ./
|
||||
|
||||
COPY --chown=$UID:$GID --from=frontend [ "/build/backend/public/", "/app/public/" ]
|
||||
COPY --chown=$UID:$GID [ "/backend/", "/app/" ]
|
||||
|
||||
EXPOSE 17442
|
||||
ENTRYPOINT [ "/app/entrypoint.sh" ]
|
||||
CMD [ "node", "app.js" ]
|
||||
@@ -222,83 +222,4 @@ exports.AVAILABLE_PERMISSIONS = [
|
||||
|
||||
exports.DETAILS_BIN_PATH = 'node_modules/youtube-dl/bin/details'
|
||||
|
||||
// args that have a value after it (e.g. -o <output> or -f <format>)
|
||||
const YTDL_ARGS_WITH_VALUES = [
|
||||
'--default-search',
|
||||
'--config-location',
|
||||
'--proxy',
|
||||
'--socket-timeout',
|
||||
'--source-address',
|
||||
'--geo-verification-proxy',
|
||||
'--geo-bypass-country',
|
||||
'--geo-bypass-ip-block',
|
||||
'--playlist-start',
|
||||
'--playlist-end',
|
||||
'--playlist-items',
|
||||
'--match-title',
|
||||
'--reject-title',
|
||||
'--max-downloads',
|
||||
'--min-filesize',
|
||||
'--max-filesize',
|
||||
'--date',
|
||||
'--datebefore',
|
||||
'--dateafter',
|
||||
'--min-views',
|
||||
'--max-views',
|
||||
'--match-filter',
|
||||
'--age-limit',
|
||||
'--download-archive',
|
||||
'-r',
|
||||
'--limit-rate',
|
||||
'-R',
|
||||
'--retries',
|
||||
'--fragment-retries',
|
||||
'--buffer-size',
|
||||
'--http-chunk-size',
|
||||
'--external-downloader',
|
||||
'--external-downloader-args',
|
||||
'-a',
|
||||
'--batch-file',
|
||||
'-o',
|
||||
'--output',
|
||||
'--output-na-placeholder',
|
||||
'--autonumber-start',
|
||||
'--load-info-json',
|
||||
'--cookies',
|
||||
'--cache-dir',
|
||||
'--encoding',
|
||||
'--user-agent',
|
||||
'--referer',
|
||||
'--add-header',
|
||||
'--sleep-interval',
|
||||
'--max-sleep-interval',
|
||||
'-f',
|
||||
'--format',
|
||||
'--merge-output-format',
|
||||
'--sub-format',
|
||||
'--sub-lang',
|
||||
'-u',
|
||||
'--username',
|
||||
'-p',
|
||||
'--password',
|
||||
'-2',
|
||||
'--twofactor',
|
||||
'--video-password',
|
||||
'--ap-mso',
|
||||
'--ap-username',
|
||||
'--ap-password',
|
||||
'--audio-format',
|
||||
'--audio-quality',
|
||||
'--recode-video',
|
||||
'--postprocessor-args',
|
||||
'--metadata-from-title',
|
||||
'--fixup',
|
||||
'--ffmpeg-location',
|
||||
'--exec',
|
||||
'--convert-subs'
|
||||
];
|
||||
|
||||
// we're using a Set here for performance
|
||||
exports.YTDL_ARGS_WITH_VALUES = new Set(YTDL_ARGS_WITH_VALUES);
|
||||
|
||||
exports.CURRENT_VERSION = 'v4.2';
|
||||
|
||||
@@ -85,6 +85,8 @@ exports.initialize = (input_db, input_users_db) => {
|
||||
}
|
||||
|
||||
exports.connectToDB = async (retries = 5, no_fallback = false, custom_connection_string = null) => {
|
||||
using_local_db = config_api.getConfigItem('ytdl_use_local_db'); // verify
|
||||
if (using_local_db && !custom_connection_string) return;
|
||||
const success = await exports._connectToDB(custom_connection_string);
|
||||
if (success) return true;
|
||||
|
||||
@@ -495,7 +497,6 @@ exports.deleteFile = async (uid, uuid = null, blacklistMode = false) => {
|
||||
|
||||
let useYoutubeDLArchive = config_api.getConfigItem('ytdl_use_youtubedl_archive');
|
||||
if (useYoutubeDLArchive) {
|
||||
const usersFileFolder = config_api.getConfigItem('ytdl_users_base_path');
|
||||
const archive_path = uuid ? path.join(usersFileFolder, uuid, 'archives', `archive_${type}.txt`) : path.join('appdata', 'archives', `archive_${type}.txt`);
|
||||
|
||||
// get ID from JSON
|
||||
|
||||
@@ -485,7 +485,7 @@ exports.generateArgs = async (url, type, options, user_uid = null, simulated = f
|
||||
}
|
||||
|
||||
if (options.additionalArgs && options.additionalArgs !== '') {
|
||||
downloadConfig = utils.injectArgs(downloadConfig, options.additionalArgs.split(',,'));
|
||||
downloadConfig = downloadConfig.concat(options.additionalArgs.split(',,'));
|
||||
}
|
||||
|
||||
const rate_limit = config_api.getConfigItem('ytdl_download_rate_limit');
|
||||
|
||||
@@ -11,7 +11,7 @@ fi
|
||||
# chown current working directory to current user
|
||||
if [ "$*" = "$CMD" ] && [ "$(id -u)" = "0" ]; then
|
||||
find . \! -user "$UID" -exec chown "$UID:$GID" -R '{}' + || echo "WARNING! Could not change directory ownership. If you manage permissions externally this is fine, otherwise you may experience issues when downloading or deleting videos."
|
||||
exec gosu "$UID:$GID" "$0" "$@"
|
||||
exec su-exec "$UID:$GID" "$0" "$@"
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# INTERACTIVE PERMISSIONS FIX SCRIPT FOR YTDL-M
|
||||
# Date: 2022-05-03
|
||||
|
||||
# If you want to run this script on a bare-metal installation instead of within Docker
|
||||
# make sure that the paths configured below match your paths! (it's wise to use the full paths)
|
||||
# USAGE: within your container's bash shell:
|
||||
# chmod -R +x ./fix-scripts/
|
||||
# ./fix-scripts/001-fix_download_permissions.sh
|
||||
|
||||
# User defines / Docker env defaults
|
||||
PATH_SUBS=/app/subscriptions
|
||||
PATH_AUDIO=/app/audio
|
||||
PATH_VIDS=/app/video
|
||||
|
||||
clear -x
|
||||
echo "\n"
|
||||
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - # horizontal line
|
||||
echo "Welcome to the INTERACTIVE PERMISSIONS FIX SCRIPT FOR YTDL-M."
|
||||
echo "This script will set YTDL-M's download paths' owner to ${USER} (${UID}:${GID})"
|
||||
echo "and permissions to the default of 644."
|
||||
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - # horizontal line
|
||||
echo "\n"
|
||||
|
||||
# check whether dirs exist
|
||||
i=0
|
||||
[ -d $PATH_SUBS ] && i=$((i+1)) && echo "✔ (${i}/3) Found Subscriptions directory at ${PATH_SUBS}"
|
||||
[ -d $PATH_AUDIO ] && i=$((i+1)) && echo "✔ (${i}/3) Found Audio directory at ${PATH_AUDIO}"
|
||||
[ -d $PATH_VIDS ] && i=$((i+1)) && echo "✔ (${i}/3) Found Video directory at ${PATH_VIDS}"
|
||||
|
||||
# Ask to proceed or cancel, exit on missing paths
|
||||
case $i in
|
||||
0)
|
||||
echo "\nCouldn't find any download path to fix permissions for! \nPlease edit this script to configure!"
|
||||
exit 2;;
|
||||
3)
|
||||
echo "\nFound all download paths to fix permissions for. \nProceed? (Y/N)";;
|
||||
*)
|
||||
echo "\nOnly found ${i} out of 3 download paths! Something about this script's config must be wrong. \nProceed anyways? (Y/N)";;
|
||||
esac
|
||||
old_stty_cfg=$(stty -g)
|
||||
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
|
||||
if echo "$answer" | grep -iq "^y" ;then
|
||||
echo "\n Running jobs now... (this may take a while)\n"
|
||||
[ -d $PATH_SUBS ] && chown "$UID:$GID" -R $PATH_SUBS && echo "✔ Set owner of ${PATH_SUBS} to ${USER}."
|
||||
[ -d $PATH_SUBS ] && chmod 644 -R $PATH_SUBS && echo "✔ Set permissions of ${PATH_SUBS} to 644."
|
||||
[ -d $PATH_AUDIO ] && chown "$UID:$GID" -R $PATH_AUDIO && echo "✔ Set owner of ${PATH_AUDIO} to ${USER}."
|
||||
[ -d $PATH_AUDIO ] && chmod 644 -R $PATH_AUDIO && echo "✔ Set permissions of ${PATH_AUDIO} to 644."
|
||||
[ -d $PATH_VIDS ] && chown "$UID:$GID" -R $PATH_VIDS && echo "✔ Set owner of ${PATH_VIDS} to ${USER}."
|
||||
[ -d $PATH_VIDS ] && chmod 644 -R $PATH_VIDS && echo "✔ Set permissions of ${PATH_VIDS} to 644."
|
||||
echo "\n✔ Done."
|
||||
echo "\n If you noticed file access errors those MAY be due to currently running downloads."
|
||||
echo " Feel free to re-run this script, however download parts should have correct file permissions anyhow. :)"
|
||||
exit
|
||||
else
|
||||
echo "\nOkay, bye."
|
||||
fi
|
||||
@@ -141,7 +141,6 @@ async function unsubscribe(sub, deleteMode, user_uid = null) {
|
||||
if (sub.archive && (await fs.pathExists(sub.archive))) {
|
||||
const archive_file_path = path.join(sub.archive, 'archive.txt');
|
||||
// deletes archive if it exists
|
||||
// TODO: Keep entries in blacklist_video.txt by moving them to a global blacklist
|
||||
if (await fs.pathExists(archive_file_path)) {
|
||||
await fs.unlink(archive_file_path);
|
||||
}
|
||||
@@ -380,11 +379,7 @@ async function generateArgsForSubscription(sub, user_uid, redownload = false, de
|
||||
if (useArchive && !redownload) {
|
||||
if (sub.archive) {
|
||||
archive_dir = sub.archive;
|
||||
if (sub.type && sub.type === 'audio') {
|
||||
archive_path = path.join(archive_dir, 'merged_audio.txt');
|
||||
} else {
|
||||
archive_path = path.join(archive_dir, 'merged_video.txt');
|
||||
}
|
||||
archive_path = path.join(archive_dir, 'archive.txt')
|
||||
}
|
||||
downloadConfig.push('--download-archive', archive_path);
|
||||
}
|
||||
|
||||
@@ -386,21 +386,6 @@ describe('Downloader', function() {
|
||||
assert(fs.existsSync(nfo_file_path), true);
|
||||
fs.unlinkSync(nfo_file_path);
|
||||
});
|
||||
|
||||
it('Inject args', async function() {
|
||||
const original_args1 = ['--no-resize-buffer', '-o', '%(title)s', '--no-mtime'];
|
||||
const new_args1 = ['--age-limit', '25', '--yes-playlist', '--abort-on-error', '-o', '%(id)s'];
|
||||
const updated_args1 = utils.injectArgs(original_args1, new_args1);
|
||||
const expected_args1 = ['--no-resize-buffer', '--no-mtime', '--age-limit', '25', '--yes-playlist', '--abort-on-error', '-o', '%(id)s'];
|
||||
assert(JSON.stringify(updated_args1), JSON.stringify(expected_args1));
|
||||
|
||||
const original_args2 = ['-o', '%(title)s.%(ext)s', '--write-info-json', '--print-json', '--audio-quality', '0', '-x', '--audio-format', 'mp3'];
|
||||
const new_args2 = ['--add-metadata', '--embed-thumbnail', '--convert-thumbnails', 'jpg'];
|
||||
const updated_args2 = utils.injectArgs(original_args2, new_args2);
|
||||
const expected_args2 = ['-o', '%(title)s.%(ext)s', '--write-info-json', '--print-json', '--audio-quality', '0', '-x', '--audio-format', 'mp3', '--add-metadata', '--embed-thumbnail', '--convert_thumbnails', 'jpg'];
|
||||
console.log(updated_args2);
|
||||
assert(JSON.stringify(updated_args2), JSON.stringify(expected_args2));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Tasks', function() {
|
||||
|
||||
@@ -415,39 +415,6 @@ async function fetchFile(url, path, file_label) {
|
||||
});
|
||||
}
|
||||
|
||||
// adds or replaces args according to the following rules:
|
||||
// - if it already exists and has value, then replace both arg and value
|
||||
// - if already exists and doesn't have value, ignore
|
||||
// - if it doesn't exist and has value, add both arg and value
|
||||
// - if it doesn't exist and doesn't have value, add arg
|
||||
function injectArgs(original_args, new_args) {
|
||||
const updated_args = original_args.slice();
|
||||
try {
|
||||
for (let i = 0; i < new_args.length; i++) {
|
||||
const new_arg = new_args[i];
|
||||
if (!new_arg.startsWith('-') && !new_arg.startsWith('--') && i > 0 && original_args.includes(new_args[i - 1])) continue;
|
||||
|
||||
if (CONSTS.YTDL_ARGS_WITH_VALUES.has(new_arg)) {
|
||||
if (original_args.includes(new_arg)) {
|
||||
const original_index = original_args.indexOf(new_arg);
|
||||
original_args.splice(original_index, 2);
|
||||
}
|
||||
|
||||
updated_args.push(new_arg, new_args[i + 1]);
|
||||
} else {
|
||||
if (!original_args.includes(new_arg)) {
|
||||
updated_args.push(new_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn(err);
|
||||
logger.warn(`Failed to inject args (${new_args}) into (${original_args})`);
|
||||
}
|
||||
|
||||
return updated_args;
|
||||
}
|
||||
|
||||
// objects
|
||||
|
||||
function File(id, title, thumbnailURL, isAudio, duration, url, uploader, size, path, upload_date, description, view_count, height, abr) {
|
||||
@@ -491,6 +458,5 @@ module.exports = {
|
||||
wait: wait,
|
||||
checkExistsWithTimeout: checkExistsWithTimeout,
|
||||
fetchFile: fetchFile,
|
||||
injectArgs: injectArgs,
|
||||
File: File
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
# and also optimizing some code with this commit.
|
||||
# xoxo :D
|
||||
|
||||
# set -xeuo pipefail
|
||||
|
||||
case $(uname -m) in
|
||||
x86_64)
|
||||
ARCH=amd64;;
|
||||
@@ -20,24 +22,15 @@ case $(uname -m) in
|
||||
exit 1
|
||||
esac
|
||||
|
||||
echo "(INFO) Architecture detected: $ARCH"
|
||||
echo "(1/5) READY - Acquire temp dependencies in ffmpeg obtain layer"
|
||||
apt-get update && apt-get -y install curl xz-utils
|
||||
echo "(2/5) DOWNLOAD - Acquire latest ffmpeg and ffprobe from John van Sickle's master-sourced builds in ffmpeg obtain layer"
|
||||
curl -o ffmpeg.txz \
|
||||
--connect-timeout 5 \
|
||||
echo "Architecture: $ARCH"
|
||||
curl --connect-timeout 5 \
|
||||
--max-time 10 \
|
||||
--retry 5 \
|
||||
--retry-delay 0 \
|
||||
--retry-max-time 40 \
|
||||
"https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-${ARCH}-static.tar.xz"
|
||||
"https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-${ARCH}-static.tar.xz" -o ffmpeg.txz
|
||||
mkdir /tmp/ffmpeg
|
||||
tar xf ffmpeg.txz -C /tmp/ffmpeg
|
||||
echo "(3/5) CLEANUP - Remove temp dependencies from ffmpeg obtain layer"
|
||||
apt-get -y remove curl xz-utils
|
||||
apt-get -y autoremove
|
||||
echo "(4/5) PROVISION - Provide ffmpeg and ffprobe from ffmpeg obtain layer"
|
||||
cp /tmp/ffmpeg/*/ffmpeg /usr/local/bin/ffmpeg
|
||||
cp /tmp/ffmpeg/*/ffprobe /usr/local/bin/ffprobe
|
||||
echo "(5/5) CLEANUP - Remove temporary downloads from ffmpeg obtain layer"
|
||||
rm -rf /tmp/ffmpeg ffmpeg.txz
|
||||
@@ -12,8 +12,7 @@
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"electron": "ng build --base-href ./ && electron .",
|
||||
"generate": "openapi --input ./\"Public API v1.yaml\" --output ./src/api-types --exportCore false --exportServices false --exportModels true",
|
||||
"i18n-source": "ng extract-i18n --output-path=src/assets/i18n"
|
||||
"generate": "openapi --input ./\"Public API v1.yaml\" --output ./src/api-types --exportCore false --exportServices false --exportModels true"
|
||||
},
|
||||
"engines": {
|
||||
"node": "12.3.1",
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
</ng-container>
|
||||
<ng-container *ngIf="postsService.config && allowSubscriptions && postsService.subscriptions && postsService.hasPermission('subscriptions')">
|
||||
<mat-divider *ngIf="postsService.subscriptions.length > 0"></mat-divider>
|
||||
<a *ngFor="let subscription of postsService.subscriptions" mat-list-item (click)="postsService.sidepanel_mode === 'over' ? sidenav.close() : null" [routerLink]="['/subscription', { id: subscription.id }]"><ngx-avatars [style.margin-right]="'10px'" size="32" [name]="subscription.name"></ngx-avatars>{{subscription.name}}</a>
|
||||
<a *ngFor="let subscription of postsService.subscriptions" mat-list-item (click)="postsService.sidepanel_mode === 'over' ? sidenav.close() : null" [routerLink]="['/subscription', { id: subscription.id }]"><ngx-avatar [style.margin-right]="'10px'" size="32" [name]="subscription.name"></ngx-avatar>{{subscription.name}}</a>
|
||||
</ng-container>
|
||||
</mat-nav-list>
|
||||
</mat-sidenav>
|
||||
|
||||
@@ -42,11 +42,6 @@ export class ConcurrentStreamComponent implements OnInit {
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.check_timeout) { clearInterval(this.check_timeout); }
|
||||
if (this.update_timeout) { clearInterval(this.update_timeout); }
|
||||
}
|
||||
|
||||
startServer() {
|
||||
this.started = true;
|
||||
this.server_started = true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, ElementRef, Input, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
|
||||
import { AfterViewInit, Component, ElementRef, Input, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
|
||||
import { PostsService } from 'app/posts.services';
|
||||
|
||||
@Component({
|
||||
@@ -6,7 +6,7 @@ import { PostsService } from 'app/posts.services';
|
||||
templateUrl: './twitch-chat.component.html',
|
||||
styleUrls: ['./twitch-chat.component.scss']
|
||||
})
|
||||
export class TwitchChatComponent implements OnInit, OnDestroy {
|
||||
export class TwitchChatComponent implements OnInit, AfterViewInit {
|
||||
|
||||
full_chat = null;
|
||||
visible_chat = null;
|
||||
@@ -33,8 +33,7 @@ export class TwitchChatComponent implements OnInit, OnDestroy {
|
||||
this.getFullChat();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.chat_check_interval_obj) { clearInterval(this.chat_check_interval_obj); }
|
||||
ngAfterViewInit() {
|
||||
}
|
||||
|
||||
private isUserNearBottom(): boolean {
|
||||
|
||||
@@ -445,7 +445,7 @@ export const isoLangs = {
|
||||
'name': 'Navajo, Navaho',
|
||||
'nativeName': 'Diné bizaad, Dinékʼehǰí'
|
||||
},
|
||||
'nb-NO': {
|
||||
'nb': {
|
||||
'name': 'Norwegian Bokmål',
|
||||
'nativeName': 'Norsk bokmål',
|
||||
'ngID': 'nb'
|
||||
|
||||
@@ -52,8 +52,6 @@ export class SubscriptionComponent implements OnInit, OnDestroy {
|
||||
this.route.params.subscribe(params => {
|
||||
this.id = params['id'];
|
||||
|
||||
if (this.sub_interval) { clearInterval(this.sub_interval); }
|
||||
|
||||
this.postsService.service_initialized.subscribe(init => {
|
||||
if (init) {
|
||||
this.getConfig();
|
||||
|
||||
@@ -36,9 +36,6 @@
|
||||
<ng-container i18n="Subscription playlist not available text">Name not available. Playlist retrieval in progress.</ng-container>
|
||||
</div>
|
||||
</a>
|
||||
<button mat-icon-button (click)="editSubscription(sub)">
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="showSubInfo(sub)">
|
||||
<mat-icon>info</mat-icon>
|
||||
</button>
|
||||
|
||||
2634
src/assets/i18n/messages.bas.xlf
Normal file
2634
src/assets/i18n/messages.bas.xlf
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3040
src/assets/i18n/messages.hi.xlf
Normal file
3040
src/assets/i18n/messages.hi.xlf
Normal file
File diff suppressed because it is too large
Load Diff
222
src/assets/i18n/messages.nb.json
Normal file
222
src/assets/i18n/messages.nb.json
Normal file
@@ -0,0 +1,222 @@
|
||||
{
|
||||
"17f0ea5d2d7a262b0e875acc70475f102aee84e6": "Opprett en spilleliste",
|
||||
"cff1428d10d59d14e45edec3c735a27b5482db59": "Navn",
|
||||
"f0baeb8b69d120073b6d60d34785889b0c3232c8": "Lyd",
|
||||
"2d1ea268a6a9f483dbc2cbfe19bf4256a57a6af4": "Video",
|
||||
"f61c6867295f3b53d23557021f2f4e0aa1d0b8fc": "Type",
|
||||
"f47e2d56dd8a145b2e9599da9730c049d52962a2": "Lydfiler",
|
||||
"a52dae09be10ca3a65da918533ced3d3f4992238": "Videoer",
|
||||
"d9e83ac17026e70ef6e9c0f3240a3b2450367f40": "Endre youtube-dl-argumenter",
|
||||
"7fc1946abe2b40f60059c6cd19975d677095fd19": "Simulerte nye argumenter",
|
||||
"0b71824ae71972f236039bed43f8d2323e8fd570": "Legg til argument",
|
||||
"c8b0e59eb491f2ac7505f0fbab747062e6b32b23": "Søk etter kategori",
|
||||
"9eeb91caef5a50256dd87e1c4b7b3e8216479377": "Bruk argument-verdi",
|
||||
"25d8ad5eba2ec24e68295a27d6a4bb9b49e3dacd": "Argument-verdi",
|
||||
"7de2451ed3fb8d8b847979bd3f0c740b970f167b": "Legg til argument",
|
||||
"d7b35c384aecd25a516200d6921836374613dfe7": "Avbryt",
|
||||
"b2623aee44b70c9a4ba1fce16c8a593b0a4c7974": "Endre",
|
||||
"a38ae1082fec79ba1f379978337385a539a28e73": "Kvalitet",
|
||||
"4be966a9dcfbc9b54dfcc604b831c0289f847fa4": "Bruk nettadresse",
|
||||
"d3f02f845e62cebd75fde451ab8479d2a8ad784d": "Vis",
|
||||
"4a9889d36910edc8323d7bab60858ab3da6d91df": "Kun lyd",
|
||||
"96a01fafe135afc58b0f8071a4ab00234495ce18": "Multi-nedlastingsmodus",
|
||||
"6a21ba5fb0ac804a525bf9ab168038c3ee88e661": "Last ned",
|
||||
"6a3777f913cf3f288664f0632b9f24794fdcc24e": "Avbryt",
|
||||
"322ed150e02666fe2259c5b4614eac7066f4ffa0": "Avansert",
|
||||
"b7ffe7c6586d6f3f18a9246806a7c7d5538ab43e": "Simulert kommando:",
|
||||
"4e4c721129466be9c3862294dc40241b64045998": "Bruk egendefinerte argumenter:",
|
||||
"ad2f8ac8b7de7945b80c8e424484da94e597125f": "Egendefinerte argumenter",
|
||||
"a6911c2157f1b775284bbe9654ce5eb30cf45d7f": "Du trenger ikke å inkludere nettadressen, kun alt etter. Argumenter skilles ved bruk av to komma, slik: ,,",
|
||||
"3a92a3443c65a52f37ca7efb8f453b35dbefbf29": "Bruk defendefinert utdata",
|
||||
"d9c02face477f2f9cdaae318ccee5f89856851fb": "Egendefinert utdata",
|
||||
"fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7": "Dokumentasjon",
|
||||
"19d1ae64d94d28a29b2c57ae8671aace906b5401": "Sti er relativ til oppsettsnedlastingsstien. Ikke inkluder utvidelse.",
|
||||
"8fad10737d3e3735a6699a4d89cbf6c20f6bb55f": "Bruk identitetsbekreftelse",
|
||||
"08c74dc9762957593b91f6eb5d65efdfc975bf48": "Brukernavn",
|
||||
"c32ef07f8803a223a83ed17024b38e8d82292407": "Passord",
|
||||
"616e206cb4f25bd5885fc35925365e43cf5fb929": "Navn:",
|
||||
"c52db455cca9109ee47e1a612c3f4117c09eb71b": "Nettadresse:",
|
||||
"c6eb45d085384903e53ab001a3513d1de6a1dbac": "Opplaster:",
|
||||
"109c6f4a5e46efb933612ededfaf52a13178b7e0": "Filstørrelse:",
|
||||
"bd630d8669b16e5f264ec4649d9b469fe03e5ff4": "Sti:",
|
||||
"a67e7d843cef735c79d5ef1c8ba4af3e758912bb": "Opplastingsdato:",
|
||||
"f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8": "Lukk",
|
||||
"4f389e41e4592f7f9bb76abdd8af4afdfb13f4f1": "Endre spilleliste",
|
||||
"511b600ae4cf037e4eb3b7a58410842cd5727490": "Legg til mer innhold",
|
||||
"52c9a103b812f258bcddc3d90a6e3f46871d25fe": "Lagre",
|
||||
"ca3dbbc7f3e011bffe32a10a3ea45cc84f30ecf1": "ID:",
|
||||
"e684046d73bcee88e82f7ff01e2852789a05fc32": "Antall:",
|
||||
"28f86ffd419b869711aa13f5e5ff54be6d70731c": "Rediger",
|
||||
"826b25211922a1b46436589233cb6f1a163d89b7": "Slett",
|
||||
"321e4419a943044e674beb55b8039f42a9761ca5": "Info",
|
||||
"34504b488c24c27e68089be549f0eeae6ebaf30b": "Slett og svartelist",
|
||||
"ebadf946ae90f13ecd0c70f09edbc0f983af8a0f": "Last opp nye kaker",
|
||||
"98a8a42e5efffe17ab786636ed0139b4c7032d0e": "Dra og slipp",
|
||||
"a8b7b9c168fd936a75e500806a8c0d7755ef1198": "Merk: Oppasting av nye kaker overskriver tidligere. Merk deg også at kaker gjelder for hele instansen, ikke per bruker.",
|
||||
"121cc5391cd2a5115bc2b3160379ee5b36cd7716": "Innstillinger",
|
||||
"801b98c6f02fe3b32f6afa3ee854c99ed83474e6": "Nettadresse",
|
||||
"54c512cca1923ab72faf1a0bd98d3d172469629a": "Nettadressen dette programmet nås fra, uten porten.",
|
||||
"cb2741a46e3560f6bc6dfd99d385e86b08b26d72": "Port",
|
||||
"22e8f1d0423a3b784fe40fab187b92c06541b577": "Ønsket port. Forvalet er 17442.",
|
||||
"d4477669a560750d2064051a510ef4d7679e2f3e": "Multi-brukermodus",
|
||||
"2eb03565fcdce7a7a67abc277a936a32fcf51557": "Bruker-basissti",
|
||||
"a64505c41150663968e277ec9b3ddaa5f4838798": "Basissti for brukere og deres nedlastede videoer.",
|
||||
"4e3120311801c4acd18de7146add2ee4a4417773": "Tillat abonnementer",
|
||||
"4bee2a4bef2d26d37c9b353c278e24e5cd309ce3": "Abonnements-basissti",
|
||||
"bc9892814ee2d119ae94378c905ea440a249b84a": "Basissti for videoer fra dine abonnementskanaler og spillelister. Den er relativ til YTDL-Material sin rotmappe.",
|
||||
"5bef4b25ba680da7fff06b86a91b1fc7e6a926e3": "Sjekkintervall",
|
||||
"0f56a7449b77630c114615395bbda4cab398efd8": "I sekunder, kun tall.",
|
||||
"27a56aad79d8b61269ed303f11664cc78bcc2522": "Drakt",
|
||||
"ff7cee38a2259526c519f878e71b964f41db4348": "Forvalg",
|
||||
"adb4562d2dbd3584370e44496969d58c511ecb63": "Mørk",
|
||||
"7a6bacee4c31cb5c0ac2d24274fb4610d8858602": "Tillat draktendring",
|
||||
"fe46ccaae902ce974e2441abe752399288298619": "Språk",
|
||||
"82421c3e46a0453a70c42900eab51d58d79e6599": "Generelt",
|
||||
"ab2756805742e84ad0cc0468f4be2d8aa9f855a5": "Lydmappe",
|
||||
"c2c89cdf45d46ea64d2ed2f9ac15dfa4d77e26ca": "Sti for lydbaserte nedlastinger. Den er relativ til YTDL-Material sin rotmappe.",
|
||||
"46826331da1949bd6fb74624447057099c9d20cd": "Videomappe",
|
||||
"17c92e6d47a213fa95b5aa344b3f258147123f93": "Sti for videonedlastinger. Den er relativ til YTDL-Material sin rotmappe.",
|
||||
"6b995e7130b4d667eaab6c5f61b362ace486d26d": "Egendefinerte argumenter for nedlastninger på hjemmesiden for hele programmet. Argumenter skilles med to komma, slik: ,,",
|
||||
"78e49b7339b4fa7184dd21bcaae107ce9b7076f6": "Bruk youtube-dl-arktivet",
|
||||
"ffc19f32b1cba0daefc0e5668f89346db1db83ad": "Inkluder miniatyrbilde",
|
||||
"384de8f8f112c9e6092eb2698706d391553f3e8d": "Inkluder metadata",
|
||||
"fb35145bfb84521e21b6385363d59221f436a573": "Drep alle nedlastinger",
|
||||
"0ba25ad86a240576c4f20a2fada4722ebba77b1e": "Nedlaster",
|
||||
"61f8fd90b5f8cb20c70371feb2ee5e1fac5a9095": "Topptittel",
|
||||
"78d3531417c0d4ba4c90f0d4ae741edc261ec8df": "Filbehandler påskrudd",
|
||||
"a5a1be0a5df07de9eec57f5d2a86ed0204b2e75a": "Nedlastingsbehandler påskrudd",
|
||||
"c33bd5392b39dbed36b8e5a1145163a15d45835f": "Tillat kvalitetsvalg",
|
||||
"bda5508e24e0d77debb28bcd9194d8fefb1cfb92": "Modus kun for nedlasting",
|
||||
"09d31c803a7252658694e1e3176b97f5655a3fe3": "Tillat multi-nedlastingsmodus",
|
||||
"1c4dbce56d96b8974aac24a02f7ab2ee81415014": "Skru på offentlig API",
|
||||
"23bd81dcc30b74d06279a26d7a42e8901c1b124e": "Offentlig API-nøkkel",
|
||||
"41016a73d8ad85e6cb26dffa0a8fab9fe8f60d8e": "Vis dokumentasjon",
|
||||
"1b258b258b4cc475ceb2871305b61756b0134f4a": "Generer",
|
||||
"00a94f58d9eb2e3aa561440eabea616d0c937fa2": "Dette vil slette din gamle API-nøkkel!",
|
||||
"d5d7c61349f3b0859336066e6d453fc35d334fe5": "Bruk YouTube-API",
|
||||
"ce10d31febb3d9d60c160750570310f303a22c22": "YouTube-API-nøkkel",
|
||||
"8602e313cdfa7c4cc475ccbe86459fce3c3fd986": "Å generere en nøkkel er lett!",
|
||||
"9b3cedfa83c6d7acb3210953289d1be4aab115c7": "Klikk her",
|
||||
"7f09776373995003161235c0c8d02b7f91dbc4df": "for å laste ned den offisielle Chrome-utvidelsen for YouTubeDL-Material selv.",
|
||||
"5b5296423906ab3371fdb2b5a5aaa83acaa2ee52": "Du må manuelt laste ned utvidelsen og endre dens innstillinger for å sette skjermflate-nettadresse.",
|
||||
"9a2ec6da48771128384887525bdcac992632c863": "for å installere den offisielle Firefox-utvidelsen for YouTubeDL-Material rett fra Firefox sin utvidelsesside.",
|
||||
"eb81be6b49e195e5307811d1d08a19259d411f37": "Detaljert oppsettsinstruks",
|
||||
"cb17ff8fe3961cf90f44bee97c88a3f3347a7e55": "Ikke mye kreves annet enn å endre utvidelses innstillinger for å sette skjermflate-nettadresse.",
|
||||
"61b81b11aad0b9d970ece2fce18405f07eac69c2": "Dra lenken nedenfor til bokmerker. Naviger til YouTube-videoen du ønsker å laste ned og klikk på bokmerket.",
|
||||
"c505d6c5de63cc700f0aaf8a4b31fae9e18024e5": "Genrer \"kun lyd\"-bookmerke",
|
||||
"d5f69691f9f05711633128b5a3db696783266b58": "Ekstra",
|
||||
"5fab47f146b0a4b809dcebf3db9da94df6299ea1": "Bruk forvalgt nedlastingsagent",
|
||||
"ec71e08aee647ea4a71fd6b7510c54d84a797ca6": "Velg en nedlaster",
|
||||
"0c43af932e6a4ee85500e28f01b3538b4eb27bc4": "Loggingsnivå",
|
||||
"db6c192032f4cab809aad35215f0aa4765761897": "Innloggingsutløp",
|
||||
"dc3d990391c944d1fbfc7cfb402f7b5e112fb3a8": "Tillat avansert nedlasting",
|
||||
"431e5f3a0dde88768d1074baedd65266412b3f02": "Bruk kaker",
|
||||
"80651a7ad1229ea6613557d3559f702cfa5aecf5": "Sett kaker",
|
||||
"bc2e854e111ecf2bd7db170da5e3c2ed08181d88": "Avansert",
|
||||
"37224420db54d4bc7696f157b779a7225f03ca9d": "Tillat brukerregistrering",
|
||||
"4f56ced9d6b85aeb1d4346433361d47ea72dac1a": "Intern",
|
||||
"e3d7c5f019e79a3235a28ba24df24f11712c7627": "LDAP",
|
||||
"fa548cee6ea11c160a416cac3e6bdec0363883dc": "Autentiseringsmetode",
|
||||
"1db9789b93069861019bd0ccaa5d4706b00afc61": "LDAP-nettadresse",
|
||||
"f50fa6c09c8944aed504f6325f2913ee6c7a296a": "BIND-DN",
|
||||
"080cc6abcba236390fc22e79792d0d3443a3bd2a": "BIND-identitetsdetaljer",
|
||||
"cfa67d14d84fe0e9fadf251dc51ffc181173b662": "Søkebase",
|
||||
"e01d54ecc1a0fcf9525a3c100ed8b83d94e61c23": "Søkefilter",
|
||||
"4d13a9cd5ed3dcee0eab22cb25198d43886942be": "Brukere",
|
||||
"eb3d5aefff38a814b76da74371cbf02c0789a1ef": "Logger",
|
||||
"fe8fd36dbf5deee1d56564965787a782a66eba44": "{VAR_SELECT, select, true {Close} false {Cancel} other {otha} }",
|
||||
"cec82c0a545f37420d55a9b6c45c20546e82f94e": "Om YouTubeDL-Material",
|
||||
"199c17e5d6a419313af3c325f06dcbb9645ca618": "er en fri YouTube-nedlaster bygd i henhold til Google sine Materielle spesifikasjoner. Du kan sømløst laste ned dine favorittvideoer som video- eller lydfiler, og tilogmed abonnere på dine favorittkanaler og spillelister for å holde deg oppdatert med nye videoer.",
|
||||
"bc0ad0ee6630acb7fcb7802ec79f5a0ee943c1a7": "har noen flotte funksjoner inkludert. Et vidtfavnende API, Docker-støtte, og lokalisering (oversettelser)-støtte. Les om alle støttede funksjoner ved å klikke på GitHub-ikonet ovenfor.",
|
||||
"a45e3b05f0529dc5246d70ef62304c94426d4c81": "Installert versjon:",
|
||||
"e22f3a5351944f3a1a10cfc7da6f65dfbe0037fe": "Ser etter oppdateringer …",
|
||||
"a16e92385b4fd9677bb830a4b796b8b79c113290": "Oppdatering tilgjengelig",
|
||||
"189b28aaa19b3c51c6111ad039c4fd5e2a22e370": "Du kan oppdatere fra innstillingsmenyen.",
|
||||
"b33536f59b94ec935a16bd6869d836895dc5300c": "Funnet en feil eller har et forslag å komme med?",
|
||||
"e1f398f38ff1534303d4bb80bd6cece245f24016": "for å opprette en feilrapport.",
|
||||
"42ff677ec14f111e88bd6cdd30145378e994d1bf": "Din profil",
|
||||
"ac9d09de42edca1296371e4d801349c9096ac8de": "UID:",
|
||||
"a5ed099ffc9e96f6970df843289ade8a7d20ab9f": "Opprettet:",
|
||||
"fa96f2137af0a24e6d6d54c598c0af7d5d5ad344": "Du er ikke innlogget.",
|
||||
"6765b4c916060f6bc42d9bb69e80377dbcb5e4e9": "Logg inn",
|
||||
"bb694b49d408265c91c62799c2b3a7e3151c824d": "Logg ut",
|
||||
"a1dbca87b9f36d2b06a5cbcffb5814c4ae9b798a": "Opprett administratorkonto",
|
||||
"2d2adf3ca26a676bca2269295b7455a26fd26980": "Fant ingen administratorkonto. Dette vil opprette og sette passord for en slik konto med brukernavn som «admin».",
|
||||
"70a67e04629f6d412db0a12d51820b480788d795": "Opprett",
|
||||
"994363f08f9fbfa3b3994ff7b35c6904fdff18d8": "Profil",
|
||||
"004b222ff9ef9dd4771b777950ca1d0e4cd4348a": "Om",
|
||||
"92eee6be6de0b11c924e3ab27db30257159c0a7c": "Hjem",
|
||||
"357064ca9d9ac859eb618e28e8126fa32be049e2": "Abonnementer",
|
||||
"822fab38216f64e8166d368b59fe756ca39d301b": "Nedlastinger",
|
||||
"a249a5ae13e0835383885aaf697d2890cc3e53e9": "Del spilleliste",
|
||||
"15da89490e04496ca9ea1e1b3d44fb5efd4a75d9": "Del video",
|
||||
"1d540dcd271b316545d070f9d182c372d923aadd": "Del lyd",
|
||||
"1f6d14a780a37a97899dc611881e6bc971268285": "Skru på deling",
|
||||
"6580b6a950d952df847cb3d8e7176720a740adc8": "Bruk tidsstempel",
|
||||
"4f2ed9e71a7c981db3e50ae2fedb28aff2ec4e6c": "Sekunder",
|
||||
"3a6e5a6aa78ca864f6542410c5dafb6334538106": "Kopier til utklippstavle",
|
||||
"5b3075e8dc3f3921ec316b0bd83b6d14a06c1a4f": "Lagre endringer",
|
||||
"4d8a18b04a1f785ecd8021ac824e0dfd5881dbfc": "Nedlastet",
|
||||
"348cc5d553b18e862eb1c1770e5636f6b05ba130": "En feil inntraff",
|
||||
"4f8b2bb476981727ab34ed40fde1218361f92c45": "Detaljer",
|
||||
"e9aff8e6df2e2bf6299ea27bb2894c70bc48bd4d": "En feil har inntruffet:",
|
||||
"77b0c73840665945b25bd128709aa64c8f017e1c": "Nedlastingsstart:",
|
||||
"08ff9375ec078065bcdd7637b7ea65fce2979266": "Nedlastingsslutt:",
|
||||
"ad127117f9471612f47d01eae09709da444a36a4": "Filsti(er):",
|
||||
"a9806cf78ce00eb2613eeca11354a97e033377b8": "Abonner på en spilleliste eller kanal",
|
||||
"93efc99ae087fc116de708ecd3ace86ca237cf30": "Spilleliste- eller kanal-nettadressen",
|
||||
"08f5d0ef937ae17feb1b04aff15ad88911e87baf": "Egendefinert navn",
|
||||
"ea30873bd3f0d5e4fb2378eec3f0a1db77634a28": "Last ned alle opplastinger",
|
||||
"28a678e9cabf86e44c32594c43fa0e890135c20f": "Last ned videoer oppdatert siste",
|
||||
"c76a955642714b8949ff3e4b4990864a2e2cac95": "Kun lyd-modus",
|
||||
"408ca4911457e84a348cecf214f02c69289aa8f1": "Kun strømming-modus",
|
||||
"f432e1a8d6adb12e612127978ce2e0ced933959c": "Disse legges til etter standard-argumentene.",
|
||||
"98b6ec9ec138186d663e64770267b67334353d63": "Egendefinert filutdata",
|
||||
"d0336848b0c375a1c25ba369b3481ee383217a4f": "Abonner",
|
||||
"e78c0d60ac39787f62c9159646fe0b3c1ed55a1d": "Type:",
|
||||
"a44d86aa1e6c20ced07aca3a7c081d8db9ded1c6": "Arkiv:",
|
||||
"8efc77bf327659c0fec1f518cf48a98cdcd9dddf": "Eksporter arkiv",
|
||||
"3042bd3ad8dffcfeca5fd1ae6159fd1047434e95": "Opphev abonnement",
|
||||
"e2319dec5b4ccfb6ed9f55ccabd63650a8fdf547": "Dine abonnementer",
|
||||
"807cf11e6ac1cde912496f764c176bdfdd6b7e19": "Kanaler",
|
||||
"29b89f751593e1b347eef103891b7a1ff36ec03f": "Navn ikke tilgjengelig. Henter kanal …",
|
||||
"4636cd4a1379c50d471e98786098c4d39e1e82ad": "Du har ingen kanalabonnementer.",
|
||||
"47546e45bbb476baaaad38244db444c427ddc502": "Spillelister",
|
||||
"2e0a410652cb07d069f576b61eab32586a18320d": "Navn ikke tilgjengelig. Henter spilleliste …",
|
||||
"587b57ced54965d8874c3fd0e9dfedb987e5df04": "Du har ingen spillelisteabonnement.",
|
||||
"3697f8583ea42868aa269489ad366103d94aece7": "Redigering",
|
||||
"7e892ba15f2c6c17e83510e273b3e10fc32ea016": "Søk",
|
||||
"2054791b822475aeaea95c0119113de3200f5e1c": "Lengde:",
|
||||
"94e01842dcee90531caa52e4147f70679bac87fe": "Slett og last ned igjen",
|
||||
"2031adb51e07a41844e8ba7704b054e98345c9c1": "Slett for alltid",
|
||||
"91ecce65f1d23f9419d1c953cd6b7bc7f91c110e": "Oppdaterer",
|
||||
"1372e61c5bd06100844bd43b98b016aabc468f62": "Velg en versjon:",
|
||||
"cfc2f436ec2beffb042e7511a73c89c372e86a6c": "Regustrer",
|
||||
"a1ad8b1be9be43b5183bd2c3186d4e19496f2a0b": "Økt-ID:",
|
||||
"eb98135e35af26a9a326ee69bd8ff104d36dd8ec": "(nåværende)",
|
||||
"b6c453e0e61faea184bbaf5c5b0a1e164f4de2a2": "Tøm alle nedlastinger",
|
||||
"7117fc42f860e86d983bfccfcf2654e5750f3406": "Ingen nedlastninger tilgjengelige!",
|
||||
"b7ff2e2b909c53abe088fe60b9f4b6ac7757247f": "Registrer en bruker",
|
||||
"024886ca34a6f309e3e51c2ed849320592c3faaa": "Brukernavn",
|
||||
"2bd201aea09e43fbfd3cd15ec0499b6755302329": "Håndter bruker",
|
||||
"29c97c8e76763bb15b6d515648fa5bd1eb0f7510": "Bruker-UID:",
|
||||
"e70e209561583f360b1e9cefd2cbb1fe434b6229": "Nytt passord",
|
||||
"6498fa1b8f563988f769654a75411bb8060134b9": "Sett nytt passord",
|
||||
"544e09cdc99a8978f48521d45f62db0da6dcf742": "Bruk rolle-forvalg",
|
||||
"4f20f2d5a6882190892e58b85f6ccbedfa737952": "Ja",
|
||||
"3d3ae7deebc5949b0c1c78b9847886a94321d9fd": "Nei",
|
||||
"57c6c05d8ebf4ef1180c2705033c044f655bb2c4": "Håndter rolle",
|
||||
"746f64ddd9001ac456327cd9a3d5152203a4b93c": "Brukernavn",
|
||||
"52c1447c1ec9570a2a3025c7e566557b8d19ed92": "Rolle",
|
||||
"59a8c38db3091a63ac1cb9590188dc3a972acfb3": "Handlinger",
|
||||
"632e8b20c98e8eec4059a605a4b011bb476137af": "Rediger bruker",
|
||||
"95b95a9c79e4fd9ed41f6855e37b3b06af25bcab": "Slett bruker",
|
||||
"4d92a0395dd66778a931460118626c5794a3fc7a": "Legg til brukere",
|
||||
"b0d7dd8a1b0349622d6e0c6e643e24a9ea0efa1d": "Rediger rolle",
|
||||
"5009630cdf32ab4f1c78737b9617b8773512c05a": "Linjer:",
|
||||
"8a0bda4c47f10b2423ff183acefbf70d4ab52ea2": "Tøm logger",
|
||||
"ccf5ea825526ac490974336cb5c24352886abc07": "Åpne fil",
|
||||
"5656a06f17c24b2d7eae9c221567b209743829a9": "Åpne fil i ny fane",
|
||||
"a0720c36ee1057e5c54a86591b722485c62d7b1a": "Gå til abonnement",
|
||||
"d02888c485d3aeab6de628508f4a00312a722894": "Mine videoer"
|
||||
}
|
||||
@@ -1545,8 +1545,8 @@
|
||||
<note priority="1" from="description">Custom args input placeholder</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="6b995e7130b4d667eaab6c5f61b362ace486d26d" datatype="html">
|
||||
<source>Global custom args for downloads on the home page. (Set args for subscriptions for each subscriptions separately!) Args are delimited using two commas like so: ,,</source>
|
||||
<target>Algemene aanvullende opties voor downloads op de overzichtspagina. (Stel de opties per abonnement in!) Scheidt deze met komma's: ,,</target>
|
||||
<source>Global custom args for downloads on the home page. Args are delimited using two commas like so: ,,</source>
|
||||
<target>Algemene aanvullende opties voor downloads op de overzichtspagina. Scheidt deze met komma's: ,,</target>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">src/app/settings/settings.component.html</context>
|
||||
<context context-type="linenumber">134</context>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en-US" datatype="plaintext" original="ng2.template" target-language="zh-Hans">
|
||||
<body>
|
||||
@@ -902,8 +902,8 @@
|
||||
<note priority="1" from="description">Video path setting input hint</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="6b995e7130b4d667eaab6c5f61b362ace486d26d" datatype="html">
|
||||
<source>Global custom args for downloads on the home page. (Set args for subscriptions for each subscriptions separately!) Args are delimited using two commas like so: ,,</source>
|
||||
<target>开始页面上用于下载的全局自定义参数。(单独为每个订阅设置订阅参数!) 参数由两个逗号分隔:,,</target>
|
||||
<source>Global custom args for downloads on the home page. Args are delimited using two commas like so: ,,</source>
|
||||
<target>开始页面上用于下载的全局自定义参数。参数由两个逗号分隔:,,</target>
|
||||
<context-group purpose="location">
|
||||
<context context-type="sourcefile">app/settings/settings.component.html</context>
|
||||
<context context-type="linenumber">146</context>
|
||||
|
||||
@@ -33,18 +33,7 @@ async function createLocalizationJSON() {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = path.basename(files[i]);
|
||||
const file_parts = file.split('.');
|
||||
if (file_parts.length !== 3 || file_parts[1] === 'en') continue;
|
||||
try {
|
||||
const locale_json = fs.readJSONSync(files[i]);
|
||||
const locale_json_keys = Object.keys(locale_json);
|
||||
let has_defined_keys = false;
|
||||
for (let i = 0; i < locale_json_keys.length; i++) {
|
||||
if (locale_json[locale_json_keys[i]] !== '') has_defined_keys = true;
|
||||
}
|
||||
if (has_defined_keys) locales.push(file_parts[1]);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
locales.push(file_parts[1]);
|
||||
}
|
||||
|
||||
fs.unlinkSync('src/assets/i18n/messages.en.json');
|
||||
|
||||
Reference in New Issue
Block a user