Divan: make env config work, ur-PK locale, own-site links relative

- AddEnvironmentVariables() where appsettings.json is read directly
- JWT ValidIssuer follows RSecurityBackend:ApplicationName (was hard-coded Ganjoor)
- deploy/entrypoint.sh: copy settings RSecurityBackend reads only from appsettings.json
- Dockerfile: pin SDK 10.0.302 (newer Razor rejects some upstream views)
- lang=ur-PK; ganjoor.net own-site links -> relative; api.ganjoor.net -> APIRoot; search.xml
- DIVAN.md: first admin password is Test!123 (upstream doc is wrong)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Anas Rashid 2026-10-04 23:32:16 +02:00
parent 1811572d9e
commit 223166ef5e
37 changed files with 76 additions and 54 deletions

View File

@ -8,7 +8,10 @@ This is a fork of [GanjoorService](https://github.com/ganjoor/GanjoorService) (G
- **Urdu basics:** pages are `lang="ur"`. The home page, footer and century groups (Hijri centuries, e.g. "تیرہویں صدی ہجری") are in Urdu. Deeper pages, such as admin and account pages, are still Persian. - **Urdu basics:** pages are `lang="ur"`. The home page, footer and century groups (Hijri centuries, e.g. "تیرہویں صدی ہجری") are in Urdu. Deeper pages, such as admin and account pages, are still Persian.
- **Fonts:** Noto Nastaliq Urdu by default, with a **نستعلیق / نسخ** switch (Noto Naskh Arabic) at the bottom left. The choice is remembered per browser. - **Fonts:** Noto Nastaliq Urdu by default, with a **نستعلیق / نسخ** switch (Noto Naskh Arabic) at the bottom left. The choice is remembered per browser.
- **Footer:** links to Ganjoor-only services (Hafez divination, music index, etc.) are removed. Links to the Wikisource source, the data and the code are added. - **Footer:** links to Ganjoor-only services (Hafez divination, music index, etc.) are removed. Links to the Wikisource source, the data and the code are added.
- **Linux/Docker:** `Dockerfile` + `docker-compose.yml` (SQL Server 2022, API, site, Caddy for HTTPS). The code itself is unchanged apart from the text above. - **Linux/Docker:** `Dockerfile` + `docker-compose.yml` (SQL Server 2022, API, site, Caddy for HTTPS).
- **Config fixes so env vars work:** the four places that read `appsettings.json` directly now also read environment variables. The JWT issuer follows `RSecurityBackend:ApplicationName` instead of the hard-coded "Ganjoor". `deploy/entrypoint.sh` copies the settings that RSecurityBackend reads only from `appsettings.json` (connection string, secret, app name, admin email) into the file at container start.
- **Links:** `ganjoor.net` links to the site's own pages are now relative. Links to Ganjoor's other services (blog, audio, etc.) are left as they are.
- **Locale:** `ur-PK`.
## Deploy (Ubuntu/Debian x86-64, e.g. Vultr) ## Deploy (Ubuntu/Debian x86-64, e.g. Vultr)
@ -29,7 +32,7 @@ SQL Server needs about 2 GB of RAM. Use a plan with at least 4 GB in total.
### Load the data ### Load the data
1. Open `https://SITE_DOMAIN/login` and sign in with `ADMIN_EMAIL` and any password that meets the password rules. That first login creates the admin account. 1. Open `https://SITE_DOMAIN/login` and sign in with `ADMIN_EMAIL` and the password **`Test!123`**. The first login creates the admin account with that fixed password (RSecurityBackend's default; upstream's guide is wrong about this). **Change it right away** in the user panel.
2. On the import page that opens (or **Admin → مالی و سایت → درون‌ریزی دادهٔ عمومی**), choose **Internet URL** and enter: 2. On the import page that opens (or **Admin → مالی و سایت → درون‌ریزی دادهٔ عمومی**), choose **Internet URL** and enter:
``` ```
https://cdn.jsdelivr.net/gh/anas-rashid/divan-data@main/ https://cdn.jsdelivr.net/gh/anas-rashid/divan-data@main/
@ -47,8 +50,9 @@ git pull && docker compose up -d --build
## Build locally (macOS/Linux) ## Build locally (macOS/Linux)
```sh ```sh
dotnet build RMuseum/RMuseum.csproj -p:EnableWindowsTargeting=true cd RMuseum # its global.json pins SDK 10.0.302; newer SDKs fail on some upstream Razor views
dotnet build GanjooRazor/GanjooRazor.csproj -p:EnableWindowsTargeting=true dotnet build RMuseum.csproj -p:EnableWindowsTargeting=true
dotnet build ../GanjooRazor/GanjooRazor.csproj -p:EnableWindowsTargeting=true
``` ```
Running it needs SQL Server, so use the Docker setup above. SQL Server's image is x86-64 only. Running it needs SQL Server, so use the Docker setup above. SQL Server's image is x86-64 only.

View File

@ -3,7 +3,8 @@
# only use the plain .NET + ASP.NET Core runtimes, so the framework-dependent output runs on Linux. # only use the plain .NET + ASP.NET Core runtimes, so the framework-dependent output runs on Linux.
# docker build --build-arg PROJECT=RMuseum . # docker build --build-arg PROJECT=RMuseum .
# docker build --build-arg PROJECT=GanjooRazor . # docker build --build-arg PROJECT=GanjooRazor .
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build # SDK pinned to RMuseum/global.json: newer Razor compilers (10.0.4xx) reject some upstream views
FROM mcr.microsoft.com/dotnet/sdk:10.0.302 AS build
ARG PROJECT ARG PROJECT
WORKDIR /src WORKDIR /src
COPY . . COPY . .
@ -14,5 +15,6 @@ ARG PROJECT
ENV APP_DLL=$PROJECT.dll ASPNETCORE_HTTP_PORTS=8080 ENV APP_DLL=$PROJECT.dll ASPNETCORE_HTTP_PORTS=8080
WORKDIR /app WORKDIR /app
COPY --from=build /app . COPY --from=build /app .
COPY deploy/entrypoint.sh /entrypoint.sh
EXPOSE 8080 EXPOSE 8080
ENTRYPOINT ["sh", "-c", "exec dotnet \"$APP_DLL\""] ENTRYPOINT ["/entrypoint.sh"]

View File

@ -18,7 +18,7 @@ namespace GanjooRazor
if (!string.IsNullOrEmpty(_url)) if (!string.IsNullOrEmpty(_url))
return _url; return _url;
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json") .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables() // divan: honour env overrides (Docker)
.Build(); .Build();
_url = configuration["APIRoot"]; _url = configuration["APIRoot"];
return _url; return _url;
@ -39,7 +39,7 @@ namespace GanjooRazor
if (!string.IsNullOrEmpty(_InternetUrl)) if (!string.IsNullOrEmpty(_InternetUrl))
return _InternetUrl; return _InternetUrl;
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json") .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables() // divan: honour env overrides (Docker)
.Build(); .Build();
_InternetUrl = configuration["GlobalAPIRoot"]; _InternetUrl = configuration["GlobalAPIRoot"];
return _InternetUrl; return _InternetUrl;
@ -64,7 +64,7 @@ namespace GanjooRazor
if (!string.IsNullOrEmpty(_semanticSearchUrl)) if (!string.IsNullOrEmpty(_semanticSearchUrl))
return _semanticSearchUrl; return _semanticSearchUrl;
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json") .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables() // divan: honour env overrides (Docker)
.Build(); .Build();
_semanticSearchUrl = configuration["SemanticSearchAPIRoot"]; _semanticSearchUrl = configuration["SemanticSearchAPIRoot"];
return _semanticSearchUrl; return _semanticSearchUrl;

View File

@ -128,7 +128,7 @@ else
</div> </div>
<div class="up-field"> <div class="up-field">
<label>تصویر شاعر</label> <label>تصویر شاعر</label>
<img src="@($"https://api.ganjoor.net{Model.GanjoorQuotedPoem.CachedRelatedPoemPoetImage}")" style="max-width:200px;" /> <img src="@($"{GanjooRazor.APIRoot.InternetUrl}{Model.GanjoorQuotedPoem.CachedRelatedPoemPoetImage}")" style="max-width:200px;" />
</div> </div>
<div class="up-field"> <div class="up-field">
<label>عنوان شعر</label> <label>عنوان شعر</label>

View File

@ -1983,7 +1983,7 @@ else
</div> </div>
<div class="up-alert up-alert--warning"> <div class="up-alert up-alert--warning">
<p class="up-mt-0">توجه داشته باشید که کارکرد برچسب‌گذاری اشعار در دیوان یافتن اشعار هم‌وزن است. از این جهت از پیشنهاد صورت‌های سلیقه‌ای و متفاوت یک وزن خودداری کنید تا این قابلیت مختل نشود. <a href="https://ganjoor.net/faq?id=14" target="_blank">این نکته</a> را هم مد نظر داشته باشید.</p> <p class="up-mt-0">توجه داشته باشید که کارکرد برچسب‌گذاری اشعار در دیوان یافتن اشعار هم‌وزن است. از این جهت از پیشنهاد صورت‌های سلیقه‌ای و متفاوت یک وزن خودداری کنید تا این قابلیت مختل نشود. <a href="/faq?id=14" target="_blank">این نکته</a> را هم مد نظر داشته باشید.</p>
</div> </div>
<div class="up-field"> <div class="up-field">

View File

@ -162,7 +162,7 @@ else
</tr> </tr>
<tr> <tr>
<td> <td>
<img src="@($"https://api.ganjoor.net{GanjoorQuotedPoem.CachedRelatedPoemPoetImage}")" /> <img src="@($"{GanjooRazor.APIRoot.InternetUrl}{GanjoorQuotedPoem.CachedRelatedPoemPoetImage}")" />
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@ -166,7 +166,7 @@ else
</div> </div>
<div class="up-alert up-alert--warning"> <div class="up-alert up-alert--warning">
<p class="up-mt-0">توجه داشته باشید که کارکرد برچسب‌گذاری اشعار در دیوان یافتن اشعار هم‌وزن است. از این جهت از پیشنهاد صورت‌های سلیقه‌ای و متفاوت یک وزن خودداری کنید تا این قابلیت مختل نشود. <a href="https://ganjoor.net/faq?id=14" target="_blank">این نکته</a> را هم مد نظر داشته باشید.</p> <p class="up-mt-0">توجه داشته باشید که کارکرد برچسب‌گذاری اشعار در دیوان یافتن اشعار هم‌وزن است. از این جهت از پیشنهاد صورت‌های سلیقه‌ای و متفاوت یک وزن خودداری کنید تا این قابلیت مختل نشود. <a href="/faq?id=14" target="_blank">این نکته</a> را هم مد نظر داشته باشید.</p>
</div> </div>
<div class="up-field"> <div class="up-field">

View File

@ -7,7 +7,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -6,7 +6,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>@ViewData["Title"]</title> <title>@ViewData["Title"]</title>

View File

@ -4,7 +4,7 @@
Layout = null; Layout = null;
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>@ViewData["Title"]</title> <title>@ViewData["Title"]</title>

View File

@ -5,7 +5,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>@ViewData["Title"]</title> <title>@ViewData["Title"]</title>

View File

@ -4,7 +4,7 @@
Layout = null; Layout = null;
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -6,7 +6,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
@ -16,7 +16,7 @@
<link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" /> <link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" />
<partial name="_DivanHead" /> <partial name="_DivanHead" />
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="https://ganjoor.net/search.xml" /> <link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
<style> <style>
code, pre { code, pre {

View File

@ -5,7 +5,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>پیشنهاد شعر مرتبط با تصویر</title> <title>پیشنهاد شعر مرتبط با تصویر</title>

View File

@ -6,7 +6,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<title>نقشهٔ دیوان</title> <title>نقشهٔ دیوان</title>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -5,7 +5,7 @@
Layout = null; Layout = null;
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
@ -16,7 +16,7 @@
<link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" /> <link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" />
<partial name="_DivanHead" /> <partial name="_DivanHead" />
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="https://ganjoor.net/search.xml" /> <link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
<script src="/lib/jquery/dist/jquery.min.js"></script> <script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/bk.js" asp-append-version="true"></script> <script src="~/js/bk.js" asp-append-version="true"></script>
<script> <script>

View File

@ -5,7 +5,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />

View File

@ -39,7 +39,7 @@
case "discussions": case "discussions":
<text> <text>
<p> <p>
<a href="https://ganjoor.net/hashieha/">حاشیه‌ها</a> دیدگاه‌های ثبت شدهٔ کاربران دیوان است. <a href="https://blog.ganjoor.net/1386/12/06/comments/">سابقهٔ امکان درج حاشیه</a> در دیوان به ۱۴ سال پیش از <a href="https://blog.ganjoor.net/1400/03/01/signupandlogin/">افزوده شدن امکان نام‌نویسی در دیوان</a> برمی‌گردد و پیش از آن کاربران می‌توانستند حتی بدون وارد کردن نامشان در دیوان حاشیه‌نویسی کنند. بعد از افزوده شدن امکان نام‌نویسی اگر کاربر با ایمیلی ثبت نام کند که پیش از آن با همان ایمیل حاشیه‌ای در دیوان ثبت کرده باشد مالکیت آن حاشیه(ها) به او منتقل می‌شود. در صورتی که کاربری حساب کاربری خود را حذف کند حاشیه‌های او هم به طور کامل حذف می‌شود. <a href="/hashieha/">حاشیه‌ها</a> دیدگاه‌های ثبت شدهٔ کاربران دیوان است. <a href="https://blog.ganjoor.net/1386/12/06/comments/">سابقهٔ امکان درج حاشیه</a> در دیوان به ۱۴ سال پیش از <a href="https://blog.ganjoor.net/1400/03/01/signupandlogin/">افزوده شدن امکان نام‌نویسی در دیوان</a> برمی‌گردد و پیش از آن کاربران می‌توانستند حتی بدون وارد کردن نامشان در دیوان حاشیه‌نویسی کنند. بعد از افزوده شدن امکان نام‌نویسی اگر کاربر با ایمیلی ثبت نام کند که پیش از آن با همان ایمیل حاشیه‌ای در دیوان ثبت کرده باشد مالکیت آن حاشیه(ها) به او منتقل می‌شود. در صورتی که کاربری حساب کاربری خود را حذف کند حاشیه‌های او هم به طور کامل حذف می‌شود.
</p> </p>
</text> </text>
break; break;

View File

@ -6,7 +6,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
@ -18,7 +18,7 @@
<link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" /> <link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" />
<partial name="_DivanHead" /> <partial name="_DivanHead" />
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="https://ganjoor.net/search.xml" /> <link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
<script> <script>
function wpopen(macagna) { function wpopen(macagna) {
window.open(macagna, '_blank', 'width=600,height=700,scrollbars=yes,status=yes'); window.open(macagna, '_blank', 'width=600,height=700,scrollbars=yes,status=yes');

View File

@ -6,7 +6,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -7,7 +7,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -1,6 +1,6 @@
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery @inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
@ -17,7 +17,7 @@
<link href="~/css/user-panel.css" asp-append-version="true" rel="stylesheet" type="text/css" /> <link href="~/css/user-panel.css" asp-append-version="true" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="/css/leaflet.css?version=2"> <link rel="stylesheet" href="/css/leaflet.css?version=2">
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="https://ganjoor.net/search.xml" /> <link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/leaflet.js"></script> <script src="~/js/leaflet.js"></script>
<script src="~/js/leaflet-providers.js"></script> <script src="~/js/leaflet-providers.js"></script>

View File

@ -26,7 +26,7 @@
// analytics), so this shouldn't matter, but flagging it since it's a real order change. // analytics), so this shouldn't matter, but flagging it since it's a real order change.
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -1,6 +1,6 @@
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery @inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
@ -16,7 +16,7 @@
<link href="~/css/user-panel.css" asp-append-version="true" rel="stylesheet" type="text/css" /> <link href="~/css/user-panel.css" asp-append-version="true" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="/css/leaflet.css?version=2"> <link rel="stylesheet" href="/css/leaflet.css?version=2">
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="https://ganjoor.net/search.xml" /> <link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
<script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/leaflet.js"></script> <script src="~/js/leaflet.js"></script>
<script src="~/js/leaflet-providers.js"></script> <script src="~/js/leaflet-providers.js"></script>

View File

@ -5,7 +5,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>انتخاب قطعهٔ موسیقی مرتبط با شعر از بیپتونز</title> <title>انتخاب قطعهٔ موسیقی مرتبط با شعر از بیپتونز</title>
@ -105,7 +105,7 @@
با استفاده از این صفحه می‌توانید آهنگهایی را که در متن آنها از شعر جاری استفاده شده است معرفی کنید. جستجو در سایت خرید قانونی موسیقی <a href="http://beeptunes.com" target="_blank">بیپ‌تونز</a> صورت می‌گیرد. جستجو با تایپ قسمتی از نام خواننده در جعبهٔ «خواننده» و کلیک بر روی آن شروع می‌شود. پس از انتخاب خواننده فهرست آلبومها و آهنگهای آلبوم جاری نمایش داده می‌شود. با کلیک بر روی پیوند صفحهٔ آهنگ می‌توانید جهت اطمینان قسمتی از آهنگ را در سایت بیپ‌تونز گوش کنید. پس از «پیشنهاد قطعه» آهنگ پیشنهادی در صف بررسی قرار می‌گیرد و پس از بازبینی و تأیید به صفحهٔ اصلی شعر اضافه می‌شود. از این که کمک می‌کنید که دیوان به نمایه‌ای برای موسیقی ایرانی بدل شود سپاسگزاریم. با استفاده از این صفحه می‌توانید آهنگهایی را که در متن آنها از شعر جاری استفاده شده است معرفی کنید. جستجو در سایت خرید قانونی موسیقی <a href="http://beeptunes.com" target="_blank">بیپ‌تونز</a> صورت می‌گیرد. جستجو با تایپ قسمتی از نام خواننده در جعبهٔ «خواننده» و کلیک بر روی آن شروع می‌شود. پس از انتخاب خواننده فهرست آلبومها و آهنگهای آلبوم جاری نمایش داده می‌شود. با کلیک بر روی پیوند صفحهٔ آهنگ می‌توانید جهت اطمینان قسمتی از آهنگ را در سایت بیپ‌تونز گوش کنید. پس از «پیشنهاد قطعه» آهنگ پیشنهادی در صف بررسی قرار می‌گیرد و پس از بازبینی و تأیید به صفحهٔ اصلی شعر اضافه می‌شود. از این که کمک می‌کنید که دیوان به نمایه‌ای برای موسیقی ایرانی بدل شود سپاسگزاریم.
</p> </p>
<p> <p>
<span style="color:red">تذکر مهم:</span> فقط مواردی تأیید می‌شود که <span style="color:red">در آهنگ متناظر همین شعر خوانده شود</span>. تعیین نام خواننده به تنهایی کارایی ندارد و لطفا جهت کاهش زمان مورد نیاز برای بررسی موارد پیشنهادی از اعلام موارد اینچنینی خودداری فرمایید. جهت مشاهدهٔ روش پیشنهادی برای کمک به این پروژه <a href="http://www.aparat.com/v/kxGre" target="_blank">این فیلم</a> را مشاهده فرمایید. فهرست کامل آهنگهای مرتبط در <a href="https://ganjoor.net/mundex/" target="_blank">این صفحه</a> در دسترس است. <span style="color:red">تذکر مهم:</span> فقط مواردی تأیید می‌شود که <span style="color:red">در آهنگ متناظر همین شعر خوانده شود</span>. تعیین نام خواننده به تنهایی کارایی ندارد و لطفا جهت کاهش زمان مورد نیاز برای بررسی موارد پیشنهادی از اعلام موارد اینچنینی خودداری فرمایید. جهت مشاهدهٔ روش پیشنهادی برای کمک به این پروژه <a href="http://www.aparat.com/v/kxGre" target="_blank">این فیلم</a> را مشاهده فرمایید. فهرست کامل آهنگهای مرتبط در <a href="/mundex/" target="_blank">این صفحه</a> در دسترس است.
</p> </p>
@if (Model.SuggestedSongs.Length > 0) @if (Model.SuggestedSongs.Length > 0)

View File

@ -4,7 +4,7 @@
Layout = null; Layout = null;
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>انتخاب قطعه‌ای از برنامهٔ گلها مرتبط با این شعر</title> <title>انتخاب قطعه‌ای از برنامهٔ گلها مرتبط با این شعر</title>

View File

@ -5,7 +5,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>انتخاب قطعهٔ موسیقی مرتبط با شعر از اسپاتیفای</title> <title>انتخاب قطعهٔ موسیقی مرتبط با شعر از اسپاتیفای</title>
@ -104,7 +104,7 @@
با استفاده از این صفحه می‌توانید آهنگهایی را که در متن آنها از شعر جاری استفاده شده است معرفی کنید. جستجو در سایت <a href="https://open.spotify.com" target="_blank">اسپاتیفای</a> صورت می‌گیرد. جستجو با تایپ قسمتی از نام خواننده در جعبهٔ «خواننده» و کلیک بر روی آن شروع می‌شود (<span style="color:red">نکتهٔ مهم:</span> لطفاً توجه فرمایید که جستجو در اسپاتیفای عموماً با حروف لاتین به نتیجه می‌رسد). پس از انتخاب خواننده فهرست آلبومها و آهنگهای آلبوم جاری نمایش داده می‌شود. با کلیک بر روی پیوند صفحهٔ آهنگ می‌توانید جهت اطمینان آهنگ را در اسپاتیفای گوش کنید (پخش آهنگ در اسپاتیفای نیازمند ثبت‌نام در این سایت است). پس از «پیشنهاد قطعه» آهنگ پیشنهادی در صف بررسی قرار می‌گیرد و پس از بازبینی و تأیید به صفحهٔ اصلی شعر اضافه می‌شود. از این که کمک می‌کنید که دیوان به نمایه‌ای برای موسیقی ایرانی بدل شود سپاسگزاریم. با استفاده از این صفحه می‌توانید آهنگهایی را که در متن آنها از شعر جاری استفاده شده است معرفی کنید. جستجو در سایت <a href="https://open.spotify.com" target="_blank">اسپاتیفای</a> صورت می‌گیرد. جستجو با تایپ قسمتی از نام خواننده در جعبهٔ «خواننده» و کلیک بر روی آن شروع می‌شود (<span style="color:red">نکتهٔ مهم:</span> لطفاً توجه فرمایید که جستجو در اسپاتیفای عموماً با حروف لاتین به نتیجه می‌رسد). پس از انتخاب خواننده فهرست آلبومها و آهنگهای آلبوم جاری نمایش داده می‌شود. با کلیک بر روی پیوند صفحهٔ آهنگ می‌توانید جهت اطمینان آهنگ را در اسپاتیفای گوش کنید (پخش آهنگ در اسپاتیفای نیازمند ثبت‌نام در این سایت است). پس از «پیشنهاد قطعه» آهنگ پیشنهادی در صف بررسی قرار می‌گیرد و پس از بازبینی و تأیید به صفحهٔ اصلی شعر اضافه می‌شود. از این که کمک می‌کنید که دیوان به نمایه‌ای برای موسیقی ایرانی بدل شود سپاسگزاریم.
</p> </p>
<p> <p>
<span style="color:red">تذکر مهم:</span> فقط مواردی تأیید می‌شود که <span style="color:red">در آهنگ متناظر همین شعر خوانده شود</span>. تعیین نام خواننده به تنهایی کارایی ندارد و لطفا جهت کاهش زمان مورد نیاز برای بررسی موارد پیشنهادی از اعلام موارد اینچنینی خودداری فرمایید. جهت مشاهدهٔ روش پیشنهادی برای کمک به این پروژه <a href="http://www.aparat.com/v/kxGre" target="_blank">این فیلم</a> را مشاهده فرمایید. فهرست کامل آهنگهای مرتبط در <a href="https://ganjoor.net/mundex/" target="_blank">این صفحه</a> در دسترس است. <span style="color:red">تذکر مهم:</span> فقط مواردی تأیید می‌شود که <span style="color:red">در آهنگ متناظر همین شعر خوانده شود</span>. تعیین نام خواننده به تنهایی کارایی ندارد و لطفا جهت کاهش زمان مورد نیاز برای بررسی موارد پیشنهادی از اعلام موارد اینچنینی خودداری فرمایید. جهت مشاهدهٔ روش پیشنهادی برای کمک به این پروژه <a href="http://www.aparat.com/v/kxGre" target="_blank">این فیلم</a> را مشاهده فرمایید. فهرست کامل آهنگهای مرتبط در <a href="/mundex/" target="_blank">این صفحه</a> در دسترس است.
</p> </p>
@if (Model.SuggestedSongs.Length > 0) @if (Model.SuggestedSongs.Length > 0)

View File

@ -6,7 +6,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
@ -16,7 +16,7 @@
<link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" /> <link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" />
<partial name="_DivanHead" /> <partial name="_DivanHead" />
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="https://ganjoor.net/search.xml" /> <link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
</head> </head>

View File

@ -6,7 +6,7 @@
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
@ -17,7 +17,7 @@
<link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" /> <link href="~/css/p8.css" asp-append-version="true" rel="stylesheet" type="text/css" />
<partial name="_DivanHead" /> <partial name="_DivanHead" />
<link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" /> <link rel="shortcut icon" href="/favicon.ico?version=1" type="image/x-icon" />
<link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="https://ganjoor.net/search.xml" /> <link rel="search" type="application/opensearchdescription+xml" title="دیوان" href="/search.xml" />
</head> </head>

View File

@ -5,7 +5,7 @@
ViewData["Title"] = "بیت تصادفی"; ViewData["Title"] = "بیت تصادفی";
} }
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ur" dir="rtl"> <html lang="ur-PK" dir="rtl">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -140,7 +140,7 @@ function vaabSelectionChanged() {
target: '_blank', target: '_blank',
}); });
$search.attr({ $search.attr({
href: text.indexOf(' ') == -1 ? 'https://ganjoor.net/search?s=' + encodeURI(text) : 'https://ganjoor.net/search?s="' + encodeURI(text) + '"', href: text.indexOf(' ') == -1 ? '/search?s=' + encodeURI(text) : '/search?s="' + encodeURI(text) + '"',
title: 'جستجوی عبارت در دیوان', title: 'جستجوی عبارت در دیوان',
target: '_blank', target: '_blank',
}); });

View File

@ -2,10 +2,10 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
xmlns:moz="http://www.mozilla.org/2006/browser/search/"> xmlns:moz="http://www.mozilla.org/2006/browser/search/">
<!-- Created on Tue, 30 Dec 2008 17:57:57 GMT --> <!-- Created on Tue, 30 Dec 2008 17:57:57 GMT -->
<ShortName>Ganjoor</ShortName> <ShortName>دیوان</ShortName>
<Description>Search inside ganjoor.net</Description> <Description>دیوان میں تلاش</Description>
<Url type="text/html" method="get" template="https://ganjoor.net/search?s={searchTerms}"/> <Url type="text/html" method="get" template="/search?s={searchTerms}"/>
<Image width="16" height="16">https://ganjoor/favicon.ico?version=1</Image> <Image width="16" height="16">/favicon.ico?version=1</Image>
<Developer>hamid reza</Developer> <Developer>hamid reza</Developer>
<InputEncoding>UTF-8</InputEncoding> <InputEncoding>UTF-8</InputEncoding>
<moz:SearchForm>https://ganjoor.net</moz:SearchForm> <moz:SearchForm>https://ganjoor.net</moz:SearchForm>

View File

@ -29,7 +29,7 @@ namespace RMuseum.DbContext
public RMuseumDbContext(DbContextOptions<RMuseumDbContext> options) : base(options) public RMuseumDbContext(DbContextOptions<RMuseumDbContext> options) : base(options)
{ {
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json") .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables() // divan: honour env overrides (Docker)
.Build(); .Build();
if (bool.Parse(configuration["DatabaseMigrate"])) if (bool.Parse(configuration["DatabaseMigrate"]))
{ {

View File

@ -44,7 +44,7 @@ namespace RMuseum.Services.Implementation
.ToListAsync(); .ToListAsync();
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json") .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables() // divan: honour env overrides (Docker)
.Build(); .Build();
ImageFileServiceEF imageFileService = new ImageFileServiceEF(context, configuration); ImageFileServiceEF imageFileService = new ImageFileServiceEF(context, configuration);

View File

@ -142,7 +142,7 @@ namespace RMuseum
ValidateAudience = false, ValidateAudience = false,
ValidAudience = "Everyone", ValidAudience = "Everyone",
ValidateIssuer = true, ValidateIssuer = true,
ValidIssuer = "Ganjoor", ValidIssuer = Configuration.GetSection("RSecurityBackend")["ApplicationName"] ?? "Ganjoor", // divan: issuer follows ApplicationName (the token issuer)
ValidateIssuerSigningKey = true, ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes($"{Configuration.GetSection("Security")["Secret"]}")), IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes($"{Configuration.GetSection("Security")["Secret"]}")),

View File

@ -15,7 +15,7 @@ namespace RMuseum
if (!string.IsNullOrEmpty(_url)) if (!string.IsNullOrEmpty(_url))
return _url; return _url;
IConfigurationRoot configuration = new ConfigurationBuilder() IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json") .SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json").AddEnvironmentVariables() // divan: honour env overrides (Docker)
.Build(); .Build();
_url = configuration["WebServiceUrl"]; _url = configuration["WebServiceUrl"];
return _url; return _url;

16
deploy/entrypoint.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
# Parts of the app (and the RSecurityBackend NuGet package) read appsettings.json directly and ignore env vars
# (connection string, JWT secret/issuer, first admin). Copy those env values into the deployed file before starting.
# Values must not contain double quotes.
set_key() { # set_key <json key> <value>: replace "key": "..." (keys below are unique in appsettings.json)
[ -n "$2" ] || return 0
esc=$(printf '%s' "$2" | sed 's/[\\&|]/\\&/g')
sed -i "s|\"$1\": \"[^\"]*\"|\"$1\": \"$esc\"|" appsettings.json
}
if [ -f appsettings.json ]; then
set_key DefaultConnection "$ConnectionStrings__DefaultConnection"
set_key Secret "$Security__Secret"
set_key ApplicationName "$RSecurityBackend__ApplicationName"
set_key FirstUserEmail "$RSecurityBackend__FirstUserEmail"
fi
exec dotnet "$APP_DLL"