From 7b03c2fbce4d3d2cd5c00f67319cf146506fadaa Mon Sep 17 00:00:00 2001 From: BlueSkyXN <63384277+BlueSkyXN@users.noreply.github.com> Date: Sat, 17 Jan 2026 16:31:18 +0800 Subject: [PATCH 1/5] Add GitHub Actions for PyInstaller and Nuitka builds Introduces CI workflows for building and releasing executables using PyInstaller and Nuitka across multiple platforms. Updates .gitignore to exclude .DS_Store, corrects the release date in README, and enhances build.py to include pystray and pillow in hidden imports and data packaging. Documentation is updated and reorganized, including moving build guides to the docs directory and adding instructions for the new workflows. --- .github/workflows/build-nuitka.yml | 170 ++++++++++++++++++ .github/workflows/build-pyinstaller.yml | 157 ++++++++++++++++ .gitignore | 1 + README.md | 2 +- build.py | 110 +++++++----- BUILD_GUIDE.md => docs/BUILD_GUIDE.md | 41 +++-- ...11\350\243\205\346\214\207\345\215\227.md" | 0 7 files changed, 423 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/build-nuitka.yml create mode 100644 .github/workflows/build-pyinstaller.yml rename BUILD_GUIDE.md => docs/BUILD_GUIDE.md (79%) rename "Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" => "docs/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" (100%) diff --git a/.github/workflows/build-nuitka.yml b/.github/workflows/build-nuitka.yml new file mode 100644 index 0000000..0630bb2 --- /dev/null +++ b/.github/workflows/build-nuitka.yml @@ -0,0 +1,170 @@ +name: Build with Nuitka + +on: + push: + tags: + - 'v*' + branches: + - main + - master + - dev + pull_request: + workflow_dispatch: + +env: + APP_NAME: LinuxDoHelper + PYTHON_VERSION: '3.11' + +jobs: + build: + name: Build on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + platform: linux-amd64 + ext: '' + - os: ubuntu-24.04-arm + platform: linux-arm64 + ext: '' + - os: macos-15 + platform: macos-arm64 + ext: '' + - os: windows-2025 + platform: windows-amd64 + ext: '.exe' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: 'pip' + + - name: Resolve version + id: version + shell: bash + run: | + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + VERSION="${GITHUB_REF_NAME}" + else + VERSION="dev-${GITHUB_SHA::7}" + fi + echo "VERSION=${VERSION}" >> "$GITHUB_ENV" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + + - name: Install system deps (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y build-essential patchelf tk tcl libgtk-3-0 + + - name: Install system deps (macOS) + if: runner.os == 'macOS' + run: | + xcode-select --install || true + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install DrissionPage pystray pillow + pip install nuitka ordered-set zstandard + + - name: Build with Nuitka (Unix) + if: runner.os != 'Windows' + run: | + python -m nuitka \ + --onefile \ + --standalone \ + --assume-yes-for-downloads \ + --enable-plugin=tk-inter \ + --include-package=DrissionPage \ + --include-package=pystray \ + --include-package=PIL \ + --include-data-file=icon.ico=icon.ico \ + --output-filename="${APP_NAME}" \ + --output-dir=dist \ + linux_do_gui.py + + - name: Build with Nuitka (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + python -m nuitka ` + --onefile ` + --standalone ` + --assume-yes-for-downloads ` + --enable-plugin=tk-inter ` + --include-package=DrissionPage ` + --include-package=pystray ` + --include-package=PIL ` + --include-data-file=icon.ico=icon.ico ` + --windows-icon-from-ico=icon.ico ` + --output-filename="${env:APP_NAME}" ` + --output-dir=dist ` + linux_do_gui.py + + - name: Rename artifact (Unix) + if: runner.os != 'Windows' + run: | + mv "dist/${APP_NAME}" "dist/${APP_NAME}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}" + + - name: Rename artifact (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + Move-Item "dist\\${env:APP_NAME}.exe" "dist\\${env:APP_NAME}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }}" + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.APP_NAME }}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }} + path: dist/${{ env.APP_NAME }}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }} + retention-days: 30 + + release: + name: Create Release (Nuitka) + needs: build + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts/ + + - name: Display artifacts + run: find artifacts/ -type f + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + name: ${{ env.APP_NAME }} ${{ github.ref_name }} (Nuitka) + body: | + ## ${{ env.APP_NAME }} ${{ github.ref_name }} (Nuitka Build) + + ### Downloads + - Linux (x64): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-linux-amd64` + - Linux (ARM64): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-linux-arm64` + - macOS (Apple Silicon): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-macos-arm64` + - Windows (x64): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-windows-amd64.exe` + + ### Build Info + - Builder: Nuitka + - Python: ${{ env.PYTHON_VERSION }} + + ### Note + Nuitka builds are compiled to native code and may start faster than PyInstaller bundles. + files: | + artifacts/** + generate_release_notes: true + draft: false + prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/build-pyinstaller.yml b/.github/workflows/build-pyinstaller.yml new file mode 100644 index 0000000..c49c86f --- /dev/null +++ b/.github/workflows/build-pyinstaller.yml @@ -0,0 +1,157 @@ +name: Build with PyInstaller + +on: + push: + tags: + - 'v*' + branches: + - main + - master + - dev + pull_request: + workflow_dispatch: + +env: + APP_NAME: LinuxDoHelper + PYTHON_VERSION: '3.11' + +jobs: + build: + name: Build on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + platform: linux-amd64 + ext: '' + - os: ubuntu-24.04-arm + platform: linux-arm64 + ext: '' + - os: macos-15 + platform: macos-arm64 + ext: '' + - os: windows-2025 + platform: windows-amd64 + ext: '.exe' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + cache: 'pip' + + - name: Resolve version + id: version + shell: bash + run: | + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + VERSION="${GITHUB_REF_NAME}" + else + VERSION="dev-${GITHUB_SHA::7}" + fi + echo "VERSION=${VERSION}" >> "$GITHUB_ENV" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + + - name: Install system deps (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y tk tcl libgtk-3-0 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install DrissionPage pystray pillow pyinstaller + + - name: Build with PyInstaller (Unix) + if: runner.os != 'Windows' + run: | + pyinstaller --onefile --windowed --clean --noconfirm \ + --name "${APP_NAME}" \ + --hidden-import tkinter \ + --hidden-import tkinter.ttk \ + --hidden-import tkinter.scrolledtext \ + --hidden-import DrissionPage \ + --hidden-import pystray \ + --hidden-import PIL \ + --add-data "icon.ico:." \ + linux_do_gui.py + + - name: Build with PyInstaller (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + pyinstaller --onefile --windowed --clean --noconfirm ` + --name "${env:APP_NAME}" ` + --hidden-import tkinter ` + --hidden-import tkinter.ttk ` + --hidden-import tkinter.scrolledtext ` + --hidden-import DrissionPage ` + --hidden-import pystray ` + --hidden-import PIL ` + --add-data "icon.ico;." ` + --icon icon.ico ` + linux_do_gui.py + + - name: Rename artifact (Unix) + if: runner.os != 'Windows' + run: | + mv "dist/${APP_NAME}" "dist/${APP_NAME}-pyinstaller-${{ steps.version.outputs.version }}-${{ matrix.platform }}" + + - name: Rename artifact (Windows) + if: runner.os == 'Windows' + shell: pwsh + run: | + Move-Item "dist\\${env:APP_NAME}.exe" "dist\\${env:APP_NAME}-pyinstaller-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }}" + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.APP_NAME }}-pyinstaller-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }} + path: dist/${{ env.APP_NAME }}-pyinstaller-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }} + retention-days: 30 + + release: + name: Create Release (PyInstaller) + needs: build + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts/ + + - name: Display artifacts + run: find artifacts/ -type f + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + name: ${{ env.APP_NAME }} ${{ github.ref_name }} (PyInstaller) + body: | + ## ${{ env.APP_NAME }} ${{ github.ref_name }} (PyInstaller Build) + + ### Downloads + - Linux (x64): `${{ env.APP_NAME }}-pyinstaller-${{ github.ref_name }}-linux-amd64` + - Linux (ARM64): `${{ env.APP_NAME }}-pyinstaller-${{ github.ref_name }}-linux-arm64` + - macOS (Apple Silicon): `${{ env.APP_NAME }}-pyinstaller-${{ github.ref_name }}-macos-arm64` + - Windows (x64): `${{ env.APP_NAME }}-pyinstaller-${{ github.ref_name }}-windows-amd64.exe` + + ### Build Info + - Builder: PyInstaller + - Python: ${{ env.PYTHON_VERSION }} + files: | + artifacts/** + generate_release_notes: true + draft: false + prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index c29c432..3514db4 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ LDStatusPro/ # Dist folder (exe files are too large for git) dist/ +.DS_Store diff --git a/README.md b/README.md index ba623d0..3bcd411 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ python linux_do_gui.py ## 更新日志 -### v8.1 (2025-01-14) +### v8.1 (2026-01-14) - 新增系统托盘功能,支持最小化到托盘 - 新增托盘图标状态显示(就绪/运行中/已完成) - 新增托盘悬停提示,显示实时统计信息 diff --git a/build.py b/build.py index 24d1946..a29c268 100644 --- a/build.py +++ b/build.py @@ -42,27 +42,33 @@ def clean_build(): os.remove(f) print(f"已清理: {f}") -def build_windows(): +def build_windows(): """打包 Windows exe""" print("\n" + "=" * 50) print("开始打包 Windows 版本...") print("=" * 50) - cmd = [ - "pyinstaller", - "--onefile", - "--windowed", - "--name", f"{APP_NAME}_v{APP_VERSION}_Windows", - "--add-data", f"{MAIN_SCRIPT};.", - "--hidden-import", "tkinter", - "--hidden-import", "tkinter.ttk", - "--hidden-import", "tkinter.scrolledtext", - "--hidden-import", "DrissionPage", - "--clean", - "--noconfirm", - MAIN_SCRIPT - ] - + cmd = [ + "pyinstaller", + "--onefile", + "--windowed", + "--name", f"{APP_NAME}_v{APP_VERSION}_Windows", + "--add-data", f"{MAIN_SCRIPT};.", + "--hidden-import", "tkinter", + "--hidden-import", "tkinter.ttk", + "--hidden-import", "tkinter.scrolledtext", + "--hidden-import", "DrissionPage", + "--hidden-import", "pystray", + "--hidden-import", "PIL", + "--clean", + "--noconfirm", + MAIN_SCRIPT + ] + + # 打包图标数据,供运行时托盘与窗口图标使用 + if os.path.exists(ICON_WIN): + cmd.extend(["--add-data", f"{ICON_WIN};."]) + # 如果有图标文件 if os.path.exists(ICON_WIN): cmd.extend(["--icon", ICON_WIN]) @@ -76,26 +82,32 @@ def build_windows(): print(f"打包失败: {e}") return False -def build_macos(): +def build_macos(): """打包 macOS app""" print("\n" + "=" * 50) print("开始打包 macOS 版本...") print("=" * 50) - cmd = [ - "pyinstaller", - "--onefile", - "--windowed", - "--name", f"{APP_NAME}_v{APP_VERSION}_macOS", - "--hidden-import", "tkinter", - "--hidden-import", "tkinter.ttk", - "--hidden-import", "tkinter.scrolledtext", - "--hidden-import", "DrissionPage", - "--clean", - "--noconfirm", - MAIN_SCRIPT - ] - + cmd = [ + "pyinstaller", + "--onefile", + "--windowed", + "--name", f"{APP_NAME}_v{APP_VERSION}_macOS", + "--hidden-import", "tkinter", + "--hidden-import", "tkinter.ttk", + "--hidden-import", "tkinter.scrolledtext", + "--hidden-import", "DrissionPage", + "--hidden-import", "pystray", + "--hidden-import", "PIL", + "--clean", + "--noconfirm", + MAIN_SCRIPT + ] + + # 打包图标数据,供运行时托盘与窗口图标使用 + if os.path.exists(ICON_WIN): + cmd.extend(["--add-data", f"{ICON_WIN}:."]) + # 如果有图标文件 if os.path.exists(ICON_MAC): cmd.extend(["--icon", ICON_MAC]) @@ -109,26 +121,32 @@ def build_macos(): print(f"打包失败: {e}") return False -def build_linux(): +def build_linux(): """打包 Linux 版本""" print("\n" + "=" * 50) print("开始打包 Linux 版本...") print("=" * 50) - cmd = [ - "pyinstaller", - "--onefile", - "--windowed", - "--name", f"{APP_NAME}_v{APP_VERSION}_Linux", - "--hidden-import", "tkinter", - "--hidden-import", "tkinter.ttk", - "--hidden-import", "tkinter.scrolledtext", - "--hidden-import", "DrissionPage", - "--clean", - "--noconfirm", - MAIN_SCRIPT - ] - + cmd = [ + "pyinstaller", + "--onefile", + "--windowed", + "--name", f"{APP_NAME}_v{APP_VERSION}_Linux", + "--hidden-import", "tkinter", + "--hidden-import", "tkinter.ttk", + "--hidden-import", "tkinter.scrolledtext", + "--hidden-import", "DrissionPage", + "--hidden-import", "pystray", + "--hidden-import", "PIL", + "--clean", + "--noconfirm", + MAIN_SCRIPT + ] + + # 打包图标数据,供运行时托盘与窗口图标使用 + if os.path.exists(ICON_WIN): + cmd.extend(["--add-data", f"{ICON_WIN}:."]) + try: subprocess.run(cmd, check=True) print(f"\nLinux 版本打包成功!") diff --git a/BUILD_GUIDE.md b/docs/BUILD_GUIDE.md similarity index 79% rename from BUILD_GUIDE.md rename to docs/BUILD_GUIDE.md index a0d4c38..08a5f31 100644 --- a/BUILD_GUIDE.md +++ b/docs/BUILD_GUIDE.md @@ -17,8 +17,8 @@ Windows exe 已打包完成,位于 `dist/LinuxDoHelper_v8.0_Windows.exe` # 1. 安装 Python 3.8+ brew install python@3.11 -# 2. 安装依赖 -pip3 install DrissionPage pyinstaller +# 2. 安装依赖 +pip3 install DrissionPage pystray pillow pyinstaller # 3. 安装 Chrome 浏览器 # 从 https://www.google.com/chrome/ 下载安装 @@ -78,8 +78,8 @@ sudo yum install python3 python3-pip python3-tkinter # Arch Linux sudo pacman -S python python-pip tk -# 安装依赖 -pip3 install DrissionPage pyinstaller +# 安装依赖 +pip3 install DrissionPage pystray pillow pyinstaller # 安装 Chrome 浏览器 # Ubuntu/Debian @@ -154,13 +154,32 @@ A: 安装 python3-tk 包 如果打包版本有问题,可以直接从源码运行: -```bash -# 安装依赖 -pip install DrissionPage - -# 运行 -python linux_do_gui.py -``` +```bash +# 安装依赖 +pip install DrissionPage pystray pillow + +# 运行 +python linux_do_gui.py +``` + +--- + +## GitHub Actions 自动打包(PyInstaller + Nuitka) + +仓库已提供 GitHub Actions 工作流,可在提交或打 Tag 时自动打包多平台可执行文件: + +- PyInstaller 工作流: `.github/workflows/build-pyinstaller.yml` +- Nuitka 工作流: `.github/workflows/build-nuitka.yml` + +### 使用方式 + +1. 创建并推送版本 Tag(示例): + ```bash + git tag v8.1.0 + git push origin v8.1.0 + ``` +2. GitHub Actions 将自动构建并上传对应平台的产物到 Release。 +3. 如需手动触发,可在 Actions 页面使用 `workflow_dispatch` 并填写 `version`。 --- diff --git "a/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" "b/docs/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" similarity index 100% rename from "Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" rename to "docs/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" From c6371325c5acfb1f9a478ea429fc17de11b5f69b Mon Sep 17 00:00:00 2001 From: BlueSkyXN <63384277+BlueSkyXN@users.noreply.github.com> Date: Sat, 17 Jan 2026 16:39:43 +0800 Subject: [PATCH 2/5] Update CI to install dependencies from requirements.txt Modified build workflows to install dependencies using requirements.txt instead of listing packages directly. This ensures consistency between local and CI environments. Also fixed a typo in the branches filter for the PyInstaller workflow. --- .github/workflows/build-nuitka.yml | 2 +- .github/workflows/build-pyinstaller.yml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-nuitka.yml b/.github/workflows/build-nuitka.yml index 0630bb2..4b8103f 100644 --- a/.github/workflows/build-nuitka.yml +++ b/.github/workflows/build-nuitka.yml @@ -72,7 +72,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install DrissionPage pystray pillow + pip install -r requirements.txt pip install nuitka ordered-set zstandard - name: Build with Nuitka (Unix) diff --git a/.github/workflows/build-pyinstaller.yml b/.github/workflows/build-pyinstaller.yml index c49c86f..b8d1460 100644 --- a/.github/workflows/build-pyinstaller.yml +++ b/.github/workflows/build-pyinstaller.yml @@ -4,7 +4,7 @@ on: push: tags: - 'v*' - branches: + branches:requirements.txt - main - master - dev @@ -67,7 +67,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install DrissionPage pystray pillow pyinstaller + pip install -r requirements.txt + pip install pyinstaller - name: Build with PyInstaller (Unix) if: runner.os != 'Windows' From dcc15aa136a72c16426b32c81771eec09202946e Mon Sep 17 00:00:00 2001 From: BlueSkyXN <63384277+BlueSkyXN@users.noreply.github.com> Date: Sun, 18 Jan 2026 08:35:35 +0800 Subject: [PATCH 3/5] Add requirements.txt and update .gitignore for requirements Added requirements.txt with DrissionPage, pystray, and pillow dependencies. Updated .gitignore to allow requirements.txt and requirements-*.txt files to be tracked. --- .gitignore | 14 ++++++++------ requirements.txt | 3 +++ 2 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 3514db4..efa27f2 100644 --- a/.gitignore +++ b/.gitignore @@ -26,12 +26,14 @@ wheels/ *.log # Local files -*.json -*.txt -*.html -*.png -*.pyw -nul +*.json +*.txt +*.html +*.png +*.pyw +nul +!requirements.txt +!requirements-*.txt # IDE .idea/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..385e989 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +DrissionPage +pystray +pillow From d335b3ae5e25a184d0af1cef23aa61f62b4149f6 Mon Sep 17 00:00:00 2001 From: BlueSkyXN <63384277+BlueSkyXN@users.noreply.github.com> Date: Sun, 18 Jan 2026 08:48:49 +0800 Subject: [PATCH 4/5] Improve build workflows and GUI stop handling Refactors the Nuitka GitHub Actions workflow for clearer artifact naming, improved macOS app packaging, and more precise trigger paths. Fixes a typo in the PyInstaller workflow trigger. In linux_do_gui.py, ensures safe content injection in the editor using json.dumps, and improves the stop logic in the GUI to correctly reflect stopped status and reset state. --- .github/workflows/build-nuitka.yml | 129 +++++++++++++----------- .github/workflows/build-pyinstaller.yml | 2 +- linux_do_gui.py | 24 +++-- 3 files changed, 88 insertions(+), 67 deletions(-) diff --git a/.github/workflows/build-nuitka.yml b/.github/workflows/build-nuitka.yml index 4b8103f..87b667e 100644 --- a/.github/workflows/build-nuitka.yml +++ b/.github/workflows/build-nuitka.yml @@ -8,8 +8,21 @@ on: - main - master - dev + paths: + - 'linux_do_gui.py' + - 'requirements.txt' + - 'icon.ico' + - 'docs/**' pull_request: + paths: + - 'linux_do_gui.py' + - 'requirements.txt' workflow_dispatch: + inputs: + version: + description: 'Version tag for release (e.g., v8.1.0)' + required: false + default: '' env: APP_NAME: LinuxDoHelper @@ -24,17 +37,14 @@ jobs: matrix: include: - os: ubuntu-24.04 - platform: linux-amd64 - ext: '' + artifact_name: LinuxDoHelper-nuitka-linux-amd64 - os: ubuntu-24.04-arm - platform: linux-arm64 - ext: '' + artifact_name: LinuxDoHelper-nuitka-linux-arm64 - os: macos-15 - platform: macos-arm64 - ext: '' + artifact_name: LinuxDoHelper-nuitka-macos-arm64.app.zip + app_dir_name: LinuxDoHelper-nuitka-macos-arm64.app - os: windows-2025 - platform: windows-amd64 - ext: '.exe' + artifact_name: LinuxDoHelper-nuitka-windows-amd64.exe steps: - name: Checkout repository @@ -46,37 +56,42 @@ jobs: python-version: ${{ env.PYTHON_VERSION }} cache: 'pip' - - name: Resolve version - id: version - shell: bash + - name: Install dependencies run: | - if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then - VERSION="${GITHUB_REF_NAME}" - else - VERSION="dev-${GITHUB_SHA::7}" - fi - echo "VERSION=${VERSION}" >> "$GITHUB_ENV" - echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - - - name: Install system deps (Linux) + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install nuitka ordered-set zstandard + + - name: Install C compiler (Ubuntu) if: runner.os == 'Linux' run: | sudo apt-get update - sudo apt-get install -y build-essential patchelf tk tcl libgtk-3-0 + sudo apt-get install -y build-essential patchelf - - name: Install system deps (macOS) + - name: Install C compiler (macOS) if: runner.os == 'macOS' run: | xcode-select --install || true - - name: Install dependencies + - name: Build with Nuitka (macOS) + if: runner.os == 'macOS' run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install nuitka ordered-set zstandard + python -m nuitka \ + --onefile \ + --standalone \ + --mode=app \ + --assume-yes-for-downloads \ + --enable-plugin=tk-inter \ + --include-package=DrissionPage \ + --include-package=pystray \ + --include-package=PIL \ + --include-data-file=icon.ico=icon.ico \ + --output-filename=${{ env.APP_NAME }} \ + --output-dir=dist \ + linux_do_gui.py - - name: Build with Nuitka (Unix) - if: runner.os != 'Windows' + - name: Build with Nuitka (Linux) + if: runner.os == 'Linux' run: | python -m nuitka \ --onefile \ @@ -87,48 +102,44 @@ jobs: --include-package=pystray \ --include-package=PIL \ --include-data-file=icon.ico=icon.ico \ - --output-filename="${APP_NAME}" \ + --output-filename=${{ env.APP_NAME }} \ --output-dir=dist \ linux_do_gui.py - name: Build with Nuitka (Windows) if: runner.os == 'Windows' - shell: pwsh run: | - python -m nuitka ` - --onefile ` - --standalone ` - --assume-yes-for-downloads ` - --enable-plugin=tk-inter ` - --include-package=DrissionPage ` - --include-package=pystray ` - --include-package=PIL ` - --include-data-file=icon.ico=icon.ico ` - --windows-icon-from-ico=icon.ico ` - --output-filename="${env:APP_NAME}" ` - --output-dir=dist ` - linux_do_gui.py + python -m nuitka --onefile --standalone --assume-yes-for-downloads --enable-plugin=tk-inter --include-package=DrissionPage --include-package=pystray --include-package=PIL --include-data-file=icon.ico=icon.ico --output-filename=${{ env.APP_NAME }} --output-dir=dist linux_do_gui.py - - name: Rename artifact (Unix) - if: runner.os != 'Windows' + - name: Rename artifact (macOS) + if: runner.os == 'macOS' + run: | + mv dist/${{ env.APP_NAME }}.app dist/${{ matrix.app_dir_name }} + + - name: Zip macOS app + if: runner.os == 'macOS' + run: | + ditto -c -k --sequesterRsrc --keepParent dist/${{ matrix.app_dir_name }} dist/${{ matrix.artifact_name }} + + - name: Rename artifact (Linux) + if: runner.os == 'Linux' run: | - mv "dist/${APP_NAME}" "dist/${APP_NAME}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}" + mv dist/${{ env.APP_NAME }} dist/${{ matrix.artifact_name }} - name: Rename artifact (Windows) if: runner.os == 'Windows' - shell: pwsh run: | - Move-Item "dist\\${env:APP_NAME}.exe" "dist\\${env:APP_NAME}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }}" + move dist\${{ env.APP_NAME }}.exe dist\${{ matrix.artifact_name }} - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: ${{ env.APP_NAME }}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }} - path: dist/${{ env.APP_NAME }}-nuitka-${{ steps.version.outputs.version }}-${{ matrix.platform }}${{ matrix.ext }} + name: ${{ matrix.artifact_name }} + path: dist/${{ matrix.artifact_name }} retention-days: 30 release: - name: Create Release (Nuitka) + name: Create Release needs: build runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/v') @@ -140,7 +151,7 @@ jobs: path: artifacts/ - name: Display artifacts - run: find artifacts/ -type f + run: find artifacts/ -type f -o -type d - name: Create GitHub Release uses: softprops/action-gh-release@v2 @@ -150,19 +161,19 @@ jobs: ## ${{ env.APP_NAME }} ${{ github.ref_name }} (Nuitka Build) ### Downloads - - Linux (x64): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-linux-amd64` - - Linux (ARM64): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-linux-arm64` - - macOS (Apple Silicon): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-macos-arm64` - - Windows (x64): `${{ env.APP_NAME }}-nuitka-${{ github.ref_name }}-windows-amd64.exe` + - **Linux (x64)**: `LinuxDoHelper-nuitka-linux-amd64` + - **Linux (ARM64)**: `LinuxDoHelper-nuitka-linux-arm64` + - **macOS (Apple Silicon)**: `LinuxDoHelper-nuitka-macos-arm64.app.zip` + - **Windows (x64)**: `LinuxDoHelper-nuitka-windows-amd64.exe` ### Build Info - - Builder: Nuitka + - Builder: Nuitka (compiled to native code) - Python: ${{ env.PYTHON_VERSION }} ### Note - Nuitka builds are compiled to native code and may start faster than PyInstaller bundles. + macOS builds use `--mode=app` to support GUI frameworks (Foundation/Tkinter). files: | - artifacts/** + artifacts/**/* generate_release_notes: true draft: false prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }} diff --git a/.github/workflows/build-pyinstaller.yml b/.github/workflows/build-pyinstaller.yml index b8d1460..2ea94a9 100644 --- a/.github/workflows/build-pyinstaller.yml +++ b/.github/workflows/build-pyinstaller.yml @@ -4,7 +4,7 @@ on: push: tags: - 'v*' - branches:requirements.txt + branches: - main - master - dev diff --git a/linux_do_gui.py b/linux_do_gui.py index b24ed95..4365058 100644 --- a/linux_do_gui.py +++ b/linux_do_gui.py @@ -488,12 +488,13 @@ def do_reply(s, content=None): s._random_delay(1.5, 3, "等待编辑器") # 输入内容 - 使用安全的方式传递内容 + safe_content = json.dumps(content) s.pg.run_js(f""" (function() {{ const textarea = document.querySelector('#reply-control textarea, .d-editor-input'); if (textarea) {{ textarea.focus(); - textarea.value = '{content}'; + textarea.value = {safe_content}; textarea.dispatchEvent(new Event('input', {{bubbles: true}})); }} }})(); @@ -700,6 +701,7 @@ def __init__(s): s.tray_icon = None s.tray_thread = None s._running_status = "就绪" + s._stop_requested = False s._ui() @@ -1368,6 +1370,7 @@ def _start(s): # 重置初始数据 s.initial_requirements = [] + s._stop_requested = False s.bot = Bot(s.cfg, s.cats, s._lg, s._update_info, s._update_progress) s.th = threading.Thread(target=s._run, daemon=True) @@ -1382,17 +1385,24 @@ def _run(s): def _done(s): s.start_btn.config(state=tk.NORMAL) s.stop_btn.config(state=tk.DISABLED) - s.status.set("已完成") - - # 更新托盘状态 - if s.bot: - s._update_tray_status("已完成", s.bot.stats) + if s._stop_requested: + s.status.set("已停止") + if s.bot: + s._update_tray_status("已停止", s.bot.stats) + else: + s._update_tray_status("已停止") else: - s._update_tray_status("已完成") + s.status.set("已完成") + if s.bot: + s._update_tray_status("已完成", s.bot.stats) + else: + s._update_tray_status("已完成") + s._stop_requested = False def _stop(s): if s.bot: s.bot.stop() + s._stop_requested = True s.status.set("正在停止...") s._update_tray_status("已停止") From 0a664454b951cdc1de6b5be0a5eb351b3018e9cc Mon Sep 17 00:00:00 2001 From: BlueSkyXN <63384277+BlueSkyXN@users.noreply.github.com> Date: Sun, 18 Jan 2026 09:23:28 +0800 Subject: [PATCH 5/5] Update docs and build guides to use requirements.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced direct pip install commands with 'pip install -r requirements.txt' in README and documentation for consistency and easier dependency management. Updated build instructions, file structure, and output file naming conventions in both BUILD_GUIDE.md and Linux 环境安装指南.md. Also adjusted the GitHub Actions workflow for Nuitka on macOS by removing unnecessary flags. --- .github/workflows/build-nuitka.yml | 2 - README.md | 71 ++++++------ docs/BUILD_GUIDE.md | 108 ++++++++++-------- ...11\350\243\205\346\214\207\345\215\227.md" | 4 +- 4 files changed, 101 insertions(+), 84 deletions(-) diff --git a/.github/workflows/build-nuitka.yml b/.github/workflows/build-nuitka.yml index 87b667e..2021246 100644 --- a/.github/workflows/build-nuitka.yml +++ b/.github/workflows/build-nuitka.yml @@ -77,8 +77,6 @@ jobs: if: runner.os == 'macOS' run: | python -m nuitka \ - --onefile \ - --standalone \ --mode=app \ --assume-yes-for-downloads \ --enable-plugin=tk-inter \ diff --git a/README.md b/README.md index 3bcd411..ff31262 100644 --- a/README.md +++ b/README.md @@ -86,11 +86,11 @@ - Python 3.8+ - Chrome 浏览器 -#### 安装依赖 - -```bash -pip install DrissionPage pystray pillow -``` +#### 安装依赖 + +```bash +pip install -r requirements.txt +``` #### 运行程序 @@ -195,33 +195,40 @@ python linux_do_gui.py 由于 PyInstaller 不支持跨平台打包(Windows 上无法打包 macOS/Linux 版本),我创建了: - 1. build.py - 通用打包脚本,在对应系统上运行即可自动打包 - 2. BUILD_GUIDE.md - 详细的打包指南,包含: - - macOS 打包步骤 - - Linux 打包步骤 - - 环境准备命令 - - 常见问题解决 - -### 在 macOS 上打包 - - pip3 install DrissionPage pyinstaller - python3 build.py - -### 在 Linux 上打包 - - pip3 install DrissionPage pyinstaller - python3 build.py - -### 项目文件结构 - -linuxdo/ -├── linux_do_gui.py # 主程序 - -├── build.py # 打包脚本 - -├── README.md # 项目说明 - -└── BUILD_GUIDE.md # 打包指南 + 1. build.py - 通用打包脚本,在对应系统上运行即可自动打包 + 2. docs/BUILD_GUIDE.md - 详细的打包指南,包含: + - macOS 打包步骤 + - Linux 打包步骤 + - 环境准备命令 + - 常见问题解决 + 3. docs/Linux 环境安装指南.md - Linux 环境安装说明 + +### 在 macOS 上打包 + + pip3 install -r requirements.txt + pip3 install pyinstaller + python3 build.py + +### 在 Linux 上打包 + + pip3 install -r requirements.txt + pip3 install pyinstaller + python3 build.py + +### 项目文件结构 + +linuxdo/ +├── linux_do_gui.py # 主程序 + +├── build.py # 打包脚本 + +├── README.md # 项目说明 + +├── requirements.txt # 依赖列表 + +└── docs/ + ├── BUILD_GUIDE.md # 打包指南 + └── Linux 环境安装指南.md # Linux 环境安装指南 ## 技术栈 diff --git a/docs/BUILD_GUIDE.md b/docs/BUILD_GUIDE.md index 08a5f31..837bed5 100644 --- a/docs/BUILD_GUIDE.md +++ b/docs/BUILD_GUIDE.md @@ -1,11 +1,12 @@ # Linux.do 刷帖助手 - 多平台打包指南 -## Windows 版本 - -Windows exe 已打包完成,位于 `dist/LinuxDoHelper_v8.0_Windows.exe` - -### 直接运行 -双击 `LinuxDoHelper_v8.0_Windows.exe` 即可运行 +## Windows 版本 + +Windows 可执行文件请优先从 GitHub Releases 或 Actions 构建产物获取,文件名示例: +- `LinuxDoHelper-pyinstaller--windows-amd64.exe` +- `LinuxDoHelper-nuitka-windows-amd64.exe` + +如需本地打包,请参考下文 PyInstaller/Nuitka 的命令并在 Windows 上执行。 --- @@ -18,7 +19,8 @@ Windows exe 已打包完成,位于 `dist/LinuxDoHelper_v8.0_Windows.exe` brew install python@3.11 # 2. 安装依赖 -pip3 install DrissionPage pystray pillow pyinstaller +pip3 install -r requirements.txt +pip3 install pyinstaller # 3. 安装 Chrome 浏览器 # 从 https://www.google.com/chrome/ 下载安装 @@ -31,29 +33,32 @@ pip3 install DrissionPage pystray pillow pyinstaller cd /path/to/linuxdo # 执行打包 -pyinstaller --onefile --windowed \ - --name "LinuxDoHelper_v8.0_macOS" \ - --hidden-import tkinter \ - --hidden-import tkinter.ttk \ - --hidden-import tkinter.scrolledtext \ - --hidden-import DrissionPage \ - --clean --noconfirm \ - linux_do_gui.py +pyinstaller --onefile --windowed \ + --name "LinuxDoHelper_v_macOS" \ + --hidden-import tkinter \ + --hidden-import tkinter.ttk \ + --hidden-import tkinter.scrolledtext \ + --hidden-import DrissionPage \ + --hidden-import pystray \ + --hidden-import PIL \ + --add-data "icon.ico:." \ + --clean --noconfirm \ + linux_do_gui.py # 或者使用打包脚本 python3 build.py ``` -### 输出文件 -- `dist/LinuxDoHelper_v8.0_macOS` (可执行文件) +### 输出文件 +- `dist/LinuxDoHelper_v_macOS` (可执行文件) ### 运行方式 ```bash -# 赋予执行权限 -chmod +x dist/LinuxDoHelper_v8.0_macOS - -# 运行 -./dist/LinuxDoHelper_v8.0_macOS +# 赋予执行权限 +chmod +x dist/LinuxDoHelper_v_macOS + +# 运行 +./dist/LinuxDoHelper_v_macOS ``` ### macOS 安全提示 @@ -79,7 +84,8 @@ sudo yum install python3 python3-pip python3-tkinter sudo pacman -S python python-pip tk # 安装依赖 -pip3 install DrissionPage pystray pillow pyinstaller +pip3 install -r requirements.txt +pip3 install pyinstaller # 安装 Chrome 浏览器 # Ubuntu/Debian @@ -95,29 +101,32 @@ sudo apt-get install -f cd /path/to/linuxdo # 执行打包 -pyinstaller --onefile --windowed \ - --name "LinuxDoHelper_v8.0_Linux" \ - --hidden-import tkinter \ - --hidden-import tkinter.ttk \ - --hidden-import tkinter.scrolledtext \ - --hidden-import DrissionPage \ - --clean --noconfirm \ - linux_do_gui.py +pyinstaller --onefile --windowed \ + --name "LinuxDoHelper_v_Linux" \ + --hidden-import tkinter \ + --hidden-import tkinter.ttk \ + --hidden-import tkinter.scrolledtext \ + --hidden-import DrissionPage \ + --hidden-import pystray \ + --hidden-import PIL \ + --add-data "icon.ico:." \ + --clean --noconfirm \ + linux_do_gui.py # 或者使用打包脚本 python3 build.py ``` -### 输出文件 -- `dist/LinuxDoHelper_v8.0_Linux` (可执行文件) +### 输出文件 +- `dist/LinuxDoHelper_v_Linux` (可执行文件) ### 运行方式 ```bash -# 赋予执行权限 -chmod +x dist/LinuxDoHelper_v8.0_Linux - -# 运行 -./dist/LinuxDoHelper_v8.0_Linux +# 赋予执行权限 +chmod +x dist/LinuxDoHelper_v_Linux + +# 运行 +./dist/LinuxDoHelper_v_Linux ``` ### Linux 注意事项 @@ -142,8 +151,8 @@ A: 检查是否安装了 Chrome 浏览器 #### Q: 提示找不到 chromedriver A: DrissionPage 会自动下载,确保网络通畅 -#### Q: macOS 提示"已损坏,无法打开" -A: 执行 `xattr -cr /path/to/LinuxDoHelper_v8.0_macOS` +#### Q: macOS 提示"已损坏,无法打开" +A: 执行 `xattr -cr /path/to/LinuxDoHelper_v_macOS` #### Q: Linux 提示 tkinter 相关错误 A: 安装 python3-tk 包 @@ -156,7 +165,7 @@ A: 安装 python3-tk 包 ```bash # 安装依赖 -pip install DrissionPage pystray pillow +pip install -r requirements.txt # 运行 python linux_do_gui.py @@ -186,11 +195,14 @@ python linux_do_gui.py ## 文件说明 ``` -linuxdo/ -├── linux_do_gui.py # 主程序 -├── build.py # 打包脚本 -├── README.md # 项目说明 -├── BUILD_GUIDE.md # 本文档 -└── dist/ - └── LinuxDoHelper_v8.0_Windows.exe # Windows 可执行文件 +linuxdo/ +├── linux_do_gui.py # 主程序 +├── build.py # 打包脚本 +├── README.md # 项目说明 +├── requirements.txt # 依赖列表 +├── docs/ +│ ├── BUILD_GUIDE.md # 本文档 +│ └── Linux 环境安装指南.md # Linux 环境安装指南 +└── dist/ + └── LinuxDoHelper_<...> # 构建产物示例 ``` diff --git "a/docs/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" "b/docs/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" index 1f5a88c..2e2535e 100644 --- "a/docs/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" +++ "b/docs/Linux \347\216\257\345\242\203\345\256\211\350\243\205\346\214\207\345\215\227.md" @@ -14,7 +14,7 @@ Linux 环境安装指南 2. 安装 Python 依赖 - pip3 install DrissionPage + pip3 install -r requirements.txt 3. 安装 Chrome 浏览器 @@ -41,7 +41,7 @@ Linux 环境安装指南 sudo apt install python3-tk Q: 提示 No module named 'DrissionPage' - pip3 install DrissionPage + pip3 install -r requirements.txt Q: 程序启动但浏览器打不开 确保安装了 Chrome 浏览器: