WolfWave

Architecture

WolfWave project structure and architecture overview

WolfWave follows a clean architecture with clear separation of concerns.

Project Structure

src/
├── WolfWaveTests/           # Unit tests (XCTest)
│   ├── AppConstantsTests.swift
│   ├── BotCommandDispatcherTests.swift
│   ├── LastSongCommandTests.swift
│   ├── OnboardingViewModelTests.swift
│   ├── SongCommandTests.swift
│   ├── TwitchViewModelTests.swift
│   ├── UpdateCheckerServiceTests.swift
│   └── WebSocketServerServiceTests.swift
└── wolfwave/
├── Core/                    # Core utilities and services
│   ├── AppConstants.swift       # Application constants
│   ├── KeychainService.swift    # Secure credential storage (Keychain API)
│   └── Logger.swift             # Centralized logging with categories
├── Monitors/                # Music playback monitoring
│   └── MusicPlaybackMonitor.swift  # ScriptingBridge-based Apple Music integration
├── Services/                # External service integrations
│   ├── Discord/
│   │   └── DiscordRPCService.swift  # Discord Rich Presence via IPC socket
│   ├── UpdateChecker/
│   │   └── UpdateCheckerService.swift  # GitHub Releases version checker
│   ├── WebSocket/
│   │   └── WebSocketServerService.swift  # Local WebSocket server (Network.framework)
│   └── Twitch/
│       ├── TwitchChatService.swift     # EventSub WebSocket + Helix API
│       ├── TwitchDeviceAuth.swift      # OAuth Device Code flow
│       └── Commands/                   # Bot command system
│           ├── BotCommand.swift        # Command protocol
│           ├── BotCommandDispatcher.swift  # Command routing
│           ├── SongCommand.swift       # !song command implementation
│           └── LastSongCommand.swift   # !lastsong command implementation
├── Views/                   # SwiftUI views
│   ├── SettingsView.swift       # Main settings interface
│   ├── Advanced/                # Advanced settings
│   ├── AppVisibility/           # App visibility settings
│   ├── Discord/                 # Discord Rich Presence settings
│   │   └── DiscordSettingsView.swift
│   ├── MusicMonitor/            # Music monitor settings
│   ├── Onboarding/              # First-launch onboarding wizard
│   │   ├── OnboardingView.swift
│   │   ├── OnboardingViewModel.swift
│   │   ├── OnboardingWelcomeStepView.swift
│   │   ├── OnboardingTwitchStepView.swift
│   │   ├── OnboardingDiscordStepView.swift
│   │   └── OnboardingOBSWidgetStepView.swift
│   ├── Shared/                  # Shared UI components
│   │   └── TwitchGlitchShape.swift
│   ├── Twitch/                  # Twitch-related views
│   │   ├── TwitchSettingsView.swift   # Twitch bot configuration UI
│   │   ├── TwitchViewModel.swift      # Twitch state management
│   │   ├── DeviceCodeView.swift       # Device auth UI
│   │   └── ...
│   └── WebSocket/               # OBS Widget settings
│       └── WebSocketSettingsView.swift
└── Resources/              # Assets and resources
    └── Assets.xcassets/

Architecture Highlights

MARK Sections

Every file uses clear section markers for easy navigation:

// MARK: - Properties
// MARK: - Initialization
// MARK: - Public Methods
// MARK: - Private Helpers

Documentation

Comprehensive DocC-style comments with parameter/return documentation throughout the codebase.

Delegation Pattern

MusicPlaybackMonitorDelegate is used for track update notifications, following Apple's delegation pattern. The delegate receives track name, artist, album, duration, and elapsed time on every update.

MVVM Architecture

ViewModels separate UI logic from business logic:

  • TwitchViewModel manages Twitch connection state
  • Views observe ViewModel changes via @StateObject / @ObservedObject

Modern Concurrency

Swift's async/await is used throughout for asynchronous operations:

func fetchData() async throws -> Data {
    // Modern async implementation
}

Key Components

KeychainService

Secure storage for sensitive credentials using the macOS Keychain API. All tokens and secrets are stored securely, never in UserDefaults or plain text.

MusicPlaybackMonitor

Uses ScriptingBridge for direct Apple Music communication without spawning subprocesses. Provides real-time track updates (including duration and elapsed time) via delegation.

TwitchChatService

Full Twitch integration using:

  • Helix API for sending messages and API requests
  • EventSub WebSocket for real-time chat message notifications
  • OAuth Device Code Flow for secure authentication

DiscordRPCService

Discord Rich Presence integration using:

  • Local IPC Socket: Communicates with Discord via Unix domain socket — no bot token or server required
  • iTunes Search API: Fetches album artwork dynamically with in-memory caching
  • Playback Progress: Displays elapsed time and duration as a progress bar on Discord
  • Auto-reconnect: Detects Discord availability and reconnects automatically
  • Sandbox Compatible: Uses SBPL entitlements for socket access within the App Sandbox

WebSocketServerService

Local WebSocket server for OBS stream overlays using:

  • Network.framework NWListener: Native WebSocket server with auto-ping and multi-client support
  • JSON Broadcasting: Sends welcome, now_playing, progress, and playback_state messages
  • Progress Timer: 1-second interval broadcasts with elapsed-time estimation to avoid polling ScriptingBridge
  • Thread Safety: NSLock instances for connections, playback state, and enabled flag
  • Auto-retry: Reconnects the listener after failures with configurable delay

UpdateCheckerService

Automatic update checker that:

  • Queries the GitHub Releases API for the latest version
  • Compares semantic versions (major.minor.patch) against the running app
  • Detects install method (Homebrew vs DMG) via bundle path inspection
  • Posts notifications for the settings UI and macOS notification center
  • Runs on a 24-hour schedule with a 10-second launch delay

BotCommandDispatcher

Extensible command routing system that:

  • Registers available commands
  • Matches incoming messages to triggers
  • Executes commands and returns responses

On this page