Compare commits

..

No commits in common. "4d2ee2d53a84a65716309a46a4d6a0659c1bf1da" and "6899d676aada7c96fd2537588c02ac67db9aaed5" have entirely different histories.

8 changed files with 84 additions and 297 deletions

5
.env.example Normal file
View file

@ -0,0 +1,5 @@
#PLAYER_BUS="org.mpris.MediaPlayer2.mpv"
USERNAME="ILoveLastDotFm"
PASSWORD="lastfm4lyfe"
API_KEY="t8mb4e0kn9it150amaeezbcfe3iusy8o"
API_SECRET="jd47iz6h1u2kbnbfm8c763lzrj1o89h3"

211
Cargo.lock generated
View file

@ -136,25 +136,10 @@ dependencies = [
]
[[package]]
name = "dirs"
version = "5.0.1"
name = "dotenvy"
version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "enum-kinds"
@ -167,6 +152,26 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "envconfig"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea81cc7e21f55a9d9b1efb6816904978d0bfbe31a50347cb24b2e75564bcac9b"
dependencies = [
"envconfig_derive",
]
[[package]]
name = "envconfig_derive"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dfca278e5f84b45519acaaff758ebfa01f18e96998bc24b8f1b722dd804b9bf"
dependencies = [
"proc-macro2",
"quote 1.0.36",
"syn 1.0.109",
]
[[package]]
name = "errno"
version = "0.3.9"
@ -174,7 +179,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
@ -244,17 +249,6 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "heck"
version = "0.3.3"
@ -302,11 +296,10 @@ name = "lastfmpris"
version = "0.1.0"
dependencies = [
"anyhow",
"dirs",
"dotenvy",
"envconfig",
"mpris",
"rustfm-scrobble-proxy",
"serde",
"serde_ini",
"tracing",
"tracing-subscriber",
]
@ -332,16 +325,6 @@ dependencies = [
"pkg-config",
]
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
@ -465,12 +448,6 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "overload"
version = "0.1.1"
@ -519,23 +496,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_users"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "result"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194d8e591e405d1eecf28819740abed6d719d1a2db87fc0bcdedee9a26d55560"
[[package]]
name = "rustfm-scrobble-proxy"
version = "2.0.0"
@ -559,7 +519,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
@ -574,7 +534,7 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
dependencies = [
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
@ -602,35 +562,24 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.209"
version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.209"
version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [
"proc-macro2",
"quote 1.0.36",
"syn 2.0.72",
]
[[package]]
name = "serde_ini"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb236687e2bb073a7521c021949be944641e671b8505a94069ca37b656c81139"
dependencies = [
"result",
"serde",
"void",
]
[[package]]
name = "serde_json"
version = "1.0.122"
@ -728,7 +677,7 @@ dependencies = [
"fastrand",
"once_cell",
"rustix",
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
@ -889,18 +838,6 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
@ -923,37 +860,13 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
"windows-targets",
]
[[package]]
@ -962,46 +875,28 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
@ -1014,48 +909,24 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"

View file

@ -7,10 +7,9 @@ edition = "2021"
[dependencies]
anyhow = "1.0.86"
dirs = "5.0.1"
dotenvy = "0.15.7"
envconfig = "0.10.0"
mpris = "2.0.1"
rustfm-scrobble-proxy = "2.0.0"
serde = "1.0.209"
serde_ini = "0.2.0"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"

View file

@ -6,52 +6,34 @@ a rust application to scrobble your currently playing song on last.fm with mpris
unfortunately, because of how most mpris players work, the [Track_Id](https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html#Simple-Type:Track_Id) (unique identifier for every song in the tracklist) object is very rarely supported, or, if supported, implemented incorrectly (looking at you, [Cider](https://cider.sh/)) meaning it is impossible to tell if the track has been played twice in a row. this means you cannot have succssive scrobbles of the same song, sorry! besides this, i'd say the program is feature complete.
also you can't configure the program through nix yet because i'm lazy, i'll do that sometime!!
## configuration
either run the program once and navigate to `.config/lastmpris/config.ini` or create the file and copy it from the `config.example.ini` file provided in this directory. once you do that, configure your authentication methods. the api keys are available [here](https://www.last.fm/login?next=/api/account/create)
copy the values from `.env.example` into a `.env` file and configure your api keys, and the api keys are available [here](https://www.last.fm/login?next=/api/account/create)
you also have the option to define your mpris bus name, which will instead wait for your specified player instead of waiting for the first active player
## how to install
you have two methods of installation
*if you're on a setup that uses nix, you can just use `nix build` or the provided devshell to build the application.*
1. install with cargo + your package manager of choice
1. obtain dependencies (this will vary on your package manager)
```sh
sudo apk add install pkgconf openssl dbus
```
2. run/build
```sh
cargo build --release
```
2. install using nix
first, clone repository:
simply run it with nix:
```sh
git clone https://git.reidlab.pink/reidlab/lastfmpris && cd lastfmpris
```
```sh
nix run git+https://git.reidlab.pink/reidlab/lastfmpris
```
second, obtain dependencies (this will vary on your package manager, here, alpine is used)
or put it into your flake as such:
```sh
sudo apk add install pkgconf openssl dbus
```
```nix
# add this into your flake inputs:
lastfmpris.url = "git+https://git.reidlab.pink/reidlab/lastfmpris";
# add this to your `homeConfiguration`:
imports = [
inputs.lastfmpris.nixosModules.lastfmpris
];
```
finally, run/build
and then just add this to use it as a home-manager option:
```nix
# add this to your home-manager configuration:
services.lastfmpris = {
enable = true;
}
```
```sh
cargo run
```
```sh
cargo build --release
```

View file

@ -1,5 +0,0 @@
; player_bus = org.mpris.MediaPlayer2.mpv
username = ILoveLastDotFm
password = lastfm4lyfe
api_key = t8mb4e0kn9it150amaeezbcfe3iusy8o
api_secret = jd47iz6h1u2kbnbfm8c763lzrj1o89h3

View file

@ -30,7 +30,7 @@
# uncomment this and let the build fail, then get the current hash
# very scuffed but endorsed!
#cargoSha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
cargoSha256 = "sha256-KOMEvg3iGjmMEFxsrIqD4SaDw63ojiNNNqCfzRlbYLw=";
cargoSha256 = "sha256-2bDHxZc5Zg7jmA8BenSbTF3fBJEB7QDEVBQLkI8qyRc=";
buildInputs = with pkgs; [ pkg-config ];
@ -54,37 +54,5 @@
RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library";
};
}) // {
homeManagerModules = {
lastfmpris = { config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.lastfmpris;
in {
options.services.lastfmpris = {
enable = mkEnableOption "enables the lastmpris scrobbler";
package = mkOption {
type = types.package;
default = self.defaultPackage.${pkgs.system};
};
};
config = mkIf cfg.enable {
home.packages = [ cfg.package ];
systemd.user.services.lastfmpris = {
Unit = {
Description = "Lastfmpris scrobbling daemon";
After = [ "graphical-session-pre.target" ];
};
Service = {
Type = "Simple";
ExecStart = "${lib.getExe cfg.package}";
Restart = "on-failure";
};
};
};
};
};
};
});
}

View file

@ -1,55 +1,19 @@
use anyhow::{Context, Result};
use serde::Deserialize;
use std::fs;
use std::fs::{create_dir_all, OpenOptions};
use std::io::Write;
use std::process;
use tracing::info;
use envconfig::Envconfig;
#[derive(Deserialize)]
#[derive(Envconfig)]
pub struct Config {
#[envconfig(from = "PLAYER_BUS")]
pub player_bus: Option<String>,
#[envconfig(from = "USERNAME")]
pub username: String,
#[envconfig(from = "PASSWORD")]
pub password: String,
#[envconfig(from = "API_KEY")]
pub api_key: String,
#[envconfig(from = "API_SECRET")]
pub api_secret: String
}
pub fn load_config() -> Result<Config> {
let path = dirs::config_dir()
.context("failed to get config directory")?
.join("lastfmpris")
.join("config.ini");
// create file if it doesnt exist and exit
if !path.exists() {
info!("configuration file doesn't exist, creating boilerplate");
// create underline paths and files
if let Some(parent) = path.parent() {
create_dir_all(parent)
.context("failed to create config file folder(s)")?;
}
let mut file = OpenOptions::new()
.write(true)
.create(true)
.open(&path)
.context("failed to create config file")?;
// write into the config file with the example configuration
// we put inside the base working directory for the project
file.write_all(include_str!("../config.example.ini").as_bytes())
.context("failed to write boilerplate config")?;
info!("configuration boilerplate generation completed: see file: {}", path.display());
// success, exit
process::exit(0)
}
let content = fs::read_to_string(path)
.context("failed to read config content")?;
let config: Config = serde_ini::from_str(&content)
.context("failed to deserialize ini into a readable format")?;
Ok(config)
}

View file

@ -6,11 +6,14 @@ mod main_loop;
mod player;
mod track;
use crate::config::Config;
use crate::lastfm::get_scrobbler;
use anyhow::{Context, Result};
use envconfig::Envconfig;
use tracing::{debug, Level};
fn main() -> Result<()> {
dotenvy::dotenv()?;
tracing_subscriber::fmt()
.with_max_level(if cfg!(debug_assertions) { Level::DEBUG } else { Level::INFO })
.init();
@ -21,8 +24,8 @@ fn main() -> Result<()> {
env!("CARGO_PKG_DESCRIPTION")
);
let config = config::load_config()
.context("failed to initiate configuration object!")?;
let config = Config::init_from_env()
.context("failed to initiate configuration from .env")?;
let scrobbler = get_scrobbler(&config)
.context("failed to create scrobbler")?;