Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jobs:
run: python3 scripts/check_dependency_sources.py
- name: Verify workspace documentation
run: python3 scripts/check_workspace_docs.py
- name: Verify GPL-3.0 source headers
run: python3 scripts/check_license_headers.py
- run: cargo fmt --all -- --check
- run: cargo clippy --workspace --all-features --locked -- -D warnings

Expand Down
14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ only with executable evidence against the governing specification.
- A new `#[allow(...)]` must have an adjacent comment that names the concrete
reason it is necessary.

## Licensing

StackArr is GPL-3.0-only. Every first-party source file starts with the SPDX
header, below any shebang and before the rest of the file:

```
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors
```

Use `#` comments in shell and Python and `/* */` in CSS. New files are covered
by `python3 scripts/check_license_headers.py`, which CI runs and which inserts
missing headers when passed `--fix`.

## Required gates

The repository toolchain is pinned in `rust-toolchain.toml`. Before every
Expand Down
3 changes: 3 additions & 0 deletions client/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
Expand Down
3 changes: 3 additions & 0 deletions client/public/sw.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

const CACHE_NAME = 'stackarr-shell-v1';
const SHELL_URLS = [
'/app/',
Expand Down
3 changes: 3 additions & 0 deletions client/src-tauri/build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

fn main() {
tauri_build::build();
}
3 changes: 3 additions & 0 deletions client/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
Expand Down
3 changes: 3 additions & 0 deletions client/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

// Prevents additional console window on Windows in release
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

Expand Down
3 changes: 3 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useEffect, useCallback } from 'react'
import { Routes, Route, NavLink, useLocation, useNavigate } from 'react-router-dom'
import { Tv, Film, Home, LogOut, User, Search, ListChecks, Bookmark, Settings, Calendar, Download, Clock } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

// ── Connection management ───────────────────────────────────────────────────

export interface ServerConnection {
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/ActivityIndicator.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { Loader2 } from 'lucide-react'
import { useRunningActivities } from '../hooks/useApi'

Expand Down
3 changes: 3 additions & 0 deletions client/src/components/DiscoverGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { Check, Clock, Library, Plus, X } from 'lucide-react'
import { imageUrl, type DiscoverResult } from '../api'
import { useMobile } from '../hooks/useMobile'
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { Component, type ReactNode } from 'react'
import type { ErrorInfo } from 'react'

Expand Down
3 changes: 3 additions & 0 deletions client/src/components/MediaRow.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useNavigate } from 'react-router-dom'
import { imageUrl, type ContinueWatchingItem } from '../api'
import { useMobile } from '../hooks/useMobile'
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/NotificationBell.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useEffect, useRef, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import { Bell } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/NotificationDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import type { UserNotification } from '../api'
import NotificationItem from './NotificationItem'
import { useMobile } from '../hooks/useMobile'
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/NotificationItem.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import type { UserNotification } from '../api'

function relativeTime(dateStr: string): string {
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/ProgressReporter.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useEffect, useRef, useCallback } from 'react'
import { api } from '../api'

Expand Down
3 changes: 3 additions & 0 deletions client/src/components/RatingStars.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState } from 'react'
import { Star } from 'lucide-react'
import { useRating, useSetRating, useDeleteRating } from '../hooks/useApi'
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/RequestCard.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { Clock, Check, X, Library } from 'lucide-react'
import { imageUrl, type MediaRequest } from '../api'

Expand Down
3 changes: 3 additions & 0 deletions client/src/components/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

const shimmerBg = 'linear-gradient(90deg, #1e293b 25%, #334155 50%, #1e293b 75%)'
const shimmerSize = '200% 100%'
const shimmerAnim = 'shimmer 1.5s infinite'
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/StreamStats.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useEffect, useState, useRef } from 'react'
import Hls from 'hls.js'

Expand Down
3 changes: 3 additions & 0 deletions client/src/components/TmdbRow.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { Film } from 'lucide-react'
import { imageUrl } from '../api'
import { useMobile } from '../hooks/useMobile'
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/WatchlistButton.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useEffect } from 'react'
import { Bookmark } from 'lucide-react'
import { api } from '../api'
Expand Down
3 changes: 3 additions & 0 deletions client/src/context/AuthContext.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

/* eslint-disable react-refresh/only-export-components -- context files co-export provider + context value */
import { createContext, useState, useEffect, useCallback, type ReactNode } from 'react'

Expand Down
3 changes: 3 additions & 0 deletions client/src/globals.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

declare const __APP_VERSION__: string
3 changes: 3 additions & 0 deletions client/src/hooks/useApi.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { api } from '../api'

Expand Down
3 changes: 3 additions & 0 deletions client/src/hooks/useAuth.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useContext } from 'react'
import { AuthContext } from '../context/AuthContext'
import type { AuthContextValue } from '../context/AuthContext'
Expand Down
3 changes: 3 additions & 0 deletions client/src/hooks/useMobile.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useSyncExternalStore } from 'react'

const MOBILE_BREAKPOINT = 768
Expand Down
3 changes: 3 additions & 0 deletions client/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

/* eslint-disable react-refresh/only-export-components -- entry point, no HMR exports needed */
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/AccountPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState } from 'react'
import { Monitor, Smartphone, Globe, Trash2, LogOut } from 'lucide-react'
import { useAuth } from '../hooks/useAuth'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/Browse.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useEffect, useMemo } from 'react'
import { useNavigate } from 'react-router-dom'
import { Search, Play, Film } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/CalendarPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useMemo, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { ChevronLeft, ChevronRight, Check, Clock } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/DiscoverPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useCallback, useRef, useEffect } from 'react'
import { useNavigate, useSearchParams } from 'react-router-dom'
import { Search, Film, Tv } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/HistoryPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { ChevronLeft, ChevronRight, Download, Upload, Search, Trash2, RotateCcw, Clock } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useMemo, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import { Play } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/LoginPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState } from 'react'
import { useAuth } from '../hooks/useAuth'
import { labelStyle, inputStyle, buttonStyleDisabled } from '../styles/forms'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/MovieView.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useCallback } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { ArrowLeft, Play, Film } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/Player.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useEffect, useRef, useState, useCallback } from 'react'
import { useParams, useNavigate, useLocation } from 'react-router-dom'
import { ArrowLeft, Maximize, Minimize, RotateCcw, RotateCw, PictureInPicture2, Play, Pause } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/QueuePage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useNavigate } from 'react-router-dom'
import { Download, Trash2, AlertCircle, ArrowDown, ArrowUp } from 'lucide-react'
import type { QueueItem } from '../api'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/RegisterPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState } from 'react'
import { useAuth } from '../hooks/useAuth'
import { labelStyle, inputStyle, buttonStyleDisabled } from '../styles/forms'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/RequestsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useMemo } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { Check, X } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/SeriesView.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useEffect, useCallback } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { ArrowLeft, Play, ChevronDown, ChevronRight } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/ServerConnect.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState } from 'react'
import { redeemClaimCode, saveConnection, assetUrl, type ServerConnection } from '../api'
import { labelStyle, inputStyle, buttonStyleDisabled } from '../styles/forms'
Expand Down
3 changes: 3 additions & 0 deletions client/src/pages/WatchlistPage.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { useState, useMemo } from 'react'
import { useNavigate } from 'react-router-dom'
import { Bookmark, X, Tv, Film } from 'lucide-react'
Expand Down
3 changes: 3 additions & 0 deletions client/src/styles/forms.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import type { CSSProperties } from 'react'

export const labelStyle: CSSProperties = {
Expand Down
3 changes: 3 additions & 0 deletions client/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann-parity/src/comparator.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Compare Prowlarr search results with StackArr Cardigann engine results.

use std::collections::HashMap;
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann-parity/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Cardigann parity test harness.
//!
//! Spins up a dedicated Prowlarr instance, provisions all public indexers,
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann-parity/src/provisioner.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Auto-provision all public Cardigann indexers in a Prowlarr instance.

use anyhow::{Context, Result};
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann-parity/src/prowlarr_api.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Prowlarr REST API client for the parity test harness.

use std::time::Duration;
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann-parity/src/report.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Parity report generation.

use std::path::Path;
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann/src/categories.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Category mapping between Cardigann indexer categories and Newznab standard categories.

use std::collections::HashMap;
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann/src/definition.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Serde structs for Cardigann YAML definitions.
//!
//! These mirror Prowlarr's `CardigannDefinition.cs` types and are deserialized
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann/src/filters.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Filter implementations for Cardigann field value transforms.
//!
//! Each filter takes an input string and optional arguments and returns
Expand Down
3 changes: 3 additions & 0 deletions crates/stackarr-cardigann/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 The StackArr Authors

//! Cardigann YAML definition engine for StackArr.
//!
//! Interprets Prowlarr-compatible Cardigann YAML indexer definitions,
Expand Down
Loading
Loading