From 17af280125f3a0a93d0c260a64bbb22f3fb6da31 Mon Sep 17 00:00:00 2001 From: AmerikanSn1p3r <79807933+V1p3rOne@users.noreply.github.com> Date: Sun, 20 Oct 2024 21:52:02 +0200 Subject: [PATCH 1/4] feat: added new things to .github --- .github/ISSUE_TEMPLATE/bug-report.yml | 161 +++++++++++++++------- .github/release-drafter.yml | 50 +++++++ .github/workflows/changelog.yml | 29 ++++ .github/workflows/release-builder.yml | 189 ++++++++++++++++++++++++++ .github/workflows/release-drafter.yml | 50 +++++++ 5 files changed, 432 insertions(+), 47 deletions(-) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/changelog.yml create mode 100644 .github/workflows/release-builder.yml create mode 100644 .github/workflows/release-drafter.yml diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index af15964..dd98cc4 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -2,50 +2,117 @@ name: Bug Report description: Found a bug? Report it here. labels: [bug] body: -- type: markdown - attributes: - value: | - **Please follow the guidelines below to help us resolve your issue.** - - **Guidelines:** - - Please **search existing issues** to ensure your issue isn't already reported by [checking here](https://github.com/justin025/onthespot/issues?q=is%3Aissue). - - **Report one bug per issue** by creating separate issues for each bug. - - **Provide a descriptive title** that clearly summarizes your issue. - - **Include detailed information** to help us reproduce and fix the problem. - - **If you don't follow the guidelines, the issue will be deleted!** - -- type: textarea - id: description - attributes: - label: Bug Description - description: A detailed and accurate description of the bug is required. - placeholder: When I perform X action, Y happens instead of the expected Z. - validations: - required: true - -- type: textarea - id: environment - attributes: - label: Environment Details - description: Provide details about your setup. - render: markdown - value: | - | **Detail** | **Your Information** | - |--------------------------|--------------------------------------| - | **Operating System** | Windows 10 / MacOS 13 / Ubuntu 22.04 | - | **Application Version** | v0.7.0 | - | **Installation Method** | GitHub Release / Build from Script | - | **Python Version** | 3.11.4 | - | **FFmpeg Version** | e.g., 4.3.1 | - validations: - required: true - -- type: textarea - id: additional_info - attributes: - label: Additional Information - description: Add any other context, screenshots, or logs. - placeholder: Include logs, screenshots, or any other relevant details here. - validations: - required: false + - type: markdown + attributes: + value: | + **Please follow the guidelines below to help us resolve your issue.** + + **Guidelines:** + - Please **search existing issues** to ensure your issue isn't already reported by [checking here](https://github.com/justin025/onthespot/issues?q=is%3Aissue). + - **Report one bug per issue** by creating separate issues for each bug. + - **Provide a descriptive title** that clearly summarizes your issue. + - **Include detailed information** to help us reproduce and fix the problem. + + **If you don't follow the guidelines, the issue will be deleted!** + + - type: textarea + id: ots_description + attributes: + label: Bug Description + description: A detailed and accurate description of the bug is required. + placeholder: When I perform X action, Y happens instead of the expected Z. + validations: + required: true + + # Environment Details Section + + - type: dropdown + id: ots_operating_system + attributes: + label: Operating System + description: Select your operating system. + options: + - Windows + - macOS + - Linux + - Other + validations: + required: true + + # Operating System Version Input + + - type: input + id: ots_os_version + attributes: + label: Operating System Version + description: Specify your operating system version. + placeholder: e.g., Windows 11, macOS Ventura (13), Ubuntu 22.04 LTS + validations: + required: true + conditions: + - field: ots_operating_system + any: + - Windows + - macOS + - Linux + + # Other Operating System Specification + + - type: input + id: ots_operating_system_other + attributes: + label: Specify Operating System + description: If you selected 'Other', please specify your OS and version. + placeholder: e.g., FreeBSD 13.0 + validations: + required: true + conditions: + - field: ots_operating_system + equals: Other + + - type: input + id: ots_application_version + attributes: + label: Application Version + description: Enter the version of the OnTheSpot application you are using. + placeholder: e.g., v0.7.0 + validations: + required: true + + - type: dropdown + id: ots_installation_method + attributes: + label: Installation Method + description: How did you install the OnTheSpot application? + options: + - GitHub Release + - Build from Script + validations: + required: true + + - type: input + id: ots_python_version + attributes: + label: Python Version + description: Enter your Python version, check with `python --version` in Terminal. + placeholder: e.g., 3.11.4 + validations: + required: true + + - type: input + id: ots_ffmpeg_version + attributes: + label: FFmpeg Version + description: Enter your FFmpeg version, check with `ffmpeg -version` in Terminal. + placeholder: e.g., 2024-09-05 + validations: + required: true + + - type: textarea + id: ots_additional_info + attributes: + label: Additional Information + description: Add any other context, screenshots, or logs. + placeholder: Include logs, screenshots, or any other relevant details here. + validations: + required: false diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..3491335 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,50 @@ +name-template: 'v$NEXT_PATCH_VERSION' +tag-template: 'v$NEXT_PATCH_VERSION' +version-template: '$MAJOR.$MINOR.$PATCH' + +categories: + - title: '## Features' + labels: + - 'feat' + - 'feature' + - title: '## Bug Fixes' + labels: + - 'fix' + - 'bug' + - title: '## Documentation' + labels: + - 'docs' + - 'documentation' + - title: '## Chores' + labels: + - 'chore' + - 'maintenance' + +change-template: '- $TITLE ([#$NUMBER]($URL)) ([`$SHORT_SHA`]($COMMIT_URL)) by @$AUTHOR' + +autolabeler: + - label: 'feat' + title: '^feat' + - label: 'fix' + title: '^fix' + - label: 'docs' + title: '^docs' + - label: 'chore' + title: '^chore' + +exclude-labels: + - 'duplicate' + - 'invalid' + - 'question' + - 'wontfix' + +template: | + # :sparkles: New Release: v$NEXT_PATCH_VERSION + + Thanks to everyone for their contributions! + + $CHANGES + + **Full Changelog**: [$PREVIOUS_TAG...$NEW_TAG]($COMPARE_URL) + + **Contributors**: $CONTRIBUTORS diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 0000000..0ba830d --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,29 @@ +name: Changelog + +on: + push: + branches: + - main + +jobs: + changelog: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Conventional Changelog Action + id: changelog + uses: TriPSs/conventional-changelog-action@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Release + uses: actions/create-release@v1 + if: ${{ steps.changelog.outputs.skipped == 'false' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.changelog.outputs.tag }} + release_name: ${{ steps.changelog.outputs.tag }} + body: ${{ steps.changelog.outputs.clean_changelog }} diff --git a/.github/workflows/release-builder.yml b/.github/workflows/release-builder.yml new file mode 100644 index 0000000..a35f4b8 --- /dev/null +++ b/.github/workflows/release-builder.yml @@ -0,0 +1,189 @@ +name: Release Builder + +on: + push: + branches: + - main + pull_request: + branches: + - main + release: + types: [published] + +jobs: + # Windows Build + windows-build: + runs-on: windows-latest + outputs: + artifact_path: artifacts/windows/ + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pyinstaller + + - name: Run Windows Build Script + run: scripts\build_windows.bat + shell: cmd + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: windows-build + path: artifacts/windows/ + + # Linux Build + linux-build: + runs-on: ubuntu-latest + outputs: + artifact_path: artifacts/linux/ + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get install -y patchelf fuse libfuse2 + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pyinstaller + + - name: Make Build Script Executable + run: chmod +x scripts/build_linux.sh + + - name: Run Linux Build Script + run: scripts/build_linux.sh + shell: bash + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: linux-build + path: artifacts/linux/ + + # macOS Build + macos-build: + runs-on: macos-latest + outputs: + artifact_path: artifacts/macos/ + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Install Dependencies + run: | + brew install pyinstaller + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install pyinstaller + + - name: Make Build Script Executable + run: chmod +x scripts/build_mac.sh + + - name: Run macOS Build Script + run: scripts/build_mac.sh + shell: bash + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: macos-build + path: artifacts/macos/ + + # Collect Artifacts + collect-artifacts: + name: Collect Artifacts + needs: [windows-build, linux-build, macos-build] + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Download Windows Artifacts + uses: actions/download-artifact@v3 + with: + name: windows-build + path: artifacts/windows/ + + - name: Download Linux Artifacts + uses: actions/download-artifact@v3 + with: + name: linux-build + path: artifacts/linux/ + + - name: Download macOS Artifacts + uses: actions/download-artifact@v3 + with: + name: macos-build + path: artifacts/macos/ + + - name: Upload Combined Artifacts + uses: actions/upload-artifact@v3 + with: + name: OnTheSpot-Builds + path: artifacts/ + + - name: Create Release + if: github.event_name == 'release' + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.event.release.tag_name }} + release_name: ${{ github.event.release.name }} + draft: false + prerelease: false + + - name: Upload Windows Executable to Release + if: github.event_name == 'release' + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: artifacts/windows/onthespot_windows.exe + asset_name: onthespot_windows.exe + asset_content_type: application/octet-stream + + - name: Upload Linux Tar.gz to Release + if: github.event_name == 'release' + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: artifacts/linux/onthespot_linux.tar.gz + asset_name: onthespot_linux.tar.gz + asset_content_type: application/gzip + + - name: Upload Linux AppImage to Release + if: github.event_name == 'release' + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: artifacts/linux/OnTheSpot.AppImage + asset_name: OnTheSpot.AppImage + asset_content_type: application/octet-stream + + - name: Upload macOS DMG to Release + if: github.event_name == 'release' + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: artifacts/macos/OnTheSpot.dmg + asset_name: OnTheSpot.dmg + asset_content_type: application/x-apple-diskimage diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..503336b --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,50 @@ +name: Release Drafter + +on: + push: + tags: + - 'v*.*.*' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '16' + + - name: Install Conventional Changelog CLI + run: | + npm install -g conventional-changelog-cli + + - name: Release Drafter + run: | + conventional-changelog -p angular -i CHANGELOG.md -s -r 0 --config ./changelog-config.js + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Commit and Push Changelog + run: | + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add CHANGELOG.md + git commit -m "docs(changelog): update changelog [skip ci]" + git push origin HEAD:${{ github.ref_name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Release + uses: ncipollo/release-action@v1 + with: + tag: ${{ github.ref_name }} + name: ${{ github.ref_name }} + commit: ${{ github.sha }} + body: | + $(cat CHANGELOG.md) + token: ${{ secrets.GITHUB_TOKEN }} From 6b825447cd3c8f67f2c4fdf78649523597bb2739 Mon Sep 17 00:00:00 2001 From: AmerikanSn1p3r <79807933+V1p3rOne@users.noreply.github.com> Date: Sun, 20 Oct 2024 22:45:04 +0200 Subject: [PATCH 2/4] docs: moved the documentation to root --- docs/contributing.md => CONTRIBUTING.md | 6 ++--- CREDITS.md | 33 ++++++++++++++++++++++++ docs/disclaimer.md => DISCLAIMER.md | 6 ++--- README.md | 20 +++++--------- assets/01_Logo/Cover_Black.png | Bin 9756 -> 9709 bytes assets/01_Logo/Cover_White.png | Bin 9779 -> 9724 bytes docs/credits.md | 15 ----------- 7 files changed, 46 insertions(+), 34 deletions(-) rename docs/contributing.md => CONTRIBUTING.md (90%) create mode 100644 CREDITS.md rename docs/disclaimer.md => DISCLAIMER.md (93%) delete mode 100644 docs/credits.md diff --git a/docs/contributing.md b/CONTRIBUTING.md similarity index 90% rename from docs/contributing.md rename to CONTRIBUTING.md index 3bca845..c75e096 100644 --- a/docs/contributing.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ - - - Logo of OnTheSpot + + + Logo of OnTheSpot
diff --git a/CREDITS.md b/CREDITS.md new file mode 100644 index 0000000..ac5b80b --- /dev/null +++ b/CREDITS.md @@ -0,0 +1,33 @@ +Logo of OnTheSpot + + +
+ +# Thanks and Acknowledgements + +We would like to thank all the contributors who have helped improve this repository. We truly appreciate your time, dedication, and commitment to helping us improve and grow. + +## Contributors + +- **Justin025** [@justin025](https://github.com/justin025/) +- **V1p3rOne** [@V1p3rOne](https://github.com/V1p3rOne) +- **Medmondson** [@medmondson-spot](https://github.com/medmondson-spot) + +## Tools Used + +- [Python](https://www.python.org/) +- [Qt for Python (PyQt/PySide)](https://riverbankcomputing.com/software/pyqt/intro)** +- [PyInstaller](https://www.pyinstaller.org/) +- [FFmpeg](https://ffmpeg.org/) +- [Spotify Developers API](https://developer.spotify.com/) +- [GitHub Actions](https://github.com/features/actions) +- [Linux AppImage](https://appimage.org/) +- [MacOS DMG Creation Tools](https://apple.com) +- [Windows Build Tools](https://learn.microsoft.com/en-us/windows/win32/debug/building-on-the-command-line) + +## Our Community + +Lastly, a big thanks to all our users and community members who have provided feedback, reported bugs, or shared their suggestions for improvement. Your insights and support keep this project moving forward! diff --git a/docs/disclaimer.md b/DISCLAIMER.md similarity index 93% rename from docs/disclaimer.md rename to DISCLAIMER.md index 04763ae..d05ba0b 100644 --- a/docs/disclaimer.md +++ b/DISCLAIMER.md @@ -1,7 +1,7 @@ - - - Logo of OnTheSpot + + + Logo of OnTheSpot
diff --git a/README.md b/README.md index a5ca129..e87e52c 100755 --- a/README.md +++ b/README.md @@ -8,12 +8,9 @@ -
- [![Issues Badge][issues-shield]][issues-url] [![Stars Badge][stars-shield]][stars-url] [![Downloads Badge][downloads-shield]][downloads-url] -[![Commits Badge][commits-shield]][commits-url] [![License Badge][license-shield]][license-url]

@@ -38,9 +35,9 @@ OnTheSpot is a open-source user-friendly music downloader built with Qt and Pyth ### Features -- [**Cross-Platform**](https://www.techopedia.com/definition/17056/cross-platform)
Available for Windows, macOS, and Linux (Including AppImage, PKGBUILD, and eBuild). -- [**High-Quality Downloads**](https://www.whathifi.com/advice/high-resolution-audio-everything-you-need-to-know)
Download music up to 320kbps directly from the source. -- [**Multi-Language Support**](https://phrase.com/blog/posts/multilingual-customer-support/)
Download track and album names translated to your application's language. +- [**Cross Platform**](https://www.techopedia.com/definition/17056/cross-platform)
Available for Windows, MacOS, and Linux (Including AppImage, PKGBUILD, and eBuild). +- [**High Quality Downloads**](https://www.whathifi.com/advice/high-resolution-audio-everything-you-need-to-know)
Download music up to 320kbps directly from the source. +- [**Multi Language Support**](https://phrase.com/blog/posts/multilingual-customer-support/)
Download track and album names translated to your application's language. - [**Comprehensive Content Coverage**](https://thisisglance.com/blog/why-spotify-is-the-outright-best-music-streaming-app)
Supports songs, podcasts, playlists, albums, singles, compilations, and audiobooks. - [**Rich Metadata Embedding**](https://sonosuite.com/en/blog/what-is-music-metadata-and-why-is-important-to-digital-music/)
Automatically embed detailed metadata like artist, album, year, and lyrics. - [**Custom Download Paths**](https://www.microsoft.com/en-us/microsoft-365/business-insights-ideas/resources/11-ideas-for-how-to-organize-digital-files)
Set personalized paths for playlists and episodes for easy organization. @@ -91,17 +88,14 @@ For full details, please read our [**Disclaimer**](docs/disclaimer.md). If you have any questions, concerns, or need assistance feel free to [contact us](mailto:justin026@protonmail.com). -[issues-shield]: https://img.shields.io/github/issues/justin025/onthespot?style=flat&label=Issues&labelColor=003366&color=1DB954 +[issues-shield]: https://img.shields.io/github/issues/justin025/onthespot?style=flat&label=Issues&labelColor=001224&color=1DB954 [issues-url]: https://github.com/justin025/onthespot/issues -[stars-shield]: https://img.shields.io/github/stars/justin025/onthespot?style=flat&label=Stars&labelColor=003366&color=1DB954 +[stars-shield]: https://img.shields.io/github/stars/justin025/onthespot?style=flat&label=Stars&labelColor=001224&color=1DB954 [stars-url]: https://github.com/justin025/onthespot/stargazers -[downloads-shield]: https://img.shields.io/github/downloads/justin025/onthespot/total.svg?style=flat&label=Downloads&labelColor=003366&color=1DB954 +[downloads-shield]: https://img.shields.io/github/downloads/justin025/onthespot/total.svg?style=flat&label=Downloads&labelColor=001224&color=1DB954 [downloads-url]: https://github.com/justin025/onthespot/releases/ - -[commits-shield]: https://img.shields.io/github/commit-activity/m/justin025/onthespot?style=flat&label=Commits&labelColor=003366&color=1DB954 -[commits-url]: https://github.com/justin025/onthespot/commits/main -[license-shield]: https://img.shields.io/github/license/justin025/onthespot?style=flat&label=License&labelColor=003366&color=1DB954 +[license-shield]: https://img.shields.io/github/license/justin025/onthespot?style=flat&label=License&labelColor=001224&color=1DB954 [license-url]: https://github.com/justin025/onthespot/blob/main/LICENSE diff --git a/assets/01_Logo/Cover_Black.png b/assets/01_Logo/Cover_Black.png index 8d67692cc556b49b97268869c3fb1a4c84490136..d3117c9d2b50482d8c9eeb4f0f9d182541ecb19c 100644 GIT binary patch literal 9709 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≈zy)Q`w5)v@v@+JYdNCuAO5G<0) zw6hn_E8u&hsgvDZ*Xwx@+OY+)p)-TswGHOyoK~a_Y3Kh5^lqqqTzx!TP!)R(xSm-5 zyFEIS+xqs)XFg?|{xWo9b@)xwVGp$o%=aO28priTvq%-s?B+XBJ)1{()<(#~Skddp zUjzBqCTe0wNgllb@#)~I(_1TuMVBb5DDR?jKIB6#Q`&>k5|JcBeaS~J9#qdXRah$| z?n}U|X$Lj`(U=rIn#gm`+6CEXNiZWdgS=W0;@>s>$HjB+V|#8f9$Z0s0(u1KT?O1G{aF z!!r>CTS-~#8Wl|R?zLV@HgND$wX9OEYjM<(VcQ}9b$s8qPY_=F@aZ>MLt3b+GZkI` z!<0+*xhg8U9y6K84La650P14vif3p5Erh4X%{jP{((TAy2_0^-y0LPbydf7`b*p+T znvh%{o2RsNGu?okg6_9mhgaDR&CBka%;=v7UNtrIe~4NMu@}EuP%D#k-aIY_OiNFO zOOQ5q%S{Po1=^5wdsjKYR+KZ47Q@F;TsEf9I-~rlwol0|>zyyimg>w)g}|$|u;ETk zuJNOw{x97Q4q$HTv5cIXmk+JvYA*rVyeh^peP^u^0qc)*2Jq09?}zS1f4zDu_>g}u z&Vv`dn?XLTwE7L%`U!*gFQL9iimb5eL&j6(KE^E# zv-T)Il*TqB#qlpu1CzOqTzY&+!&SN8 z7j4t?k`2wc^P13G;0iub%mmgCc)YACIbX0=Y4=;7U0(51{^=Y5eS;IA<}PYxvkEU< zQLK_}Civ4FwguMW=N%Rfv~ZU>Q-1%2j!_*s>|^__XHJ#BAI&#S7M!0|Z4OXUt_5*4 zk^sPG)&4g)pVDt3PXT~k9881(^MdXxk-I;Vy*dq60d61if2mABf;_40zp{t@4couc zA?|-kDWd;3Dwrhkf1>-*pVK2^3E|&{fB;gK|9^*Dmn43HSe07IsGNWQL!RnAseEkv G_WuDi!Vkv) literal 9756 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 diff --git a/assets/01_Logo/Cover_White.png b/assets/01_Logo/Cover_White.png index 357dd25e27fe2dd3f468af2c2a6c62c99a15460d..fc0c276c0461354cf93f8c8afec7e0ae114965e1 100644 GIT binary patch literal 9724 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 diff --git a/docs/credits.md b/docs/credits.md deleted file mode 100644 index 5cbc1cb..0000000 --- a/docs/credits.md +++ /dev/null @@ -1,15 +0,0 @@ - - - - Logo of OnTheSpot - - -
- -# Thanks and Acknowledgements - -We would like to thank all the contributors who have helped improve this repository. We truly appreciate your time, dedication, and commitment to helping us improve and grow. - -* Justin025 [@justin025](https://github.com/justin025/) -* V1p3rOne [@V1p3rOne](https://github.com/V1p3rOne) -* Medmondson [@medmondson-spot](https://github.com/medmondson-spot) From df7866bc73975950079aee7752036b1c5aecb645 Mon Sep 17 00:00:00 2001 From: AmerikanSn1p3r <79807933+V1p3rOne@users.noreply.github.com> Date: Sun, 20 Oct 2024 22:45:20 +0200 Subject: [PATCH 3/4] chore: fixed build scripts --- .github/workflows/release-builder.yml | 10 +-- scripts/{ => user}/build_appimage.sh | 0 scripts/{ => user}/build_linux.sh | 0 scripts/{ => user}/build_mac.sh | 0 scripts/{ => user}/build_windows.bat | 0 scripts/workflow/build_linux.sh | 110 ++++++++++++++++++++++++++ scripts/workflow/build_mac.sh | 69 ++++++++++++++++ scripts/workflow/build_windows.bat | 76 ++++++++++++++++++ 8 files changed, 260 insertions(+), 5 deletions(-) rename scripts/{ => user}/build_appimage.sh (100%) mode change 100755 => 100644 rename scripts/{ => user}/build_linux.sh (100%) mode change 100755 => 100644 rename scripts/{ => user}/build_mac.sh (100%) mode change 100755 => 100644 rename scripts/{ => user}/build_windows.bat (100%) create mode 100644 scripts/workflow/build_linux.sh create mode 100644 scripts/workflow/build_mac.sh create mode 100644 scripts/workflow/build_windows.bat diff --git a/.github/workflows/release-builder.yml b/.github/workflows/release-builder.yml index a35f4b8..ee5996c 100644 --- a/.github/workflows/release-builder.yml +++ b/.github/workflows/release-builder.yml @@ -32,7 +32,7 @@ jobs: pip install pyinstaller - name: Run Windows Build Script - run: scripts\build_windows.bat + run: scripts/workflow/build_windows.bat shell: cmd - name: Upload Artifacts @@ -59,10 +59,10 @@ jobs: pip install pyinstaller - name: Make Build Script Executable - run: chmod +x scripts/build_linux.sh + run: chmod +x scripts/workflow/build_linux.sh - name: Run Linux Build Script - run: scripts/build_linux.sh + run: scripts/workflow/build_linux.sh shell: bash - name: Upload Artifacts @@ -88,10 +88,10 @@ jobs: pip install pyinstaller - name: Make Build Script Executable - run: chmod +x scripts/build_mac.sh + run: chmod +x scripts/workflow/build_mac.sh - name: Run macOS Build Script - run: scripts/build_mac.sh + run: scripts/workflow/build_mac.sh shell: bash - name: Upload Artifacts diff --git a/scripts/build_appimage.sh b/scripts/user/build_appimage.sh old mode 100755 new mode 100644 similarity index 100% rename from scripts/build_appimage.sh rename to scripts/user/build_appimage.sh diff --git a/scripts/build_linux.sh b/scripts/user/build_linux.sh old mode 100755 new mode 100644 similarity index 100% rename from scripts/build_linux.sh rename to scripts/user/build_linux.sh diff --git a/scripts/build_mac.sh b/scripts/user/build_mac.sh old mode 100755 new mode 100644 similarity index 100% rename from scripts/build_mac.sh rename to scripts/user/build_mac.sh diff --git a/scripts/build_windows.bat b/scripts/user/build_windows.bat similarity index 100% rename from scripts/build_windows.bat rename to scripts/user/build_windows.bat diff --git a/scripts/workflow/build_linux.sh b/scripts/workflow/build_linux.sh new file mode 100644 index 0000000..8fb14e2 --- /dev/null +++ b/scripts/workflow/build_linux.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +echo "========= OnTheSpot Linux Build Script =========" + +# Get the directory of the script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Change to the project root directory (parent of scripts directory) +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +cd "$PROJECT_ROOT" + +echo "Current directory: $(pwd)" + +# Clean up previous builds +echo " => Cleaning up!" +rm -f ./dist/onthespot_linux ./dist/onthespot_linux_ffm +rm -f ./dist/onthespot_linux.tar.gz +rm -f ./dist/OnTheSpot.AppImage +rm -rf ./AppDir + +# Check for FFmpeg and set build options +if [ -f "ffbin_nix/ffmpeg" ]; then + echo " => Found 'ffbin_nix' directory and ffmpeg binary. Including FFmpeg in the build." + FFBIN="--add-binary=ffbin_nix/*:onthespot/bin/ffmpeg" + NAME="onthespot_linux_ffm" +else + echo " => FFmpeg binary not found. Building without it." + FFBIN="" + NAME="onthespot_linux" +fi + +# Run PyInstaller +echo " => Running PyInstaller..." +pyinstaller --onefile \ + --hidden-import=zeroconf._utils.ipaddress \ + --hidden-import=zeroconf._handlers.answers \ + --add-data="src/onthespot/gui/qtui/*.ui:onthespot/gui/qtui" \ + --add-data="src/onthespot/resources/icons/*.png:onthespot/resources/icons" \ + --add-data="src/onthespot/resources/themes/*.qss:onthespot/resources/themes" \ + --add-data="src/onthespot/resources/translations/*.qm:onthespot/resources/translations" \ + $FFBIN \ + --paths="src/onthespot" \ + --name="$NAME" \ + --icon="src/onthespot/resources/icons/onthespot.png" \ + src/portable.py + +# Check if the build was successful +if [ -f "./dist/$NAME" ]; then + # Set executable permissions + echo " => Setting executable permissions..." + chmod +x "./dist/$NAME" +else + echo " => Build failed or output file not found." + exit 1 +fi + +# Create .tar.gz archive +echo " => Creating tar.gz archive..." +cd dist +tar -czvf "$NAME.tar.gz" "$NAME" +cd .. + +# Build AppImage +echo " => Building AppImage..." + +# Download linuxdeploy +wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage +chmod +x linuxdeploy-x86_64.AppImage + +# Create AppDir structure +mkdir -p AppDir/usr/bin +cp "dist/$NAME" AppDir/usr/bin/onthespot + +# Copy desktop file and icon +mkdir -p AppDir/usr/share/applications +mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps + +cp src/onthespot/resources/icons/onthespot.png AppDir/usr/share/icons/hicolor/256x256/apps/onthespot.png + +# Create desktop file +cat > AppDir/usr/share/applications/onthespot.desktop < Moving artifacts to artifacts folder..." +mkdir -p artifacts/linux +mv dist/"$NAME.tar.gz" artifacts/linux/ +mv dist/OnTheSpot.AppImage artifacts/linux/ + +# Clean up +rm linuxdeploy-x86_64.AppImage +rm -rf AppDir + +# Clean up unnecessary files +echo " => Cleaning up temporary files..." +rm -rf __pycache__ build *.spec + +echo " => Done!" diff --git a/scripts/workflow/build_mac.sh b/scripts/workflow/build_mac.sh new file mode 100644 index 0000000..7ae494d --- /dev/null +++ b/scripts/workflow/build_mac.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +echo "========= OnTheSpot MacOS Build Script ==========" + +# Get the directory of the script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Change to the project root directory (parent of scripts directory) +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +cd "$PROJECT_ROOT" + +echo "Current directory: $(pwd)" + +# Clean up previous builds +echo " => Cleaning up!" +rm -rf ./dist/OnTheSpot.app +rm -f ./dist/OnTheSpot.dmg + +# Check for FFmpeg binary and set build options +if [ -f "ffbin_mac/ffmpeg" ]; then + echo " => Found 'ffbin_mac' directory and ffmpeg binary. Including FFmpeg in the build." + FFBIN='--add-binary=ffbin_mac/*:onthespot/bin/ffmpeg' +else + echo " => FFmpeg binary not found. Building without it." + FFBIN="" +fi + +# Run PyInstaller to create the app +echo " => Running PyInstaller..." +pyinstaller --windowed \ + --hidden-import=zeroconf._utils.ipaddress \ + --hidden-import=zeroconf._handlers.answers \ + --add-data="src/onthespot/gui/qtui/*.ui:onthespot/gui/qtui" \ + --add-data="src/onthespot/resources/icons/*.png:onthespot/resources/icons" \ + --add-data="src/onthespot/resources/themes/*.qss:onthespot/resources/themes" \ + --add-data="src/onthespot/resources/translations/*.qm:onthespot/resources/translations" \ + $FFBIN \ + --paths="src/onthespot" \ + --name="OnTheSpot" \ + --icon="src/onthespot/resources/icons/onthespot.icns" \ + src/portable.py + +# Check if the build was successful +if [ -d "./dist/OnTheSpot.app" ]; then + # Set executable permissions + echo " => Setting executable permissions..." + chmod +x "./dist/OnTheSpot.app" +else + echo " => Build failed or output app not found." + exit 1 +fi + +# Create .dmg file +echo " => Creating DMG file..." +mkdir -p dist/dmg_contents +cp -R dist/OnTheSpot.app dist/dmg_contents/ +hdiutil create -volname "OnTheSpot" -srcfolder dist/dmg_contents -ov -format UDZO dist/OnTheSpot.dmg +rm -rf dist/dmg_contents + +# Move the DMG to artifacts folder +echo " => Moving DMG to artifacts folder..." +mkdir -p artifacts/macos +mv dist/OnTheSpot.dmg artifacts/macos/ + +# Clean up unnecessary files +echo " => Cleaning up temporary files..." +rm -rf __pycache__ build *.spec + +echo " => Done!" diff --git a/scripts/workflow/build_windows.bat b/scripts/workflow/build_windows.bat new file mode 100644 index 0000000..3da6a77 --- /dev/null +++ b/scripts/workflow/build_windows.bat @@ -0,0 +1,76 @@ +@echo off + +echo ========= OnTheSpot Windows Build Script ========= + +REM Navigate to the root directory if in scripts +set FOLDER_NAME=%cd% +for %%F in ("%cd%") do set FOLDER_NAME=%%~nxF +if /i "%FOLDER_NAME%"=="scripts" ( + echo You are in the scripts folder. Changing to the parent directory... + cd .. +) + +REM Clean up previous builds +echo => Cleaning up previous builds... +del /F /Q dist\* 2>nul + +REM Bundle ffmpeg +echo => Downloading FFmpeg binary... +mkdir build +curl -L https://github.com/GyanD/codexffmpeg/releases/download/7.1/ffmpeg-7.1-essentials_build.zip -o build\ffmpeg.zip || ( + echo Failed to download FFmpeg. Exiting... + exit /b 1 +) + +powershell -Command "Expand-Archive -Path build\ffmpeg.zip -DestinationPath build\ffmpeg" || ( + echo Failed to extract FFmpeg. Exiting... + exit /b 1 +) + +mkdir ffbin_win + +REM Find the extracted FFmpeg directory +set FFMPEG_DIR= +for /d %%D in ("build\ffmpeg\*") do set FFMPEG_DIR=%%D +if defined FFMPEG_DIR ( + copy "%FFMPEG_DIR%\bin\ffmpeg.exe" ffbin_win\ || ( + echo Failed to copy FFmpeg binary. Exiting... + exit /b 1 + ) +) else ( + echo Failed to find extracted FFmpeg directory. Exiting... + exit /b 1 +) + +REM Build with PyInstaller +echo => Building executable with PyInstaller... +pyinstaller --onefile --noconsole --noconfirm ^ + --hidden-import=zeroconf._utils.ipaddress ^ + --hidden-import=zeroconf._handlers.answers ^ + --add-data="src/onthespot/resources/translations/*.qm;onthespot/resources/translations" ^ + --add-data="src/onthespot/resources/themes/*.qss;onthespot/resources/themes" ^ + --add-data="src/onthespot/gui/qtui/*.ui;onthespot/gui/qtui" ^ + --add-data="src/onthespot/resources/icons/*.png;onthespot/resources/icons" ^ + --add-binary="ffbin_win/ffmpeg.exe;onthespot/bin/ffmpeg" ^ + --paths=src/onthespot ^ + --name=onthespot_windows ^ + --icon=src/onthespot/resources/icons/onthespot.png ^ + src\portable.py || ( + echo PyInstaller build failed. Exiting... + exit /b 1 +) + +REM Move the executable to artifacts folder +echo => Moving executable to artifacts folder... +mkdir artifacts +mkdir artifacts\windows +move dist\onthespot_windows.exe artifacts\windows\ + +REM Clean up unnecessary files +echo => Cleaning up temporary files... +del /F /Q *.spec 2>nul +rd /s /q build 2>nul +rd /s /q __pycache__ 2>nul +rd /s /q ffbin_win 2>nul + +echo => Done! From 27d62eb4d51bb235e61851fd6d948f9830664cdd Mon Sep 17 00:00:00 2001 From: AmerikanSn1p3r <79807933+V1p3rOne@users.noreply.github.com> Date: Sun, 20 Oct 2024 22:56:51 +0200 Subject: [PATCH 4/4] docs: fixed some small issues --- CREDITS.md | 10 +++++----- docs/installation.md | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index ac5b80b..b872269 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,7 +1,7 @@ Logo of OnTheSpot + + + Logo of OnTheSpot
@@ -19,7 +19,7 @@ We would like to thank all the contributors who have helped improve this reposit ## Tools Used - [Python](https://www.python.org/) -- [Qt for Python (PyQt/PySide)](https://riverbankcomputing.com/software/pyqt/intro)** +- [Qt for Python (PyQt/PySide)](https://riverbankcomputing.com/software/pyqt/intro) - [PyInstaller](https://www.pyinstaller.org/) - [FFmpeg](https://ffmpeg.org/) - [Spotify Developers API](https://developer.spotify.com/) @@ -30,4 +30,4 @@ We would like to thank all the contributors who have helped improve this reposit ## Our Community -Lastly, a big thanks to all our users and community members who have provided feedback, reported bugs, or shared their suggestions for improvement. Your insights and support keep this project moving forward! +Lastly, a big thanks to all our users and community members who have provided feedback, reported bugs, or shared their suggestions for improvement. Thanks for your help with this project! diff --git a/docs/installation.md b/docs/installation.md index e302cf5..297ae7a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -55,10 +55,10 @@ If you prefer to build OnTheSpot yourself, follow these steps. 2. **Run the Build Script for Your Operating System** - - **Windows**: Open the `scripts` Folder. Double-click [`build_windows.bat`](scripts/build_windows.bat) or run it in Command Prompt. - - **MacOS**: Run [`build_mac.sh`](scripts/build_mac.sh) in Terminal with `./scripts/build_mac.sh`. - - **Linux**: Run [`build_linux.sh`](scripts/build_linux.sh) in Terminal with `./scripts/build_linux.sh`. - - **Linux AppImage**: Run [`build_appimage.sh`](scripts/build_appimage.sh) in Terminal with `./scripts/build_appimage.sh`. + - **Windows**: Open the `scripts` Folder. Double-click [`build_windows.bat`](scripts/workflow/build_windows.bat) or run it in Command Prompt. + - **MacOS**: Run [`build_mac.sh`](scripts/workflow/build_mac.sh) in Terminal with `./scripts/workflow/build_mac.sh`. + - **Linux**: Run [`build_linux.sh`](scripts/workflow/build_linux.sh) in Terminal with `./scripts/workflow/build_linux.sh`. + - **Linux AppImage**: Run [`build_appimage.sh`](scripts/workflow/build_appimage.sh) in Terminal with `./scripts/workflow/build_appimage.sh`. > [!WARNING] > Make sure to run the correct script for your platform to avoid any build failures.