23 Commits

Author SHA1 Message Date
0db9b6a795 Archival Notice 2025-01-17 14:40:36 -06:00
3b8e27d9a4 Bump rust version to 1.79 to support absolute paths feature [stabilized] 2025-01-17 14:35:13 -06:00
31b5e6ee8b Setup basic parsing, 'proper' implementation 2025-01-17 14:10:34 -06:00
20c863e660 Use keep-a-changelog style for CHANGELOG.md 2024-10-08 15:31:04 -05:00
0d0fe8a9e5 Use GH_RELEASE_TOKEN for build 'Release' step 2024-10-08 00:06:01 -05:00
3fb288f404 Updated changelog 2024-10-07 15:12:15 -05:00
8e33506f61 Improve paths-ignore, disable paths-ignore for build 'push' trigger 2024-10-07 15:04:39 -05:00
48b0101dab Disable hooks from changing repository language statistics 2024-10-07 15:00:46 -05:00
f583dac944 Update version to v0.1.6 2024-10-07 14:49:17 -05:00
dbfad44a51 Add schedule for workflow test 2024-10-07 14:43:02 -05:00
a636c6301a Mark TODO for pre-commit hook 2024-10-07 14:42:50 -05:00
30d135a4dc rename other workflows to lowercase 2024-10-07 14:32:22 -05:00
62fb74a153 Add testing badge, update changelog 2024-10-07 14:28:02 -05:00
c3e15fd9a5 Disable workflow_dispatch fail_fast input 2024-10-07 14:27:51 -05:00
0cc92b8978 Add optional artifact step for ubuntu build, fix fail_fast evaluation for non-dispatch 2024-10-07 14:25:15 -05:00
2e15d81dc9 Remove x86_64-unknown-linux-musl target runner detail, use defaults 2024-10-07 14:12:25 -05:00
28faf71583 Fix typo in name, simplify fail-fast evaluation 2024-10-07 14:12:06 -05:00
9ef2aac601 Add testing workflow (every push) 2024-10-07 13:59:33 -05:00
7e7af5920b lowercase the build workflow name 2024-10-07 13:52:13 -05:00
978b0ab264 Add CHANGELOG.md 2024-10-07 13:44:00 -05:00
a4568b2e72 Update README.md 2024-10-07 13:38:56 -05:00
7eaea3e2f4 Switch build pipeline to MSRV 1.74 2024-10-07 13:38:47 -05:00
22606aad30 Fix pre-commit.sh hook 2024-10-07 13:28:47 -05:00
13 changed files with 402 additions and 95 deletions

View File

@@ -1,6 +1,3 @@
[target.x86_64-unknown-linux-musl]
runner = "musl-gcc"
[profile.release] [profile.release]
opt-level = "z" opt-level = "z"
strip = true strip = true

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
.hooks/*.sh linguist-vendored

View File

@@ -1,4 +1,4 @@
name: Build name: build
permissions: permissions:
contents: write contents: write
@@ -7,27 +7,29 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
fail_fast: fail_fast:
description: 'Fail fast strategy' description: "Use fail-fast strategy"
required: false required: false
default: 'true' default: "true"
verbose: verbose:
description: 'Verbose output' description: "Verbose output"
required: false required: false
default: 'false' default: "false"
push: push:
tags: tags:
- 'v*.*.*' - "v*.*.*"
paths-ignore: # We don't filter by paths here, because we filter by tags, which means we're releasing. All releases should be built.
- README.md
- .gitignore
- LICENSE
- run.sh
pull_request: pull_request:
paths-ignore: paths-ignore:
- .hooks/**
- CARGO_README.md
- README.md - README.md
- CHANGELOG.md
- INTEGRATION.md
- .gitignore - .gitignore
- LICENSE - .gitattributes
- LICENSE*
- run.sh - run.sh
- run.ps1
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
@@ -72,7 +74,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
with: with:
toolchain: stable toolchain: 1.79
targets: ${{ matrix.target }} targets: ${{ matrix.target }}
- name: Cache Rust dependencies - name: Cache Rust dependencies
@@ -180,6 +182,7 @@ jobs:
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
with: with:
token: ${{ secrets.GH_RELEASE_TOKEN }}
files: | files: |
${{ env.ARCHIVE_DIR }}/${{ env.ARCHIVE }} ${{ env.ARCHIVE_DIR }}/${{ env.ARCHIVE }}
${{ env.ARCHIVE_DIR }}/${{ env.ARCHIVE }}.sig ${{ env.ARCHIVE_DIR }}/${{ env.ARCHIVE }}.sig

View File

@@ -1,4 +1,4 @@
name: Integration name: integration
on: on:
workflow_dispatch: workflow_dispatch:

View File

@@ -1,4 +1,4 @@
name: GitHub Pages name: github-pages
permissions: permissions:
pages: write pages: write

98
.github/workflows/test.yaml vendored Normal file
View File

@@ -0,0 +1,98 @@
name: test
on:
workflow_dispatch:
push:
paths-ignore:
- .hooks/**
- CARGO_README.md
- README.md
- CHANGELOG.md
- INTEGRATION.md
- .gitignore
- .gitattributes
- LICENSE*
- run.sh
- run.ps1
pull_request:
paths-ignore:
- .hooks/**
- CARGO_README.md
- README.md
- CHANGELOG.md
- INTEGRATION.md
- .gitignore
- .gitattributes
- LICENSE*
- run.sh
- run.ps1
schedule:
- cron: "30 14 * * 1" # every Monday, 9:30 AM CDT
env:
CARGO_TERM_COLOR: always
jobs:
build:
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
tools: musl-tools
artifact: true
- os: macos-13
target: x86_64-apple-darwin
# - os: macos-latest
# target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
name: test-${{ matrix.os }}-${{ matrix.target }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.79
targets: ${{ matrix.target }}
- name: Install Linker Tools
if: matrix.tools
run: |
sudo apt-get update
sudo apt-get install ${{ matrix.tools }}
# ensure has a newline at the end
[ "$(tail -c 1 .cargo/config.toml)" != "" ] && echo >> .cargo/config.toml
cat .cargo/config.github.toml >> .cargo/config.toml
- name: Cache Rust dependencies
uses: actions/cache@v4.0.2
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git
target
key: testing-${{ runner.os }}-${{ matrix.target }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
testing-${{ runner.os }}-${{ matrix.target }}-
testing-${{ runner.os }}-
- name: Run tests
run: cargo test --verbose --target ${{ matrix.target }}
- name: Build
if: matrix.artifact
run: cargo build --verbose --target ${{ matrix.target }}
- name: Upload Artifact
if: matrix.artifact
uses: actions/upload-artifact@v4
with:
name: spotify-quickauth-${{ github.sha }}-${{ matrix.target }}
path: target/${{ matrix.target }}/debug/spotify-quickauth

View File

@@ -1,7 +1,10 @@
#!/bin/sh #!/bin/sh
# Remove all lines starting with >[! from CARGO_README.md # TODO: Only run when README.md is modified
sed -i '/^>\[!/d' CARGO_README.md # TODO: Support partial staging, where the 'Staged' version is copied to CARGO_README.md, and then `sed` is ran.
# Remove markdown extension lines for Cargo publishing
sed '/^>\[!/d' README.md > CARGO_README.md
# Add the modified file to the commit # Add the modified file to the commit
git add CARGO_README.md git add CARGO_README.md

View File

@@ -1,8 +1,20 @@
> [!IMPORTANT]
> This application is not 'real'; I mostly created it to learn about building a CLI application in Rust with high-end CI/CD pipelines and easy to execute multi-platform scripts.
> Interestingly enough, I never really developed the program itself, just the scripts and the CI/CD pipeline.
> And by the time I was ready to write it, the `spotify-player` project had already solved the [primary issue](https://github.com/aome510/spotify-player/issues/201#issuecomment-2439565162) I was trying to address.
> Thus, I'm archiving this project, as it's no longer necessary.
>
> This project is still pretty cool though in it's own right, with multi-platform ephemeral binaries over `curl` commands, Windows support, Linux MUSL targets (smaller binaries), ARM64 MacOS support, binary deployment to GitHub pages, automatic GitHub release uploads, and a pretty decent README - this project has it all.
# spotify-quickauth # spotify-quickauth
[![Build Status](https://github.com/Xevion/spotify-quickauth/workflows/Build/badge.svg)](https://github.com/Xevion/spotify-quickauth/actions) [![Build Status](https://github.com/Xevion/spotify-quickauth/workflows/build/badge.svg)](https://github.com/Xevion/spotify-quickauth/actions)
[![Testing Status](https://github.com/Xevion/spotify-quickauth/workflows/test/badge.svg)](https://github.com/Xevion/spotify-quickauth/actions)
[![Crates.io](https://img.shields.io/crates/v/spotify-quickauth.svg)](https://crates.io/crates/spotify-quickauth) [![Crates.io](https://img.shields.io/crates/v/spotify-quickauth.svg)](https://crates.io/crates/spotify-quickauth)
![Crates.io MSRV](https://img.shields.io/crates/msrv/spotify-quickauth)
![GitHub last commit](https://img.shields.io/github/last-commit/Xevion/spotify-quickauth)
<!-- TODO: Add testing status badge -->
A simple CLI-based application for creating a `credentials.json` file, used by `librespot` derived applications, such as [spotify-player][spotify-player], [spotifyd][spotifyd], and [raspotify][raspotify]. A simple CLI-based application for creating a `credentials.json` file, used by `librespot` derived applications, such as [spotify-player][spotify-player], [spotifyd][spotifyd], and [raspotify][raspotify].
@@ -10,8 +22,6 @@ A simple CLI-based application for creating a `credentials.json` file, used by `
- Automatically places configuration files - Automatically places configuration files
- No dependencies, no installation, no fuss - No dependencies, no installation, no fuss
>This README is literally filled with lies. I'm not joking, I've just typed up a bunch of features I plan to implement, and am planning them out now. A fair amount of it works, but most of the specific options aren't currently implemented. I'm working on it, I promise!
## Quickstart ## Quickstart
You can run this application without installing anything by using the following commands. You can run this application without installing anything by using the following commands.
@@ -22,6 +32,7 @@ curl -sSL https://xevion.github.io/spotify-quickauth/run.sh | sh -s --
The default invocation is likely fine for most users, it will try to understand the available paths for `credentials.json` to be written to, and allow you to select them. The default invocation is likely fine for most users, it will try to understand the available paths for `credentials.json` to be written to, and allow you to select them.
> [!NOTE]
> Automatic detection is dependent on the related software being installed and/or relevant configuration files being present. > Automatic detection is dependent on the related software being installed and/or relevant configuration files being present.
For **Windows**, you can paste this command into PowerShell: For **Windows**, you can paste this command into PowerShell:
@@ -34,6 +45,7 @@ iex (irm "https://xevion.github.io/spotify-quickauth/run.ps1")
This application is dead simple to use. Just run the command, and it'll tell you to connect to a fake 'device' in your Spotify interface. This application is dead simple to use. Just run the command, and it'll tell you to connect to a fake 'device' in your Spotify interface.
> [!NOTE]
> You must be connected to the same network running `spotify-quickauth`, as the `zeroconf` technology **does not work** across **networks** nor **proxies**. > You must be connected to the same network running `spotify-quickauth`, as the `zeroconf` technology **does not work** across **networks** nor **proxies**.
Once you connect, the credentials file will be created, and you'll be prompted to select which location(s) to place it in. Even if none of the relevant `librespot` applications are detected or installed, you can specify manual locations, or the current working directory. Once you connect, the credentials file will be created, and you'll be prompted to select which location(s) to place it in. Even if none of the relevant `librespot` applications are detected or installed, you can specify manual locations, or the current working directory.
@@ -42,14 +54,15 @@ Once you connect, the credentials file will be created, and you'll be prompted t
Installation is not necessary to use this application, but if you're having trouble, want to compile it yourself, or are using it frequently, you might want to install it. Installation is not necessary to use this application, but if you're having trouble, want to compile it yourself, or are using it frequently, you might want to install it.
>The scripts above can be given the `-K` or `--keep` flag to keep the downloaded binary. This will prevent repeated API calls to GitHub if you're using the script frequently within a short period. > [!NOTE]
> The scripts above can be given the `-K` or `--keep` flag to keep the downloaded binary. This will prevent repeated API calls to GitHub if you're using the script frequently within a short period.
### Pre-built Binaries ### Pre-built Binaries
Binaries are always available for download from the [releases page][releases], and they're the same ones used by the shell scripts above. Binaries are always available for download from the [releases page][latestRelease], and they're the same ones used by the shell scripts above.
Currently, the following targets are available for download: Currently, the following targets are available for download:
- x64 Linux (MUSL) `x86_64-unknown-linux-musl` - x64 Linux (MUSL) `x86_64-unknown-linux-musl`
- ARM64 Linux (MUSL) `aarch64-unknown-linux-musl` - ARM64 Linux (MUSL) `aarch64-unknown-linux-musl`
- ARMv7 Linux `armv7-unknown-linux-musleabihf` - ARMv7 Linux `armv7-unknown-linux-musleabihf`
@@ -58,14 +71,33 @@ Currently, the following targets are available for download:
- x64 Windows `x86_64-pc-windows-msvc` - x64 Windows `x86_64-pc-windows-msvc`
- ARM64 Windows `aarch64-pc-windows-msvc` - ARM64 Windows `aarch64-pc-windows-msvc`
Please [file an issue][new-issue] if you are on a platform that is not supported, or if you encounter issues with the binaries.
### Via `cargo-binstall`
> [!NOTE]
> If the package cannot be found for your target or fails to be downloaded for any reason, `cargo-binstall` will automatically fall back to building the package from source.
`cargo-binstall` is a tool that allows you to install binaries from crates.io without needing to compile them yourself.
```
cargo binstall spotify-quickauth
```
If you're curious where the binary comes from, `cargo-binstall` will likely pull the binary directly from the [latest release][latestRelease] by this repository, selecting the most appropriate target for your host.
### Manual Installation
If you'd like to use the shell script above to install the binary, you can use the `-S/--stop` flag to prevent the script from running the binary after downloading it. It implicitly applies the `--keep` flag too. If you'd like to use the shell script above to install the binary, you can use the `-S/--stop` flag to prevent the script from running the binary after downloading it. It implicitly applies the `--keep` flag too.
You'll need to move the binary yourself though:
```bash ```bash
curl -sSL https://xevion.github.io/spotify-quickauth/run.sh | sh -s -- -S curl -sSL https://xevion.github.io/spotify-quickauth/run.sh | sh -s -- -S
mv spotify-quickauth /usr/local/bin mv spotify-quickauth /usr/local/bin
``` ```
Then you can move it to whatever location you'd like. Make sure that directory is in your $PATH though! Make sure your directory of choice is in your $PATH though!
### Building from Source ### Building from Source
@@ -82,9 +114,11 @@ spotify-quickauth --help
``` ```
If you have any troubles building the project If you have any troubles building the project
- Make sure you're using a target that's supported by the project (see above). - Make sure you're using a target that's supported by the project (see above).
- Certain targets may require specfic linkers. For example, - Certain targets may require specfic linkers. For example,
[latestRelease]: https://github.com/Xevion/spotify-quickauth/releases/latest/
[spotify-player]: https://github.com/aome510/spotify-player [spotify-player]: https://github.com/aome510/spotify-player
[spotifyd]: https://github.com/Spotifyd/spotifyd [spotifyd]: https://github.com/Spotifyd/spotifyd
[raspotify]: https://github.com/dtcooper/raspotify [raspotify]: https://github.com/dtcooper/raspotify
@@ -92,3 +126,5 @@ If you have any troubles building the project
[git]: https://git-scm.com [git]: https://git-scm.com
[binstall]: https://github.com/cargo-bins/cargo-binstall [binstall]: https://github.com/cargo-bins/cargo-binstall
[quickinstall]: https://github.com/cargo-bins/cargo-quickinstall [quickinstall]: https://github.com/cargo-bins/cargo-quickinstall
[binstall-installation]: https://github.com/cargo-bins/cargo-binstall#installation
[new-issue]: https://github.com/Xevion/spotify-quickauth/issues/new

37
CHANGELOG.md Normal file
View File

@@ -0,0 +1,37 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## v0.1.7
### Added
- Archival notice.
### Changed
- Bumped MSRV to 1.79 to access stabilized `std::path::absolute`
- Adjusted `github-linguist` statistics, ignoring `.hooks`
- Widened `paths-ignore` for `build` and `test` workflows.
- Switched release step token to use `secrets.GH_RELEASE_TOKEN`, so the author is bound to `Xevion` instead of `github-actions` (a bot).
- Switched changelog format to `keep-a-changelog` style.
### Removed
- Removed `paths-ignore` for `build` workflow on `push` trigger.
## v0.1.6
### Added
- Began tracking changes in the `CHANGELOG.md` file.
- Added testing workflow to the repository, targeting only major x64 platforms.
- Added testing badge to README
### Changed
- [breaking] Lowered MSRV to 1.74 to match `librespot`'s `0.5.0-dev` branch.
- Fixed `pre-commit` hook to properly process the `CARGO_README.md` file.

2
Cargo.lock generated
View File

@@ -1287,7 +1287,7 @@ dependencies = [
[[package]] [[package]]
name = "spotify-quickauth" name = "spotify-quickauth"
version = "0.1.5" version = "0.1.7"
dependencies = [ dependencies = [
"env_logger", "env_logger",
"futures", "futures",

View File

@@ -1,9 +1,9 @@
[package] [package]
name = "spotify-quickauth" name = "spotify-quickauth"
version = "0.1.5" version = "0.1.7"
edition = "2021" edition = "2021"
description = "Quickly authenticate librespot-based applications with Spotify" description = "Quickly authenticate librespot-based applications with Spotify"
rust-version = "1.81" rust-version = "1.79"
authors = ["Ryan Walters <xevion@xevion.dev>"] authors = ["Ryan Walters <xevion@xevion.dev>"]
homepage = "https://github.com/Xevion/spotify-quickauth" homepage = "https://github.com/Xevion/spotify-quickauth"
repository = "https://github.com/Xevion/spotify-quickauth" repository = "https://github.com/Xevion/spotify-quickauth"

View File

@@ -1,12 +1,20 @@
> [!IMPORTANT]
> This application is not 'real'; I mostly created it to learn about building a CLI application in Rust with high-end CI/CD pipelines and easy to execute multi-platform scripts.
> Interestingly enough, I never really developed the program itself, just the scripts and the CI/CD pipeline.
> And by the time I was ready to write it, the `spotify-player` project had already solved the [primary issue](https://github.com/aome510/spotify-player/issues/201#issuecomment-2439565162) I was trying to address.
> Thus, I'm archiving this project, as it's no longer necessary.
>
> This project is still pretty cool though in it's own right, with multi-platform ephemeral binaries over `curl` commands, Windows support, Linux MUSL targets (smaller binaries), ARM64 MacOS support, binary deployment to GitHub pages, automatic GitHub release uploads, and a pretty decent README - this project has it all.
# spotify-quickauth # spotify-quickauth
[![Build Status](https://github.com/Xevion/spotify-quickauth/workflows/Build/badge.svg)](https://github.com/Xevion/spotify-quickauth/actions) [![Build Status](https://github.com/Xevion/spotify-quickauth/workflows/build/badge.svg)](https://github.com/Xevion/spotify-quickauth/actions)
<!-- TODO: Add testing status badge --> [![Testing Status](https://github.com/Xevion/spotify-quickauth/workflows/test/badge.svg)](https://github.com/Xevion/spotify-quickauth/actions)
[![Crates.io](https://img.shields.io/crates/v/spotify-quickauth.svg)](https://crates.io/crates/spotify-quickauth) [![Crates.io](https://img.shields.io/crates/v/spotify-quickauth.svg)](https://crates.io/crates/spotify-quickauth)
![Crates.io MSRV](https://img.shields.io/crates/msrv/spotify-quickauth) ![Crates.io MSRV](https://img.shields.io/crates/msrv/spotify-quickauth)
![GitHub last commit](https://img.shields.io/github/last-commit/Xevion/spotify-quickauth) ![GitHub last commit](https://img.shields.io/github/last-commit/Xevion/spotify-quickauth)
<!-- TODO: Add testing status badge -->
A simple CLI-based application for creating a `credentials.json` file, used by `librespot` derived applications, such as [spotify-player][spotify-player], [spotifyd][spotifyd], and [raspotify][raspotify]. A simple CLI-based application for creating a `credentials.json` file, used by `librespot` derived applications, such as [spotify-player][spotify-player], [spotifyd][spotifyd], and [raspotify][raspotify].
@@ -14,9 +22,6 @@ A simple CLI-based application for creating a `credentials.json` file, used by `
- Automatically places configuration files - Automatically places configuration files
- No dependencies, no installation, no fuss - No dependencies, no installation, no fuss
>[!WARNING]
>This README is literally filled with lies. I'm not joking, I've just typed up a bunch of features I plan to implement, and am planning them out now. A fair amount of it works, but most of the specific options aren't currently implemented. I'm working on it, I promise!
## Quickstart ## Quickstart
You can run this application without installing anything by using the following commands. You can run this application without installing anything by using the following commands.
@@ -27,7 +32,7 @@ curl -sSL https://xevion.github.io/spotify-quickauth/run.sh | sh -s --
The default invocation is likely fine for most users, it will try to understand the available paths for `credentials.json` to be written to, and allow you to select them. The default invocation is likely fine for most users, it will try to understand the available paths for `credentials.json` to be written to, and allow you to select them.
>[!NOTE] > [!NOTE]
> Automatic detection is dependent on the related software being installed and/or relevant configuration files being present. > Automatic detection is dependent on the related software being installed and/or relevant configuration files being present.
For **Windows**, you can paste this command into PowerShell: For **Windows**, you can paste this command into PowerShell:
@@ -40,7 +45,7 @@ iex (irm "https://xevion.github.io/spotify-quickauth/run.ps1")
This application is dead simple to use. Just run the command, and it'll tell you to connect to a fake 'device' in your Spotify interface. This application is dead simple to use. Just run the command, and it'll tell you to connect to a fake 'device' in your Spotify interface.
>[!NOTE] > [!NOTE]
> You must be connected to the same network running `spotify-quickauth`, as the `zeroconf` technology **does not work** across **networks** nor **proxies**. > You must be connected to the same network running `spotify-quickauth`, as the `zeroconf` technology **does not work** across **networks** nor **proxies**.
Once you connect, the credentials file will be created, and you'll be prompted to select which location(s) to place it in. Even if none of the relevant `librespot` applications are detected or installed, you can specify manual locations, or the current working directory. Once you connect, the credentials file will be created, and you'll be prompted to select which location(s) to place it in. Even if none of the relevant `librespot` applications are detected or installed, you can specify manual locations, or the current working directory.
@@ -49,15 +54,15 @@ Once you connect, the credentials file will be created, and you'll be prompted t
Installation is not necessary to use this application, but if you're having trouble, want to compile it yourself, or are using it frequently, you might want to install it. Installation is not necessary to use this application, but if you're having trouble, want to compile it yourself, or are using it frequently, you might want to install it.
>[!NOTE] > [!NOTE]
>The scripts above can be given the `-K` or `--keep` flag to keep the downloaded binary. This will prevent repeated API calls to GitHub if you're using the script frequently within a short period. > The scripts above can be given the `-K` or `--keep` flag to keep the downloaded binary. This will prevent repeated API calls to GitHub if you're using the script frequently within a short period.
### Pre-built Binaries ### Pre-built Binaries
Binaries are always available for download from the [releases page][latestRelease], and they're the same ones used by the shell scripts above. Binaries are always available for download from the [releases page][latestRelease], and they're the same ones used by the shell scripts above.
Currently, the following targets are available for download: Currently, the following targets are available for download:
- x64 Linux (MUSL) `x86_64-unknown-linux-musl` - x64 Linux (MUSL) `x86_64-unknown-linux-musl`
- ARM64 Linux (MUSL) `aarch64-unknown-linux-musl` - ARM64 Linux (MUSL) `aarch64-unknown-linux-musl`
- ARMv7 Linux `armv7-unknown-linux-musleabihf` - ARMv7 Linux `armv7-unknown-linux-musleabihf`
@@ -70,7 +75,7 @@ Please [file an issue][new-issue] if you are on a platform that is not supported
### Via `cargo-binstall` ### Via `cargo-binstall`
>[!NOTE] > [!NOTE]
> If the package cannot be found for your target or fails to be downloaded for any reason, `cargo-binstall` will automatically fall back to building the package from source. > If the package cannot be found for your target or fails to be downloaded for any reason, `cargo-binstall` will automatically fall back to building the package from source.
`cargo-binstall` is a tool that allows you to install binaries from crates.io without needing to compile them yourself. `cargo-binstall` is a tool that allows you to install binaries from crates.io without needing to compile them yourself.
@@ -81,7 +86,6 @@ cargo binstall spotify-quickauth
If you're curious where the binary comes from, `cargo-binstall` will likely pull the binary directly from the [latest release][latestRelease] by this repository, selecting the most appropriate target for your host. If you're curious where the binary comes from, `cargo-binstall` will likely pull the binary directly from the [latest release][latestRelease] by this repository, selecting the most appropriate target for your host.
### Manual Installation ### Manual Installation
If you'd like to use the shell script above to install the binary, you can use the `-S/--stop` flag to prevent the script from running the binary after downloading it. It implicitly applies the `--keep` flag too. If you'd like to use the shell script above to install the binary, you can use the `-S/--stop` flag to prevent the script from running the binary after downloading it. It implicitly applies the `--keep` flag too.
@@ -110,6 +114,7 @@ spotify-quickauth --help
``` ```
If you have any troubles building the project If you have any troubles building the project
- Make sure you're using a target that's supported by the project (see above). - Make sure you're using a target that's supported by the project (see above).
- Certain targets may require specfic linkers. For example, - Certain targets may require specfic linkers. For example,

View File

@@ -1,42 +1,174 @@
use std::{env, fs::File, process::exit}; use std::{env, fs::File, path::PathBuf, process::exit};
use futures::StreamExt; use futures::StreamExt;
use librespot_core::config::DeviceType; use librespot_core::config::DeviceType;
use librespot_discovery::Discovery; use librespot_discovery::Discovery;
use log::{info, warn}; use log::{debug, error, info, warn};
use sha1::{Digest, Sha1}; use sha1::{Digest, Sha1};
use std::io::Write; use std::io::Write;
struct Arguments {
force: bool,
path: PathBuf,
}
fn parse_arguments(args: &Vec<String>) -> Result<Arguments, String> {
let mut force: Option<bool> = None;
let mut path: Option<PathBuf> = None;
let mut skip = 1;
// If '--' is provided, all arguments before it are skipped
if let Some(index) = args.iter().position(|arg| arg == "--") {
skip = index + 1;
}
let args = &args[skip..];
debug!("Arguments: {:?}", args);
for arg in args.iter() {
match arg.as_str() {
"-f" | "--force" => {
if force.is_some() {
return Err("Force flag provided multiple times".to_string());
}
force = Some(true)
}
_ => {
if path.is_some() {
return Err("Path provided multiple times".to_string());
}
// Parse the path, validate that the argument looks like a path
let parsed = PathBuf::from(arg);
debug!("Parsed path: {}", parsed.display());
if parsed.exists() {
if parsed.is_dir() {
path = Some(parsed.join("credentials.json"));
} else if parsed.is_file() {
if path.is_some() {
return Err("Path provided multiple times".to_string());
}
path = Some(parsed);
} else {
return Err("Path is not a file or directory".to_string());
}
} else {
// File does not exist, check if it looks like a directory
if parsed.ends_with("/") || parsed.ends_with("\\") {
// If the parent directory exists, it's okay to create a directory then the file in it
if parsed.parent().is_some_and(|p| p.exists()) {
path = Some(parsed.join("credentials.json"));
} else {
return Err(
"Cannot create more than one folder for output path".to_string()
);
}
} else {
// No need to create a directory, just create the file
if parsed.parent().is_some_and(|p| p.exists()) {
path = Some(parsed);
} else {
return Err(
"Cannot create a file in a non-existent directory".to_string()
);
}
}
}
}
}
}
// If no path was provided, default to credentials.json in the current directory
let path = match path {
Some(p) => match std::path::absolute(p) {
Ok(p) => p,
Err(e) => return Err(format!("Invalid path: {}", e)),
},
None => {
// No path provided, try to identify a default in the current directory
let pwd = env::current_dir();
if pwd.is_err() {
// For some reason the current directory
return Err("Current directory is invalid or indeterminate, please provide an explicit output path".to_string());
}
// Default to credentials.json in the current directory
pwd.unwrap().join("credentials.json")
}
};
// If the *file* already exists, check if the force flag was provided
if path.exists() && path.is_file() && !force.unwrap_or(false) {
return Err(format!(
"Output file already exists, use -f to overwrite ({})",
path.display()
));
}
Ok(Arguments {
force: force.unwrap_or(false),
path,
})
}
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn main() { async fn main() {
// Initialize the logger
if env::var("RUST_LOG").is_err() { if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "info") env::set_var("RUST_LOG", "info")
} }
env_logger::builder().init(); env_logger::builder().init();
let credentials_file = match home::home_dir() { // Parse the arguments
// ~/.cache/spotify_player/credentials.json let args = match parse_arguments(&env::args().collect()) {
Some(path) => path.join(".cache/spotify_player/credentials.json"), Ok(a) => a,
None => { Err(e) => {
warn!("Cannot determine home directory for credentials file."); error!("Error parsing arguments: {}", e);
exit(1); exit(1);
} }
}; };
info!("Credentials file: {}", &credentials_file.display());
// TODO: If credentials file exists, confirm overwrite info!("Credentials file: {}", &args.path.display());
if credentials_file.exists() {
warn!("Credentials file already exists: {}", &credentials_file.display());
exit(1);
}
// TODO: If spotifyd is running, ask if shutdown is desired // TODO: If spotifyd is running, ask if shutdown is desired
let username = match env::consts::OS { // Figure out the username
let mut username = match env::consts::OS {
"windows" => env::var("USERNAME"), "windows" => env::var("USERNAME"),
_ => env::var("USER"), _ => env::var("USER"),
}.unwrap_or_else(|_| "unknown".to_string()); }
// Trim whitespace from the username
.map(|u| u.trim().to_string())
.unwrap_or("unknown".to_string());
// Default the username to 'unknown' if it doesn't fit the expected format
if username != "unknown" {
let valid_characters = r"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
if match &username {
u if u.is_empty() => {
warn!("Cannot determine username, defaulting to 'unknown'");
true
}
u if u.len() > 20 => {
warn!("Username is too long, defaulting to 'unknown'");
true
}
u if u.len() < 2 => {
warn!("Username is too short, defaulting to 'unknown'");
true
}
u if u.contains(|c| !valid_characters.contains(c)) => {
warn!("Username contains invalid characters, defaulting to 'unknown'");
true
}
_ => false,
} {
username = "unknown".to_string();
}
}
// Create the device metadata
let device_name = format!("spotify-quickauth-{}", username); let device_name = format!("spotify-quickauth-{}", username);
let device_id = hex::encode(Sha1::digest(device_name.as_bytes())); let device_id = hex::encode(Sha1::digest(device_name.as_bytes()));
let device_type = DeviceType::Computer; let device_type = DeviceType::Computer;
@@ -47,35 +179,30 @@ async fn main() {
.launch() .launch()
.unwrap(); .unwrap();
println!("Open Spotify and select output device: {}", device_name); info!("Open Spotify and select output device: {}", device_name);
let mut written = false;
while let Some(credentials) = server.next().await { while let Some(credentials) = server.next().await {
let result = File::create("./credentials.json").and_then(|mut file| { // Check if file exists
if args.path.exists() && !args.force {
warn!("Output file already exists (appeared after startup), use -f to overwrite");
exit(1);
}
// Write the credentials to the file
let result = File::create(&args.path).and_then(|mut file| {
let data = serde_json::to_string(&credentials)?; let data = serde_json::to_string(&credentials)?;
write!(file, "{data}") write!(file, "{data}")
}); });
written = true;
// Check if the file was created successfully
if let Err(e) = result { if let Err(e) = result {
warn!("Cannot save credentials to cache: {}", e); warn!("Cannot save credentials to cache: {}", e);
exit(1); exit(1);
} else { } else {
println!("Credentials saved: {}", &credentials_file.display()); info!("Credentials saved: {}", &args.path.display());
exit(0); exit(0);
} }
} }
if !written {
warn!("No credentials were written.");
exit(1);
}
} }
mod tests {}
mod tests {
#[test]
fn test_nothing() {
assert_eq!(1, 1);
}
}