-
Notifications
You must be signed in to change notification settings - Fork 5
feat: Discogs music scraper plugin (#87) #100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
57 commits
Select commit
Hold shift + click to select a range
1f59d6a
feat: add Discogs music scraper plugin (#87)
fabiodalez-dev 32f574a
feat: music-aware labels, Discogs settings, CodeRabbit fixes
fabiodalez-dev 498c2bc
feat: add Discogs to bundled plugins + 7 E2E tests
fabiodalez-dev ea3a5d0
test: add Discogs import E2E test (barcode → scraping → save)
fabiodalez-dev 7016608
fix: prevent barcode from being stuffed into isbn13 for music media
fabiodalez-dev 9400e5e
fix: handle SweetAlert confirmation in Discogs import test
fabiodalez-dev 873e73f
feat: human-readable format names + HTML tracklist
fabiodalez-dev f1786b0
feat: add tipo_media column for media type filtering (#87)
fabiodalez-dev e3c383b
fix: Discogs enrichment + CodeRabbit review fixes
fabiodalez-dev ed8694c
fix: address CodeRabbit review findings (round 3)
fabiodalez-dev 2fb459d
fix: address CodeRabbit review (round 4)
fabiodalez-dev 063e8ff
test: add 5 advanced Discogs E2E tests
fabiodalez-dev 5724f16
fix: admin detail uses formatTracklist for music records
fabiodalez-dev 9ec7d98
feat: extend music plugin with MusicBrainz + Deezer sources
fabiodalez-dev 475e8b5
fix: use unique barcode in plugin test (avoid EAN UNIQUE conflict)
fabiodalez-dev 5adf824
fix: CodeRabbit round 5 + Schema.org media-specific shapes
fabiodalez-dev c7a419c
Fix Discogs review follow-ups and multisource tests
fabiodalez-dev b5a247d
Address follow-up CodeRabbit review fixes
fabiodalez-dev 63df3aa
fix: 4 logic bugs from code review
fabiodalez-dev ff03d06
chore: bump version to 0.5.4 (matches migration filename)
fabiodalez-dev 610c29c
fix: CodeRabbit round 6 — logic hardening
fabiodalez-dev a12f4d4
fix: CodeRabbit round 7 — 3 quick fixes
fabiodalez-dev 6dfd7e5
test: add 10 reusable PR #100 feature tests + fix PHPStan level 5
fabiodalez-dev 328a9cb
fix: bulk cover download message — 'senza ISBN/barcode' instead of 'l…
fabiodalez-dev 5c0d069
fix: genres from Discogs now saved as parole_chiave
fabiodalez-dev 1d46bf9
fix: CodeRabbit round 8 — 8 fixes
fabiodalez-dev 3a3469f
fix: address 10-agent review findings + add .coderabbit.yaml
fabiodalez-dev fc399cb
fix: address CodeRabbit review #11 on PR #100
fabiodalez-dev 875a710
fix: PR #100 10-agent review follow-up + barcode-ISBN guard hardening
fabiodalez-dev 4ff5d3b
test: pre-clean existing barcode in discogs-import beforeAll
fabiodalez-dev 5ef3db3
chore: ignore local-release artifacts and local release script
fabiodalez-dev c9bd82c
fix: add missing placeholder for metadata in autoRegisterBundledPlugins
fabiodalez-dev fb1e881
fix: correct bind_param type order in autoRegisterBundledPlugins
fabiodalez-dev 434b46f
test: activate optional discogs plugin via SQL in test 1
fabiodalez-dev 76daf8d
test: add installed-state guards to prevent cross-spec pollution
fabiodalez-dev 402a4a1
test: use RUN_ID in book title + author name in smoke-install
fabiodalez-dev 5f1d302
test: search by RUN_ID in Edit book verification
fabiodalez-dev e4c1181
fix: address 8-agent review findings (critical + important + security)
fabiodalez-dev bdd4184
fix: use SecureLogger::info for success events (CodeRabbit feedback)
fabiodalez-dev 9f39049
fix: stop excluding public/installer/assets from release ZIP
fabiodalez-dev ab011be
test: fix assertion string after log message rewording
fabiodalez-dev df82f9e
fix: address all CodeRabbit PR #100 findings (19 files)
fabiodalez-dev e1a58ed
feat: bulk ISBN enrichment service with cron + admin UI (#99)
fabiodalez-dev 47de8b9
fix: use copertina_url (not copertina) in bulk-enrich test SQL
fabiodalez-dev 7f07916
fix: CSRF + copertina_url in bulk-enrich tests
fabiodalez-dev 2bdba5a
fix: set_time_limit(300) in batch start + unique ISBNs for no-overwri…
fabiodalez-dev 71af10c
fix: use json.results path in all bulk-enrich tests
fabiodalez-dev 26aa486
fix: add skipped counter to batch summary + use results path in test 14
fabiodalez-dev e5ed75e
fix: use unique ISBN for tipo_media preservation test 15
fabiodalez-dev 742e2c4
fix: unique ISBN for EAN preservation test 17
fabiodalez-dev 8810660
fix: address CodeRabbit round 2 — prepare guard, sort fix, XSS hardening
fabiodalez-dev 7f6c6a1
fix: replace public/installer/assets symlink with real directory
fabiodalez-dev b15d7c1
Revert "fix: replace public/installer/assets symlink with real direct…
fabiodalez-dev ffa43c5
Reapply "fix: replace public/installer/assets symlink with real direc…
fabiodalez-dev 77fba6b
fix: address 16 CodeRabbit Major findings (PR #100)
fabiodalez-dev 23db85d
chore: bump version to 0.5.5, add deezer + musicbrainz bundled plugins
fabiodalez-dev 9b69fcc
fix: address CodeRabbit round N (20 findings) — last round before squash
fabiodalez-dev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,155 @@ | ||
| # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json | ||
| # Pinakes — CodeRabbit Configuration | ||
| # PHP/Slim 4 library management system with MySQL | ||
|
|
||
| language: "it-IT" | ||
|
|
||
| tone_instructions: | | ||
| Sii conciso e diretto. Concentrati su bug reali, vulnerabilità di sicurezza | ||
| e violazioni delle regole del progetto. Evita suggerimenti stilistici minori. | ||
|
|
||
| early_access: true | ||
|
|
||
| reviews: | ||
| max_files: 200 | ||
| profile: "assertive" | ||
| request_changes_workflow: false | ||
| high_level_summary: true | ||
| poem: false | ||
| review_status: true | ||
|
|
||
| # ── File Filters ────────────────────────────────────────────────── | ||
| path_filters: | ||
| - "!vendor/**" | ||
| - "!node_modules/**" | ||
| - "!public/assets/tinymce/**" | ||
| - "!public/assets/fontawesome/**" | ||
| - "!public/assets/choices/**" | ||
| - "!public/assets/flatpickr/**" | ||
| - "!public/assets/sweetalert2/**" | ||
| - "!*.min.js" | ||
| - "!*.min.css" | ||
| - "!*.map" | ||
| - "!pinakes-*.zip" | ||
| - "!pinakes-*.sha256" | ||
| - "!test-results/**" | ||
|
|
||
| # ── Path-Specific Review Instructions ────────────────────────────── | ||
| path_instructions: | ||
| # Controllers — input validation, auth, soft-delete | ||
| - path: "app/Controllers/**" | ||
| instructions: | | ||
| - CRITICO: ogni query sulla tabella `libri` DEVE avere `AND deleted_at IS NULL` | ||
| - Verifica che `getParsedBody()` non sia usato per JSON — serve `json_decode((string)$request->getBody())` | ||
| - Input utente: validare e sanitizzare PRIMA dell'uso | ||
| - Sessione: `$_SESSION['user']['id']` (NON `$_SESSION['user_id']`) | ||
| - Eccezioni: catturare `\Throwable` non `\Exception` (strict_types TypeError extends \Error) | ||
| - Logging: `SecureLogger::error()` non `error_log()` per contesti sensibili | ||
| - Route: mai hardcodare percorsi URL, usare `route_path('key')` o `RouteTranslator::route('key')` | ||
| - Export CSV: tipo_media deve essere incluso, usare stringa vuota come fallback (non 'libro') | ||
|
|
||
| # Models / Repository — query safety | ||
| - path: "app/Models/**" | ||
| instructions: | | ||
| - CRITICO: ogni SELECT/UPDATE/DELETE sulla tabella `libri` DEVE avere `AND deleted_at IS NULL` | ||
| - Soft-delete: nullificare isbn10, isbn13, ean quando si fa soft-delete (prevent unique constraint violations) | ||
| - Transaction safety: mai annidare `begin_transaction()` in mysqli (causa commit implicito) | ||
| - Pattern: verificare `@@autocommit` per rilevare transazioni in corso | ||
| - hasColumn() guard per colonne aggiunte in migrazioni recenti (backward compat) | ||
| - tipo_media: usare `array_key_exists` guard, non sovrascrivere il valore se non esplicitamente fornito | ||
|
|
||
| # Views — escaping, XSS prevention | ||
| - path: "app/Views/**" | ||
| instructions: | | ||
| - CRITICO: `htmlspecialchars(url(...), ENT_QUOTES, 'UTF-8')` in TUTTI gli attributi HTML (href, action, src) | ||
| - `route_path()` richiede lo stesso escaping negli attributi HTML | ||
| - PHP->JS: usare `json_encode(..., JSON_HEX_TAG)` per qualsiasi dato PHP inserito in JavaScript | ||
| - TinyMCE: SEMPRE includere `model: 'dom'` e `license_key: 'gpl'` in ogni `tinymce.init({})` | ||
| - Mai usare `HtmlHelper::e()` nelle view — usare `htmlspecialchars(..., ENT_QUOTES, 'UTF-8')` | ||
| - Schema.org: ogni tipo_media deve avere il proprio branch con proprietà specifiche (non mescolare Book con CreativeWork) | ||
| - DataTable: ogni valore da API deve passare per `escapeHtml()` prima del rendering | ||
|
|
||
| # Support classes — helpers, utilities | ||
| - path: "app/Support/**" | ||
| instructions: | | ||
| - MediaLabels: `isMusic()` deve essere autoritativo su tipo_media quando impostato | ||
| - `inferTipoMedia()`: attenzione ai false positive su token corti ('cd' matcha 'CD-ROM', 'lp' matcha parole con 'lp') | ||
| - `formatTracklist()`: deve rilevare HTML pre-formattato (`<ol>`) e restituirlo as-is | ||
| - PluginManager: usare `\Throwable` non `\Exception`, `BundledPlugins::LIST` centralizzato | ||
| - Route translation: mai hardcodare percorsi, usare `RouteTranslator::route('key')` | ||
|
|
||
| # Plugins — API safety, rate limiting | ||
| - path: "storage/plugins/**" | ||
| instructions: | | ||
| - SICUREZZA: ogni chiamata curl DEVE avere CURLOPT_PROTOCOLS (HTTP/HTTPS only), CURLOPT_MAXREDIRS, CURLOPT_CONNECTTIMEOUT, CURLOPT_SSL_VERIFYPEER | ||
| - SSRF: validare/castare ID esterni (es. releaseId a int) prima di usarli in URL | ||
| - Rate limiting: deve essere elapsed-based (microtime) e static (persistere tra istanze) | ||
| - Ogni `curl_exec()` deve avere `curl_error()` check con logging | ||
| - Hook registration: transazione + rethrow on failure | ||
| - Non enrichire dati di libri con cover musicali (gate su resolveTipoMedia) | ||
|
|
||
| # Migrations — versioning, idempotency | ||
| - path: "installer/database/migrations/**" | ||
| instructions: | | ||
| - CRITICO: il nome del file di migrazione DEVE avere versione <= version.json (altrimenti viene silenziosamente saltata) | ||
| - L'updater usa `version_compare($migrationVersion, $toVersion, '<=')` — versioni superiori sono IGNORATE | ||
| - Ogni migrazione DEVE essere completamente idempotente (IF NOT EXISTS, IF @col_exists = 0, etc.) | ||
| - LIKE patterns: evitare `%cd%` e `%lp%` che matchano false positive ('CD-ROM', parole con 'lp') — usare REGEXP word boundaries | ||
| - Se servono più migrazioni per una release: unirle in UN file con la versione della release | ||
|
|
||
| # Translations — completeness | ||
| - path: "locale/**" | ||
| instructions: | | ||
| - Ogni chiave presente in it_IT.json DEVE essere presente anche in en_US.json e de_DE.json | ||
| - Le chiavi di traduzione devono corrispondere esattamente (case-sensitive) | ||
| - I placeholder (%s, %d) devono essere preservati in tutte le lingue | ||
| - Nuove chiavi aggiunte nel codice PHP/JS devono essere aggiunte in TUTTE le lingue | ||
|
|
||
| # Tests — E2E patterns | ||
| - path: "tests/**" | ||
| instructions: | | ||
| - I test E2E richiedono `/tmp/run-e2e.sh` per credenziali DB/admin | ||
| - `--workers=1` obbligatorio per esecuzione seriale | ||
| - SweetAlert: dopo form submit, verificare e cliccare `.swal2-confirm` | ||
| - Choices.js: usare `fill` + `waitForTimeout` + click suggestion | ||
| - Flatpickr: interagire via JS evaluate, non click diretto | ||
| - Pulizia dati test: FK-safe order (prima tabelle figlie, poi padri) | ||
|
|
||
| # Release scripts | ||
| - path: "scripts/**" | ||
| instructions: | | ||
| - MAI creare ZIP manualmente — SEMPRE usare `create-release.sh` | ||
| - Lo script verifica 9 file critici nel ZIP prima del rilascio | ||
| - `git archive` usa file COMMITTATI, non la working directory | ||
| - Verificare che `public/assets/tinymce/models/dom/model.min.js` sia nel ZIP | ||
|
|
||
| # ── Auto Review Settings ─────────────────────────────────────────── | ||
| auto_review: | ||
| enabled: true | ||
| drafts: false | ||
|
|
||
| # ── Tools ────────────────────────────────────────────────────────── | ||
| tools: | ||
| phpstan: | ||
| enabled: true | ||
| shellcheck: | ||
| enabled: true | ||
| semgrep: | ||
| enabled: true | ||
| gitleaks: | ||
| enabled: true | ||
| yamllint: | ||
| enabled: true | ||
|
|
||
| # ── Chat ────────────────────────────────────────────────────────────── | ||
| chat: | ||
| auto_reply: true | ||
|
|
||
| # ── Knowledge Base ──────────────────────────────────────────────────── | ||
| knowledge_base: | ||
| opt_out: false | ||
| learnings: | ||
| scope: "local" | ||
| issues: | ||
| scope: "auto" | ||
| pull_requests: | ||
| scope: "auto" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
CodeRabbit path_filters glob syntax recursive ** vs * matching💡 Result:
In CodeRabbit's path_filters, glob patterns follow the minimatch library syntax. The '' pattern enables recursive directory matching (zero or more directories/subdirectories), while '' matches zero or more characters within a single path segment (non-recursive, does not cross directory boundaries). Key differences and examples from CodeRabbit docs: - '!dist/': Excludes the 'dist' directory and all files/subdirectories recursively within it. - '!/dist/': Excludes any 'dist' directory (at any level) and its recursive contents. - '!/node_modules/': Excludes any 'node_modules' directory anywhere and recursively. - '!/.min.js': Excludes all minified JS files anywhere in the repo (recursive due to leading '/', combined with file pattern). - 'src/': Includes 'src' directory and all subdirectories/files recursively. In contrast: - '*' alone would match any file or directory name in the current level only (e.g., equivalent to '' with noglobstar option enabled). - Use '/' to separate path segments; patterns are evaluated relative to the repository root. This syntax keeps reviews focused by excluding build artifacts, dependencies, etc. Patterns with '!' prefix exclude; without include/override exclusions. Defaults include many recursive excludes like '!/dist/'. For full details, see CodeRabbit's reference to minimatch documentation.
Citations:
🏁 Script executed:
Repository: fabiodalez-dev/Pinakes
Length of output: 415
🏁 Script executed:
Repository: fabiodalez-dev/Pinakes
Length of output: 1069
🏁 Script executed:
Repository: fabiodalez-dev/Pinakes
Length of output: 615
Use recursive glob patterns for minified and map file exclusions.
The patterns
!*.min.js,!*.min.css, and!*.mapmatch only files at the repository root. Minified assets and source maps exist in nested paths (e.g.,public/assets/js/sortable.min.js,public/assets/css/sortable.min.css,public/assets/star-rating/dist/star-rating.min.js), so these exclusions fail to filter them. While specific paths like!public/assets/tinymce/**are excluded, other build artifacts in subdirectories will still be reviewed.🛠️ Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents