Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c54ee7876c | ||
|
|
9ba2c68ff9 | ||
|
|
db460fb9b3 | ||
|
|
b3ce276d1b |
Binary file not shown.
+16
-4
@@ -9,11 +9,13 @@ cd "$(dirname "$0")"
|
|||||||
APP_NAME="HSRename"
|
APP_NAME="HSRename"
|
||||||
APPDIR="${APP_NAME}.AppDir"
|
APPDIR="${APP_NAME}.AppDir"
|
||||||
EXE_NAME="$APP_NAME"
|
EXE_NAME="$APP_NAME"
|
||||||
|
VERSION="$(tr -d '[:space:]' < VERSION 2>/dev/null || echo "")"
|
||||||
|
|
||||||
echo "=== Installing build deps ==="
|
echo "=== Installing build deps ==="
|
||||||
pip install -q -r requirements.txt -r requirements-build.txt
|
pip install -q -r requirements.txt -r requirements-build.txt
|
||||||
|
|
||||||
echo "=== Running PyInstaller ==="
|
echo "=== Running PyInstaller (clean) ==="
|
||||||
|
rm -rf build dist HSRename.spec
|
||||||
pyinstaller --noconfirm --onedir --windowed \
|
pyinstaller --noconfirm --onedir --windowed \
|
||||||
-n "$EXE_NAME" \
|
-n "$EXE_NAME" \
|
||||||
--hidden-import=engine \
|
--hidden-import=engine \
|
||||||
@@ -30,6 +32,11 @@ echo "=== Creating AppDir ==="
|
|||||||
rm -rf "$APPDIR"
|
rm -rf "$APPDIR"
|
||||||
mkdir -p "$APPDIR/usr/bin"
|
mkdir -p "$APPDIR/usr/bin"
|
||||||
cp -a "dist/$EXE_NAME" "$APPDIR/usr/bin/"
|
cp -a "dist/$EXE_NAME" "$APPDIR/usr/bin/"
|
||||||
|
mkdir -p "$APPDIR/usr/share/hsrename"
|
||||||
|
echo "$VERSION" > "$APPDIR/usr/share/hsrename/VERSION"
|
||||||
|
if [[ -f "packaging/release-stamp-${VERSION}.txt" ]]; then
|
||||||
|
cp "packaging/release-stamp-${VERSION}.txt" "$APPDIR/usr/share/hsrename/release-stamp.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
cat > "$APPDIR/AppRun" << EOF
|
cat > "$APPDIR/AppRun" << EOF
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
@@ -39,7 +46,7 @@ exec "\$HERE/usr/bin/$EXE_NAME/$EXE_NAME" "\$@"
|
|||||||
EOF
|
EOF
|
||||||
chmod +x "$APPDIR/AppRun"
|
chmod +x "$APPDIR/AppRun"
|
||||||
|
|
||||||
cat > "$APPDIR/hsrename.desktop" << 'EOF'
|
cat > "$APPDIR/hsrename.desktop" << EOF
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Name=HSRename
|
Name=HSRename
|
||||||
Comment=Mass rename files with preview and flexible rules
|
Comment=Mass rename files with preview and flexible rules
|
||||||
@@ -47,6 +54,7 @@ Exec=HSRename
|
|||||||
Icon=HSRename
|
Icon=HSRename
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Utility;FileTools;
|
Categories=Utility;FileTools;
|
||||||
|
X-AppImage-Version=${VERSION}
|
||||||
EOF
|
EOF
|
||||||
# Use project icon as app icon and logo
|
# Use project icon as app icon and logo
|
||||||
if [[ -f HSRename.png ]]; then
|
if [[ -f HSRename.png ]]; then
|
||||||
@@ -56,7 +64,6 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "=== Building AppImage (requires appimagetool) ==="
|
echo "=== Building AppImage (requires appimagetool) ==="
|
||||||
# Note: appimagetool does not accept plain https URLs for -u; use zsync/gh-releases-zsync per AppImage docs.
|
|
||||||
if command -v appimagetool &>/dev/null; then
|
if command -v appimagetool &>/dev/null; then
|
||||||
OUT="${APP_NAME}.AppImage"
|
OUT="${APP_NAME}.AppImage"
|
||||||
appimagetool "$APPDIR" "$OUT"
|
appimagetool "$APPDIR" "$OUT"
|
||||||
@@ -65,5 +72,10 @@ else
|
|||||||
echo "AppDir is ready at $APPDIR/"
|
echo "AppDir is ready at $APPDIR/"
|
||||||
echo "To create the .AppImage, install appimagetool and run:"
|
echo "To create the .AppImage, install appimagetool and run:"
|
||||||
echo " appimagetool $APPDIR ${APP_NAME}.AppImage"
|
echo " appimagetool $APPDIR ${APP_NAME}.AppImage"
|
||||||
echo " # Get it from: https://github.com/AppImage/appimagetool/releases"
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! strings "dist/$EXE_NAME/$EXE_NAME" | grep -q "engine.tvdb_client"; then
|
||||||
|
echo "ERROR: Built executable is missing TheTVDB modules." >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
+48
-39
@@ -1,58 +1,67 @@
|
|||||||
# Using HSRename with Gear Lever
|
# Using HSRename with Gear Lever
|
||||||
|
|
||||||
[Gear Lever](https://github.com/mijorus/gearlever) can manage and update the HSRename AppImage. Because releases are hosted on **Gitea** (not GitHub), use one of the options below.
|
[Gear Lever](https://github.com/mijorus/gearlever) 4.x can update HSRename from Gitea releases. Gitea uses the same API as **Forgejo**, which Gear Lever supports directly.
|
||||||
|
|
||||||
## Option 1: Custom update URL (recommended to try first)
|
## Important: use Forgejo, not Default
|
||||||
|
|
||||||
Gitea uses the same release path style as GitHub:
|
In the HSRename details screen:
|
||||||
`/owner/repo/releases/download/{tag}/{filename}`
|
|
||||||
|
|
||||||
1. Open **Gear Lever** and add the HSRename AppImage (drag & drop or **Add**).
|
- **Source** must be **Forgejo** (not `Default`).
|
||||||
2. Select the HSRename entry and open **Update** / **Custom update URL** (or the equivalent in your Gear Lever version).
|
- The **Website** field is only metadata. It does **not** check for updates.
|
||||||
3. Try this URL pattern (with a wildcard for the tag):
|
- Do **not** paste the release download URL into Website.
|
||||||
```
|
|
||||||
https://git.hisora.dev/Dawnsorrow/HS-Rename/releases/download/*/HSRename.AppImage
|
|
||||||
```
|
|
||||||
4. If Gear Lever accepts it (e.g. field turns green or validates), it may use the Gitea releases page to resolve the latest tag and offer updates when you push new releases.
|
|
||||||
5. Use **Check for updates** / **List updates** to see if it detects new versions.
|
|
||||||
|
|
||||||
If your Gear Lever only supports GitHub-style URLs and rejects this, use Option 2.
|
## Configure updates (Gear Lever 4+)
|
||||||
|
|
||||||
## Option 2: Static URL (manual update link)
|
1. Open **Gear Lever** → select **HSRename**.
|
||||||
|
2. Set **Source** to **Forgejo**.
|
||||||
|
3. Fill in:
|
||||||
|
|
||||||
If the wildcard URL does not work:
|
| Field | Value |
|
||||||
|
|-------|--------|
|
||||||
|
| **Repo URL** | `https://git.hisora.dev/Dawnsorrow/HS-Rename` |
|
||||||
|
| **Release file name** | `HSRename.AppImage` |
|
||||||
|
| **Allow pre-releases** | Off (unless you want draft releases) |
|
||||||
|
|
||||||
1. In Gear Lever, add HSRename and set **Update** to **Static URL**.
|
4. Save, then use **Check for updates** / **List updates**.
|
||||||
2. Paste the **direct download URL** of the current release, for example:
|
|
||||||
- **v1.0.3:**
|
|
||||||
`https://git.hisora.dev/Dawnsorrow/HS-Rename/releases/download/v1.0.3/HSRename.AppImage`
|
|
||||||
3. When a new version is released (e.g. v1.0.4), open the [releases page](https://git.hisora.dev/Dawnsorrow/HS-Rename/releases), open the new release, right‑click **HSRename.AppImage** → **Copy link address**, then in Gear Lever set the Static URL to that new link and run **Update**.
|
|
||||||
|
|
||||||
So: Gear Lever will only “see” updates if you change the Static URL to the new release’s download link when you want to update.
|
If the fields validate (no error), Gear Lever queries:
|
||||||
|
|
||||||
## Option 3: CLI (if you use Gear Lever from the terminal)
|
`https://git.hisora.dev/api/v1/repos/Dawnsorrow/HS-Rename/releases/latest`
|
||||||
|
|
||||||
After adding the AppImage in Gear Lever, you can set the update URL from the command line:
|
and compares the release asset size with your local AppImage.
|
||||||
|
|
||||||
```bash
|
## Direct download URL pattern
|
||||||
# Set custom update URL (try the wildcard pattern)
|
|
||||||
gearlever --set-update-url /path/to/HSRename.AppImage "https://git.hisora.dev/Dawnsorrow/HS-Rename/releases/download/*/HSRename.AppImage"
|
|
||||||
|
|
||||||
# Check for updates
|
For release tag `vX.Y.Z`:
|
||||||
gearlever --list-updates
|
|
||||||
|
|
||||||
# Apply update
|
|
||||||
gearlever --update /path/to/HSRename.AppImage
|
|
||||||
```
|
|
||||||
|
|
||||||
Replace `/path/to/HSRename.AppImage` with the actual path where Gear Lever stores the AppImage.
|
|
||||||
|
|
||||||
## Release download URL pattern
|
|
||||||
|
|
||||||
For any release tag `vX.Y.Z`, the direct download URL is:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
https://git.hisora.dev/Dawnsorrow/HS-Rename/releases/download/vX.Y.Z/HSRename.AppImage
|
https://git.hisora.dev/Dawnsorrow/HS-Rename/releases/download/vX.Y.Z/HSRename.AppImage
|
||||||
```
|
```
|
||||||
|
|
||||||
So when we push a new release (e.g. v1.0.4), that new tag’s URL is what Gear Lever needs (either via the wildcard in Option 1 or by pasting the new URL in Option 2).
|
Latest release today:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://git.hisora.dev/Dawnsorrow/HS-Rename/releases/download/v1.0.3/HSRename.AppImage
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fallback: Static URL
|
||||||
|
|
||||||
|
If Forgejo does not work in your Gear Lever build, set **Source** to **Static URL** and paste the **exact** URL of the newest release (update this manually each release):
|
||||||
|
|
||||||
|
```
|
||||||
|
https://git.hisora.dev/Dawnsorrow/HS-Rename/releases/download/v1.0.3/HSRename.AppImage
|
||||||
|
```
|
||||||
|
|
||||||
|
## CLI (if `gearlever` is installed)
|
||||||
|
|
||||||
|
Gear Lever 4 may use different CLI options than older docs. Prefer the GUI Forgejo fields above. If your install still supports `--set-update-url`, the old wildcard pattern is **not** reliable for self-hosted Gitea; use Forgejo instead.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
| Symptom | Likely cause |
|
||||||
|
|---------|----------------|
|
||||||
|
| No update offered | Source is still **Default**, or local file is already the latest release (same size as `releases/latest`). |
|
||||||
|
| URL looks truncated in Website | Website is cosmetic only; configure **Forgejo** fields instead. |
|
||||||
|
| Update never finds newer builds | Wrong repo URL, wrong filename, or release has no `HSRename.AppImage` asset attached. |
|
||||||
|
|
||||||
|
Releases page: https://git.hisora.dev/Dawnsorrow/HS-Rename/releases
|
||||||
|
|||||||
+28
-4
@@ -4,6 +4,7 @@ TheTVDB API v4 client (read-only). Uses stdlib urllib — no extra dependencies.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import re
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import urllib.request
|
import urllib.request
|
||||||
@@ -42,6 +43,29 @@ class TvdbError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_series_id(item: dict[str, Any]) -> Optional[int]:
|
||||||
|
"""Extract numeric series id from a TheTVDB v4 search hit."""
|
||||||
|
tvdb_id = item.get("tvdb_id")
|
||||||
|
if tvdb_id is not None:
|
||||||
|
try:
|
||||||
|
return int(tvdb_id)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
raw_id = item.get("id")
|
||||||
|
if raw_id is None:
|
||||||
|
return None
|
||||||
|
if isinstance(raw_id, int):
|
||||||
|
return raw_id
|
||||||
|
if isinstance(raw_id, str):
|
||||||
|
if raw_id.isdigit():
|
||||||
|
return int(raw_id)
|
||||||
|
m = re.match(r"^series-(\d+)$", raw_id, re.IGNORECASE)
|
||||||
|
if m:
|
||||||
|
return int(m.group(1))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class TvdbClient:
|
class TvdbClient:
|
||||||
def __init__(self, api_key: str, pin: str = ""):
|
def __init__(self, api_key: str, pin: str = ""):
|
||||||
self.api_key = api_key.strip()
|
self.api_key = api_key.strip()
|
||||||
@@ -112,11 +136,11 @@ class TvdbClient:
|
|||||||
)
|
)
|
||||||
results: list[TvdbSeries] = []
|
results: list[TvdbSeries] = []
|
||||||
for item in payload.get("data") or []:
|
for item in payload.get("data") or []:
|
||||||
if item.get("type") != "series":
|
item_type = item.get("type") or item.get("primary_type")
|
||||||
|
if item_type and item_type != "series":
|
||||||
continue
|
continue
|
||||||
try:
|
series_id = _parse_series_id(item)
|
||||||
series_id = int(item["id"])
|
if series_id is None:
|
||||||
except (KeyError, TypeError, ValueError):
|
|
||||||
continue
|
continue
|
||||||
year = item.get("year")
|
year = item.get("year")
|
||||||
if year is not None:
|
if year is not None:
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
HSRename release stamp 1.0.4
|
||||||
|
TheTVDB search hotfix: accept TheTVDB v4 search ids like series-76320.
|
||||||
|
Built for Gear Lever update testing.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
HSRename 1.0.5
|
||||||
|
- Restore TheTVDB episode match feature in published AppImage (v1.0.4 asset was an outdated binary)
|
||||||
|
- TheTVDB search fix for series-76320 style IDs
|
||||||
+49
-19
@@ -2,33 +2,59 @@
|
|||||||
# Push tag to Gitea and publish HSRename.AppImage as a release asset.
|
# Push tag to Gitea and publish HSRename.AppImage as a release asset.
|
||||||
# Usage:
|
# Usage:
|
||||||
# GITEA_TOKEN=your_token ./release_gitea.sh
|
# GITEA_TOKEN=your_token ./release_gitea.sh
|
||||||
# Optional: ./release_gitea.sh --build (rebuild AppImage first)
|
|
||||||
#
|
#
|
||||||
# Requires: curl, git, and network access to your Gitea instance.
|
# Always rebuilds the AppImage before upload so releases never ship a stale binary.
|
||||||
|
#
|
||||||
|
# Requires: curl, git, appimagetool, and network access to your Gitea instance.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
GITEA_HOST="${GITEA_HOST:-https://git.hisora.dev}"
|
GITEA_HOST="${GITEA_HOST:-https://git.hisora.dev}"
|
||||||
GITEA_OWNER="${GITEA_OWNER:-Dawnsorrow}"
|
GITEA_OWNER="${GITEA_OWNER:-Dawnsorrow}"
|
||||||
|
if remote_url="$(git remote get-url origin 2>/dev/null)"; then
|
||||||
|
GITEA_REPO="$(basename "${remote_url%.git}")"
|
||||||
|
elif [[ -z "${GITEA_REPO:-}" ]]; then
|
||||||
|
GITEA_REPO="HS-Rename"
|
||||||
|
fi
|
||||||
GITEA_REPO="${GITEA_REPO:-HS-Rename}"
|
GITEA_REPO="${GITEA_REPO:-HS-Rename}"
|
||||||
APP_IMAGE="HSRename.AppImage"
|
APP_IMAGE="HSRename.AppImage"
|
||||||
|
|
||||||
VERSION="$(tr -d '[:space:]' < VERSION)"
|
VERSION="$(tr -d '[:space:]' < VERSION)"
|
||||||
TAG="v${VERSION}"
|
TAG="v${VERSION}"
|
||||||
|
|
||||||
if [[ "${1:-}" == "--build" ]]; then
|
verify_appimage() {
|
||||||
|
if [[ ! -f "$APP_IMAGE" ]]; then
|
||||||
|
echo "Missing $APP_IMAGE after build." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "dist/HSRename/HSRename" ]]; then
|
||||||
|
echo "Missing dist/HSRename/HSRename after build." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! strings "dist/HSRename/HSRename" | grep -q "engine.tvdb_client"; then
|
||||||
|
echo "ERROR: Built executable is missing TheTVDB modules; refusing to publish." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! strings "dist/HSRename/HSRename" | grep -q "engine.episode_match"; then
|
||||||
|
echo "ERROR: Built executable is missing episode matching; refusing to publish." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
export PATH="/tmp:${PATH}"
|
export PATH="/tmp:${PATH}"
|
||||||
if ! command -v appimagetool &>/dev/null && [[ -x /tmp/appimagetool ]]; then
|
if ! command -v appimagetool &>/dev/null && [[ -x /tmp/appimagetool ]]; then
|
||||||
export PATH="/tmp:${PATH}"
|
export PATH="/tmp:${PATH}"
|
||||||
fi
|
fi
|
||||||
./build_appimage.sh
|
if ! command -v appimagetool &>/dev/null; then
|
||||||
|
curl -fsSL -o /tmp/appimagetool "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
|
||||||
|
chmod +x /tmp/appimagetool
|
||||||
|
export PATH="/tmp:${PATH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -f "$APP_IMAGE" ]]; then
|
echo "=== Building fresh AppImage for ${TAG} ==="
|
||||||
echo "Missing $APP_IMAGE. Run ./build_appimage.sh or ./release_gitea.sh --build"
|
./build_appimage.sh
|
||||||
exit 1
|
verify_appimage
|
||||||
fi
|
|
||||||
|
|
||||||
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
|
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||||
echo "Tag $TAG not found. Create it with: git tag $TAG"
|
echo "Tag $TAG not found. Create it with: git tag $TAG"
|
||||||
@@ -41,10 +67,8 @@ git push origin "$TAG"
|
|||||||
|
|
||||||
if [[ -z "${GITEA_TOKEN:-}" ]]; then
|
if [[ -z "${GITEA_TOKEN:-}" ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "Code and tag pushed. To upload the AppImage, set GITEA_TOKEN and re-run:"
|
echo "Built and verified $APP_IMAGE. Set GITEA_TOKEN and re-run to upload:"
|
||||||
echo " GITEA_TOKEN=... ./release_gitea.sh"
|
echo " GITEA_TOKEN=... ./release_gitea.sh"
|
||||||
echo ""
|
|
||||||
echo "Or create the release manually on Gitea and attach $APP_IMAGE."
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -52,21 +76,27 @@ API="${GITEA_HOST}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/releases"
|
|||||||
NOTES="$(cat <<EOF
|
NOTES="$(cat <<EOF
|
||||||
## HSRename ${TAG}
|
## HSRename ${TAG}
|
||||||
|
|
||||||
- TheTVDB episode title matching: fix SxxExx numbering against TheTVDB order (default, aired, DVD, etc.)
|
- Fix botched v1.0.4 AppImage (restores TheTVDB episode match + search fix)
|
||||||
- Episode renumbering and multi-episode ranges unchanged
|
- Always verify/update via Gear Lever Forgejo: \`https://git.hisora.dev/Dawnsorrow/HS-Rename\`
|
||||||
|
|
||||||
Gear Lever update URL:
|
Download:
|
||||||
\`${GITEA_HOST}/${GITEA_OWNER}/${GITEA_REPO}/releases/download/${TAG}/${APP_IMAGE}\`
|
\`${GITEA_HOST}/${GITEA_OWNER}/${GITEA_REPO}/releases/download/${TAG}/${APP_IMAGE}\`
|
||||||
EOF
|
EOF
|
||||||
)"
|
)"
|
||||||
|
|
||||||
echo "=== Creating Gitea release $TAG ==="
|
echo "=== Creating Gitea release $TAG on ${GITEA_OWNER}/${GITEA_REPO} ==="
|
||||||
curl -fsS -X POST "$API" \
|
RELEASE_JSON="$(curl -fsS -X POST "$API" \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
-F "tag_name=${TAG}" \
|
-F "tag_name=${TAG}" \
|
||||||
-F "title=${TAG}" \
|
-F "name=${TAG}" \
|
||||||
-F "body=${NOTES}" \
|
-F "body=${NOTES}")"
|
||||||
-F "attachment=@${APP_IMAGE};filename=${APP_IMAGE}"
|
RELEASE_ID="$(python3 -c "import json,sys; print(json.loads(sys.argv[1])['id'])" "$RELEASE_JSON")"
|
||||||
|
|
||||||
|
echo "=== Uploading ${APP_IMAGE} (${RELEASE_ID}) ==="
|
||||||
|
curl -fsS --max-time 300 -X POST \
|
||||||
|
"${API}/${RELEASE_ID}/assets?name=${APP_IMAGE}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-F "attachment=@${APP_IMAGE}" >/dev/null
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Release published:"
|
echo "Release published:"
|
||||||
|
|||||||
Reference in New Issue
Block a user