Go to file
Ehsan Mohandesi cb7b1b03a3 Replace Spotify search with a validated music link box
The Spotify Web API integration stopped working, leaving /spotify unable to
suggest songs at all. Replace the artist/album/track search flow with a single
box where the user pastes a link to the track on a music service.

Links are checked against a hardcoded allow-list of legal streaming and store
domains so links to ripped audio cannot be submitted. The check lives in the
service layer, not just the page: any authenticated user can POST to
/api/ganjoor/song directly and bypass the UI. Hosts are matched against the
full host or a dot-prefixed suffix, so look-alikes such as
open.spotify.com.evil.com are rejected; https is required, and userinfo and
non-default ports are refused. Accepted URLs are canonicalised - https,
lowercased host, tracking parameters stripped - so the same track always yields
the same stored URL and duplicate detection actually works.

Links are stored under one new type, PoemMusicTrackType.MusicUrl, with the
platform derived from the host at render time. That needs no migration or
backfill, and supporting another service later needs no new enum value. The
duplicate check no longer keys on TrackType, which closes a gap where the same
URL could be resubmitted as a different type. Several links per poem remain
allowed; only an identical URL for the same poem is refused.

The Spotify search page and its OAuth plumbing are kept and simply redirect to
/musiclink while the existing SpotifyWorking flag is false, so the old flow can
be restored if that API ever works again.

Track URLs are no longer written through Html.Raw into href attributes. They
previously came from the Spotify API; now that they are user supplied, encoding
them prevents stored XSS.

Also fixes two latent bugs in SuggestSong that this flow would have hit: a null
dereference when TrackUrl is empty, and a singer lookup that matched any singer
with an empty Url.
2026-09-13 22:16:18 -05:00
docs/getting-started documents 2026-08-14 18:46:17 +03:30
GanjooRazor Replace Spotify search with a validated music link box 2026-09-13 22:16:18 -05:00
RMuseum Replace Spotify search with a validated music link box 2026-09-13 22:16:18 -05:00
TajikGanjoor tajik recitation fix 2026-09-12 13:28:23 +03:30
.gitattributes Add project files. 2020-08-14 21:06:22 +04:30
.gitignore Add project files. 2020-08-14 21:06:22 +04:30
GanjoorService.sln refactoring 2026-07-19 16:50:22 +03:30
LICENSE Create LICENSE 2020-08-14 21:35:13 +04:30
README.md semantic search dev guide 2026-09-11 08:33:31 +03:30
RUNNING_LOCALLY.md documentations 2026-08-14 19:41:04 +03:30
SEMANTIC_SEARCH_SETUP.md semantic search dev guide 2026-09-11 08:30:48 +03:30

GanjoorService

Ganjoor museum and ganjoor.net own backend (ASP.NET Core Web API) and frontend (Razor Pages) code

این کد وب سرویس گنجینهٔ گنجور و گنجور و همچنین کد سایت گنجور است.

فهرست توابع در دسترس

https://api.ganjoor.net

Running it locally

New to this codebase and want to run your own copy? See RUNNING_LOCALLY.md for a full step-by-step guide — cloning, database setup, and Visual Studio configuration.

The one thing that guide covers in more depth but is worth knowing up front: the production database is never published, since it contains private/user-linked data. What is published is a git repository of the poetry content itself (poets, categories, poems — allowlisted, no user data): github.com/ganjoor/ganjoor-data. A fresh local install can pull real content from there via Admin → مالی و سایت → درون‌ریزی دادهٔ عمومی (also reachable automatically the first time you run the site against an empty database) instead of starting from nothing.

The "find a poem about..." feature has its own setup guide, separate from the main one above — it needs a downloaded ONNX model and published embeddings data on top of the usual database setup: SEMANTIC_SEARCH_SETUP.md. Also has a real troubleshooting section covering the actual problems hit building this feature, not a generic checklist — worth reading before assuming something new is broken.