Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/x-eon-max/LiveLyrics/llms.txt

Use this file to discover all available pages before exploring further.

LiveLyrics communicates with Discord by sending HTTP PATCH requests directly to Discord’s user settings API. Each request replaces your custom status with the current lyric line, paired with a 🎡 emoji. No Discord bot, OAuth flow, or Rich Presence socket is involved β€” LiveLyrics acts as your own account making changes on your behalf, authenticated with your personal user token.

Authentication

LiveLyrics uses a Discord user token β€” the credential your own Discord client uses to authenticate your account β€” rather than a bot token. This token is stored in the TOKEN variable near the top of LiveLyrics.py:
TOKEN = 'YOUR-TOKEN-HERE'
The token is sent as the value of the authorization header in every request. Unlike bot tokens, user tokens are passed without a Bearer prefix, matching the convention Discord’s own client uses:
headers = {"authorization": TOKEN}
Your Discord user token is a full account credential. Anyone who obtains it can log in to your account, read your messages, and perform any action you can. Never share your token, commit it to version control, include it in screenshots, or expose it in any public place. If you believe your token has been compromised, change your Discord password immediately β€” this invalidates the current token and generates a new one.

The PATCH Request

Status updates are sent by the update_status() function, which issues a single PATCH request to the Discord user settings endpoint:
def update_status(text):
    url = "https://discord.com/api/v9/users/@me/settings"
    headers = {"authorization": TOKEN}
    payload = {"custom_status": {"text": text, "emoji_name": "🎡"}}
    r = requests.patch(url, json=payload, headers=headers, timeout=10)
    r.raise_for_status()
The custom_status object accepts two fields:
  • text β€” the string displayed as your status. LiveLyrics passes the current lyric line, capped at 128 characters (Discord’s limit for custom status text).
  • emoji_name β€” the emoji rendered beside the status text. LiveLyrics always uses 🎡 to signal that the status is music-related.
update_status() is called only when the current lyric line changes β€” when line != last_line in main(). If the same line is still active on the next loop iteration (because the playback position has not yet advanced past the next timestamp), no request is sent.

Rate Limiting and Efficiency

LiveLyrics is designed to be a light, low-overhead process:
  • Change-gated updates β€” update_status() is only called on a lyric transition, not on every loop tick. A typical song has 30–60 lyric lines, so even a three-minute track generates fewer than 60 PATCH requests.
  • Fast loop, minimal CPU β€” the main loop sleeps 10 ms between iterations (asyncio.sleep(0.01)), giving the event loop time to yield without introducing noticeable latency in lyric changes. If an unexpected error occurs during media retrieval, the loop instead backs off for 2 seconds (asyncio.sleep(2)) before retrying, avoiding a tight error spin.
Discord does not publish official rate-limit figures for the user settings endpoint. However, because LiveLyrics sends at most one PATCH request per lyric-line change, the update frequency is naturally bounded by the cadence of the lyrics themselves β€” typically one request every few seconds β€” which sits well within any reasonable threshold.

Error Handling

update_status() wraps the network call in a try/except block so that transient failures never bring down the main loop:
try:
    r = requests.patch(url, json=payload, headers=headers, timeout=10)
    log(f"Discord response: status_code={r.status_code}")
    if r.status_code >= 400:
        log(f"Discord response body (error): {r.text}")
    r.raise_for_status()
except requests.RequestException as e:
    log(f"ERROR update_status: {e}")
  • Any requests.RequestException (connection timeout, DNS failure, etc.) is logged with a timestamp and swallowed, allowing the next iteration to proceed normally.
  • HTTP 4xx responses β€” such as a 401 Unauthorized caused by an invalid or expired token β€” are detected before raise_for_status() and the full response body is logged, giving you the diagnostic detail needed to identify the problem.

Build docs developers (and LLMs) love