Files
hamkadr/src/JobsMedical.Web/Pages/Admin/Settings.cshtml.cs
T
soroush.asadi b1e474ba33
CI/CD / CI · dotnet build (push) Successful in 56s
CI/CD / Deploy · hamkadr (push) Successful in 1m6s
[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>
2026-06-04 18:46:48 +03:30

187 lines
7.9 KiB
C#

using JobsMedical.Web.Data;
using JobsMedical.Web.Models;
using JobsMedical.Web.Services;
using JobsMedical.Web.Services.Scraping;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace JobsMedical.Web.Pages.Admin;
[Authorize(Roles = "Admin")]
public class SettingsModel : PageModel
{
private readonly SettingsService _settings;
private readonly ISmsSender _sms;
private readonly AppDbContext _db;
public SettingsModel(SettingsService settings, ISmsSender sms, AppDbContext db)
{
_settings = settings;
_sms = sms;
_db = db;
}
[BindProperty] public IngestionMode Mode { get; set; }
[BindProperty] public int AutoPublishMinConfidence { get; set; }
[BindProperty] public bool AiEnabled { get; set; }
[BindProperty] public string? AiEndpoint { get; set; }
[BindProperty] public string? AiApiKey { get; set; }
[BindProperty] public string? AiModel { get; set; }
[BindProperty] public string AiSystemPrompt { get; set; } = "";
[BindProperty] public bool AiAutoApprove { get; set; }
// Channel scraping sources
[BindProperty] public bool AutoIngestEnabled { get; set; }
[BindProperty] public int IngestIntervalMinutes { get; set; } = 30;
[BindProperty] public bool TelegramEnabled { get; set; }
[BindProperty] public string? TelegramChannels { get; set; }
[BindProperty] public bool BaleEnabled { get; set; }
[BindProperty] public string? BaleBotToken { get; set; }
[BindProperty] public bool DivarEnabled { get; set; }
[BindProperty] public string? DivarCity { get; set; }
[BindProperty] public string? DivarQueries { get; set; }
[BindProperty] public bool MedjobsEnabled { get; set; }
[BindProperty] public int MedjobsMaxAds { get; set; } = 40;
[BindProperty] public bool SmsEnabled { get; set; }
[BindProperty] public string? SmsApiKey { get; set; }
[BindProperty] public string? SmsTemplate { get; set; }
[BindProperty] public string? SmsSender { get; set; }
[BindProperty] public string? NeshanMapKey { get; set; }
[BindProperty] public bool WebNotificationsEnabled { get; set; }
[BindProperty] public bool PushEnabled { get; set; }
[BindProperty] public string? VapidPublicKey { get; set; }
[BindProperty] public string? VapidPrivateKey { get; set; }
[BindProperty] public string? VapidSubject { get; set; }
[BindProperty] public string? TestPhone { get; set; }
[BindProperty] public bool DemoMode { get; set; }
[BindProperty] public bool WebsitesEnabled { get; set; }
[BindProperty] public string? WebsiteUrls { 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? SmsTest { get; set; }
[TempData] public string? DemoMsg { get; set; }
public async Task OnGetAsync()
{
var s = await _settings.GetAsync();
Mode = s.Mode;
AutoPublishMinConfidence = s.AutoPublishMinConfidence;
AiEnabled = s.AiEnabled;
AiEndpoint = s.AiEndpoint;
AiApiKey = s.AiApiKey;
AiModel = s.AiModel;
AiSystemPrompt = s.AiSystemPrompt;
AiAutoApprove = s.AiAutoApprove;
AutoIngestEnabled = s.AutoIngestEnabled;
IngestIntervalMinutes = s.IngestIntervalMinutes;
TelegramEnabled = s.TelegramEnabled;
TelegramChannels = s.TelegramChannels;
BaleEnabled = s.BaleEnabled;
BaleBotToken = s.BaleBotToken;
DivarEnabled = s.DivarEnabled;
DivarCity = s.DivarCity;
DivarQueries = s.DivarQueries;
MedjobsEnabled = s.MedjobsEnabled;
MedjobsMaxAds = s.MedjobsMaxAds;
SmsEnabled = s.SmsEnabled;
SmsApiKey = s.SmsApiKey;
SmsTemplate = s.SmsTemplate;
SmsSender = s.SmsSender;
NeshanMapKey = s.NeshanMapKey;
DemoMode = s.DemoMode;
WebsitesEnabled = s.WebsitesEnabled;
WebsiteUrls = s.WebsiteUrls;
IngestProxyUrl = s.IngestProxyUrl;
TelegramUseProxy = s.TelegramUseProxy;
BaleUseProxy = s.BaleUseProxy;
DivarUseProxy = s.DivarUseProxy;
MedjobsUseProxy = s.MedjobsUseProxy;
WebsitesUseProxy = s.WebsitesUseProxy;
WebNotificationsEnabled = s.WebNotificationsEnabled;
PushEnabled = s.PushEnabled;
VapidPublicKey = s.VapidPublicKey;
VapidPrivateKey = s.VapidPrivateKey;
VapidSubject = s.VapidSubject;
}
public async Task<IActionResult> OnPostAsync()
{
await _settings.SaveAsync(new AppSetting
{
Mode = Mode,
AutoPublishMinConfidence = AutoPublishMinConfidence,
AiEnabled = AiEnabled,
AiEndpoint = AiEndpoint,
AiApiKey = AiApiKey,
AiModel = AiModel,
AiSystemPrompt = AiSystemPrompt,
AiAutoApprove = AiAutoApprove,
AutoIngestEnabled = AutoIngestEnabled,
IngestIntervalMinutes = IngestIntervalMinutes,
TelegramEnabled = TelegramEnabled,
TelegramChannels = TelegramChannels,
BaleEnabled = BaleEnabled,
BaleBotToken = BaleBotToken,
DivarEnabled = DivarEnabled,
DivarCity = DivarCity,
DivarQueries = DivarQueries,
MedjobsEnabled = MedjobsEnabled,
MedjobsMaxAds = MedjobsMaxAds,
SmsEnabled = SmsEnabled,
SmsApiKey = SmsApiKey,
SmsTemplate = SmsTemplate,
SmsSender = SmsSender,
NeshanMapKey = NeshanMapKey,
DemoMode = DemoMode,
WebsitesEnabled = WebsitesEnabled,
WebsiteUrls = WebsiteUrls,
IngestProxyUrl = IngestProxyUrl,
TelegramUseProxy = TelegramUseProxy,
BaleUseProxy = BaleUseProxy,
DivarUseProxy = DivarUseProxy,
MedjobsUseProxy = MedjobsUseProxy,
WebsitesUseProxy = WebsitesUseProxy,
WebNotificationsEnabled = WebNotificationsEnabled,
PushEnabled = PushEnabled,
VapidPublicKey = VapidPublicKey,
VapidPrivateKey = VapidPrivateKey,
VapidSubject = VapidSubject,
});
Saved = "تنظیمات ذخیره شد.";
return RedirectToPage();
}
public async Task<IActionResult> OnPostSeedDemoAsync()
{
var n = await SeedData.SeedDemoAsync(_db);
DemoMsg = n > 0 ? $"داده‌های نمونه ثبت شد ({n} مرکز + شیفت/استخدام)." : "داده‌های نمونه از قبل موجود است.";
return RedirectToPage();
}
public async Task<IActionResult> OnPostClearDemoAsync()
{
var n = await SeedData.ClearDemoAsync(_db);
DemoMsg = $"داده‌های نمونه حذف شد ({n} مرکز و آگهی‌های وابسته).";
return RedirectToPage();
}
public async Task<IActionResult> OnPostTestSmsAsync()
{
var s = await _settings.GetAsync();
var phone = OtpService.Normalize(TestPhone ?? "");
if (phone.Length < 10) { SmsTest = "شماره معتبر وارد کنید."; return RedirectToPage(); }
if (!s.SmsEnabled) { SmsTest = "ابتدا SMS را فعال و ذخیره کنید."; return RedirectToPage(); }
try
{
var ok = await _sms.SendOtpAsync(phone, Random.Shared.Next(10000, 100000).ToString(), s);
SmsTest = ok ? $"پیامک آزمایشی به {phone} ارسال شد." : "ارسال ناموفق بود (پاسخ منفی از سرویس).";
}
catch (Exception ex) { SmsTest = "خطا در ارسال: " + ex.Message; }
return RedirectToPage();
}
}