[Ingest] Per-source proxy toggle instead of one global switch
Each ingestion source now decides independently whether to route through the proxy: added TelegramUseProxy/BaleUseProxy/DivarUseProxy/MedjobsUseProxy/WebsitesUseProxy flags (migration). ScrapeHttpClients.For(s, useProxy) takes the source's own flag; a source is proxied only when its flag is on AND a proxy URL is set. Settings 'sources' tab: removed the global enable checkbox, kept the proxy address field, and added an «از پروکسی استفاده شود» checkbox under each source. Old IngestProxyEnabled column kept for compatibility but no longer gates routing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,73 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace JobsMedical.Web.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class PerSourceProxy : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "BaleUseProxy",
|
||||||
|
table: "AppSettings",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "DivarUseProxy",
|
||||||
|
table: "AppSettings",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "MedjobsUseProxy",
|
||||||
|
table: "AppSettings",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "TelegramUseProxy",
|
||||||
|
table: "AppSettings",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "WebsitesUseProxy",
|
||||||
|
table: "AppSettings",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "BaleUseProxy",
|
||||||
|
table: "AppSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DivarUseProxy",
|
||||||
|
table: "AppSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MedjobsUseProxy",
|
||||||
|
table: "AppSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "TelegramUseProxy",
|
||||||
|
table: "AppSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "WebsitesUseProxy",
|
||||||
|
table: "AppSettings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,6 +66,9 @@ namespace JobsMedical.Web.Migrations
|
|||||||
b.Property<bool>("BaleEnabled")
|
b.Property<bool>("BaleEnabled")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("BaleUseProxy")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<bool>("DemoMode")
|
b.Property<bool>("DemoMode")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
@@ -80,6 +83,9 @@ namespace JobsMedical.Web.Migrations
|
|||||||
.HasMaxLength(2000)
|
.HasMaxLength(2000)
|
||||||
.HasColumnType("character varying(2000)");
|
.HasColumnType("character varying(2000)");
|
||||||
|
|
||||||
|
b.Property<bool>("DivarUseProxy")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<int>("IngestIntervalMinutes")
|
b.Property<int>("IngestIntervalMinutes")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
@@ -96,6 +102,9 @@ namespace JobsMedical.Web.Migrations
|
|||||||
b.Property<int>("MedjobsMaxAds")
|
b.Property<int>("MedjobsMaxAds")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("MedjobsUseProxy")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<int>("Mode")
|
b.Property<int>("Mode")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
@@ -128,6 +137,9 @@ namespace JobsMedical.Web.Migrations
|
|||||||
b.Property<bool>("TelegramEnabled")
|
b.Property<bool>("TelegramEnabled")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("TelegramUseProxy")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<DateTime>("UpdatedAt")
|
b.Property<DateTime>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
@@ -153,6 +165,9 @@ namespace JobsMedical.Web.Migrations
|
|||||||
b.Property<bool>("WebsitesEnabled")
|
b.Property<bool>("WebsitesEnabled")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<bool>("WebsitesUseProxy")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("AppSettings");
|
b.ToTable("AppSettings");
|
||||||
|
|||||||
@@ -51,13 +51,22 @@ public class AppSetting
|
|||||||
/// <summary>Generic web pages to scrape, one URL per line.</summary>
|
/// <summary>Generic web pages to scrape, one URL per line.</summary>
|
||||||
[MaxLength(4000)] public string? WebsiteUrls { get; set; }
|
[MaxLength(4000)] public string? WebsiteUrls { get; set; }
|
||||||
|
|
||||||
/// <summary>Route ingestion fetches through a proxy (needed in Iran for Telegram etc.).</summary>
|
|
||||||
public bool IngestProxyEnabled { get; set; } = false;
|
|
||||||
/// <summary>Local proxy an Xray/V2Ray client sidecar exposes, e.g. socks5://xray:10808
|
/// <summary>Local proxy an Xray/V2Ray client sidecar exposes, e.g. socks5://xray:10808
|
||||||
/// (also accepts socks4:// or http://). The app cannot read vmess/vless/trojan directly;
|
/// (also accepts socks4:// or http://). The app cannot read vmess/vless/trojan directly;
|
||||||
/// the sidecar converts that config into this local proxy.</summary>
|
/// the sidecar converts that config into this local proxy. Per-source toggles below decide
|
||||||
|
/// which channels actually route through it.</summary>
|
||||||
[MaxLength(200)] public string? IngestProxyUrl { get; set; }
|
[MaxLength(200)] public string? IngestProxyUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Legacy global flag — kept for compatibility; per-source flags below now control routing.</summary>
|
||||||
|
public bool IngestProxyEnabled { get; set; } = false;
|
||||||
|
|
||||||
|
// Per-source: route this source's fetches through IngestProxyUrl (only when a URL is set).
|
||||||
|
public bool TelegramUseProxy { get; set; } = false;
|
||||||
|
public bool BaleUseProxy { get; set; } = false;
|
||||||
|
public bool DivarUseProxy { get; set; } = false;
|
||||||
|
public bool MedjobsUseProxy { get; set; } = false;
|
||||||
|
public bool WebsitesUseProxy { get; set; } = false;
|
||||||
|
|
||||||
public bool DivarEnabled { get; set; } = false;
|
public bool DivarEnabled { get; set; } = false;
|
||||||
[MaxLength(60)] public string? DivarCity { get; set; } = "tehran";
|
[MaxLength(60)] public string? DivarCity { get; set; } = "tehran";
|
||||||
/// <summary>Divar search terms, one per line or comma-separated.</summary>
|
/// <summary>Divar search terms, one per line or comma-separated.</summary>
|
||||||
|
|||||||
@@ -94,13 +94,16 @@
|
|||||||
<div class="filter-group">
|
<div class="filter-group">
|
||||||
<label>یوزرنیم کانالها (هر خط یک کانال)</label>
|
<label>یوزرنیم کانالها (هر خط یک کانال)</label>
|
||||||
<textarea name="TelegramChannels" rows="3" dir="ltr" placeholder="shift_channel another_channel">@Model.TelegramChannels</textarea>
|
<textarea name="TelegramChannels" rows="3" dir="ltr" placeholder="shift_channel another_channel">@Model.TelegramChannels</textarea>
|
||||||
|
<label class="proxy-toggle"><input type="checkbox" name="TelegramUseProxy" value="true" checked="@Model.TelegramUseProxy" /> از پروکسی استفاده شود</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<label class="toggle-row">
|
<label class="toggle-row">
|
||||||
<input type="checkbox" name="BaleEnabled" value="true" checked="@Model.BaleEnabled" />
|
<input type="checkbox" name="BaleEnabled" value="true" checked="@Model.BaleEnabled" />
|
||||||
<span class="t-body"><span>بله (بات باید عضو کانال باشد)</span></span>
|
<span class="t-body"><span>بله (بات باید عضو کانال باشد)</span></span>
|
||||||
</label>
|
</label>
|
||||||
<div class="filter-group"><label>توکن بات بله</label><input type="password" name="BaleBotToken" value="@Model.BaleBotToken" dir="ltr" /></div>
|
<div class="filter-group"><label>توکن بات بله</label><input type="password" name="BaleBotToken" value="@Model.BaleBotToken" dir="ltr" />
|
||||||
|
<label class="proxy-toggle"><input type="checkbox" name="BaleUseProxy" value="true" checked="@Model.BaleUseProxy" /> از پروکسی استفاده شود</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label class="toggle-row">
|
<label class="toggle-row">
|
||||||
<input type="checkbox" name="DivarEnabled" value="true" checked="@Model.DivarEnabled" />
|
<input type="checkbox" name="DivarEnabled" value="true" checked="@Model.DivarEnabled" />
|
||||||
@@ -110,12 +113,15 @@
|
|||||||
<div style="flex:0 0 120px;"><label>شهر (slug)</label><input type="text" name="DivarCity" value="@Model.DivarCity" dir="ltr" placeholder="tehran" /></div>
|
<div style="flex:0 0 120px;"><label>شهر (slug)</label><input type="text" name="DivarCity" value="@Model.DivarCity" dir="ltr" placeholder="tehran" /></div>
|
||||||
<div style="flex:1;"><label>عبارتهای جستجو (هر خط یکی)</label><textarea name="DivarQueries" rows="3">@Model.DivarQueries</textarea></div>
|
<div style="flex:1;"><label>عبارتهای جستجو (هر خط یکی)</label><textarea name="DivarQueries" rows="3">@Model.DivarQueries</textarea></div>
|
||||||
</div>
|
</div>
|
||||||
|
<label class="proxy-toggle"><input type="checkbox" name="DivarUseProxy" value="true" checked="@Model.DivarUseProxy" /> از پروکسی استفاده شود</label>
|
||||||
|
|
||||||
<label class="toggle-row">
|
<label class="toggle-row">
|
||||||
<input type="checkbox" name="MedjobsEnabled" value="true" checked="@Model.MedjobsEnabled" />
|
<input type="checkbox" name="MedjobsEnabled" value="true" checked="@Model.MedjobsEnabled" />
|
||||||
<span class="t-body"><span>مدجابز (medjobs.ir)</span><span class="t-hint">خواندن کامل آگهیها از سایتمپ.</span></span>
|
<span class="t-body"><span>مدجابز (medjobs.ir)</span><span class="t-hint">خواندن کامل آگهیها از سایتمپ.</span></span>
|
||||||
</label>
|
</label>
|
||||||
<div class="filter-group"><label>حداکثر آگهی در هر اجرا</label><input type="number" name="MedjobsMaxAds" min="1" max="500" value="@Model.MedjobsMaxAds" dir="ltr" /></div>
|
<div class="filter-group"><label>حداکثر آگهی در هر اجرا</label><input type="number" name="MedjobsMaxAds" min="1" max="500" value="@Model.MedjobsMaxAds" dir="ltr" />
|
||||||
|
<label class="proxy-toggle"><input type="checkbox" name="MedjobsUseProxy" value="true" checked="@Model.MedjobsUseProxy" /> از پروکسی استفاده شود</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label class="toggle-row">
|
<label class="toggle-row">
|
||||||
<input type="checkbox" name="WebsitesEnabled" value="true" checked="@Model.WebsitesEnabled" />
|
<input type="checkbox" name="WebsitesEnabled" value="true" checked="@Model.WebsitesEnabled" />
|
||||||
@@ -124,18 +130,15 @@
|
|||||||
<div class="filter-group">
|
<div class="filter-group">
|
||||||
<label>آدرس صفحهها (هر خط یک URL)</label>
|
<label>آدرس صفحهها (هر خط یک URL)</label>
|
||||||
<textarea name="WebsiteUrls" rows="3" dir="ltr" placeholder="https://example.ir/jobs/123">@Model.WebsiteUrls</textarea>
|
<textarea name="WebsiteUrls" rows="3" dir="ltr" placeholder="https://example.ir/jobs/123">@Model.WebsiteUrls</textarea>
|
||||||
|
<label class="proxy-toggle"><input type="checkbox" name="WebsitesUseProxy" value="true" checked="@Model.WebsitesUseProxy" /> از پروکسی استفاده شود</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr style="border:none; border-top:1px solid var(--line); margin:18px 0;" />
|
<hr style="border:none; border-top:1px solid var(--line); margin:18px 0;" />
|
||||||
<label class="toggle-row">
|
<h3 style="margin-top:0;">پروکسی (Xray/V2Ray)</h3>
|
||||||
<input type="checkbox" name="IngestProxyEnabled" value="true" checked="@Model.IngestProxyEnabled" />
|
|
||||||
<span class="t-body"><span>ارسال جمعآوری از طریق پروکسی</span>
|
|
||||||
<span class="t-hint">برای دسترسی به تلگرام و … در ایران (Xray/V2Ray).</span></span>
|
|
||||||
</label>
|
|
||||||
<div class="filter-group">
|
<div class="filter-group">
|
||||||
<label>آدرس پروکسی محلی</label>
|
<label>آدرس پروکسی محلی</label>
|
||||||
<input type="text" name="IngestProxyUrl" value="@Model.IngestProxyUrl" dir="ltr" placeholder="socks5://xray:10808" />
|
<input type="text" name="IngestProxyUrl" value="@Model.IngestProxyUrl" dir="ltr" placeholder="socks5://xray:10808" />
|
||||||
<p class="muted" style="font-size:12px; margin:4px 0 0;">یک کلاینت Xray/V2Ray کانفیگ vmess/vless/trojan تو را به یک پروکسی محلی تبدیل میکند (socks5:// یا socks4:// یا http://).</p>
|
<p class="muted" style="font-size:12px; margin:4px 0 0;">یک کلاینت Xray/V2Ray کانفیگ vmess/vless/trojan تو را به یک پروکسی محلی تبدیل میکند (socks5:// یا socks4:// یا http://). <strong>هر منبع جداگانه</strong> با تیکِ «از پروکسی استفاده شود» تعیین میکند که از این پروکسی عبور کند یا نه.</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,12 @@ public class SettingsModel : PageModel
|
|||||||
[BindProperty] public bool DemoMode { get; set; }
|
[BindProperty] public bool DemoMode { get; set; }
|
||||||
[BindProperty] public bool WebsitesEnabled { get; set; }
|
[BindProperty] public bool WebsitesEnabled { get; set; }
|
||||||
[BindProperty] public string? WebsiteUrls { get; set; }
|
[BindProperty] public string? WebsiteUrls { get; set; }
|
||||||
[BindProperty] public bool IngestProxyEnabled { get; set; }
|
|
||||||
[BindProperty] public string? IngestProxyUrl { get; set; }
|
[BindProperty] public string? IngestProxyUrl { get; set; }
|
||||||
|
[BindProperty] public bool TelegramUseProxy { get; set; }
|
||||||
|
[BindProperty] public bool BaleUseProxy { get; set; }
|
||||||
|
[BindProperty] public bool DivarUseProxy { get; set; }
|
||||||
|
[BindProperty] public bool MedjobsUseProxy { get; set; }
|
||||||
|
[BindProperty] public bool WebsitesUseProxy { get; set; }
|
||||||
[TempData] public string? Saved { get; set; }
|
[TempData] public string? Saved { get; set; }
|
||||||
[TempData] public string? SmsTest { get; set; }
|
[TempData] public string? SmsTest { get; set; }
|
||||||
[TempData] public string? DemoMsg { get; set; }
|
[TempData] public string? DemoMsg { get; set; }
|
||||||
@@ -91,8 +95,12 @@ public class SettingsModel : PageModel
|
|||||||
DemoMode = s.DemoMode;
|
DemoMode = s.DemoMode;
|
||||||
WebsitesEnabled = s.WebsitesEnabled;
|
WebsitesEnabled = s.WebsitesEnabled;
|
||||||
WebsiteUrls = s.WebsiteUrls;
|
WebsiteUrls = s.WebsiteUrls;
|
||||||
IngestProxyEnabled = s.IngestProxyEnabled;
|
|
||||||
IngestProxyUrl = s.IngestProxyUrl;
|
IngestProxyUrl = s.IngestProxyUrl;
|
||||||
|
TelegramUseProxy = s.TelegramUseProxy;
|
||||||
|
BaleUseProxy = s.BaleUseProxy;
|
||||||
|
DivarUseProxy = s.DivarUseProxy;
|
||||||
|
MedjobsUseProxy = s.MedjobsUseProxy;
|
||||||
|
WebsitesUseProxy = s.WebsitesUseProxy;
|
||||||
WebNotificationsEnabled = s.WebNotificationsEnabled;
|
WebNotificationsEnabled = s.WebNotificationsEnabled;
|
||||||
PushEnabled = s.PushEnabled;
|
PushEnabled = s.PushEnabled;
|
||||||
VapidPublicKey = s.VapidPublicKey;
|
VapidPublicKey = s.VapidPublicKey;
|
||||||
@@ -131,8 +139,12 @@ public class SettingsModel : PageModel
|
|||||||
DemoMode = DemoMode,
|
DemoMode = DemoMode,
|
||||||
WebsitesEnabled = WebsitesEnabled,
|
WebsitesEnabled = WebsitesEnabled,
|
||||||
WebsiteUrls = WebsiteUrls,
|
WebsiteUrls = WebsiteUrls,
|
||||||
IngestProxyEnabled = IngestProxyEnabled,
|
|
||||||
IngestProxyUrl = IngestProxyUrl,
|
IngestProxyUrl = IngestProxyUrl,
|
||||||
|
TelegramUseProxy = TelegramUseProxy,
|
||||||
|
BaleUseProxy = BaleUseProxy,
|
||||||
|
DivarUseProxy = DivarUseProxy,
|
||||||
|
MedjobsUseProxy = MedjobsUseProxy,
|
||||||
|
WebsitesUseProxy = WebsitesUseProxy,
|
||||||
WebNotificationsEnabled = WebNotificationsEnabled,
|
WebNotificationsEnabled = WebNotificationsEnabled,
|
||||||
PushEnabled = PushEnabled,
|
PushEnabled = PushEnabled,
|
||||||
VapidPublicKey = VapidPublicKey,
|
VapidPublicKey = VapidPublicKey,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class BaleListingSource : IListingSource
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = _clients.For(s);
|
var client = _clients.For(s, s.BaleUseProxy);
|
||||||
var body = await client.GetStringAsync($"{BaseUrl}/bot{s.BaleBotToken}/getUpdates", ct);
|
var body = await client.GetStringAsync($"{BaseUrl}/bot{s.BaleBotToken}/getUpdates", ct);
|
||||||
using var doc = JsonDocument.Parse(body);
|
using var doc = JsonDocument.Parse(body);
|
||||||
if (!doc.RootElement.TryGetProperty("result", out var result) || result.ValueKind != JsonValueKind.Array)
|
if (!doc.RootElement.TryGetProperty("result", out var result) || result.ValueKind != JsonValueKind.Array)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class DivarListingSource : IListingSource
|
|||||||
if (!s.DivarEnabled || queries.Count == 0) return Array.Empty<ScrapedItem>();
|
if (!s.DivarEnabled || queries.Count == 0) return Array.Empty<ScrapedItem>();
|
||||||
var city = string.IsNullOrWhiteSpace(s.DivarCity) ? "tehran" : s.DivarCity.Trim();
|
var city = string.IsNullOrWhiteSpace(s.DivarCity) ? "tehran" : s.DivarCity.Trim();
|
||||||
|
|
||||||
var client = _clients.For(s);
|
var client = _clients.For(s, s.DivarUseProxy);
|
||||||
var items = new List<ScrapedItem>();
|
var items = new List<ScrapedItem>();
|
||||||
foreach (var q in queries)
|
foreach (var q in queries)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class MedjobsListingSource : IListingSource
|
|||||||
{
|
{
|
||||||
if (!s.MedjobsEnabled) return Array.Empty<ScrapedItem>();
|
if (!s.MedjobsEnabled) return Array.Empty<ScrapedItem>();
|
||||||
var max = Math.Clamp(s.MedjobsMaxAds, 1, 500);
|
var max = Math.Clamp(s.MedjobsMaxAds, 1, 500);
|
||||||
var client = _clients.For(s);
|
var client = _clients.For(s, s.MedjobsUseProxy);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ public sealed class ScrapeHttpClients : IDisposable
|
|||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, HttpClient> _cache = new();
|
private readonly ConcurrentDictionary<string, HttpClient> _cache = new();
|
||||||
|
|
||||||
/// <summary>The HttpClient for the given settings — proxied when enabled, direct otherwise.</summary>
|
/// <summary>The HttpClient for a source — proxied only when that source opts in AND a proxy
|
||||||
public HttpClient For(AppSetting s)
|
/// URL is configured; otherwise a direct client. Pass the source's own per-source flag.</summary>
|
||||||
|
public HttpClient For(AppSetting s, bool useProxy)
|
||||||
{
|
{
|
||||||
var key = (s.IngestProxyEnabled && !string.IsNullOrWhiteSpace(s.IngestProxyUrl))
|
var key = (useProxy && !string.IsNullOrWhiteSpace(s.IngestProxyUrl))
|
||||||
? s.IngestProxyUrl.Trim()
|
? s.IngestProxyUrl.Trim()
|
||||||
: "direct";
|
: "direct";
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,12 @@ public class SettingsService
|
|||||||
s.DemoMode = incoming.DemoMode;
|
s.DemoMode = incoming.DemoMode;
|
||||||
s.WebsitesEnabled = incoming.WebsitesEnabled;
|
s.WebsitesEnabled = incoming.WebsitesEnabled;
|
||||||
s.WebsiteUrls = incoming.WebsiteUrls?.Trim();
|
s.WebsiteUrls = incoming.WebsiteUrls?.Trim();
|
||||||
s.IngestProxyEnabled = incoming.IngestProxyEnabled;
|
|
||||||
s.IngestProxyUrl = incoming.IngestProxyUrl?.Trim();
|
s.IngestProxyUrl = incoming.IngestProxyUrl?.Trim();
|
||||||
|
s.TelegramUseProxy = incoming.TelegramUseProxy;
|
||||||
|
s.BaleUseProxy = incoming.BaleUseProxy;
|
||||||
|
s.DivarUseProxy = incoming.DivarUseProxy;
|
||||||
|
s.MedjobsUseProxy = incoming.MedjobsUseProxy;
|
||||||
|
s.WebsitesUseProxy = incoming.WebsitesUseProxy;
|
||||||
s.DivarEnabled = incoming.DivarEnabled;
|
s.DivarEnabled = incoming.DivarEnabled;
|
||||||
s.DivarCity = string.IsNullOrWhiteSpace(incoming.DivarCity) ? "tehran" : incoming.DivarCity.Trim();
|
s.DivarCity = string.IsNullOrWhiteSpace(incoming.DivarCity) ? "tehran" : incoming.DivarCity.Trim();
|
||||||
s.DivarQueries = incoming.DivarQueries?.Trim();
|
s.DivarQueries = incoming.DivarQueries?.Trim();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class TelegramListingSource : IListingSource
|
|||||||
var channels = AppSetting.SplitList(s.TelegramChannels);
|
var channels = AppSetting.SplitList(s.TelegramChannels);
|
||||||
if (!s.TelegramEnabled || channels.Count == 0) return Array.Empty<ScrapedItem>();
|
if (!s.TelegramEnabled || channels.Count == 0) return Array.Empty<ScrapedItem>();
|
||||||
|
|
||||||
var client = _clients.For(s);
|
var client = _clients.For(s, s.TelegramUseProxy);
|
||||||
var items = new List<ScrapedItem>();
|
var items = new List<ScrapedItem>();
|
||||||
foreach (var ch in channels.Select(c => c.TrimStart('@')).Where(c => c.Length > 0))
|
foreach (var ch in channels.Select(c => c.TrimStart('@')).Where(c => c.Length > 0))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class WebsiteListingSource : IListingSource
|
|||||||
var urls = AppSetting.SplitList(s.WebsiteUrls);
|
var urls = AppSetting.SplitList(s.WebsiteUrls);
|
||||||
if (!s.WebsitesEnabled || urls.Count == 0) return Array.Empty<ScrapedItem>();
|
if (!s.WebsitesEnabled || urls.Count == 0) return Array.Empty<ScrapedItem>();
|
||||||
|
|
||||||
var client = _clients.For(s);
|
var client = _clients.For(s, s.WebsitesUseProxy);
|
||||||
var items = new List<ScrapedItem>();
|
var items = new List<ScrapedItem>();
|
||||||
foreach (var url in urls.Where(u => u.StartsWith("http")))
|
foreach (var url in urls.Where(u => u.StartsWith("http")))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -287,6 +287,9 @@ label { font-size: 13px; }
|
|||||||
.toggle-row .t-body { display: flex; flex-direction: column; gap: 3px; }
|
.toggle-row .t-body { display: flex; flex-direction: column; gap: 3px; }
|
||||||
.toggle-row .t-hint { font-size: 12px; font-weight: 500; color: var(--muted); }
|
.toggle-row .t-hint { font-size: 12px; font-weight: 500; color: var(--muted); }
|
||||||
.settings-save { position: sticky; bottom: 0; padding-top: 12px; background: linear-gradient(transparent, var(--bg) 40%); }
|
.settings-save { position: sticky; bottom: 0; padding-top: 12px; background: linear-gradient(transparent, var(--bg) 40%); }
|
||||||
|
.proxy-toggle { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px;
|
||||||
|
font-size: 12.5px; font-weight: 600; color: var(--muted); cursor: pointer; }
|
||||||
|
.proxy-toggle input { width: 15px; height: 15px; }
|
||||||
|
|
||||||
@media (max-width: 760px) {
|
@media (max-width: 760px) {
|
||||||
.settings-layout { grid-template-columns: 1fr; }
|
.settings-layout { grid-template-columns: 1fr; }
|
||||||
|
|||||||
Reference in New Issue
Block a user