Skip to content

Improve track title and author display for Discord RPC.#4441

Open
sakshamyep wants to merge 2 commits intopear-devs:masterfrom
sakshamyep:fix(discord-rpc)-use-YTM-title-and-author-instead-of-YT-for-better-display
Open

Improve track title and author display for Discord RPC.#4441
sakshamyep wants to merge 2 commits intopear-devs:masterfrom
sakshamyep:fix(discord-rpc)-use-YTM-title-and-author-instead-of-YT-for-better-display

Conversation

@sakshamyep
Copy link
Copy Markdown

@sakshamyep sakshamyep commented Apr 26, 2026

This PR fixes an issue where the Discord RPC shows track title and author from YT videos rather than using metadata from YTM which is more suitable and a clean approach.

More detailed explanation is available here:
#4413

Summary by CodeRabbit

  • Bug Fixes
    • Improved Discord Rich Presence status to consistently display artist information, providing clearer presence indicators
    • Enhanced song metadata handling to prioritize YouTube Music titles, ensuring more accurate and reliable track information throughout the application

Copilot AI review requested due to automatic review settings April 26, 2026 23:51
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

📝 Walkthrough

Walkthrough

The pull request modifies metadata handling for song information and Discord Rich Presence display. The Discord service now uses artist information consistently for the state field, while the song info provider adjusts how alternative titles are sourced from microformat data, with YouTube Music metadata taking precedence.

Changes

Cohort / File(s) Summary
Discord Rich Presence
src/plugins/discord/discord-service.ts
Modified state field generation to use songInfo.artist instead of the first tag as the primary source for display.
Song Metadata Provider
src/providers/song-info.ts
Changed alternativeTitle sourcing from microformat.linkAlternates to microformat.title directly, with conditional title override logic to prioritize YouTube Music metadata.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A whisker twitch of metadata delight,
Artist fields now shine so bright,
Alternative titles find their way,
Through microformat's cleaner display.
Hop along, the streams sing true! 🎵

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly aligns with the main objectives: improving Discord RPC display by using YouTube Music metadata for track title and author instead of YouTube metadata.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to improve Discord Rich Presence track metadata by preferring YouTube Music (YTM) metadata over the underlying YouTube video metadata, addressing issue #4413.

Changes:

  • Update SongInfo to source alternativeTitle from microformat.title and prefer it for the primary title.
  • Adjust Discord RPC “artist” (state) to always use songInfo.artist instead of falling back to tags[0].

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/providers/song-info.ts Switches alternative title source to microformat.title and sets songInfo.title from it when present.
src/plugins/discord/discord-service.ts Changes Discord RPC artist display to always use songInfo.artist.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +118 to +121
// Prefer YouTube Music metadata title when available
if (songInfo.alternativeTitle) {
songInfo.title = songInfo.alternativeTitle;
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overwriting songInfo.title with songInfo.alternativeTitle here changes the canonical title for all consumers (notifications, MPRIS, scrobblers, etc.), not just Discord RPC. This also bypasses the earlier cleanupName(videoDetails.title) sanitization and effectively makes the scrobbler alternativeTitles toggle meaningless (the “alternative” title becomes the only title). Suggest keeping songInfo.title as the cleaned videoDetails.title and letting Discord (or a config-gated path) prefer alternativeTitle when desired, rather than mutating the shared field.

Suggested change
// Prefer YouTube Music metadata title when available
if (songInfo.alternativeTitle) {
songInfo.title = songInfo.alternativeTitle;
}
// Keep the canonical title as the sanitized videoDetails.title.
// Consumers that want to prefer YouTube Music metadata can use
// songInfo.alternativeTitle explicitly instead of mutating shared state.

Copilot uses AI. Check for mistakes.
), // Song title
detailsUrl: songInfo.url ?? undefined,
state: sanitizeActivityText(songInfo.tags?.at(0) ?? songInfo.artist), // Artist name
state: sanitizeActivityText(songInfo.artist), // Artist name
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes Discord RPC always display songInfo.artist, which is populated from videoDetails.author in the song-info provider. Given the PR goal/issue is to prefer YouTube Music metadata for the author as well, this looks like it may move the artist display further away from microformat-derived metadata (previously tags?.at(0) was used as a fallback). If the intent is to show YTM’s artist, consider keeping the fallback or sourcing the artist from microformat/page owner details instead.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/plugins/discord/discord-service.ts (1)

117-121: Optional: details fallback is now redundant given the upstream override.

Because src/providers/song-info.ts (lines 118–122) now copies alternativeTitle into title whenever it is set, songInfo.alternativeTitle ?? songInfo.title always resolves to the same string. You can simplify to sanitizeActivityText(songInfo.title) for symmetry with the new state line.

That said, please resolve the upstream concern in song-info.ts first — if the override there is removed or scoped to Discord only, this fallback should remain.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugins/discord/discord-service.ts` around lines 117 - 121, The details
field currently uses a redundant fallback (songInfo.alternativeTitle ??
songInfo.title); update the Discord activity creation to just call
sanitizeActivityText(songInfo.title) for symmetry with the state line and remove
the alternativeTitle fallback, referencing sanitizeActivityText and the
songInfo.alternativeTitle / songInfo.title properties; ensure this change is
only applied after the upstream song-info override is confirmed or adjust
accordingly if that override is removed or made Discord-specific.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/providers/song-info.ts`:
- Line 103: The change unconditionally sets songInfo.alternativeTitle =
microformat.title which broadens population beyond YouTube Music; either confirm
this is intended and update the comment to state alternativeTitle now uses any
microformat title, or restrict behavior by reverting to the previous conditional
lookup (use linkAlternates to find an entry with a title) or add explicit
detection for YouTube Music metadata before assigning (e.g., check
linkAlternates for a YTM track or inspect microformat/renderer type) so that
alternativeTitle is only set for YTM tracks if that was the original intent.
- Around line 118-122: The override of songInfo.title with raw
songInfo.alternativeTitle bypasses cleanupName() and reintroduces suffixes;
update the assignment so that when songInfo.alternativeTitle is used it is
passed through cleanupName() (e.g., set songInfo.title =
cleanupName(songInfo.alternativeTitle) or assign the cleanedAlternative only if
non-empty), leaving the existing fallback logic in discord-service.ts unchanged.

---

Nitpick comments:
In `@src/plugins/discord/discord-service.ts`:
- Around line 117-121: The details field currently uses a redundant fallback
(songInfo.alternativeTitle ?? songInfo.title); update the Discord activity
creation to just call sanitizeActivityText(songInfo.title) for symmetry with the
state line and remove the alternativeTitle fallback, referencing
sanitizeActivityText and the songInfo.alternativeTitle / songInfo.title
properties; ensure this change is only applied after the upstream song-info
override is confirmed or adjust accordingly if that override is removed or made
Discord-specific.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 82bb02cc-e5e0-4577-8132-9791183cb9aa

📥 Commits

Reviewing files that changed from the base of the PR and between 7b1c574 and e6fe1b3.

📒 Files selected for processing (2)
  • src/plugins/discord/discord-service.ts
  • src/providers/song-info.ts

songInfo.alternativeTitle = microformat.linkAlternates.find(
(link) => link.title,
)?.title;
songInfo.alternativeTitle = microformat.title;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the GetPlayerResponse / microformat type definition for `title` and `linkAlternates`.
fd -t f 'get-player-response' | head
fd -t f 'get-player-response' --exec cat {}

Repository: pear-devs/pear-desktop

Length of output: 10356


🏁 Script executed:

#!/bin/bash
# Find any other consumers of `microformat.title` / `microformatDataRenderer.title` to gauge precedent.
rg -nP '\bmicroformat(DataRenderer)?\.title\b' -C2
rg -nP 'linkAlternates' -C3

Repository: pear-devs/pear-desktop

Length of output: 1403


🏁 Script executed:

sed -n '95,130p' src/providers/song-info.ts

Repository: pear-devs/pear-desktop

Length of output: 1605


🏁 Script executed:

# Check git history for this file to see the previous implementation
git log --oneline -n 20 -- src/providers/song-info.ts
git show HEAD:src/providers/song-info.ts | sed -n '95,130p'

Repository: pear-devs/pear-desktop

Length of output: 1658


🏁 Script executed:

# Get the diff for this specific file to see what changed
git diff HEAD~1 src/providers/song-info.ts | head -80

Repository: pear-devs/pear-desktop

Length of output: 253


🏁 Script executed:

# If that doesn't work, search the entire file history
git log -p --all -- src/providers/song-info.ts | grep -A5 -B5 "alternativeTitle\|linkAlternates" | head -100

Repository: pear-devs/pear-desktop

Length of output: 48


Confirm the semantic broadening of alternativeTitle population and verify intentionality.

microformat.title is correctly defined as string on MicroformatDataRenderer, so the type is valid. However, the change fundamentally alters when alternativeTitle gets populated:

  • Previous behavior (inferred): Only set when linkAlternates contained an entry with a title (typically YouTube Music tracks)
  • Current behavior: Now set unconditionally for any video with a microformat block, including regular YouTube videos, UGC, and podcasts

This broadens the scope of the override at lines 118–122 ("Prefer YouTube Music metadata title when available") to apply beyond YouTube Music. If this is intentional, the comment should reflect it. If alternativeTitle is meant only for YTM tracks, consider reverting to the conditional linkAlternates lookup or add explicit logic to detect YTM metadata.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/song-info.ts` at line 103, The change unconditionally sets
songInfo.alternativeTitle = microformat.title which broadens population beyond
YouTube Music; either confirm this is intended and update the comment to state
alternativeTitle now uses any microformat title, or restrict behavior by
reverting to the previous conditional lookup (use linkAlternates to find an
entry with a title) or add explicit detection for YouTube Music metadata before
assigning (e.g., check linkAlternates for a YTM track or inspect
microformat/renderer type) so that alternativeTitle is only set for YTM tracks
if that was the original intent.

Comment on lines +118 to +122
// Prefer YouTube Music metadata title when available
if (songInfo.alternativeTitle) {
songInfo.title = songInfo.alternativeTitle;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Enumerate consumers of songInfo.title to size the cross-plugin impact.
rg -nP '\bsongInfo\.title\b' -C2
rg -nP '\bsongInfo\.alternativeTitle\b' -C2

Repository: pear-devs/pear-desktop

Length of output: 8250


🏁 Script executed:

#!/bin/bash

# 1. Find and examine the cleanupName function
echo "=== cleanupName function ==="
rg -nA 15 'function cleanupName|const cleanupName.*=' src/providers/song-info.ts

# 2. Look for suffixesToRemove mentioned in the review
echo -e "\n=== suffixesToRemove ==="
rg -nA 15 'suffixesToRemove' src/providers/song-info.ts

# 3. Check if there's a config for preferring alternativeTitle
echo -e "\n=== Config for alternativeTitle preference ==="
rg -n 'alternativeTitle' src/config.ts src/types.ts

# 4. Check microformat structure
echo -e "\n=== microformat handling ==="
rg -nB5 'microformat.title' src/providers/song-info.ts

Repository: pear-devs/pear-desktop

Length of output: 1715


🏁 Script executed:

#!/bin/bash

# Find config-related files
echo "=== Looking for config files ==="
fd -t f 'config|types' src/ | head -20

# Check for any config flag related to alternativeTitle
echo -e "\n=== Searching for config flags related to title ==="
rg -i 'alternativeTitle|prefer.*title' src/ --type ts --type js

# Look at the full context around lines 103 and 118-122
echo -e "\n=== Context around microformat and override ==="
sed -n '95,125p' src/providers/song-info.ts

Repository: pear-devs/pear-desktop

Length of output: 3958


Title override bypasses cleanupName() and replaces cleaned title unconditionally.

songInfo.alternativeTitle is sourced from raw microformat.title (line 103) and never passes through cleanupName(). The previous songInfo.title = cleanupName(videoDetails.title) (line 109) stripped suffixes like (Official Music Video), (Lyrics), [Official Visualizer], - Topic, etc. (lines 260–274).

Lines 118–122 unconditionally override the cleaned title with the raw alternative, affecting all plugins that consume songInfo.title without fallback logic:

  • tray.ts — tooltip
  • lumiastream — data.title
  • mpris — xesam:title
  • tuna-obs — title field
  • touchbar — label
  • notifications — title and body

Only discord-service.ts (line 118) and the scrobbler plugins have conditional logic with fallback (alternativeTitle ?? songInfo.title or config flag). For non-music content types, microformat.title can include the exact suffixes cleanupName() was designed to remove — this is a regression.

Suggested fix: apply cleanupName() to the overridden title:

♻️ Proposed fix
-    // Prefer YouTube Music metadata title when available
-    if (songInfo.alternativeTitle) {
-      songInfo.title = songInfo.alternativeTitle;
-    }
+    // Prefer YouTube Music metadata title when available, but still run it
+    // through cleanupName so suffixes like "(Official Music Video)" are stripped
+    // for non-YTM content that also exposes a microformat.title.
+    if (songInfo.alternativeTitle) {
+      songInfo.title = cleanupName(songInfo.alternativeTitle);
+    }

Alternatively, revert lines 118–122 and let Discord handle the preference explicitly at line 118 of discord-service.ts, which already uses fallback logic.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Prefer YouTube Music metadata title when available
if (songInfo.alternativeTitle) {
songInfo.title = songInfo.alternativeTitle;
}
// Prefer YouTube Music metadata title when available, but still run it
// through cleanupName so suffixes like "(Official Music Video)" are stripped
// for non-YTM content that also exposes a microformat.title.
if (songInfo.alternativeTitle) {
songInfo.title = cleanupName(songInfo.alternativeTitle);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/providers/song-info.ts` around lines 118 - 122, The override of
songInfo.title with raw songInfo.alternativeTitle bypasses cleanupName() and
reintroduces suffixes; update the assignment so that when
songInfo.alternativeTitle is used it is passed through cleanupName() (e.g., set
songInfo.title = cleanupName(songInfo.alternativeTitle) or assign the
cleanedAlternative only if non-empty), leaving the existing fallback logic in
discord-service.ts unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants