Compare commits

..

2 Commits

Author SHA1 Message Date
Gauvino
06510d2bd6 chore(security): harden helpers + document conflict-labeler safety
From the workflow security audit:
- symlink-native-dirs.js: drop the execSync shell strings for fs.symlink/mkdir
  (removes a latent shell-injection surface; also clears dead commented code).
- automerge.sh: add 'set -euo pipefail' and restore the starting branch on exit
  so a mid-merge failure can't leave the repo on the wrong branch.
- conflict.yml: document that this pull_request_target workflow must never check
  out or run PR-head code (it only labels via the API today).
2026-06-01 20:35:05 +02:00
lance chant
54ee507209 fix: fixing the time variable (#1638)
Signed-off-by: Lance Chant <13349722+lancechant@users.noreply.github.com>
2026-06-01 15:22:39 +02:00
7 changed files with 133 additions and 172 deletions

29
.gitattributes vendored
View File

@@ -1,28 +1 @@
# Normalise line endings to LF for everyone. Files are stored as LF in git and .modules/vlc-player/Frameworks/*.xcframework filter=lfs diff=lfs merge=lfs -text
# checked out as LF on every OS, so Windows clones stop producing CRLF churn
# (no more "LF will be replaced by CRLF" warnings) regardless of core.autocrlf.
* text=auto eol=lf
# Windows-only scripts must stay CRLF
*.bat text eol=crlf
*.cmd text eol=crlf
# Binary assets — never touched / never normalised
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.webp binary
*.ico binary
*.icns binary
*.ttf binary
*.otf binary
*.woff binary
*.woff2 binary
*.mp3 binary
*.mp4 binary
*.mov binary
*.pdf binary
*.keystore binary
*.jks binary
*.p12 binary

View File

@@ -3,6 +3,11 @@ name: 🏷🔀Merge Conflict Labeler
on: on:
push: push:
branches: [develop] branches: [develop]
# SECURITY: pull_request_target runs with the base repo's write token and secrets.
# This job only labels via the API and is safe ONLY because it never checks out or
# runs the PR head's code. NEVER add `actions/checkout` of the PR head (or any `run:`
# that interpolates PR-controlled data) to this workflow — that would turn it into a
# full repo-compromise vector.
pull_request_target: pull_request_target:
branches: [develop] branches: [develop]
types: [synchronize] types: [synchronize]

11
.gitignore vendored
View File

@@ -1,5 +1,6 @@
# Dependencies and Package Managers # Dependencies and Package Managers
node_modules/ node_modules/
bun.lock
bun.lockb bun.lockb
package-lock.json package-lock.json
@@ -20,8 +21,10 @@ web-build/
# Gradle caches (top-level + per-module native projects) # Gradle caches (top-level + per-module native projects)
**/.gradle/ **/.gradle/
# Native module build outputs (any module) # Module-specific Builds
modules/*/android/build/ modules/mpv-player/android/build
modules/player/android
modules/hls-downloader/android/build
# Generated Applications # Generated Applications
Streamyfin.app Streamyfin.app
@@ -66,6 +69,10 @@ certs/
# Version and Backup Files # Version and Backup Files
/version-backup-* /version-backup-*
/modules/sf-player/android/build
/modules/music-controls/android/build
modules/background-downloader/android/build/*
/modules/mpv-player/android/build
# ios:unsigned-build Artifacts # ios:unsigned-build Artifacts
build/ build/

View File

@@ -1254,7 +1254,7 @@ export const Controls: FC<Props> = ({
<Text <Text
style={[styles.endsAtText, { fontSize: typography.callout }]} style={[styles.endsAtText, { fontSize: typography.callout }]}
> >
{t("player.ends_at")} {getFinishTime()} {t("player.ends_at", { time: getFinishTime() })}
</Text> </Text>
</View> </View>
)} )}
@@ -1448,7 +1448,7 @@ export const Controls: FC<Props> = ({
<Text <Text
style={[styles.endsAtText, { fontSize: typography.callout }]} style={[styles.endsAtText, { fontSize: typography.callout }]}
> >
{t("player.ends_at")} {getFinishTime()} {t("player.ends_at", { time: getFinishTime() })}
</Text> </Text>
</View> </View>
)} )}

View File

@@ -1,12 +1,22 @@
#!/bin/bash #!/bin/bash
[[ -z $(git status --porcelain) ]] && # Local helper: fast-forward master into develop and back. Aborts on any failure and
git checkout master && # restores the branch you started on. Not used in CI.
git pull --ff-only && set -euo pipefail
git checkout develop &&
git merge master && if [[ -n $(git status --porcelain) ]]; then
git push --follow-tags && echo "Error: working tree is not clean — commit or stash first." >&2
git checkout master && exit 1
git merge develop --ff-only && fi
git push &&
git checkout develop || start_branch=$(git rev-parse --abbrev-ref HEAD)
(echo "Error: Failed to merge" && exit 1) trap 'git checkout "$start_branch" >/dev/null 2>&1 || true' EXIT
git checkout master
git pull --ff-only
git checkout develop
git merge master
git push --follow-tags
git checkout master
git merge develop --ff-only
git push
git checkout develop

View File

@@ -1,62 +1,28 @@
#!/usr/bin/env node #!/usr/bin/env node
const _fs = require("node:fs"); // Symlinks the platform-specific native dirs to `ios` / `android` depending on EXPO_TV.
// Uses fs APIs (no shell) so there is no command-injection surface.
const fs = require("node:fs");
const path = require("node:path"); const path = require("node:path");
const process = require("node:process");
const { execSync } = require("node:child_process");
const root = process.cwd(); const root = process.cwd();
// const tvosPath = path.join(root, 'iostv'); const isTV = process.env.EXPO_TV && process.env.EXPO_TV !== "0";
// const iosPath = path.join(root, 'iosmobile');
// const androidPath = path.join(root, 'androidmobile');
// const androidTVPath = path.join(root, 'androidtv');
// const device = process.argv[2];
// const platform = process.argv[2];
const isTV = process.env.EXPO_TV || false;
const paths = new Map([ const links = isTV
["tvos", path.join(root, "iostv")], ? { ios: path.join(root, "iostv"), android: path.join(root, "androidtv") }
["ios", path.join(root, "iosmobile")], : {
["android", path.join(root, "androidmobile")], ios: path.join(root, "iosmobile"),
["androidtv", path.join(root, "androidtv")], android: path.join(root, "androidmobile"),
]); };
// const platformPath = paths.get(platform); for (const [link, target] of Object.entries(links)) {
fs.mkdirSync(target, { recursive: true });
if (isTV) { try {
stdout = execSync( fs.unlinkSync(link); // replace an existing symlink/file (ln -nsf)
`mkdir -p ${paths.get("tvos")}; ln -nsf ${paths.get("tvos")} ios`, } catch {
); // nothing to remove
console.log(stdout.toString()); }
stdout = execSync( fs.symlinkSync(target, link);
`mkdir -p ${paths.get("androidtv")}; ln -nsf ${paths.get( console.log(`${link} -> ${target}`);
"androidtv",
)} android`,
);
console.log(stdout.toString());
} else {
stdout = execSync(
`mkdir -p ${paths.get("ios")}; ln -nsf ${paths.get("ios")} ios`,
);
console.log(stdout.toString());
stdout = execSync(
`mkdir -p ${paths.get("android")}; ln -nsf ${paths.get("android")} android`,
);
console.log(stdout.toString());
} }
// target = "";
// switch (platform) {
// case "tvos":
// target = "ios";
// break;
// case "ios":
// target = "ios";
// break;
// case "android":
// target = "android";
// break;
// case "androidtv":
// target = "android";
// break;
// }