* bump to 6.1.0 * chore: updated build images * New: add TTL setting for pushover notifications (cherry picked from commit 317cdf15582746bd4e713d6b99e17a21dcb8abeb) * Chore: Remove Readarr donation logo * Skip proxy tests on MacOsX * Fix: (#11303) collection API error when using `Movie CollectionThe` (#11304) Co-authored-by: Bogdan <mynameisbogdan@users.noreply.github.com> * feat: initial project branding and setup * chore: move project config to development folder * feat(ci): add GitHub Actions and Docker configuration * docs: update documentation for rebrand * chore: update Windows and macOS distribution branding * feat(privacy): remove telemetry, analytics, fingerprinting * docs: add privacy section and document cleanup candidates * docs: simplify privacy section * feat: rebrand to Logarr with teal theme * refactor(ui): update page titles and manifest for rebrand * fix(security): patch SQL injection, path traversal, command injection * docs: update CHANGELOG with security fixes and branding * fix: resolve build issues for local development * chore: update GitHub username to cheir-mneme * refactor: rename project from Logarr to Aletheia * fix(ci): add disk space cleanup for Docker multi-arch builds * refactor: remove empty housekeeping classes and commented properties * docs: update PR template for Aletheia workflow * fix(build): use pipe delimiter in sed for branch names with slashes * fix(security): address pre-release security blockers - Reject unknown sender types in certificate validation - Disable auto-redirect in SkyHookProxy to prevent HTTPS downgrade - Use proper JSON serialization in InitializeJsonController - Add whitelist validation for Type.GetType in converters * docs: update community standards with conventional commits and Aletheia branding * docs: link README to CONTRIBUTING.md * chore: add pre-commit hooks and CI coverage reporting - Add pre-commit hook for JS/TS and CSS lint checks - Add setup script to install hooks - Add coverage reporting to CI workflow - Add coverage threshold warning (60%) - Update CONTRIBUTING.md with hooks setup instructions * feat(download): add automatic archive extraction (Unpackerr absorption) - Add SharpCompress for RAR/7z support - Extend ArchiveService with RAR, 7z extraction via SharpCompress - Add DownloadExtractionService for orchestrating extraction - Add config: AutoExtractArchives (default: false) - Add config: DeleteArchiveAfterExtraction (default: true) - Integrate extraction into CompletedDownloadService Note: UI settings page not yet implemented - backend foundation only. * fix(style): use explicit HashSet type for StyleCop SA1000 * fix(style): use explicit HashSet type for StyleCop SA1000 * fix(ci): copy test DLLs to expected location for test.sh * fix(style): use explicit JsonSerializerOptions type * fix(style): remove unused using, use AsSpan over Substring * chore(deps): bump js-yaml in the npm_and_yarn group across 1 directory Bumps the npm_and_yarn group with 1 update in the / directory: [js-yaml](https://github.com/nodeca/js-yaml). Updates `js-yaml` from 4.1.0 to 4.1.1 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.1.1 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] <support@github.com> * feat(indexer): add multi-media type foundation Add MediaType enum and indexer support for books/audiobooks: - MediaType enum (Movie, TV, Music, Book, Audiobook, Podcast, Comic) - NewznabStandardCategory constants for all media types - Database migration 243 for SupportedMediaTypes column - Updated IndexerDefinition, IIndexer, IndexerBase - Updated README with current project status * feat(indexer): add book/audiobook search criteria Add search criteria classes and update request generators: - BookSearchCriteria (Author, Title, ISBN, Publisher, Year) - AudiobookSearchCriteria (Author, Title, Narrator, ASIN, ISBN) - Updated IIndexerRequestGenerator interface - Implemented book/audiobook search in NewznabRequestGenerator - Added stub implementations to all other request generators * Add SonarCloud analysis workflow This workflow triggers a SonarCloud analysis of the code and populates GitHub Code Scanning alerts with vulnerabilities found. * fix: disable SA1200 StyleCop rule to match stylecop.json config * Add GitHub Super Linter workflow This workflow runs multiple linters on code changes in the 'develop' branch for both pushes and pull requests. * Add Trivy vulnerability scanning workflow * ci: fix workflow configs and add dependabot - SonarCloud: add proper projectKey and organization - Trivy: fix image reference, add schedule comment - Super Linter: upgrade to v6, configure linter selection - Add Dependabot for NuGet, npm, Docker, GitHub Actions * fix(ci): correct Dockerfile path and skip SonarCloud when token missing * fix(ci): use filesystem scan instead of image scan for Trivy * fix(ci): use exclusion-only config for super-linter * fix(ci): disable checkov and github_actions linters in super-linter * ci(deps): bump actions/checkout from 4 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * ci(deps): bump actions/cache from 4 to 5 Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * ci(deps): bump codecov/codecov-action from 4 to 5 Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * ci(deps): bump dessant/label-actions from 3 to 5 Bumps [dessant/label-actions](https://github.com/dessant/label-actions) from 3 to 5. - [Release notes](https://github.com/dessant/label-actions/releases) - [Changelog](https://github.com/dessant/label-actions/blob/main/CHANGELOG.md) - [Commits](https://github.com/dessant/label-actions/compare/v3...v5) --- updated-dependencies: - dependency-name: dessant/label-actions dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * Bump the nuget group with 1 update Bumps System.Private.Uri from 4.3.0 to 4.3.2 --- updated-dependencies: - dependency-name: System.Private.Uri dependency-version: 4.3.2 dependency-type: direct:production dependency-group: nuget - dependency-name: System.Private.Uri dependency-version: 4.3.2 dependency-type: direct:production dependency-group: nuget ... Signed-off-by: dependabot[bot] <support@github.com> * docs: update CLA to reference Aletheia * ci: remove super-linter workflow Linting covered by existing tools: - C#: StyleCop during build - GitHub Actions: CodeQL - Frontend: eslint in package.json * feat(indexer): add MyAnonamouse indexer for books and audiobooks * feat(indexer): enable book and audiobook support in Newznab/Torznab * feat(ui): add media type badge to poster view * fix: address code review findings - Fix Torznab default definition protocol (Usenet -> Torrent) - Add try-catch around JSON deserialization in MAM parser - Add logging for author info parse failures - Add null check for JSON response * fix: add timeout to regex for DoS prevention * fix: mark React component props as Readonly Bulk update to make all component props immutable at the type level. This prevents accidental prop mutation and improves type safety. Resolves ~50 SonarCloud code smells. * refactor: replace ApplicationException with domain-specific exceptions Create custom exception classes: - InvalidDatabaseSchemaException for migration errors - ServiceInstallationException for service install failures - DataRetrievalException for repository query mismatches - InvalidRequestException for HTTP request validation - InvalidHeaderException for HTTP header validation Resolves SonarCloud S3988 (ApplicationException usage). * refactor(ui): extract PosterDateRow to reduce MovieIndexPoster complexity Extract repetitive date display logic into PosterDateRow component. Reduces cognitive complexity from 30 to ~20 by consolidating 4 similar conditional blocks into reusable component calls. * refactor: reduce MyAnonamouseParser cognitive complexity Extract helper methods for author parsing, title flags, and freeleech detection to simplify the main ParseResponse loop. Addresses #30 * refactor: reduce LanguageParser cognitive complexity Replace 40+ individual if statements with dictionary-based lookup. Extract helper methods for keyword, case-sensitive regex, and case-insensitive regex language detection. Original method reduced from ~400 lines to ~17 lines while preserving all behavior. * refactor: make methods static where instance data not used (S2325) ~243 methods converted to static where they don't access instance data. Fixed call sites that needed to use type name instead of instance. * refactor: seal non-derived private classes (S3260) 63 private nested classes marked as sealed since they have no derived classes. * perf: use char overloads for StartsWith/EndsWith (S6610) Use single character overloads instead of single-character string overloads for better performance. * refactor: use Number.parseInt/parseFloat/isNaN (S7773) Use Number static methods instead of global functions for better clarity and consistency. * Update README for clarity and typo corrections Corrected typos and improved clarity in the README. * refactor: remove redundant boolean literals (S1125) Replace == false with negation operator, remove == true comparisons * ci: remove sonarcloud workflow (conflicts with automatic analysis) * docs: add comprehensive technical debt tracking * docs: remove tech debt tracking from repo (moved to wrapper) * fix(security): sanitize user-controlled strings in log statements Add SanitizeForLog() extension method to prevent log forging attacks by replacing control characters (newlines, etc.) with spaces. Applied across 30 files that log user-controlled data like paths, titles, URLs, and usernames. Fixes CodeQL log-forging alerts. * fix: resolve technical debt and npm vulnerabilities NPM Security (0 vulnerabilities remaining): - Add yarn resolutions for cross-spawn, brace-expansion, color-string, glob, postcss Bug fixes: - Bug-002: Use FirstOrDefault with null check (DownloadStationTaskProxyV2) - Bug-007: Fix inverted exception logic for magnet fallback (TorrentClientBase) - Bug-008: Fix stale closure using ref (MovieSearchInput) - Bug-009: Fix Number.Number.parseInt typos across 50+ files - Bug-010: Add regex timeout and Compiled flag (RegexReplace) - Bug-011: Add null checks for XML queries (ConfigFileProvider) - Bug-012: Remove empty touch handler (MovieDetails) - Bug-013: Use Path.GetFileName for safer check (InstallUpdateService) - Bug-014: Return Ok instead of Accepted for sync PUT (MovieController) - Bug-016: Fix double bracket typo in log message (InstallUpdateService) - Bug-017: Add console.warn to catch block (MovieTagInput) - Bug-018: Remove stray debug console.log (SignalRConnector) - Bug-019: Document disabled regex with ReDoS justification (Parser) * Fix deadlock risk in ReleasePushController with async SemaphoreSlim * Add log sanitization for CodeQL log forging alerts * Add custom CodeQL config to exclude log-forging false positives * Fix CodeQL qlpack.yml - add library: true * Trigger CI after disabling default CodeQL * Update CodeQL config to exclude path-injection and use security-extended * Exclude additional CodeQL false positives for single-user app * Exclude SonarCloud S5145 false positive log injection warnings * Suppress S5145 log injection false positive in editorconfig * Add CI-based SonarCloud workflow with rule exclusions * Remove sonar-project.properties - not supported by SonarScanner for .NET * Remove SonarCloud CI workflow - conflicts with automatic analysis * Fix CodeQL rule ID for insecure-direct-object-reference * Fix remaining technical debt bugs - Bug-001: Add null check for SingleOrDefault() in TorrentRssParser - Bug-006: Replace generic Exception with PathCombinationException in OsPath - Bug-006: Replace generic Exception with NotSupportedException in IMDbListRequestGenerator * Fix blocking semaphore in MediaCoverService Convert _semaphore.Wait() to async pattern with WaitAsync() to prevent thread blocking during image resizing operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix CancellationTokenSource resource leaks (BLOCKER severity) - ManagedHttpDispatcher: Dispose quickFailCts and linkedTokenSource in finally block - CommandExecutor: Dispose _cancellationTokenSource on shutdown - Scheduler: Dispose _cancellationTokenSource on shutdown - IntegrationTestBase: Store CTS as field and dispose in TearDown 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add IMDb list error message verification tests * fix: thread-safe SHA1 hashing in HashConverter * fix(ci): pin Trivy action and update branding * fix(ci): add CODEOWNERS, enable test blocking, add pre-commit hooks * chore: update yarn.lock with husky and lint-staged * fix(ci): P2 improvements - editorconfig, integration tests, Prettier 3 - Remove duplicate dotnet_style_qualification rules in .editorconfig - Update Radarr branding to Aletheia in .editorconfig - Add integration tests step to build.yml (with continue-on-error) - Upgrade Prettier to 3.7.4, eslint-plugin-prettier to 5.5.4 - Upgrade eslint-config-prettier to 10.1.8 - Fix pre-existing lint errors (unused vars, radix parameter) - Reformat frontend code with Prettier 3 formatting changes Closes #57 (SonarCloud deferred - needs org setup) Closes #58, #62 (partial - ESLint 9 deferred), #63 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(security): address P3 vulnerabilities and add mitigations Security fixes: - XXE prevention: disable XmlResolver in UTorrentProxy.cs (#42) - Path traversal: validate paths in LogFileController.cs (#44) - Path traversal: validate paths in MediaCoverController.cs (#44) - ReDoS mitigation: add 5s timeout to user regex patterns Documentation: - CORS: document security rationale in Startup.cs (#43) Closes #42, #43, #44 Related: #59, #60, #61 (SonarCloud triage - GitHub alerts now at 0 open) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Cache regex instances as static compiled fields - SkyHookProxy: Cache IMDB/TMDB URL regexes - PushsaferSettings: Cache hex color validation regex - Parser: Cache IMDB ID validation regex * Optimize O(n*m) Contains patterns with HashSet - MovieService.FindByTitle: Convert title lists to HashSets - MoviesSearchService: Convert queue IDs to HashSet * fix(security): add path validation to OpenWriteStream and regex timeouts - DiskProviderBase: Add Ensure.That path validation to OpenWriteStream - CleanseLogMessage: Add 5-second timeout to all 22 regex patterns to prevent ReDoS * fix(frontend): address React and TypeScript quality issues - Replace index-as-key antipattern with stable keys (#34) - Remove TypeScript any types in favor of proper types (#37) - Memoize inline style objects to prevent unnecessary re-renders (#41) Files: 17 frontend components updated * Migrate to ESLint 9 flat config - Create eslint.config.mjs with ESM flat config format - Remove legacy .eslintrc.js and .eslintignore - Remove eslint-plugin-filenames (not ESLint 9 compatible) - Update lint-staged to use new config - Clean up unused eslint-disable directives * Fix SonarCloud issues and add suppression config Backend: - Add regex timeout to prevent ReDoS (S6444): - SkyHookProxy.cs: ImdbUrlRegex, TmdbUrlRegex - PushsaferSettings.cs: HexColorRegex - Parser.cs: ImdbIdRegex Frontend: - Fix sorting without localeCompare (S2871): - MovieIndex.tsx, Collection.js, DiscoverMovie.js Config: - Add sonar-project.properties with documented false positive suppressions: - S8135: TMDB public API token (not a secret) - S6680: Directory depth iteration (naturally bounded) - S6674: NLog structured logging placeholder syntax - S4662: PostCSS mixin directives - S5145: Sanitized log data * Fix SonarCloud bugs: threading, React state, sorting Backend: - S2445: Make _connections readonly in MessageHub.cs to fix locking issue Frontend: - S6756: Use callback form of setState when referencing previous state - Collection.js, DiscoverMovie.js, ImportMovie.js - ImportMovieSelectMovie.js, EditQualityProfileModalContentConnector.js - S2871: Add localeCompare for proper alphabetical sorting - Collection.js, DiscoverMovie.js, MovieIndex.tsx - S1764: Remove duplicate condition in QualityProfileSelectInput.tsx * fix: SonarCloud bugs batch 2 - S2445: Make _connections readonly for thread-safe locking (MessageHub.cs) - S6756: Use setState callbacks for 5 React components - S1764: Remove duplicate expression in QualityProfileSelectInput.tsx - S2583: Remove unreachable conditions in NotificationDefinition.cs - S2259: Fix null reference in Pushcut.cs * fix: SonarCloud null safety and struct comparison issues - OsPath.cs: Remove ReferenceEquals checks on struct (always false) - SkyHookProxy.cs: Add null-conditional operators for Credits.Cast/Crew * fix: remaining React index-as-key issues + backend null safety (#78) * fix: SonarCloud null safety and struct comparison issues - OsPath.cs: Remove ReferenceEquals checks on struct (always false) - SkyHookProxy.cs: Add null-conditional operators for Credits.Cast/Crew * fix: remaining React index-as-key issues and backend null safety Frontend: - Fix 8 remaining index-as-key violations using content-based keys - ImportMovieSelectFolder.js: use errorMessage as key - ImportMovieFooter.js: use errorMessage as key - CustomFormat.js: use item.name as key - AddSpecificationItem.js: use preset.name as key - QualityProfileItems.js: use message as key - QualityProfileFormatItems.js: use message as key Backend (cherry-picked from batch-3): - OsPath.cs: Remove ReferenceEquals on struct - SkyHookProxy.cs: Add null-conditional for Credits --------- Co-authored-by: admin <admin@ardentleatherworks.com> * refactor: notification provider deduplication + docs (#81) * fix: SonarCloud null safety and struct comparison issues - OsPath.cs: Remove ReferenceEquals checks on struct (always false) - SkyHookProxy.cs: Add null-conditional operators for Credits.Cast/Crew * fix: remaining React index-as-key issues and backend null safety Frontend: - Fix 8 remaining index-as-key violations using content-based keys - ImportMovieSelectFolder.js: use errorMessage as key - ImportMovieFooter.js: use errorMessage as key - CustomFormat.js: use item.name as key - AddSpecificationItem.js: use preset.name as key - QualityProfileItems.js: use message as key - QualityProfileFormatItems.js: use message as key Backend (cherry-picked from batch-3): - OsPath.cs: Remove ReferenceEquals on struct - SkyHookProxy.cs: Add null-conditional for Credits * refactor(notifications): consolidate GetPosterUrl to base class * docs: add architectural decisions log * fix(sonar): enable path traversal suppressions for media management app --------- Co-authored-by: admin <admin@ardentleatherworks.com> * perf: cache regex patterns in Parser.ToUrlSlug and FileNameBuilder.GetEditionToken (#82) Co-authored-by: admin <admin@ardentleatherworks.com> * fix: add null safety to LINQ First/Single calls (#83) Co-authored-by: admin <admin@ardentleatherworks.com> * fix(frontend): remove index from React keys in dynamic lists (#84) Co-authored-by: admin <admin@ardentleatherworks.com> * chore: update GitHub Actions and consolidate .editorconfig rules (#85) Co-authored-by: admin <admin@ardentleatherworks.com> * fix(ui): update user-facing links to Aletheia resources (#86) - MoreInfo: point to Aletheia GitHub instead of Radarr resources - UpdateChanges: link issue numbers to Aletheia repo - Add "Upstream" translation key for Radarr reference link Closes #53 Co-authored-by: admin <admin@ardentleatherworks.com> * fix(frontend): memoize inline JSX objects for performance (#87) - MovieIndexTable: memoize itemData, move row flex styles to CSS - MovieIndexOverviews: memoize itemData, extract listStyle constant - MovieIndexOverview: memoize elementStyle and infoStyle - CircularProgressBar: memoize containerStyle and circleStyle Reduces unnecessary re-renders in virtualized lists and frequently rendered components. Closes #41 Co-authored-by: admin <admin@ardentleatherworks.com> * chore(ci): standardize branch naming to use main instead of master (#90) - Update workflow triggers to use main instead of master - Update CONTRIBUTING.md to reference main branch - Aligns with documentation in CLAUDE.md Closes #52 Note: Actual branch rename (master → main) must be done on GitHub. Co-authored-by: admin <admin@ardentleatherworks.com> * fix(frontend): replace any types with proper TypeScript types (#88) * fix(frontend): replace any types with proper TypeScript types - AutoSuggestInput: use Data type from popper.js for modifier callback - Tooltip: use Data type from popper.js for computeMaxSize callback - OverlayScroller: use ComponentPropsWithoutRef<'div'> for renderView - index.ts: use unknown[] instead of any[] for logError parameters Improves type safety and removes eslint-disable comments. Partially addresses #37 * fix(frontend): use ModifierFn type and string values for Popper styles - Use ModifierFn type from popper.js for modifier callbacks - Calculate bottom/right from offset properties (top+height, left+width) - Convert numeric style values to strings with 'px' suffix - Fix typo: 'botton' -> 'bottom' in AutoSuggestInput --------- Co-authored-by: admin <admin@ardentleatherworks.com> * perf(backend): cache additional regex patterns (#89) * perf(backend): cache regex patterns for better performance - TransmissionBase: add static VersionRegex, share with Transmission - SearchCriteriaBase: cache RepeatingPlusRegex - SearchMovieComparer: cache QueryYearRegex - XbmcMetadata: cache WatchedRegex Avoids regex compilation on each method call. Partially addresses #36 * fix(security): add regex timeout to prevent ReDoS vulnerabilities All cached regex patterns now include TimeSpan.FromSeconds(1) timeout to prevent potential denial of service from malicious input patterns. --------- Co-authored-by: admin <admin@ardentleatherworks.com> * chore(ci): standardize branch naming to use main instead of master (#91) - Update workflow triggers to use main instead of master - Update CONTRIBUTING.md to reference main branch - Aligns with documentation in CLAUDE.md Closes #52 Note: Actual branch rename (master → main) must be done on GitHub. Co-authored-by: admin <admin@ardentleatherworks.com> * perf: replace List.Contains() with HashSet for O(1) lookups (#92) - ReleaseSearchService: wrap wantedLanguages in HashSet<Language> - FileNameBuilder: convert splitFilter array to HashSet<string> - NewznabCategoryFieldOptionsConverter: use HashSet<int> for category filters Addresses Issue #35 Co-authored-by: admin <admin@ardentleatherworks.com> * perf: fix remaining regex caching and add timeouts (#93) - XbmcNfoDetector: convert instance regex to static readonly with timeout - Parser: add RegexOptions.Compiled and timeout to ReportMovieTitleFolderRegex Addresses Issue #36 Co-authored-by: admin <admin@ardentleatherworks.com> * fix: add null/empty checks before First() in download clients (#94) - FileStationProxy: throw if no file info returned from API - NzbVortex: return outputPath if no files in response - RTorrent: use FirstOrDefault() for validation errors Prevents InvalidOperationException on empty collections Co-authored-by: admin <admin@ardentleatherworks.com> * fix: use SingleOrDefault() with null check in UserService (#95) Replace .Single() with .SingleOrDefault() when reading Config element from XML to prevent InvalidOperationException on malformed config files Co-authored-by: admin <admin@ardentleatherworks.com> * fix: add empty checks before First() in MovieFileController (#96) Add guard clauses to prevent InvalidOperationException when movieFiles list is empty in bulk update/delete operations Co-authored-by: admin <admin@ardentleatherworks.com> * fix(security): add regex timeouts for ReDoS prevention (#97) Add TimeSpan.FromSeconds(1) timeout to remaining regex patterns: - FileNameBuilder.cs: EditionOrdinalRegex, EditionUppercaseRegex - Parser.cs: SlugSpaceRegex, SlugInvalidCharsRegex, SlugDuplicateDefaultRegex Clears final 5 SonarCloud security hotspots for 100% review coverage Co-authored-by: admin <admin@ardentleatherworks.com> * fix: resolve thread safety issues in ConfigService cache (#98) Co-authored-by: admin <admin@ardentleatherworks.com> * fix: add empty catch comment and SingleOrDefault safety (#99) Co-authored-by: admin <admin@ardentleatherworks.com> * fix: add null safety to QualityProfile First/Last methods (#100) Co-authored-by: admin <admin@ardentleatherworks.com> * fix: avoid redundant First() calls in BasicRepository (#101) Co-authored-by: admin <admin@ardentleatherworks.com> * fix(security): prevent path traversal and command injection (#102) Co-authored-by: admin <admin@ardentleatherworks.com> * fix(frontend): use ref to avoid stale movies closure in search (#103) Co-authored-by: admin <admin@ardentleatherworks.com> * fix(deps): remove obsolete System.Private.Uri package (#104) Closes #28 Co-authored-by: admin <admin@ardentleatherworks.com> * fix(ci): make test failures block builds (#105) - Remove continue-on-error from integration tests - Set fail-on-error: true on test reporter Closes #56 Co-authored-by: admin <admin@ardentleatherworks.com> * refactor(api): use async/await in MovieController.AllMovie (#107) Convert blocking GetAwaiter().GetResult() to proper await pattern in the API controller method. Partial fix for #32 Co-authored-by: admin <admin@ardentleatherworks.com> * fix: add readonly modifier to static regex field (#106) PerlRegexFactory: static Regex field should be readonly to prevent accidental reassignment. Closes #36 Co-authored-by: admin <admin@ardentleatherworks.com> * refactor: reduce cognitive complexity in FileNameBuilder.GetLanguagesToken (#108) Extract helper methods: - NormalizeLanguageCode: handles ISO639B mapping and culture conversion - ApplyLanguageFilter: handles include/exclude filter logic Uses LINQ for cleaner initial token processing. Closes #75 Co-authored-by: admin <admin@ardentleatherworks.com> * Bump the nuget group with 1 update (#109) Bumps System.Private.Uri from 4.3.0 to 4.3.2 --- updated-dependencies: - dependency-name: System.Private.Uri dependency-version: 4.3.2 dependency-type: direct:production dependency-group: nuget - dependency-name: System.Private.Uri dependency-version: 4.3.2 dependency-type: direct:production dependency-group: nuget ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [WIP] Fix open issues after research and analysis (#110) * Initial plan * feat(ci): Add secret scanning with secretlint to pre-commit hooks - Install secretlint and @secretlint/secretlint-rule-preset-recommend - Configure secretlint with .secretlintrc.json - Add secretlint to lint-staged configuration - Update CONTRIBUTING.md to document secret scanning - Resolves #55 Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * feat(privacy): Disable telemetry and analytics by default - Set SentryEnabled to false by default in SentryTarget - Update English localization to clarify error reporting is opt-in - Update README with detailed privacy information - Machine fingerprinting already removed (returns "anonymous") - Piwik analytics already removed - AnalyticsEnabled defaults to false in config This ensures no telemetry is sent without explicit user consent. Resolves #8 Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * refactor: Address code review feedback for pre-commit and telemetry changes - Optimize secretlint to only scan relevant file types (not all files) - Add ignoreFiles configuration to secretlint to exclude build artifacts - Clarify comment in SentryTarget about reconfiguration location Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * Extract common notification provider helpers to reduce duplication (#111) * Initial plan * Extract common notification helper methods to reduce duplication - Create NotificationHelpers class with BytesToString, GetLinksString, and GetTitle methods - Update Discord notification to use shared helper methods - Remove duplicate helper methods from Discord.cs - Reduces ~60 lines of duplicate code Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * Add common message helpers and update 11 notification providers - Add GetMovieAddedMessage and GetHealthRestoredMessage to NotificationHelpers - Update Discord, Gotify, Join, Mailgun, Prowl, PushBullet, Pushcut, Pushover, Pushsafer, Slack, and Telegram - Replace duplicate message strings with shared helper methods - Reduces ~22 lines of duplicate code across 11 providers Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * Update 5 more notification providers with common message helpers - Update Apprise, Email, Ntfy, Simplepush, and Signal - Standardize movie added and health restored messages - Total of 16 providers now using shared helper methods Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * Address code review feedback - Revert Apprise to use year in movie added message (preserve original behavior) - Return empty string instead of null in GetLinksString and GetTitle helpers - Improves null safety for consuming code Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * Add null checks to GetMovieAddedMessage and GetHealthRestoredMessage - Prevent potential null reference exceptions - Return empty strings when parameters are null - Maintains consistency with other helper methods Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * Standardize API response codes: PUT returns 200, DELETE returns 204 (#112) * Initial plan * Fix API response codes: PUT returns 200 Ok, DELETE returns 204 NoContent Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * docs: Update Radarr references to Aletheia and document test suite status (#113) * Initial plan * docs: update package.json metadata for Aletheia fork Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * docs: update code comments to reference Aletheia instead of Radarr Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * docs: add test status documentation Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * docs: clarify Notifiarr integration naming in comment Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * docs: add comprehensive documentation cleanup summary Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * docs: update CLEANUP_CANDIDATES.md with completed items Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * [WIP] Fix issues introduced by recent merges (#114) * Initial plan * Fix inconsistent HTTP response codes: PUT endpoints return 200 OK instead of 202 Accepted Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> * fix: resolve build errors from Copilot API response code changes (#115) - Fix void return handling in Update() methods that Copilot incorrectly assumed returned the updated object - Remove unused System.Linq using in NotificationHelpers.cs - Fix trailing whitespace style violations Co-authored-by: admin <admin@ardentleatherworks.com> * feat(db): add MediaType discriminator to Movies table (#116) Adds foundation for multi-media support by: - Adding MediaType column to Movies table (migration 244) - Adding MediaType property to Movie entity, defaulting to Movie Existing movies will have MediaType=1 (Movie) after migration. This prepares for future Book and Audiobook media types. Addresses Issue #1 Co-authored-by: admin <admin@ardentleatherworks.com> * refactor(core): create MediaItem abstract base class (#117) * feat(db): add MediaType discriminator to Movies table Adds foundation for multi-media support by: - Adding MediaType column to Movies table (migration 244) - Adding MediaType property to Movie entity, defaulting to Movie Existing movies will have MediaType=1 (Movie) after migration. This prepares for future Book and Audiobook media types. Addresses Issue #1 * refactor(core): create MediaItem abstract base class Extracts common properties from Movie into a new MediaItem base class: - MediaType, Monitored, QualityProfileId - Path, RootFolderPath, Added, Tags, LastSearchTime Movie now inherits from MediaItem and implements abstract methods GetTitle() and GetYear() while maintaining backward-compatible Title/Year property accessors. This prepares for Book and Audiobook entities that will share the same base structure. Addresses Issue #1 --------- Co-authored-by: admin <admin@ardentleatherworks.com> * feat(core): add Author and Series entities for hierarchical monitoring (#118) * feat(db): add MediaType discriminator to Movies table Adds foundation for multi-media support by: - Adding MediaType column to Movies table (migration 244) - Adding MediaType property to Movie entity, defaulting to Movie Existing movies will have MediaType=1 (Movie) after migration. This prepares for future Book and Audiobook media types. Addresses Issue #1 * refactor(core): create MediaItem abstract base class Extracts common properties from Movie into a new MediaItem base class: - MediaType, Monitored, QualityProfileId - Path, RootFolderPath, Added, Tags, LastSearchTime Movie now inherits from MediaItem and implements abstract methods GetTitle() and GetYear() while maintaining backward-compatible Title/Year property accessors. This prepares for Book and Audiobook entities that will share the same base structure. Addresses Issue #1 * feat(core): add Author and Series entities for hierarchical monitoring Introduces hierarchical structure for books/audiobooks: - Author entity: tracks authors with monitoring, quality profiles, paths - Series entity: groups books/audiobooks by series, linked to Author - MediaItem: adds AuthorId and SeriesId for hierarchy support - Migration 245: creates Authors and Series tables, adds columns to Movies This enables Author → Series → Item monitoring inheritance for future book and audiobook support. Addresses Issue #2 --------- Co-authored-by: admin <admin@ardentleatherworks.com> * feat(core): add generic IProvideMediaInfo interface (#119) * feat(db): add MediaType discriminator to Movies table Adds foundation for multi-media support by: - Adding MediaType column to Movies table (migration 244) - Adding MediaType property to Movie entity, defaulting to Movie Existing movies will have MediaType=1 (Movie) after migration. This prepares for future Book and Audiobook media types. Addresses Issue #1 * refactor(core): create MediaItem abstract base class Extracts common properties from Movie into a new MediaItem base class: - MediaType, Monitored, QualityProfileId - Path, RootFolderPath, Added, Tags, LastSearchTime Movie now inherits from MediaItem and implements abstract methods GetTitle() and GetYear() while maintaining backward-compatible Title/Year property accessors. This prepares for Book and Audiobook entities that will share the same base structure. Addresses Issue #1 * feat(core): add Author and Series entities for hierarchical monitoring Introduces hierarchical structure for books/audiobooks: - Author entity: tracks authors with monitoring, quality profiles, paths - Series entity: groups books/audiobooks by series, linked to Author - MediaItem: adds AuthorId and SeriesId for hierarchy support - Migration 245: creates Authors and Series tables, adds columns to Movies This enables Author → Series → Item monitoring inheritance for future book and audiobook support. Addresses Issue #2 * feat(core): add generic IProvideMediaInfo interface Introduces generic metadata provider interfaces: - IProvideMediaInfo<T>: Base interface for all metadata providers - GetByExternalId, GetById, GetBulkInfo - GetTrending, GetPopular, GetChangedItems - ISearchableMediaProvider<T>: Search capability interface - SearchByTitle with optional year filtering These interfaces establish the contract for future book and audiobook metadata providers while maintaining compatibility with the existing IProvideMovieInfo. Addresses Issue #3 --------- Co-authored-by: admin <admin@ardentleatherworks.com> * feat(qualities): add book and audiobook quality definitions (#120) * feat(db): add MediaType discriminator to Movies table Adds foundation for multi-media support by: - Adding MediaType column to Movies table (migration 244) - Adding MediaType property to Movie entity, defaulting to Movie Existing movies will have MediaType=1 (Movie) after migration. This prepares for future Book and Audiobook media types. Addresses Issue #1 * refactor(core): create MediaItem abstract base class Extracts common properties from Movie into a new MediaItem base class: - MediaType, Monitored, QualityProfileId - Path, RootFolderPath, Added, Tags, LastSearchTime Movie now inherits from MediaItem and implements abstract methods GetTitle() and GetYear() while maintaining backward-compatible Title/Year property accessors. This prepares for Book and Audiobook entities that will share the same base structure. Addresses Issue #1 * feat(core): add Author and Series entities for hierarchical monitoring Introduces hierarchical structure for books/audiobooks: - Author entity: tracks authors with monitoring, quality profiles, paths - Series entity: groups books/audiobooks by series, linked to Author - MediaItem: adds AuthorId and SeriesId for hierarchy support - Migration 245: creates Authors and Series tables, adds columns to Movies This enables Author → Series → Item monitoring inheritance for future book and audiobook support. Addresses Issue #2 * feat(core): add generic IProvideMediaInfo interface Introduces generic metadata provider interfaces: - IProvideMediaInfo<T>: Base interface for all metadata providers - GetByExternalId, GetById, GetBulkInfo - GetTrending, GetPopular, GetChangedItems - ISearchableMediaProvider<T>: Search capability interface - SearchByTitle with optional year filtering These interfaces establish the contract for future book and audiobook metadata providers while maintaining compatibility with the existing IProvideMovieInfo. Addresses Issue #3 * feat(qualities): add book and audiobook quality definitions Add quality source types and definitions for eBooks and audiobooks: - EBOOK source: Unknown, EPUB, MOBI, AZW3, PDF, TXT - AUDIOBOOK source: Unknown, MP3-128, MP3-320, M4B, FLAC Quality definitions include appropriate size limits for each format. New qualities auto-seed to database via QualityDefinitionService on startup. Closes #4, Closes #5 --------- Co-authored-by: admin <admin@ardentleatherworks.com> * feat(ui): add Books and Audiobooks navigation sections (#121) Add navigation sidebar entries for Books and Audiobooks with: - New BOOK and AUDIOBOOK icons in props - Books/Audiobooks sections in PageSidebar with Add New/Import children - Routes for /books and /audiobooks paths - Placeholder index pages for both media types - Translation strings for Books/Audiobooks Part of Phase 3 UI work for Issue #7. Co-authored-by: admin <admin@ardentleatherworks.com> * feat(database): add Book and Audiobook entities (#122) Add entities for books and audiobooks with: - Book entity: title, ISBN, ASIN, publisher, author/series links - Audiobook entity: title, narrator, duration, abridged flag, book link - Database migration 246 for Books and Audiobooks tables - Entity registrations in TableMapping Note: Depends on PR #118 (Author/Series tables) for full FK support. Co-authored-by: admin <admin@ardentleatherworks.com> * fix(core): code quality improvements (#123) - Remove debug Console.WriteLine from migration 170 - Fix DelayProfileService.Reorder to throw ModelNotFoundException instead of silent failure - Remove unused using directives Co-authored-by: admin <admin@ardentleatherworks.com> * feat(core): add Book and Audiobook repositories, services, and API controllers (#124) Adds the complete data layer for Books and Audiobooks: - BookRepository with query methods for ISBN, ASIN, Author, Series - BookService with business logic and event publishing - AudiobookRepository with narrator-aware query methods - AudiobookService with duration and narrator support - Domain events for both entity types - REST API controllers with full CRUD operations Co-authored-by: admin <admin@ardentleatherworks.com> * feat: Phase 2 Multi-Media Infrastructure - Books/Audiobooks Backend & Frontend (#125) * feat(api): add Book and Audiobook lookup and editor controllers Adds search and bulk edit functionality for Books and Audiobooks: - BookLookupController: search by ISBN, ISBN13, ASIN, ForeignId, title - AudiobookLookupController: search by ISBN, ASIN, narrator, title - BookEditorController: bulk update/delete books - AudiobookEditorController: bulk update/delete audiobooks - Editor validators and resources for both entity types * feat(core): add AddBookService and AddAudiobookService Adds services for adding new books and audiobooks with validation: - AddBookService: handles book creation with path generation - AddAudiobookService: handles audiobook creation with narrator-aware paths - AddBookValidator: validates book additions - AddAudiobookValidator: validates audiobook additions * feat(core): add BookFile and AudiobookFile entities and repositories Adds file tracking infrastructure for books and audiobooks: - BookFile entity with format tracking - AudiobookFile entity with audio metadata (duration, bitrate, etc.) - BookFileRepository for book file queries - AudiobookFileRepository for audiobook file queries - Database migration for new tables - Table mappings for new entities * feat(metadata): add Book and Audiobook metadata provider interfaces Adds metadata provider infrastructure for books and audiobooks: - IProvideBookInfo: interface for book metadata lookups - IProvideAudiobookInfo: interface for audiobook metadata lookups - BookMetadata: model for book metadata from external sources - AudiobookMetadata: model for audiobook metadata with narrator info - BookInfoProxy: stub implementation (to be replaced with Goodreads, etc.) - AudiobookInfoProxy: stub implementation (to be replaced with Audible, etc.) * feat(api): add Author and Series repositories, services, and API controllers * feat(ui): add Book and Audiobook Redux store and index pages --------- Co-authored-by: admin <admin@ardentleatherworks.com> * feat: add Author/Series services and frontend pages (#126) * feat(core): add AddAuthorService and AddSeriesService with validators * feat(api): add Author and Series lookup controllers * feat(ui): add Author and Series frontend index pages * feat(ui): add Book and Audiobook search pages * feat(ui): add Book and Audiobook detail pages * feat(ui): add Author and Series detail pages --------- Co-authored-by: admin <admin@ardentleatherworks.com> * ci(deps): bump actions/labeler from 4 to 6 (#127) Bumps [actions/labeler](https://github.com/actions/labeler) from 4 to 6. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](https://github.com/actions/labeler/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ci(deps): bump actions/setup-dotnet from 4 to 5 (#128) Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4 to 5. - [Release notes](https://github.com/actions/setup-dotnet/releases) - [Commits](https://github.com/actions/setup-dotnet/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-dotnet dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ci(deps): bump github/codeql-action from 3 to 4 (#129) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ci(deps): bump dessant/lock-threads from 4 to 6 (#130) Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 4 to 6. - [Release notes](https://github.com/dessant/lock-threads/releases) - [Changelog](https://github.com/dessant/lock-threads/blob/main/CHANGELOG.md) - [Commits](https://github.com/dessant/lock-threads/compare/v4...v6) --- updated-dependencies: - dependency-name: dessant/lock-threads dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: address SonarCloud code quality issues (#131) * fix: address SonarCloud code quality issues - Remove unused private fields from services and repositories - Replace Object.assign with spread operator in Redux actions - Use structuredClone instead of _.cloneDeep - Add exception parameters to catch clause logging - Use Number.parseInt instead of parseInt in detail pages - Mark React component props as readonly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: update CHANGELOG with Phase 2 multi-media work * fix: update labeler.yml for actions/labeler v6 format --------- Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * feat(monitoring): implement hierarchical monitoring for Author/Series/Book/Audiobook (#132) * feat(monitoring): implement hierarchical monitoring for Author/Series/Book/Audiobook - Add cascade logic: unmonitoring parent cascades to children - Re-monitoring parent does not auto-monitor children (explicit control) - EffectivelyMonitored computed from item AND all ancestors - Database indexes for efficient cascade queries (migration 248) - AuthorMonitoringChangedEvent and SeriesMonitoringChangedEvent - EffectivelyMonitored field added to Book/Audiobook API resources Closes #2 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor(monitoring): reduce code duplication in HierarchicalMonitoringService - Extract common ancestor check to IsAncestorUnmonitored helper - Consolidate monitoring context retrieval to GetMonitoringContext - Create generic UnmonitorEntities helper for cascade operations - Reduce code from 302 to 233 lines while preserving all functionality * ci(sonar): exclude intentional structural duplication from CPD * ci(codeql): exclude user-controlled-bypass for monitoring cascade logic --------- Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * feat: add statistics services and analytics dashboard (#133) - Add BookStatistics and AudiobookStatistics services - Create unified Dashboard with media type stats - Add statistics to Book/Audiobook controllers - Make dashboard the default landing page Closes #6 Co-authored-by: admin <admin@ardentleatherworks.com> * refactor(database): unify Book/Audiobook inheritance with MediaItem (#134) Book and Audiobook now extend MediaItem instead of ModelBase, eliminating duplicate properties and enabling cross-media operations. - Remove duplicate MediaType, Monitored, Path, Tags, etc. from entities - Implement abstract GetTitle() and GetYear() methods - Add migration 249 (documentation only - no DB changes needed) Co-authored-by: admin <admin@ardentleatherworks.com> * feat(database): add Music entities and tables (#135) Add foundation for Music support: - Artist entity (parallel to Author) - Album entity (parallel to Series) - Track entity (extends MediaItem) - MusicFile entity for audio files - Migration 250 creates Artists, Albums, Tracks, MusicFiles tables - Register all entities in TableMapping Co-authored-by: admin <admin@ardentleatherworks.com> * feat(music): add repositories and services (#136) Add data access and business logic layers for Music support: - ArtistRepository/ArtistService for artist management - AlbumRepository/AlbumService for album management - TrackRepository/TrackService for track management - MusicFileRepository for audio file management Co-authored-by: admin <admin@ardentleatherworks.com> * refactor: extract BaseMediaService<T> base class (#137) * refactor: extract BaseMediaService<T> base class Extract common CRUD operations into BaseMediaService<T>: - Get, GetAll, Paged, Add, AddMany, Delete, DeleteMany, Update, UpdateMany - SetAddedTimestamp with reflection for non-MediaItem types - Virtual event hooks (OnItemAdded, OnItemDeleted, etc.) Migrate services to use base class: - BookService: 180 → 89 lines - AudiobookService: 192 → 93 lines - AlbumService: 132 → 58 lines - ArtistService: 107 → 50 lines - TrackService: 114 → 50 lines Net reduction: ~385 lines * chore: cleanup stale files and fix branding Remove IDE/editor config files that should not be tracked: - .vscode/, frontend/.vscode/, src/.idea/ - azure-pipelines.yml (obsolete CI) - Empty localization files (bs, ta, et, lt, sr, es_MX) Remove unused npm packages: - react-addons-shallow-compare - react-async-script Fix remaining Radarr→Aletheia branding: - ConsoleApp.cs error messages - openapi.json title/description/license - FileNameBuilder.cs default release group --------- Co-authored-by: admin <admin@ardentleatherworks.com> * chore: P2/P3 code cleanup batch (#138) - Remove unused RemoveTitle() methods from AlternativeTitleService, MovieTranslationService, CreditService - Clean commented-out code blocks in EventAggregator, Pneumatic, MovieStatisticsFixture - Consolidate 4 duplicate TagsModalContent.css files into shared Components/Styles module - Fix BaseMediaService StyleCop violations (SA1127, SA1502) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract BaseMediaCrudController for Book/Audiobook (#139) - Create BaseMediaCrudController with common CRUD patterns - Extract shared validation setup (path, quality, title) - Move Create, Update, Delete endpoints to base class - BookController: 219 -> 168 lines (-51) - AudiobookController: 227 -> 177 lines (-50) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract BaseMediaEditorController for bulk operations (#140) - Create IEditorResource interface for common editor properties - Create BaseMediaEditorController with common bulk edit/delete logic - Extract tag handling (Add/Remove/Replace) to base class - BookEditorController: 92 -> 36 lines (-56) - AudiobookEditorController: 92 -> 36 lines (-56) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * refactor: extract focused config services from ConfigService (#141) Create DownloadConfigService and ImportConfigService as focused interfaces for download-related and import-related configuration. Uses delegation pattern for backward compatibility. Co-authored-by: admin <admin@ardentleatherworks.com> * refactor: extract UIConfigService and ProxyConfigService (#142) Continue ConfigService split with UI and proxy-related settings. Uses delegation pattern for backward compatibility. Co-authored-by: admin <admin@ardentleatherworks.com> * refactor: add IMediaResource interface for resource mapping consolidation (#143) Create common interface for media resource properties (Id, Monitored, QualityProfileId, Path, RootFolderPath, Added, Tags). BookResource, AudiobookResource, and AuthorResource now implement IMediaResource. Foundation for future resource mapping consolidation. Co-authored-by: admin <admin@ardentleatherworks.com> * feat(music): complete Music API layer with hierarchical monitoring (#144) * feat(music): add events, statistics, and API resources Foundation layer for Music API support: - Events: Artist/Album/Track added/edited/deleted events - Statistics: MusicStatistics with album-level tracking - Resources: Artist, Album, Track, MusicFile, MusicStatistics DTOs * feat(music): add validators and add services for artist and album * feat(music): add main API controllers for artist, album, track, and music files * feat(music): add editor and lookup controllers for artist and album * feat(music): integrate hierarchical monitoring for artist/album/track * fix: address SonarCloud static method and indexer issues * fix: address SonarCloud code quality issues - Add SuppressMessage for S107 (constructor params) on DI controllers - Add SuppressMessage for S6968 (ASP.NET validation) on resource DTOs - Use global:: prefix to avoid namespace conflicts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: exclude Music API from duplication checks Music resources/controllers follow same pattern as Books/Audiobooks. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: expand duplication exclusion to core Music files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add MusicStats to duplication exclusions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: expand duplication exclusions to all media type directories 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * New: Parse Group GiLG (#145) Co-authored-by: TRaSH <trash-pm@protonmail.ch> Co-authored-by: admin <admin@ardentleatherworks.com> * feat(metadata): add Music and Book metadata providers (#146) * New: Parse Group GiLG * feat(metadata): add Music and Book metadata providers - Add MusicBrainz proxy for Artist/Album/Track lookups - Implement OpenLibrary integration for Book searches - Support ISBN, title, author lookups for books - Support MusicBrainz ID and name searches for music * fix: address SonarCloud issues in metadata providers --------- Co-authored-by: TRaSH <trash-pm@protonmail.ch> Co-authored-by: admin <admin@ardentleatherworks.com> * feat(music): comprehensive music quality support (#147) * feat(music): add comprehensive music quality support - Add MUSIC to QualitySource enum - Add Music qualities (ID 300-310): MP3-128/192/256/320, AAC-256, OGG-320, FLAC, FLAC 24bit, WAV, ALAC - Add DefaultQualityDefinitions for music (Weight 300+) - Add music file extensions (.mp3, .flac, .wav, .ogg, .m4a, .aac, .alac, .ape, .wv, .dsf, .dff) - Add ebook extensions (.epub, .mobi, .azw3, .pdf, .txt, .djvu, .cbr, .cbz) - Add audiobook extensions (.m4b, .aa, .aax) - Add MediaFileExtensions helper properties (MusicExtensions, EbookExtensions, AudiobookExtensions) - Create MusicQualityParser for bitrate/format/bit-depth detection - Create BookQualityParser for ebook format detection - Create AudiobookQualityParser for audiobook format/bitrate detection * feat(music): comprehensive quality system with full granularity Expand music quality system to 60+ distinct quality levels: Lossy (IDs 300-315): - MP3: 128/192/256/320 kbps - AAC: 128/256/320 kbps - OGG: 128/192/256/320 kbps - Opus: 128/192/256 kbps - WMA Lossless FLAC (IDs 320-327): - 16/44.1, 16/48, 24/44.1, 24/48, 24/88.2, 24/96, 24/176.4, 24/192 - 24/96 designated as target quality Lossless WAV (IDs 340-347): - Same bit-depth/sample-rate variants as FLAC Lossless AIFF (IDs 350-357): - Same bit-depth/sample-rate variants as FLAC DSD (IDs 360-363): - DSD64 (2.8MHz), DSD128 (5.6MHz), DSD256 (11.2MHz), DSD512 (22.4MHz) Other Lossless (IDs 370-377): - ALAC: 16/44.1, 16/48, 24/44.1, 24/48, 24/96, 24/192 - APE (Monkey's Audio), WavPack Special (IDs 380-381): - MQA, MQA Studio Add MusicFileAnalyzer service: - Uses ffprobe for accurate metadata detection - Extracts bit depth, sample rate, codec, bitrate - Maps to appropriate quality based on actual file properties Update MusicQualityParser: - Comprehensive regex patterns for all formats - Bit-depth/sample-rate detection from filenames - DSD variant detection - MQA detection - Hi-Res keyword recognition * fix(music): address SonarCloud code quality issues - S1172: Use unused codec/ext parameters in format detection - S6667: Pass exceptions to logger in catch blocks - S1192: Extract duplicate strings to constants - S3776: Reduce cognitive complexity via method extraction 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address additional SonarCloud issues in music module - S1192: Extract string constants in MusicBrainzProxy and BookInfoProxy - S2325: Make LinkAlbumStatistics static in AlbumController - S4136: Reorder method overloads to be adjacent in Resource files - S6964: Use nullable value types in Resource classes where appropriate * fix(parser): reduce cognitive complexity in AudiobookQualityParser Extract format and bitrate parsing into separate methods to reduce cognitive complexity of ParseQualityName from 20 to under 15. * fix(security): add regex timeout to quality parsers Add 5-second timeout to all Regex patterns in AudiobookQualityParser, BookQualityParser, and MusicQualityParser to prevent ReDoS attacks. --------- Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> * docs: update changelog with Phase 3-6 work - Add Phase 3 (Multi-Media Foundation) entries - Add Phase 4 (Books & Audiobooks) entries - Add Phase 6 (Music Foundation) entries with 60+ quality definitions - Document SonarCloud fixes from PR #147 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Robin Dadswell <19610103+RobinDadswell@users.noreply.github.com> Co-authored-by: Stevie Robinson <stevie.robinson@gmail.com> Co-authored-by: plz12345 <132735020+plz12345@users.noreply.github.com> Co-authored-by: Erik Frantz <39980629+BardezAnAvatar@users.noreply.github.com> Co-authored-by: Bogdan <mynameisbogdan@users.noreply.github.com> Co-authored-by: admin <admin@ardentleatherworks.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: cheir-mneme <176430037+cheir-mneme@users.noreply.github.com> Co-authored-by: TRaSH <trash-pm@protonmail.ch>
5.4 KiB
Contributor Covenant Code of Conduct
Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement via issues on github.com/cheir-mneme/aletheia. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
1. Correction
Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
2. Warning
Community Impact: A violation through a single incident or series of actions.
Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
3. Temporary Ban
Community Impact: A serious violation of community standards, including sustained inappropriate behavior.
Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
4. Permanent Ban
Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
Consequence: A permanent ban from any sort of public interaction within the community.
Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.
For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.