Skip to content

Releases: tobfd/spicetify-websocket

v0.3.1

Choose a tag to compare

@tobfd tobfd released this 05 Aug 22:17
a85dc90

📦 Release v0.3.1

This patch release improves library compatibility across various Python environments and integrations by broadening the allowed Pydantic version range.

🐛 Fixes & Improvements

  • Broader Pydantic 2.x Compatibility:
    • Relaxed the lower bound requirement for pydantic in pyproject.toml from >=2.13.4 to >=2.0.0,<3.0.0.
    • Ensures seamless installation in environments with pinned Pydantic versions (such as Home Assistant custom components or older 2.x environments).

What's Changed

  • fix: update pydantic version constraint to allow 2.0.0 by @tobfd in #9
  • feat: bump version to 0.3.1 by @tobfd in #10

Full Changelog: 0.3.0...0.3.1

v0.3.0

Choose a tag to compare

@tobfd tobfd released this 04 Aug 19:05
788c9cc

🚀 Release v0.3.0

Version v0.3.0 is a major upgrade featuring standardized event signatures, expanded Pydantic V2 models with rich metadata, wildcard event listening, and full Heart/Like track management.

Important

Version v0.3.0 or higher of spicetify-connect-api is required.


🚨 Breaking Changes

Warning

Please review your event handler signatures before upgrading from v0.2.x to v0.3.0.

  1. Standardized Event Callbacks (PlayerState Payload):

    • All state-change event callbacks (@server.on_song_changed, @server.on_volume_changed, @server.on_repeat_changed, @server.on_shuffle_changed, @server.on_seek_changed, @server.on_play_pause_changed) now receive the full PlayerState snapshot object instead of individual primitive values or sub-models.
    • Migration Example:
      # OLD (v0.2.x)
      @server.on_song_changed
      def on_song(track: TrackInfo):
          print(track.title)
      
      # NEW (v0.3.0)
      @server.on_song_changed
      def on_song(state: PlayerState):
          if state.track:
              print(state.track.title)

    (Note: @server.on_ping continues to receive a UTC datetime object).

  2. Internalization of Request Models:

    • Internal wire request models (PlayRequest, SetVolumeRequest, etc.) have been prefixed with _ (e.g. _PlayRequest, _SetVolumeRequest) and removed from the public module exports to maintain a clean API surface.

✨ New Features

This version introduces several new Pydantic models and parses significantly more metadata fields directly from Spotify:

1. PlayerState (Top-Level Snapshot)

  • event_name: str | None – Name of the event that triggered the state update (e.g. "SongChanged", "VolumeChanged").
  • is_hearted: bool – Whether the currently playing track is liked/hearted.
  • item_index: int | None – 0-based index of the active song in the current context/playlist.
  • context: PlaybackContext | None – Active context metadata object.
  • restrictions: PlaybackRestrictions – Action permissions for the player.
  • timestamp: datetime | None – UTC timestamp of the state snapshot.
  • is_buffering: bool – Stream buffering flag.
  • previous_tracks: list[TrackInfo] – History of previously played tracks in current session.
  • next_tracks: list[TrackInfo] – Upcoming tracks queue.

2. New Sub-Models

  • PlaybackContext: Contains uri, description (e.g. Playlist/Album title), owner, owner_url, image_url, track_count, and url.
  • PlaybackRestrictions: Boolean permissions (can_pause, can_resume, can_seek, can_skip_previous, can_skip_next, can_toggle_repeat_context, can_toggle_repeat_track, can_toggle_shuffle, can_toggle_smart_shuffle).
  • TrackImages: Multi-resolution cover artwork links (small, standard, large, xlarge).

3. Expanded TrackInfo & AlbumInfo

  • TrackInfo: Added images: TrackImages, has_lyrics: bool | None, popularity: int | None, and is_hearted: bool | None.
  • AlbumInfo: Added release_date: str | None and images: list[str].

  • 🌐 Wildcard State Decorator (@server.on_state_changed):
    Subscribe to every player state update event using a single decorator. Access the triggering event name via state.event_name.

    @server.on_state_changed
    def on_any_update(state: PlayerState):
        print(f"[{state.event_name}] Playing: {state.is_playing} | Vol: {state.volume}%")
  • 💚 Full Heart / Like Support:

    • Control liking/unliking tracks: await server.get_heart(), await server.set_heart(status), and await server.toggle_heart().
    • New event decorator: @server.on_heart_changed.
    • New attribute is_hearted available on PlayerState and TrackInfo (for the active song).

What's Changed

  • patch: add permissions for CI content access by @tobfd in #5
  • docs: repo health by @tobfd in #7
  • feat: return playerstate by event by @tobfd in #8

Full Changelog: 0.2.0...0.3.0

v0.2.0

Choose a tag to compare

@tobfd tobfd released this 30 Jul 19:52
95a9e60

Release Notes v0.2.0

🚀 What's New in v0.2.0

Version v0.2.0 introduces major security features, native WSS (SSL/TLS) support, active ping latency measurement, and comprehensive deployment documentation.


🔑 Features & Security

  • API Key Token Authorization:

    • Secure server commands and push events with optional API key authentication (SpotifyServer(api_key="your-token")).
    • Incoming messages with invalid or missing tokens are safely dropped.
    • Command execution with invalid tokens raises UnauthorizedError.
  • Secure WebSockets (WSS):

    • Built-in support for encrypted WebSocket connections using certfile/keyfile paths or custom ssl.SSLContext.
    • Seamless integration with reverse proxies (e.g., Nginx, Caddy) for SSL Offloading.
  • Active Ping & Latency Checks:

    • Measure round-trip latency to the connected Spicetify client using await server.ping().
    • Convenience decorator @server.on_ping to listen to client heartbeat events with typed UTC datetime objects.

📚 Documentation & Guides

  • New Deployment Guides:

    • Local WSS Guide: Step-by-step instructions for local SSL setups via OpenSSL or native Windows 11 using mkcert.
    • VPS Deployment Guide: Production setup using Nginx as a Reverse Proxy with Let's Encrypt certificates and bot-filtering (426 Upgrade Required).
  • Expanded Examples & Docs:

    • Dedicated code examples for API key authentication (examples/api_key.py) and WSS (examples/wss.py).
    • Added a dedicated Documentation & Guides section in README.md.

🐛 Fixes & Maintenance

  • Fixed setuptools package discovery error in pyproject.toml by explicitly setting packages.find.include.
  • Cleaned up Sphinx build warnings (myst.header and duplicate autodoc descriptions in docs/conf.py).
  • Fixed double brackets in README.md link formatting.
  • Added local SSL key files (*.pem) to .gitignore.

💻 Quick Example

import asyncio
from datetime import datetime
from spicetify import SpotifyServer, TrackInfo, UnauthorizedError

async def main():
    async with SpotifyServer(api_key="your-secret-key") as server:
        @server.on_song_changed
        def on_song(track: TrackInfo):
            print(f"🎵 Now playing: {track.title}")

        @server.on_ping
        def on_ping(ping_time: datetime):
            print(f"💓 Heartbeat at: {ping_time.strftime('%H:%M:%S UTC')}")

        await server.wait_for_connection()

        # Measure round-trip latency
        latency = await server.ping()
        print(f"⚡ Latency: {latency:.2f} ms")

        await asyncio.Event().wait()

if __name__ == "__main__":
    asyncio.run(main())

What's Changed

  • feat: add api key support by @tobfd in #4

Full Changelog: 0.1.1...0.2.0

v0.1.1

Choose a tag to compare

@tobfd tobfd released this 29 Jul 00:16
74a6b37

🚀 Release v0.1.1

A quick patch release bringing bug fixes, code cleanup, documentation updates, and automated publishing!


🐛 Bug Fixes

  • Volume Precision: Rounded volume levels to 2 decimal places in server.py to eliminate floating-point precision noise.
  • Documentation Links: Fixed formatting for the spicetify-connect-api repository link in README.md.

🧹 Refactoring & Cleanup

  • Unused Code: Removed unused internal classes from models.py.
  • Version Bump: Bumped package version to 0.1.1.

📚 Documentation & Examples

  • Example Code: Reorganized example scripts to ensure event handlers are registered before executing actions, preventing potential race conditions.

🤖 CI/CD & Automation

  • Automated Releases: Added GitHub Actions workflow for automated Python package releases to PyPI.

Full Changelog: 0.1.0...0.1.1

v0.1.0 - Release

Choose a tag to compare

@tobfd tobfd released this 28 Jul 20:17

🎉 Initial Release v0.1.0

We are excited to announce the first official release of spicetify-websocket! 🚀

An asynchronous Python wrapper and WebSocket server for controlling the Spotify desktop client via Spicetify and the spicetify-connect-api extension.


✨ Highlights

  • ⚡ Real-Time Push Events: Receive instant updates for song changes, volume adjustments, play/pause state, repeat mode, shuffle, and timeline seeking.
  • 🎮 Full Playback Control: Play, pause, skip, force previous track, seek, set volume (0–100%), toggle mute, shuffle, and repeat modes.
  • 🛠️ Convenience Decorators: Expressive event listening with syntax like @server.on_song_changed.
  • 🏷️ Fully Typed Models: Built on Pydantic V2 (TrackInfo, PlayerState, RepeatMode).
  • 🔄 Non-Blocking Async: Powered by asyncio and websockets for maximum performance and zero polling overhead.

📦 Installation

pip install spicetify-websocket

Note: Requires the spicetify-connect-api extension to be enabled in your Spicetify setup.


🔗 Links

Full Changelog: https://github.com/tobfd/spicetify-websocket/commits/0.1.0