Skip to content

Commit 740e483

Browse files
authored
Merge pull request #14 from patryk-ku/dev
v0.2.1
2 parents 65aa32b + f11aa57 commit 740e483

File tree

12 files changed

+156
-21
lines changed

12 files changed

+156
-21
lines changed

.github/assets/banner.png

54 KB
Loading

.github/assets/banner.xcf

346 KB
Binary file not shown.

.github/release-notes.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
## Changes:
22

3-
- (⚠️ **Breaking**) The `-n`, `--player-name` argument has been removed. Use `-a`, `--allowlist-add` instead.
4-
- (⚠️ **Breaking**) The previous button arguments (`-p`, `--profile-button`, `-y`, `--yt-button`) have been consolidated into a single new argument: `-b, --button` with options: `yt`, `lastfm`, `listenbrainz` and separate arguments for setting service usernames. More additional buttons coming in the future.
5-
- Added support for configuring the program via a configuration file.
6-
- Added commands for easy setup of autostart using systemd.
7-
- Now available as `.deb` and `.rpm` packages, and in the AUR.
8-
- Print debug logs with `--debug-log`.
3+
- Added option to hide album title in activity.
4+
- Added the ability to customize displayed icon adjacent to album artwork. Available options: none, play/pause icons, music player icon, Last.fm avatar.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## v0.2.1
2+
3+
- Added option to hide album title in activity.
4+
- Added the ability to customize displayed icon adjacent to album artwork. Available options: none, play/pause icons, music player icon, Last.fm avatar.
5+
16
## v0.2.0
27

38
- (⚠️ **Breaking**) The `-n`, `--player-name` argument has been removed. Use `-a`, `--allowlist-add` instead.

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mpris-discord-rpc"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2021"
55
authors = ["Patryk Kurdziel <patryk.kurdziel@protonmail.com>"]
66
description = "MPRIS Discord music rich presence status with support for album covers and progress bar."

PKGBUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Maintainer: Patryk Kurdziel <patryk.kurdziel@protonmail.com>
22

33
pkgname=mpris-discord-rpc
4-
pkgver=0.2.0
4+
pkgver=0.2.1
55
pkgrel=1
66
pkgdesc='MPRIS Discord music rich presence status with support for album covers and progress bar.'
77
url="https://github.com/patryk-ku/$pkgname"

README.md

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# mpris-discord-rpc
22

3-
![img-min-optimized](https://github.com/user-attachments/assets/15990d23-51af-4d98-ae7d-7feabe84c351)
3+
![banner](.github/assets/banner.png)
44

5-
MPRIS Discord music rich presence status **with support for album covers and progress bar**. In addition, there is also an option to enable buttons with links to your profile on last.fm and a search song on Youtube. Written in Rust.
5+
Linux Discord rich presence for music, using MPRIS with **album cover and progress bar support**. You can customize additional buttons, such as linking to your Last.fm profile or searching for the current song on YouTube. There's also an option to display either the music player's icon or your Last.fm avatar next to the album cover. The application is written in Rust.
66

77
## Supported players
88

@@ -113,8 +113,10 @@ Options:
113113
-b, --button <name> Select visible buttons [possible values: yt, lastfm, listenbrainz, shamelessAd]
114114
--lastfm-name <nickname> Your Last.fm nickname
115115
--listenbrainz-name <nickname> Your Listenbrainz nickname
116+
-s, --small-image <name> Select the icon displayed next to the album cover (default playPause) [possible values: playPause, player, lastfmAvatar, none]
116117
-l, --list-players Displays all available music player names and exits. Use to get your player name for -a argument
117118
-a, --allowlist-add <Player Name> Get status only from given player. Use multiple times to add several players
119+
--hide-album-name Hide album name
118120
-d, --disable-cache Disable cache (not recommended)
119121
--debug-log Show debug log
120122
--reset-config Reset config file (overwrites the old file if exists)
@@ -196,6 +198,31 @@ lastfm_name: "nickname"
196198

197199
> You can request more buttons by opening an Issue.
198200

201+
### The icon next to the album cover
202+
203+
You can choose from available options: `playPause`, `player`, `lastfmAvatar`, `none`.
204+
205+
arguments:
206+
207+
```sh
208+
mpris-discord-rpc -s player
209+
```
210+
211+
config:
212+
213+
```yaml
214+
small_image: player
215+
```
216+
217+
Available music player icons: `Amberol`, `Elisa`, `GNOME Music`, `Google Chrome`, `Lollypop`, `Mozilla Firefox`, `Spotify`, `Strawberry`, `Tauon`, `VLC Media Player`, `Zen Browser`.
218+
219+
Missing your player icon? Open an Issue with:
220+
221+
- Icon link (png, min. 512x512 resolution - Discord requirement)
222+
- Player ID (obtainable by running with `--debug-log` parameter, search for the line with `[debug] player_id:`)
223+
224+
Icons are managed through Discord Developer Portal, so no app update is needed after adding new ones.
225+
199226
### Flatpak Discord fix
200227

201228
As flatpak applications are sandboxed this makes it difficult for any other programs to communicate with them. But this can be easily fixed using the following command:
@@ -238,3 +265,5 @@ If not disabled, the program stores the cache in `$XDG_CACHE_HOME/mpris-discord-
238265
## Credits
239266

240267
I wouldn't have been able to create this without two fantastic crates: [mpris-rs](https://github.com/Mange/mpris-rs) and [discord-rich-presence](https://github.com/vionya/discord-rich-presence). Implementing these features myself would have been beyond my current skills. A huge thank you to their creators.
268+
269+
Any trademarks, featured track metadata, artwork and coverart in banner, music player icons and streaming service logos belong to their respective owners.

config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ interval: 10
1717
# lastfm_name: "nickname"
1818
# listenbrainz_name: "nickname"
1919

20+
# Select the icon displayed next to the album cover (default playPause) [possible values: playPause, player, lastfmAvatar, none]
21+
small_image: playPause
22+
2023
# Only use the status from the following music players
2124
# Use -l, --list-players to get player exact name to use with this option
2225
# The order matters and the first is the most important.
@@ -25,5 +28,8 @@ interval: 10
2528
# - "Chrome"
2629
# - "Any other player"
2730

31+
# Hide the album name to decrease activity height
32+
hide_album_name: false
33+
2834
# Disable cache (not recommended)
2935
disable_cache: false

src/main.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
5050
let lastfm_name = settings.lastfm_name.unwrap_or_default();
5151
let listenbrainz_name = settings.listenbrainz_name.unwrap_or_default();
5252

53+
let small_image = settings.small_image.unwrap_or(String::from("playPause"));
54+
let mut lastfm_avatar = String::new();
55+
if small_image == "lastfmAvatar" && !lastfm_name.is_empty() {
56+
lastfm_avatar = utils::get_lastfm_avatar(&lastfm_name, LASTFM_API_KEY);
57+
debug_log!(settings.debug_log, "lastfm_avatar: {}", lastfm_avatar);
58+
}
59+
let lastfm_icon_text = if !lastfm_name.is_empty() {
60+
lastfm_name.to_string() + " on Last.fm"
61+
} else {
62+
String::new()
63+
};
64+
5365
// Enable/disable use of cache
5466
let mut cache_enabled: bool = !settings.disable_cache;
5567
if !home_exists {
@@ -226,6 +238,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
226238
}
227239
};
228240

241+
let player_name = player.identity();
242+
let player_id = utils::sanitize_name(player_name);
243+
debug_log!(settings.debug_log, "player_name: {}", player_name);
244+
debug_log!(settings.debug_log, "player_id: {}", player_id);
245+
229246
// Connect with Discord
230247
if is_first_time {
231248
match client.connect() {
@@ -423,19 +440,37 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
423440
"paused".to_string()
424441
};
425442

426-
let payload = activity::Activity::new()
443+
let mut assets = activity::Assets::new().large_image(&image);
444+
445+
if !settings.hide_album_name {
446+
assets = assets.large_text(&album);
447+
}
448+
449+
match small_image.as_str() {
450+
"player" => assets = assets.small_image(&player_id).small_text(&player_name),
451+
"lastfmAvatar" => {
452+
if !lastfm_avatar.is_empty() {
453+
assets = assets
454+
.small_image(&lastfm_avatar)
455+
.small_text(&lastfm_icon_text);
456+
}
457+
}
458+
"none" => {}
459+
_ => assets = assets.small_image(&status_text).small_text(&status_text),
460+
}
461+
462+
// Display paused icon anyway if playpack is paused or stopped
463+
if status_text != "playing" {
464+
assets = assets.small_image(&status_text).small_text(&status_text)
465+
}
466+
467+
let mut payload = activity::Activity::new()
427468
.state(&artist)
428469
.details(&title)
429-
.assets(
430-
activity::Assets::new()
431-
.large_image(&image)
432-
.small_image(&status_text)
433-
.large_text(&album)
434-
.small_text(&status_text),
435-
)
470+
.assets(assets)
436471
.activity_type(activity::ActivityType::Listening);
437472

438-
let payload = if is_track_position & (track_duration > 0) {
473+
payload = if is_track_position & (track_duration > 0) {
439474
let time_end = time_start + track_duration;
440475
if is_playing {
441476
payload.timestamps(
@@ -517,7 +552,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
517552
}
518553
}
519554

520-
let payload = match buttons.is_empty() {
555+
payload = match buttons.is_empty() {
521556
false => payload.buttons(buttons),
522557
true => payload,
523558
};

src/settings.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ pub struct Cli {
2929
#[arg(long, value_name = "nickname", value_parser = clap::value_parser!(String))]
3030
pub listenbrainz_name: Option<String>,
3131

32+
/// Select the icon displayed next to the album cover (default playPause)
33+
#[arg(short, long, value_name = "name", value_parser = ["playPause", "player", "lastfmAvatar", "none"])]
34+
pub small_image: Option<String>,
35+
3236
/// Displays all available music player names and exits. Use to get your player name for -a argument
3337
#[arg(short, long)]
3438
#[serde(skip_deserializing)]
@@ -38,6 +42,10 @@ pub struct Cli {
3842
#[arg(short = 'a', long = "allowlist-add", value_name = "Player Name", value_parser = clap::value_parser!(String))]
3943
pub allowlist: Vec<String>,
4044

45+
/// Hide album name
46+
#[arg(long)]
47+
pub hide_album_name: bool,
48+
4149
/// Disable cache (not recommended)
4250
#[arg(short, long)]
4351
pub disable_cache: bool,
@@ -102,6 +110,9 @@ interval: 10
102110
# lastfm_name: "nickname"
103111
# listenbrainz_name: "nickname"
104112
113+
# Select the icon displayed next to the album cover (default playPause) [possible values: playPause, player, lastfmAvatar, none]
114+
small_image: playPause
115+
105116
# Only use the status from the following music players
106117
# Use -l, --list-players to get player exact name to use with this option
107118
# The order matters and the first is the most important.
@@ -110,6 +121,9 @@ interval: 10
110121
# - "Chrome"
111122
# - "Any other player"
112123
124+
# Hide the album name to decrease activity height
125+
hide_album_name: false
126+
113127
# Disable cache (not recommended)
114128
disable_cache: false
115129
"#;
@@ -200,6 +214,14 @@ pub fn load_settings() -> Cli {
200214
config.listenbrainz_name = args.listenbrainz_name;
201215
}
202216

217+
if args.small_image != config.small_image && args.small_image.is_some() {
218+
config.small_image = args.small_image;
219+
}
220+
221+
if args.hide_album_name {
222+
config.hide_album_name = args.hide_album_name;
223+
}
224+
203225
if args.disable_cache {
204226
config.disable_cache = args.disable_cache;
205227
}

src/utils.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,45 @@ pub fn get_cover_url(
225225

226226
return String::from("missing-cover");
227227
}
228+
229+
pub fn get_lastfm_avatar(username: &str, lastfm_api_key: &str) -> String {
230+
let request_url = format!(
231+
"http://ws.audioscrobbler.com/2.0/?method=user.getinfo&api_key={}&user={}&format=json",
232+
lastfm_api_key,
233+
url_escape::encode_component(username)
234+
);
235+
236+
let mut url: String = match reqwest::blocking::get(request_url) {
237+
Ok(res) => match res.json::<serde_json::Value>() {
238+
Ok(data) => data["user"]["image"][3]["#text"].to_string(),
239+
Err(_) => String::new(),
240+
},
241+
Err(_) => String::new(),
242+
};
243+
244+
if !url.is_empty() && (url.len() > 15) {
245+
url.pop();
246+
url.remove(0);
247+
println!("[last.fm] fetched avatar link: {}", url);
248+
return url;
249+
}
250+
251+
return String::new();
252+
}
253+
254+
pub fn sanitize_name(input: &str) -> String {
255+
input
256+
.to_lowercase()
257+
.split_whitespace()
258+
.collect::<Vec<&str>>()
259+
.join("_")
260+
.chars()
261+
.filter(|c| c.is_alphanumeric() || *c == '_')
262+
.collect()
263+
}
264+
265+
// pub fn format_time(seconds: u64) -> String {
266+
// let minutes = seconds / 60;
267+
// let remaining_seconds = seconds % 60;
268+
// format!("{:02}:{:02}", minutes, remaining_seconds)
269+
// }

0 commit comments

Comments
 (0)