diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf61ced..0a991d7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: image: archlinux:latest steps: - name: Install packages - run: pacman -Syy -q --noconfirm && pacman -S -q --noconfirm git sudo base-devel p7zip nodejs jq asar electron29 libpulse dpkg unzip xdg-utils python rpm-tools + run: pacman -Syy -q --noconfirm && pacman -S -q --noconfirm git sudo base-devel p7zip nodejs jq asar dpkg unzip python rpm-tools glibc icu - name: Checkout uses: actions/checkout@v4 with: @@ -29,10 +29,10 @@ jobs: run: mkdir -p dist - name: Fix permissions for build - run: mkdir /home/build && chgrp nobody /home/build && chmod g+ws /home/build && setfacl -m u::rwx,g::rwx /home/build && setfacl -d --set u::rwx,g::rwx,o::- /home/build && chown nobody . + run: mkdir /home/build && chgrp nobody /home/build && chmod g+ws /home/build && setfacl -m u::rwx,g::rwx /home/build && setfacl -d --set u::rwx,g::rwx,o::- /home/build && chown nobody . && mkdir -p arch && chown nobody arch - name: Make Arch package - run: sudo -u nobody makepkg --log && mv *.pkg.tar.zst dist/ + run: cp PKGBUILD arch && cd arch && sudo -u nobody makepkg -d --log && mv *.pkg.tar.zst ../dist/ && mv ./src/app/yandex-music.asar ../dist/ && mv ./src/app/release_notes.json ../dist/ && cd .. && rm -rf arch - name: Build tarball packages run: bash ./build_tarball.sh -a all && cp tar/* dist/ @@ -43,9 +43,6 @@ jobs: - name: Build RPM packages run: bash ./build_rpm.sh && mv rpm/*.rpm dist - - name: Retrieve Asar and release notes - run: mv ./src/app/yandex-music.asar dist/yandex-music.asar && mv ./src/app/release_notes.json dist/release_notes.json - - name: Upload Arch artifacts uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/update-build-release.yml b/.github/workflows/update-build-release.yml index dc116e1..cf61d50 100644 --- a/.github/workflows/update-build-release.yml +++ b/.github/workflows/update-build-release.yml @@ -18,7 +18,7 @@ jobs: steps: - name: Install dependencies - run: pacman -Syy -q --noconfirm && pacman -S -q --noconfirm git jq nix python python-requests + run: pacman -Syy -q --noconfirm && pacman -S -q --noconfirm git jq nix python python-requests openssl gcc-libs glibc - name: Checkout uses: actions/checkout@v4 @@ -49,6 +49,13 @@ jobs: echo "VERSION=$VERSION" >> $GITHUB_OUTPUT echo "release_name=$release_name" >> $GITHUB_OUTPUT echo "tag_name=$tag_name" >> $GITHUB_OUTPUT + + - name: Tag Repo + uses: rickstaa/action-create-tag@v1 + with: + tag: ${{ steps.version.outputs.tag_name }} + force_push_tag: true + commit_sha: ${{ steps.commit.outputs.commit_long_sha || github.event.head_commit.id}} - name: Outputs id: outputs @@ -63,12 +70,12 @@ jobs: outputs: - commited: ${{ steps.outputs.commited != '' }} - commit_long_sha: ${{ steps.outputs.commit_long_sha }} - commit_name: ${{ steps.outputs.commit_name }} - tag_name: ${{ steps.outputs.tag_name }} - release_name: ${{ steps.outputs.release_name }} - version: ${{ steps.outputs.VERSION }} + commited: ${{ steps.outputs.outputs.commited != '' }} + commit_long_sha: ${{ steps.outputs.outputs.commit_long_sha }} + commit_name: ${{ steps.outputs.outputs.commit_name }} + tag_name: ${{ steps.outputs.outputs.tag_name }} + release_name: ${{ steps.outputs.outputs.release_name }} + version: ${{ steps.outputs.outputs.VERSION }} build: @@ -81,7 +88,7 @@ jobs: upload-release: needs: [build, update_packages] - if: ${{ needs.update_packages.outputs.commited && github.ref_name == 'main' }} + if: ${{ needs.update_packages.outputs.commited && github.ref_name == 'master' }} runs-on: ubuntu-latest steps: - name: Checkout @@ -90,7 +97,7 @@ jobs: ref: ${{ needs.update_packages.outputs.commit_long_sha }} - name: Publish package changes to AUR - uses: KSXGitHub/github-actions-deploy-aur@v2.7.0 + uses: KSXGitHub/github-actions-deploy-aur@v2.7.2 with: pkgname: "yandex-music" pkgbuild: "PKGBUILD" @@ -100,7 +107,7 @@ jobs: commit_email: "loraner123@gmail.com" ssh_private_key: "${{ secrets.AUR_SSH_PRIVATE_KEY }}" commit_message: "${{ needs.update_packages.outputs.commit_name }}" - ssh_keyscan_types: "rsa,dsa,ecdsa,ed25519" + ssh_keyscan_types: "rsa,ecdsa,ed25519" - name: Download artifact uses: actions/download-artifact@v4 @@ -118,14 +125,7 @@ jobs: run: echo "release_html=$(jq -r --arg version "${{ needs.update_packages.outputs.version }}" '.["desktop-release-notes." + $version]' ./dist/release_notes.json)" >> $GITHUB_OUTPUT - run: rm -rf dist/release_notes.json - - - name: Tag Repo - uses: richardsimko/update-tag@v1 - with: - tag_name: ${{ needs.update_packages.outputs.tag_name}} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - + - name: Upload files to a GitHub release uses: ncipollo/release-action@v1.13.0 with: diff --git a/PKGBUILD b/PKGBUILD index d14b988..95826f7 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,20 +1,20 @@ # Maintainer: Andrey Onischenko loraner123@gmail.com pkgname=yandex-music -pkgver="5.0.14" -pkgrel="1" +pkgver=5.18.2 +pkgrel=1 pkgdesc="Yandex Music - Personal recommendations, selections for any occasion and new music" arch=("any") url="https://github.com/cucumber-sp/yandex-music-linux" -license=("custom") -depends=("electron29" "libpulse" "xdg-utils") -makedepends=("p7zip" "nodejs" "asar" "jq" "python") +license=("Unlicense") +depends=("electron29" "libpulse" "xdg-utils" "bash" "hicolor-icon-theme") +makedepends=("p7zip" "nodejs" "asar" "jq" "python" "git") -source=("https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.0.14.exe" "git+https://github.com/cucumber-sp/yandex-music-linux") -sha256sums=("c10c6c4b5d596f9bf490a231d7c13bbd2627109f71c9c57aa4e2b034e31252f4" "SKIP") +source=("https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.18.2.exe" "git+${url}#tag=v${pkgver}") +sha256sums=("a513eb6aa4bd05bae8503f5578a8e91d778794ffe4eb3a450040903570106941" "SKIP") build() { - bash "$srcdir/yandex-music-linux/repack.sh" "$srcdir/Yandex_Music_x64_5.0.14.exe" + bash "$srcdir/yandex-music-linux/repack.sh" "$srcdir/Yandex_Music_x64_5.18.2.exe" } package() { @@ -31,9 +31,10 @@ package() { install -Dm644 "$srcdir/yandex-music-linux/templates/desktop" "$pkgdir/usr/share/applications/yandex-music.desktop" install -Dm644 "$srcdir/yandex-music-linux/templates/default.conf" "$pkgdir/usr/lib/yandex-music/default.conf" - sed -i "s|%electron_path%|/usr/bin/electron29|g" "$pkgdir/usr/lib/yandex-music/default.conf" install -Dm644 "$srcdir/yandex-music-linux/LICENSE.md" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" install -Dm755 "$srcdir/yandex-music-linux/templates/yandex-music.sh" "$pkgdir/usr/bin/yandex-music" + sed -i "s|%electron_path%|/usr/bin/electron29|g" "$pkgdir/usr/bin/yandex-music" + sed -i "s|%asar_path%|/usr/lib/yandex-music/yandex-music.asar|g" "$pkgdir/usr/bin/yandex-music" } diff --git a/README.md b/README.md index 94a4674..89e10e1 100644 --- a/README.md +++ b/README.md @@ -8,16 +8,28 @@ Native YandexMusic client for Linux. Built using repacking of Windows client (El - [Installation](#installation) - [Arch Linux](#arch-linux) - [Debian/Ubuntu](#debianubuntu) + - [RPM-based](#rpm-based) +- [Configuration](#configuration) + - [Configuration file](#configuration-file) + - [Custom Electron binary](#custom-electron-binary) + - [Electron arguments](#electron-arguments) + - [Tray mode](#tray-mode) - [Manual Build](#manual-build) - [Prerequisites](#prerequisites) - [Extract app only](#extract-app-only) - [ASAR archive](#asar-archive) - [Arch Linux](#arch-linux-1) - [Debian/Ubuntu](#debianubuntu-1) + - [RPM-based](#rpm-based-1) - [Run with nix](#run-with-nix) - - [Run with flakes](#run-with-flakes) - - [Run old style](#run-old-style) - - [Install to NixOS](#install-to-nixos) + - [NixOS unstable](#nixos-unstable) + - [Run from unstable channel with flakes](#run-from-unstable-channel-with-flakes) + - [Install from unstable channel](#install-from-unstable-channel) + - [Overriding](#overriding) + - [Built-in module](#built-in-module) + - [Run with flakes](#run-with-flakes) + - [Run old style](#run-old-style) + - [Install to NixOS](#install-to-nixos) ## Screenshots ![image](https://github.com/cucumber-sp/yandex-music-linux/assets/100789522/ab2f69ee-efc4-4a33-8110-131b4c4ff4de) @@ -28,8 +40,6 @@ Native YandexMusic client for Linux. Built using repacking of Windows client (El ### Arch Linux -*** - #### AUR You can obtain the latest version of package from `AUR` using one of the [AUR Helpers](https://wiki.archlinux.org/title/AUR_helpers). Then install it with `yandex-music` as package name. @@ -54,11 +64,18 @@ pacman -U yandex-music--any.pkg.tar.zst ### Debian/Ubuntu -*** - #### APT -Package is currently unavailable at APT. We're still working on it +Download key and add repository to mirror list +```bash +curl -fsSL https://apt.cucumber-space.online/key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/cucumber-space.key.gpg +echo 'deb [signed-by=/etc/apt/keyrings/cucumber-space.key.gpg] https://apt.cucumber-space.online ./' | sudo tee /etc/apt/sources.list.d/cucumber-space.list > /dev/null +sudo apt update +``` +Then you can install app with +```bash +sudo apt install yandex-music +``` #### Binary package file @@ -72,6 +89,67 @@ dpkg -i yandex-music__.deb *** +### RPM-based + +#### DNF + +Package is currently unavailable at DNF. If you'd like to help us with publishing, feel free to open new issue. + +#### Binary package file + +Download prebuilt binary package from [Releases](https://github.com/cucumber-sp/yandex-music-linux/releases) section. +Unfortunatelly, we only provide packages for x64 architecture. If you need package for different architecture, you can build it manually. + +Then you can install it with the following command + +```bash +rpm -i yandex-music--1.x86_64.rpm +``` + +*** + +## Configuration + +### Configuration file + +You can find configuration file at `HOME/.config/yandex-music.conf`. It's a simple `key=value` file that's sourced before launching the app. This means you can set environment variables and other options there. + +*** + +### Custom Electron binary + +You can set path to custom Electron binary with `ELECTRON_CUSTOM_BIN` option. For example: + +```bash +ELECTRON_CUSTOM_BIN=/usr/bin/electron +``` + +*** + +### Electron arguments + +You can set custom Electron flags with `ELECTRON_ARGS` option. By default it's set to `--no-sandbox`. For example: + +```bash +ELECTRON_ARGS="--no-sandbox --trace-warnings" +``` + +*** + +### Tray mode + +Tray mode is disabled by default. It allows program to be minimized to tray instead of closing. To enable it set `TRAY_ENABLED` option to `1`. + +![image](https://github.com/cucumber-sp/yandex-music-linux/assets/100789522/5998ba7f-9ee7-4725-9d51-fbe5510a799d) + +*** + +### Dev tools + +Chromium developer/debug tools can be enabled by setting `DEV_TOOLS` option to `1`. + +*** + ## Manual Build ### Prerequisites @@ -137,12 +215,55 @@ bash build_deb.sh [-a default=x64] *** +### RPM-based + +You can build `.rpm` binary package using the following command: + +```bash +bash build_rpm.sh [-a default=x64] +``` + ## Run with nix The `yandex-music` package has unlicensed license, so you need to have `allowUnfree` option enabled. -### Run with flakes +### NixOS unstable + +The `yandex-music` package is +[available](https://github.com/NixOS/nixpkgs/pull/337425) at nixos-unstable +channel. + +#### Run from unstable channel with flakes + +```bash +nix run github:NixOS/nixpkgs/nixos-unstable#yandex-music +``` + +#### Install from unstable channel + +Add next to your configuration: + +```nix +environment.systemPackages = with pkgs; [ yandex-music ]; +``` + +#### Overriding + +There is several option of package available to override: + +```nix +yandex-music.override { + trayEnabled = true; # Whenether to enable tray support + electronArguments = ""; # Extra arguments to electron executable +} +``` + +### Built-in module + +This repository contains its own nix-related receipts. + +#### Run with flakes Execute next to build and run yandex music directly from github @@ -150,7 +271,7 @@ Execute next to build and run yandex music directly from github nix run github:cucumber-sp/yandex-music-linux ``` -### Run old style +#### Run old style Execute next in this repository to build yandex-music package without using flakes. @@ -159,7 +280,7 @@ flakes. nix-build --expr '(import {}).callPackage ./nix {}' ``` -### Install to NixOS +#### Install to NixOS 1. Add input in your flake.nix @@ -169,27 +290,24 @@ nix-build --expr '(import {}).callPackage ./nix {}' }; ``` -2. Import module in your `configuration.nix` or `home-manager.nix` - +2. Import module in your `configuration.nix`: ```nix imports = [ - yandex-music.nixosModule + yandex-music.nixosModules.default ]; ``` -3. Add package `yandex-music` + or in `home-manager.nix`: + ```nix + imports = [ + yandex-music.homeManagerModules.default + ]; + ``` - For `configuration.nix`: + +3. Enable `yandex-music` ```nix - environment.systemPackages = with pkgs; [ - yandex-music - ]; - ``` - For Home Manager: - - ```nix - home.packages = with pkgs; [ - yandex-music - ]; + programs.yandex-music.enable = true; + programs.yandex-music.tray.enable = true; # to enable tray support ``` diff --git a/build_tarball.sh b/build_tarball.sh index 91b70dc..f9be65e 100644 --- a/build_tarball.sh +++ b/build_tarball.sh @@ -34,14 +34,15 @@ build_tarball(){ install -Dm644 "${TEMPDIR}/app/favicon.png" "${app_dir}/usr/share/pixmaps/yandex-music.png" install -Dm644 "${TEMPDIR}/app/favicon.png" "${app_dir}/usr/share/icons/hicolor/48x48/apps/yandex-music.png" install -Dm644 "${TEMPDIR}/app/favicon.svg" "${app_dir}/usr/share/icons/hicolor/scalable/apps/yandex-music.svg" - + install -Dm644 "./templates/desktop" "${app_dir}/usr/share/applications/yandex-music.desktop" install -Dm644 "./templates/default.conf" "${app_dir}/usr/lib/yandex-music/default.conf" - sed -i "s|%electron_path%|/usr/lib/yandex-music/electron/electron|g" "${app_dir}/usr/lib/yandex-music/default.conf" install -Dm644 "./LICENSE.md" "${app_dir}/usr/share/licenses/yandex-music/LICENSE" mv "${TEMPDIR}/electron-${arch}/" "${app_dir}/usr/lib/yandex-music/electron" install -Dm755 "./templates/yandex-music.sh" "${app_dir}/usr/bin/yandex-music" + sed -i "s|%electron_path%|/usr/lib/yandex-music/electron/electron|g" "${app_dir}/usr/bin/yandex-music" + sed -i "s|%asar_path%|/usr/lib/yandex-music/yandex-music.asar|g" "${app_dir}/usr/bin/yandex-music" cd "${app_dir}" tar -czf "${OUTPUT_DIR}/yandex-music_${version}_${arch}.tar.gz" * @@ -128,4 +129,4 @@ fi if [ ${arm64} -eq 1 ]; then download_electron_binary "arm64" build_tarball "arm64" -fi \ No newline at end of file +fi diff --git a/flake.lock b/flake.lock index 54f2b75..dc9b5c2 100644 --- a/flake.lock +++ b/flake.lock @@ -56,13 +56,13 @@ "ymExe": { "flake": false, "locked": { - "narHash": "sha256-6YOx1r40nBcexbeqmQn5/FkuUaHxRrg4Qn1mEwPVnTs=", + "narHash": "sha256-DtSXyYlViRVFWka3SLVaJjB/r6lgaQEPbCM7uXvmtHI=", "type": "file", - "url": "https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.0.14.exe" + "url": "https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.18.2.exe" }, "original": { "type": "file", - "url": "https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.0.14.exe" + "url": "https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.18.2.exe" } } }, diff --git a/flake.nix b/flake.nix index eb705bf..85ce0f2 100644 --- a/flake.nix +++ b/flake.nix @@ -2,40 +2,38 @@ description = "Native Yandex Music desktop client"; inputs = { - ymExe.url = https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.0.14.exe; + ymExe.url = "https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.18.2.exe"; ymExe.flake = false; }; outputs = { self, ymExe, nixpkgs, flake-utils }: - let - yandex-music-with = pkgs: pkgs.callPackage ./nix { - inherit ymExe; - }; - in - flake-utils.lib.eachDefaultSystem - (system: - let - pkgs = import nixpkgs { inherit system; }; - in - { - packages = rec { - yandex-music = yandex-music-with pkgs; - yandex-music-noflakes = pkgs.callPackage ./nix {}; - default = yandex-music; - }; - } - ) // { - nixosModules = rec { - yandex-music = { - nixpkgs.overlays = [ - (final: prev: { - yandex-music = yandex-music-with prev; - }) - ]; + let + yandex-music-with = pkgs: pkgs.callPackage ./nix { + inherit ymExe; }; - default = yandex-music; - }; + modules = isHm: rec { + yandex-music = { + imports = [ (import ./nix/module.nix { inherit isHm yandex-music-with; }) ]; + }; + default = yandex-music; + }; + in + flake-utils.lib.eachDefaultSystem + (system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + packages = rec { + yandex-music = yandex-music-with pkgs; + yandex-music-noflakes = pkgs.callPackage ./nix { }; + default = yandex-music; + }; + } + ) // { + nixosModules = modules false; + homeManagerModules = modules true; - nixosModule = self.nixosModules.default; - }; + nixosModule = self.nixosModules.default; + }; } diff --git a/nix/default.nix b/nix/default.nix index 95b6638..35363f9 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -10,6 +10,8 @@ , electron , ymExe ? null +, electronArguments ? "" +, trayEnabled ? false }: let version_info = with builtins; fromJSON (readFile ../utility/version_info.json); @@ -32,6 +34,7 @@ stdenvNoCC.mkDerivation utility = ./../utility; icons = ./../icons; desktopItem = ../templates/desktop; + ymScript = ../templates/yandex-music.sh; src = if ymExe != null then ymExe @@ -54,9 +57,17 @@ stdenvNoCC.mkDerivation mkdir -p "$out/share/nodejs" mv app/yandex-music.asar "$out/share/nodejs" - # use makeWrapper on electron binary to make it call our asar package - makeWrapper "${electron}/bin/electron" "$out/bin/yandex-music" \ - --add-flags "$out/share/nodejs/yandex-music.asar" + CONFIG_FILE="$out/share/yandex-music.conf" + echo "TRAY_ENABLED=${if trayEnabled then "1" else "0"}" >> "$CONFIG_FILE" + echo "ELECTRON_ARGS=\"${electronArguments}\"" >> "$CONFIG_FILE" + + + install -Dm755 "$ymScript" "$out/bin/yandex-music" + sed -i "s|%electron_path%|${electron}/bin/electron|g" "$out/bin/yandex-music" + sed -i "s|%asar_path%|$out/share/nodejs/yandex-music.asar|g" "$out/bin/yandex-music" + + wrapProgram "$out/bin/yandex-music" \ + --set-default YANDEX_MUSIC_CONFIG "$CONFIG_FILE" install -Dm644 "./app/favicon.png" "$out/share/pixmaps/yandex-music.png" install -Dm644 "./app/favicon.png" "$out/share/icons/hicolor/48x48/apps/yandex-music.png" diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 0000000..f81c461 --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,53 @@ +{ yandex-music-with +, isHm ? false +}: +{ lib, pkgs, config, ... }: +let + cfg = config.programs.yandex-music; + +in +{ + imports = [{ + nixpkgs.overlays = [ + (final: prev: { + yandex-music = yandex-music-with prev; + }) + ]; + }]; + + options = { + programs.yandex-music = { + enable = lib.mkEnableOption "yandex music application"; + tray.enable = lib.mkEnableOption "tray icon for yandex music application"; + electronArguments = lib.mkOption { + description = "Extra electron arguments"; + example = "--no-sandbox --trace-warnings"; + type = lib.types.str; + default = ""; + }; + package = lib.mkOption { + description = "Finalized package of yandex music application"; + type = lib.types.package; + default = pkgs.yandex-music.override { + trayEnabled = cfg.tray.enable; + electronArguments = cfg.electronArguments; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable ( + if isHm then + { + home.packages = [ + cfg.package + ]; + } + else + { + environment.systemPackages = [ + cfg.package + ]; + } + ); +} diff --git a/patches/0001-Add-package-licence.patch b/patches/0001-Add-package-licence.patch index 13bb32b..88fc6b9 100644 --- a/patches/0001-Add-package-licence.patch +++ b/patches/0001-Add-package-licence.patch @@ -1,10 +1,10 @@ diff --git a/package.json b/package.json --- a/package.json +++ b/package.json -@@ -39,5 +39,6 @@ - "COPYRIGHT": "Яндекс Музыка", - "TRADEMARK": "Яндекс Музыка", - "DEEPLINK_PROTOCOL": "yandexmusic" +@@ -50,5 +50,6 @@ + "kk", + "az" + ] - } + }, + "license": "UNLICENSED" diff --git a/patches/0002-Add-package-icon.patch b/patches/0002-Add-package-icon.patch deleted file mode 100644 index b8d42ba..0000000 --- a/patches/0002-Add-package-icon.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/package.json b/package.json ---- a/package.json -+++ b/package.json -@@ -40,5 +40,9 @@ - "TRADEMARK": "Яндекс Музыка", - "DEEPLINK_PROTOCOL": "yandexmusic" - }, -- "license": "UNLICENSED" -+ "license": "UNLICENSED", -+ "icon": { -+ "48x48": "build/next-desktop/favicon.png", -+ "scalable": "build/next-desktop/favicon.svg" -+ } - } diff --git a/patches/0002-Create-app-tray-icon.patch b/patches/0002-Create-app-tray-icon.patch new file mode 100644 index 0000000..dddb3e6 --- /dev/null +++ b/patches/0002-Create-app-tray-icon.patch @@ -0,0 +1,84 @@ +diff --git a/main/lib/createTray.js b/main/lib/createTray.js +--- a/main/lib/createTray.js ++++ b/main/lib/createTray.js +@@ -0,0 +1,21 @@ ++const { app, Menu, Tray, nativeImage } = require('electron'); ++const path = require('path'); ++ ++function createTray(window) { ++ const iconPath = path.join(__dirname, '../../app/favicon.png'); ++ const tray = new Tray(iconPath); ++ const contextMenu = Menu.buildFromTemplate([ ++ {label: 'Открыть', click: () => window.show()}, ++ {label: 'Закрыть Яндекс Музыку', click: () => app.quit()} ++ ]); ++ tray.setToolTip('Яндекс Музыка'); ++ tray.setContextMenu(contextMenu); ++ ++ tray.on('click', () => { ++ window.show(); ++ }); ++ tray.setIgnoreDoubleClickEvents(true); ++} ++ ++exports.createTray = createTray; ++ + + +diff --git a/main/index.js b/main/index.js +--- a/main/index.js ++++ b/main/index.js +@@ -46,6 +46,9 @@ Logger_js_1.Logger.setupLogger(); + (0, handleDeeplink_js_1.handleDeeplink)(window); + (0, handleMetrikaRequests_js_1.handleMetrikaRequests)(window); + (0, handleCrash_js_1.handleCrash)(); ++ const {createTray} = require('./lib/createTray.js'); ++ const trayEnabled = process.env.TRAY_ENABLED && process.env.TRAY_ENABLED > 0; ++ if (trayEnabled){createTray(window);} + await (0, loadURL_js_1.loadURL)(window); + if (node_os_1.default.platform() === platform_js_1.Platform.WINDOWS) { + (0, customTitleBar_js_1.createCustomTitleBar)(window); + + +diff --git a/main/lib/handlers/handleWindowLifecycleEvents.js b/main/lib/handlers/handleWindowLifecycleEvents.js +--- a/main/lib/handlers/handleWindowLifecycleEvents.js ++++ b/main/lib/handlers/handleWindowLifecycleEvents.js +@@ -31,9 +31,8 @@ const handleWindowLifecycleEvents = (window) => { + state_js_1.state.willQuit = true; + }); + electron_1.app.on('window-all-closed', () => { +- if (node_os_1.default.platform() === platform_js_1.Platform.WINDOWS) { +- electron_1.app.quit(); +- } ++ const trayEnabled = process.env.TRAY_ENABLED && process.env.TRAY_ENABLED > 0; ++ if (!trayEnabled) {electron_1.app.quit();} + }); + electron_1.app.on('browser-window-blur', () => { + setBlurredTime(); +@@ -54,22 +53,11 @@ const handleWindowLifecycleEvents = (window) => { + checkAndUpdateApplicationData(window); + }); + window.on('close', (event) => { +- if (node_os_1.default.platform() !== platform_js_1.Platform.MACOS) { +- return; +- } +- if (state_js_1.state.willQuit) { +- return; +- } ++ const trayEnabled = process.env.TRAY_ENABLED && process.env.TRAY_ENABLED > 0; ++ if (!trayEnabled) {electron_1.app.quit();} ++ if (state_js_1.state.willQuit) {return;} + event.preventDefault(); +- if (window.isFullScreen()) { +- window.once('leave-full-screen', () => { +- (0, createWindow_js_1.toggleWindowVisibility)(window, false); +- }); +- window.setFullScreen(false); +- } +- else { +- (0, createWindow_js_1.toggleWindowVisibility)(window, false); +- } ++ (0, createWindow_js_1.toggleWindowVisibility)(window, false); + }); + const webContents = window.webContents; + webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedUrl) => { diff --git a/patches/0003-Create-app-tray-icon.patch b/patches/0003-Create-app-tray-icon.patch deleted file mode 100644 index 7956999..0000000 --- a/patches/0003-Create-app-tray-icon.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff --git a/main/lib/createTray.js b/main/lib/createTray.js ---- a/main/lib/createTray.js -+++ b/main/lib/createTray.js -@@ -0,0 +1,20 @@ -+const { app, Menu, Tray, nativeImage } = require('electron'); -+const path = require('path'); -+ -+function createTray(window) { -+ const iconPath = path.join(__dirname, '../../build/next-desktop/favicon.png'); -+ const tray = new Tray(iconPath); -+ const contextMenu = Menu.buildFromTemplate([ -+ {label: 'Открыть', click: () => window.show()}, -+ {label: 'Закрыть Яндекс Музыку', click: () => app.quit()} -+ ]); -+ tray.setToolTip('Яндекс Музыка'); -+ tray.setContextMenu(contextMenu); -+ -+ tray.on('click', () => { -+ window.show(); -+ }); -+ tray.setIgnoreDoubleClickEvents(true); -+} -+ -+exports.createTray = createTray; - -diff --git a/main/index.js b/main/index.js ---- a/main/index.js -+++ b/main/index.js -@@ -23,6 +23,7 @@ const handleMetrikaRequests_js_1 = require("./lib/handlers/handleMetrikaRequests - const loadURL_js_1 = require("./lib/loadURL.js"); - const safeRedirects_js_1 = require("./lib/safeRedirects.js"); - const handleWindowSessionEvents_js_1 = require("./lib/handlers/handleWindowSessionEvents.js"); -+const {createTray} = require('./lib/createTray.js'); - (0, handleError_js_1.handleUncaughtException)(); - (0, singleInstance_js_1.checkForSingleInstance)(); - (0, handleDeeplink_js_1.handleDeeplinkOnApplicationStartup)(); -@@ -30,6 +31,7 @@ const handleWindowSessionEvents_js_1 = require("./lib/handlers/handleWindowSessi - await electron_1.app.whenReady(); - (0, menu_js_1.setupMenu)(); - const window = await (0, createWindow_js_1.createWindow)(); -+ createTray(window); - (0, safeRedirects_js_1.safeRedirects)(window); - (0, handleWindowLifecycleEvents_js_1.handleWindowLifecycleEvents)(window); - (0, handleWindowSessionEvents_js_1.handleWindowSessionEvents)(window); diff --git a/patches/0004-Fix-window-resize.patch b/patches/0003-Fix-window-resize.patch similarity index 84% rename from patches/0004-Fix-window-resize.patch rename to patches/0003-Fix-window-resize.patch index c1c9ae1..8ad7409 100644 --- a/patches/0004-Fix-window-resize.patch +++ b/patches/0003-Fix-window-resize.patch @@ -1,7 +1,7 @@ diff --git a/main/lib/createWindow.js b/main/lib/createWindow.js --- a/main/lib/createWindow.js +++ b/main/lib/createWindow.js -@@ -16,8 +16,6 @@ const createWindow = async () => { +@@ -45,8 +45,6 @@ const createWindow = async () => { x: 16, y: 10 }, diff --git a/patches/0004-Dev-Tools-from-config.patch b/patches/0004-Dev-Tools-from-config.patch new file mode 100644 index 0000000..300d14e --- /dev/null +++ b/patches/0004-Dev-Tools-from-config.patch @@ -0,0 +1,14 @@ +diff --git a/main/config.js b/main/config.js +--- a/main/config.js ++++ b/main/config.js +@@ -5,8 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.applyCommonConfig = exports.config = void 0; + const package_json_1 = __importDefault(require("../package.json")); ++const devTools = process.env.DEV_TOOLS && process.env.DEV_TOOLS > 0; + exports.config = { +- enableDevTools: false, ++ enableDevTools: devTools, + enableWebSecurity: true, + enableAutoUpdate: true, + bypassCSP: false, diff --git a/repack.sh b/repack.sh index 7ce5e27..7f0118a 100755 --- a/repack.sh +++ b/repack.sh @@ -67,13 +67,14 @@ curdir="$PWD" cd "$TEMPDIR/app" -# fixing secretKey issue echo "Fixing SecretKey" +echo "Spoofing OS" find "./" -type f \( -name "*.js" -o -name "*.js.map" \) -print0 | while IFS= read -r -d $'\0' file; do # Use 'sed' to perform the replacement in-place - sed -i "s/secretKey:this.secretKey/secretKey:'superSecretKey'/g" "$file" + sed -i "s/a.t.WINDOWS/a.t.LINUX/g" "$file" + sed -i "s/B.LINUX/B.WINDOWS/g" "$file" done -echo "SecretKey replaced" +echo "OS spoofed" # fixing titile echo "Fixing Title" @@ -84,7 +85,7 @@ done echo "Title Fixed" echo "Replacing Icons" -cp -drf "$SCRIPT_DIR/icons/." "./build/next-desktop/" +cp -drf "$SCRIPT_DIR/icons/." "./app/" echo "Replaced Icons" # applying patches @@ -131,8 +132,8 @@ echo "Packing" cd "$curdir" asar pack "$TEMPDIR/app" "$dst/yandex-music.asar" for ext in png svg; do - mv "$TEMPDIR/app/build/next-desktop/favicon.$ext" "$dst" + mv "$TEMPDIR/app/app/favicon.$ext" "$dst" done -python "$SCRIPT_DIR/utility/extract_release_notes.py" "$TEMPDIR/app/build/next-desktop/album.txt" "$dst/release_notes.json" +python "$SCRIPT_DIR/utility/extract_release_notes.py" "$TEMPDIR/app/main/translations/compiled/ru.json" "$dst/release_notes.json" echo "Done" diff --git a/templates/PKGBUILD b/templates/PKGBUILD index c1e56e0..537c2a4 100644 --- a/templates/PKGBUILD +++ b/templates/PKGBUILD @@ -1,16 +1,16 @@ # Maintainer: Andrey Onischenko loraner123@gmail.com pkgname=yandex-music -pkgver="%version%" -pkgrel="%release%" +pkgver=%version% +pkgrel=%release% pkgdesc="Yandex Music - Personal recommendations, selections for any occasion and new music" arch=("any") url="https://github.com/cucumber-sp/yandex-music-linux" -license=("custom") -depends=("electron29" "libpulse" "xdg-utils") -makedepends=("p7zip" "nodejs" "asar" "jq" "python") +license=("Unlicense") +depends=("electron29" "libpulse" "xdg-utils" "bash" "hicolor-icon-theme") +makedepends=("p7zip" "nodejs" "asar" "jq" "python" "git") -source=("%exe_link%" "git+https://github.com/cucumber-sp/yandex-music-linux") +source=("%exe_link%" "git+${url}#tag=v${pkgver}") sha256sums=("%exe_sha256%" "SKIP") build() { @@ -31,9 +31,10 @@ package() { install -Dm644 "$srcdir/yandex-music-linux/templates/desktop" "$pkgdir/usr/share/applications/yandex-music.desktop" install -Dm644 "$srcdir/yandex-music-linux/templates/default.conf" "$pkgdir/usr/lib/yandex-music/default.conf" - sed -i "s|%electron_path%|/usr/bin/electron29|g" "$pkgdir/usr/lib/yandex-music/default.conf" install -Dm644 "$srcdir/yandex-music-linux/LICENSE.md" "$pkgdir/usr/share/licenses/$pkgname/LICENSE" install -Dm755 "$srcdir/yandex-music-linux/templates/yandex-music.sh" "$pkgdir/usr/bin/yandex-music" + sed -i "s|%electron_path%|/usr/bin/electron29|g" "$pkgdir/usr/bin/yandex-music" + sed -i "s|%asar_path%|/usr/lib/yandex-music/yandex-music.asar|g" "$pkgdir/usr/bin/yandex-music" } diff --git a/templates/default.conf b/templates/default.conf index 522dd2a..b875b3a 100644 --- a/templates/default.conf +++ b/templates/default.conf @@ -1,2 +1,4 @@ -ELECTRON_BIN=%electron_path% -ELECTRON_ARGS="--no-sandbox" \ No newline at end of file +ELECTRON_CUSTOM_BIN= +ELECTRON_ARGS="--no-sandbox" +TRAY_ENABLED=0 +DEV_TOOLS=0 \ No newline at end of file diff --git a/templates/desktop b/templates/desktop index ff34882..aefda5f 100644 --- a/templates/desktop +++ b/templates/desktop @@ -9,4 +9,5 @@ Icon=yandex-music Type=Application StartupNotify=true StartupWMClass=YandexMusic +MimeType=x-scheme-handler/yandexmusic Categories=Audio;Music;Player;AudioVideo diff --git a/templates/yandex-music.sh b/templates/yandex-music.sh index 1a1ac59..6c67ded 100644 --- a/templates/yandex-music.sh +++ b/templates/yandex-music.sh @@ -17,12 +17,12 @@ source "$CONFIG_FILE" WAYLAND_FLAGS="" if [ "$XDG_SESSION_TYPE" == "wayland" ]; then - WAYLAND_FLAGS="--enable-features=UseOzonePlatform --ozone-platform=wayland" + WAYLAND_FLAGS="--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --ozone-platform=wayland" fi -if [ -z "$ELECTRON_BIN" ]; then - echo "ELECTRON_BIN is not set" - exit 1 -fi +ELECTRON_BIN=${ELECTRON_CUSTOM_BIN:-%electron_path%} -exec "${ELECTRON_BIN}" /usr/lib/yandex-music/yandex-music.asar "${ELECTRON_ARGS}" "${WAYLAND_FLAGS}" \ No newline at end of file +export TRAY_ENABLED=${TRAY_ENABLED:-0} +export DEV_TOOLS=${DEV_TOOLS:-0} + +exec "${ELECTRON_BIN}" "%asar_path%" $ELECTRON_ARGS $WAYLAND_FLAGS diff --git a/utility/extract_release_notes.py b/utility/extract_release_notes.py index 509d164..b3c8e24 100644 --- a/utility/extract_release_notes.py +++ b/utility/extract_release_notes.py @@ -1,5 +1,5 @@ -import sys import json +import sys if len(sys.argv) < 3: print("Usage: python extract_release_notes.py ") @@ -7,7 +7,8 @@ if len(sys.argv) < 3: file_name = sys.argv[1] save_file_name = sys.argv[2] - + + def build_html(data, first_launch=False): html = "" for i, element in enumerate(data): @@ -16,35 +17,23 @@ def build_html(data, first_launch=False): html += f"

{element['value']}

".replace('\n', '
') continue if element['value'] == '\n': - html += "
" + continue else: html += f"{element['value']}".replace('\n', '
') elif element['type'] == 8: html += f"<{element['value']}>{build_html(element['children'])}" return html + with open(file_name, "r", encoding='utf-8') as file: - full_text = file.read() + translation = json.load(file) notes = {} -position = full_text.find("desktop-release-notes.") -while position != -1: - start_position = position - while full_text[position] != '"': - position += 1 - name = full_text[start_position:position] - position += 2 - start_position = position - braces_count = 1 - while braces_count > 0: - position += 1 - if full_text[position] == '{' or full_text[position] == '[': - braces_count += 1 - elif full_text[position] == '}' or full_text[position] == ']': - braces_count -= 1 - data = full_text[start_position:position + 1] - notes[name] = build_html(json.loads(data), True) - position = full_text.find("desktop-release-notes.", position) +element_key: str +for element_key in translation.keys(): + if not element_key.startswith("desktop-release-notes."): + continue + notes[element_key] = build_html(translation[element_key], True) with open(save_file_name, "w", encoding='utf-8') as file: - file.write(json.dumps(notes, ensure_ascii=False, indent=4)) \ No newline at end of file + file.write(json.dumps(notes, ensure_ascii=False, indent=4)) diff --git a/utility/generate_packages.py b/utility/generate_packages.py index 95343dc..429cc77 100644 --- a/utility/generate_packages.py +++ b/utility/generate_packages.py @@ -3,12 +3,14 @@ import os import shutil import subprocess + def check_dependency(dependency): if shutil.which(dependency): return True print(f"{dependency} not installed.") return False + script_dir = os.path.dirname(os.path.realpath(__file__)) # loading versions information from json @@ -16,6 +18,7 @@ version_info_path = os.path.join(script_dir, "version_info.json") with open(version_info_path, "r") as f: version_info = json.load(f) + # Arch def generate_arch(): pkgbuild_template = os.path.join(script_dir, "../templates/PKGBUILD") @@ -35,14 +38,16 @@ def generate_arch(): # Nix - + def is_nix_version_2_19(): version = subprocess.run(["nix", "--version"], capture_output=True, text=True).stdout.split()[2] + print(f"Nix version: {version}") major, minor, _ = map(int, version.split(".")) if major > 2 or (minor >= 19 and major == 2): return True return False + def generate_nix(): nixcmd = "nix --extra-experimental-features nix-command --extra-experimental-features flakes" flake_path = os.path.join(script_dir, "../flake.nix") @@ -52,14 +57,14 @@ def generate_nix(): flake = f.read() _start_index = flake.find("ymExe.url = ") _end_index = flake.find(";", _start_index) - flake = flake.replace(flake[_start_index:_end_index+1], f'ymExe.url = {version_info["ym"]["exe_link"]};') + flake = flake.replace(flake[_start_index:_end_index + 1], f'ymExe.url = "{version_info["ym"]["exe_link"]}";') with open(flake_path, "w") as f: f.write(flake) if not check_dependency("nix"): print("flake.nix was updated, but nix is not installed to update flake.lock") return - + if is_nix_version_2_19(): subprocess.run(f"{nixcmd} flake update ymExe", shell=True) else: @@ -70,4 +75,4 @@ def generate_nix(): generate_arch() -generate_nix() \ No newline at end of file +generate_nix() diff --git a/utility/update_version.py b/utility/update_version.py index 4148cbb..e3fb4bb 100644 --- a/utility/update_version.py +++ b/utility/update_version.py @@ -4,6 +4,7 @@ import json import os import shutil import tempfile + import requests YM_VERSIONS_URL = "https://music-desktop-application.s3.yandex.net/stable/download.json" @@ -13,17 +14,21 @@ ELECTRON_DOWNLOAD_URL = "https://github.com/electron/electron/releases/download/ script_dir = os.path.dirname(os.path.realpath(__file__)) tempdir = tempfile.mkdtemp() + def clear(): shutil.rmtree(tempdir) + atexit.register(clear) + def assert_dependency(dependency): if shutil.which(dependency): return print(f"{dependency} not installed.") exit(1) + # loading versions json versions_obj = requests.get(YM_VERSIONS_URL).json() exe_link = versions_obj["windows"] @@ -74,4 +79,4 @@ version_file = os.path.join(script_dir, "version_info.json") with open(version_file, "w") as f: f.write(json.dumps(version_info, indent=4)) -print(f"Version info written to {version_file}") \ No newline at end of file +print(f"Version info written to {version_file}") diff --git a/utility/version_info.json b/utility/version_info.json index aadbd85..961a6d0 100644 --- a/utility/version_info.json +++ b/utility/version_info.json @@ -1,14 +1,14 @@ { "ym": { - "version": "5.0.14", - "exe_name": "Yandex_Music_x64_5.0.14.exe", - "exe_link": "https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.0.14.exe", - "exe_sha256": "c10c6c4b5d596f9bf490a231d7c13bbd2627109f71c9c57aa4e2b034e31252f4" + "version": "5.18.2", + "exe_name": "Yandex_Music_x64_5.18.2.exe", + "exe_link": "https://music-desktop-application.s3.yandex.net/stable/Yandex_Music_x64_5.18.2.exe", + "exe_sha256": "a513eb6aa4bd05bae8503f5578a8e91d778794ffe4eb3a450040903570106941" }, "electron": { - "version": "29.1.1", - "x64": "https://github.com/electron/electron/releases/download/v29.1.1/electron-v29.1.1-linux-x64.zip", - "armv7l": "https://github.com/electron/electron/releases/download/v29.1.1/electron-v29.1.1-linux-armv7l.zip", - "arm64": "https://github.com/electron/electron/releases/download/v29.1.1/electron-v29.1.1-linux-arm64.zip" + "version": "29.4.6", + "x64": "https://github.com/electron/electron/releases/download/v29.4.6/electron-v29.4.6-linux-x64.zip", + "armv7l": "https://github.com/electron/electron/releases/download/v29.4.6/electron-v29.4.6-linux-armv7l.zip", + "arm64": "https://github.com/electron/electron/releases/download/v29.4.6/electron-v29.4.6-linux-arm64.zip" } } \ No newline at end of file