Move ingestion + Telegram/Bale/Divar config to DB-backed admin settings
- AppSetting gains source config: AutoIngestEnabled, IngestIntervalMinutes, Telegram/Bale/Divar enabled+channels/token/queries - IListingSource.FetchAsync(AppSetting) — sources read config from DB, not IOptions/appsettings; sample source dev-only - IngestionWorker reads AutoIngest+interval from DB each cycle (toggle at runtime, no redeploy) - /Admin/Settings gets a 'منابع جمعآوری' section; removed Ingestion env/appsettings + compose env vars - ENV_FILE shrinks to HOST_PORT + POSTGRES_* + ADMIN_PHONE (AI + sources are all in-admin); migration Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -26,16 +26,10 @@
|
||||
<div class="layout-2">
|
||||
<aside class="card card-pad filter-card">
|
||||
<h3>موتور جمعآوری</h3>
|
||||
<p class="muted" style="font-size:13px;">منابع متصل:</p>
|
||||
<ul style="margin:0 0 12px; padding-inline-start:18px; font-size:13.5px;">
|
||||
@foreach (var src in Model.Sources)
|
||||
{
|
||||
<li>@src.Name —
|
||||
@if (src.Enabled) { <span style="color:var(--primary-dark);">فعال</span> }
|
||||
else { <span class="muted">غیرفعال (نیازمند تنظیمات)</span> }
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<p class="muted" style="font-size:13px;">منابع: @string.Join("، ", Model.SourceNames)</p>
|
||||
<p class="muted" style="font-size:12px; margin:0 0 12px;">
|
||||
فعال/غیرفعالسازی و تنظیم کانالها در <a asp-page="/Admin/Settings">تنظیمات</a>.
|
||||
</p>
|
||||
<form method="post">
|
||||
<button type="submit" asp-page-handler="RunIngestion" class="btn btn-accent btn-block">اجرای جمعآوری اکنون</button>
|
||||
</form>
|
||||
|
||||
@@ -22,7 +22,7 @@ public class IndexModel : PageModel
|
||||
|
||||
public List<RawListing> Queue { get; private set; } = new();
|
||||
public List<RawListing> Flagged { get; private set; } = new();
|
||||
public IReadOnlyList<(string Name, bool Enabled)> Sources { get; private set; } = new List<(string, bool)>();
|
||||
public IReadOnlyList<string> SourceNames { get; private set; } = new List<string>();
|
||||
public int PublishedShifts { get; private set; }
|
||||
public int PublishedJobs { get; private set; }
|
||||
|
||||
@@ -64,7 +64,7 @@ public class IndexModel : PageModel
|
||||
Flagged = await _db.RawListings
|
||||
.Where(r => r.Status == RawListingStatus.Flagged)
|
||||
.OrderByDescending(r => r.FetchedAt).ToListAsync();
|
||||
Sources = _ingest.Sources;
|
||||
SourceNames = _ingest.SourceNames;
|
||||
PublishedShifts = await _db.Shifts.CountAsync(s => s.Source != ShiftSource.Direct);
|
||||
PublishedJobs = await _db.JobOpenings.CountAsync();
|
||||
}
|
||||
|
||||
@@ -62,6 +62,49 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<hr style="border:none; border-top:1px solid var(--line); margin:18px 0;" />
|
||||
|
||||
<h3 style="margin-top:0;">منابع جمعآوری (اسکرپ کانالها)</h3>
|
||||
<div class="filter-group">
|
||||
<label style="display:flex; align-items:center; gap:8px; font-weight:700;">
|
||||
<input type="checkbox" name="AutoIngestEnabled" value="true" style="width:auto;" checked="@Model.AutoIngestEnabled" />
|
||||
اجرای خودکار جمعآوری روی زمانبند
|
||||
</label>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>فاصله اجرای خودکار (دقیقه)</label>
|
||||
<input type="number" name="IngestIntervalMinutes" min="1" value="@Model.IngestIntervalMinutes" dir="ltr" />
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label style="display:flex; align-items:center; gap:8px; font-weight:700;">
|
||||
<input type="checkbox" name="TelegramEnabled" value="true" style="width:auto;" checked="@Model.TelegramEnabled" />
|
||||
تلگرام (کانالهای عمومی — بدون توکن)
|
||||
</label>
|
||||
<label style="margin-top:6px;">یوزرنیم کانالها (هر خط یک کانال)</label>
|
||||
<textarea name="TelegramChannels" rows="3" dir="ltr" placeholder="shift_channel another_channel">@Model.TelegramChannels</textarea>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label style="display:flex; align-items:center; gap:8px; font-weight:700;">
|
||||
<input type="checkbox" name="BaleEnabled" value="true" style="width:auto;" checked="@Model.BaleEnabled" />
|
||||
بله (بات باید عضو کانال باشد)
|
||||
</label>
|
||||
<label style="margin-top:6px;">توکن بات بله</label>
|
||||
<input type="password" name="BaleBotToken" value="@Model.BaleBotToken" dir="ltr" />
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label style="display:flex; align-items:center; gap:8px; font-weight:700;">
|
||||
<input type="checkbox" name="DivarEnabled" value="true" style="width:auto;" checked="@Model.DivarEnabled" />
|
||||
دیوار
|
||||
</label>
|
||||
<div style="display:flex; gap:8px; margin-top:6px;">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-accent btn-block btn-lg">ذخیره تنظیمات</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -20,6 +20,16 @@ public class SettingsModel : PageModel
|
||||
[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; }
|
||||
[TempData] public string? Saved { get; set; }
|
||||
|
||||
public async Task OnGetAsync()
|
||||
@@ -33,6 +43,15 @@ public class SettingsModel : PageModel
|
||||
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;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostAsync()
|
||||
@@ -47,6 +66,15 @@ public class SettingsModel : PageModel
|
||||
AiModel = AiModel,
|
||||
AiSystemPrompt = AiSystemPrompt,
|
||||
AiAutoApprove = AiAutoApprove,
|
||||
AutoIngestEnabled = AutoIngestEnabled,
|
||||
IngestIntervalMinutes = IngestIntervalMinutes,
|
||||
TelegramEnabled = TelegramEnabled,
|
||||
TelegramChannels = TelegramChannels,
|
||||
BaleEnabled = BaleEnabled,
|
||||
BaleBotToken = BaleBotToken,
|
||||
DivarEnabled = DivarEnabled,
|
||||
DivarCity = DivarCity,
|
||||
DivarQueries = DivarQueries,
|
||||
});
|
||||
Saved = "تنظیمات ذخیره شد.";
|
||||
return RedirectToPage();
|
||||
|
||||
Reference in New Issue
Block a user