feat: add Scheduler provider + multi-provider UX fixes
Scheduler provider: - Virtual provider (no external service) that emits SCHEDULED_MESSAGE events on user-defined intervals or cron expressions - Custom variables stored in tracker filters, flattened into template context - fire_count persists across triggers via tracker state - APScheduler CronTrigger support for cron-mode schedules - Default templates (EN+RU), seeded on startup Multi-provider UX fixes: - Tracking config hides Immich-specific sections (periodic, scheduled, memory, asset display) for non-Immich providers - Command config driven by provider capabilities — hides commands/settings for providers without bot commands - Template config hides empty "Scheduled Messages" group - Test menu on tracker targets is provider-aware (Immich shows all 4 test types, others show only basic) - Removed redundant Test button from tracker card - System-owned tracking configs (user_id=0) seeded for Gitea + Scheduler - Fixed ownership checks to allow system configs in tracker-target links - Capabilities cache shared across template-configs and command-configs - Command tracker bot selector uses EntitySelect instead of raw select - Sample context includes Gitea + Scheduler variables for template preview
This commit is contained in:
@@ -100,4 +100,5 @@ export const previewTargetTypeItems = (): GridItem[] => [
|
||||
export const providerTypeItems = (): GridItem[] => [
|
||||
{ value: 'immich', icon: 'mdiCamera', label: t('providers.typeImmich') },
|
||||
{ value: 'gitea', icon: 'mdiGit', label: t('providers.typeGitea') },
|
||||
{ value: 'scheduler', icon: 'mdiClockOutline', label: t('providers.typeScheduler') },
|
||||
];
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
"checking": "Checking...",
|
||||
"typeImmich": "Immich",
|
||||
"typeGitea": "Gitea",
|
||||
"typeScheduler": "Scheduler",
|
||||
"loadError": "Failed to load providers.",
|
||||
"externalDomain": "External Domain",
|
||||
"optional": "optional",
|
||||
@@ -134,6 +135,14 @@
|
||||
"eventTypes": "Event Types",
|
||||
"notificationTargets": "Notification Targets",
|
||||
"scanInterval": "Scan Interval (seconds)",
|
||||
"scheduleType": "Schedule",
|
||||
"intervalMode": "Interval",
|
||||
"cronMode": "Cron expression",
|
||||
"cronExpression": "Cron expression",
|
||||
"cronHint": "Standard 5-field cron: minute hour day month weekday. Example: 0 9 * * 1-5 (weekdays at 9:00)",
|
||||
"customVariables": "Custom Variables",
|
||||
"customVariablesHint": "Define key-value pairs available in templates as {{ key }}.",
|
||||
"addVariable": "Add variable",
|
||||
"createTracker": "Create Tracker",
|
||||
"noTrackers": "No trackers yet. Add a provider first, then create a tracker.",
|
||||
"active": "Active",
|
||||
@@ -310,6 +319,7 @@
|
||||
"rateSearch": "Search cooldown",
|
||||
"rateFind": "Find cooldown",
|
||||
"rateDefault": "Default cooldown",
|
||||
"noCommandsForProvider": "This provider type does not support bot commands.",
|
||||
"syncCommands": "Sync with Telegram",
|
||||
"discoverChats": "Discover chats from Telegram",
|
||||
"clickToCopy": "Click to copy chat ID",
|
||||
@@ -365,6 +375,7 @@
|
||||
"prMerged": "PR merged",
|
||||
"prCommented": "PR commented",
|
||||
"releasePublished": "Release published",
|
||||
"scheduledMessage": "Scheduled message",
|
||||
"trackImages": "Track images",
|
||||
"trackVideos": "Track videos",
|
||||
"favoritesOnly": "Favorites only",
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
"checking": "Проверка...",
|
||||
"typeImmich": "Immich",
|
||||
"typeGitea": "Gitea",
|
||||
"typeScheduler": "Планировщик",
|
||||
"loadError": "Не удалось загрузить провайдеры.",
|
||||
"externalDomain": "Внешний домен",
|
||||
"optional": "необязательно",
|
||||
@@ -134,6 +135,14 @@
|
||||
"eventTypes": "Типы событий",
|
||||
"notificationTargets": "Получатели уведомлений",
|
||||
"scanInterval": "Интервал проверки (секунды)",
|
||||
"scheduleType": "Расписание",
|
||||
"intervalMode": "Интервал",
|
||||
"cronMode": "Cron выражение",
|
||||
"cronExpression": "Cron выражение",
|
||||
"cronHint": "Стандартный 5-полевой cron: минута час день месяц день_недели. Пример: 0 9 * * 1-5 (будни в 9:00)",
|
||||
"customVariables": "Пользовательские переменные",
|
||||
"customVariablesHint": "Определите пары ключ-значение, доступные в шаблонах как {{ ключ }}.",
|
||||
"addVariable": "Добавить переменную",
|
||||
"createTracker": "Создать трекер",
|
||||
"noTrackers": "Трекеров пока нет. Сначала добавьте провайдер, затем создайте трекер.",
|
||||
"active": "Активен",
|
||||
@@ -310,6 +319,7 @@
|
||||
"rateSearch": "Кулдаун поиска",
|
||||
"rateFind": "Кулдаун поиска файлов",
|
||||
"rateDefault": "Кулдаун по умолчанию",
|
||||
"noCommandsForProvider": "Этот тип провайдера не поддерживает команды бота.",
|
||||
"syncCommands": "Синхронизировать с Telegram",
|
||||
"discoverChats": "Обнаружить чаты из Telegram",
|
||||
"clickToCopy": "Нажмите, чтобы скопировать ID чата",
|
||||
@@ -365,6 +375,7 @@
|
||||
"prMerged": "PR влит",
|
||||
"prCommented": "Комментарий к PR",
|
||||
"releasePublished": "Релиз опубликован",
|
||||
"scheduledMessage": "Запланированное сообщение",
|
||||
"trackImages": "Фото",
|
||||
"trackVideos": "Видео",
|
||||
"favoritesOnly": "Только избранные",
|
||||
|
||||
@@ -53,6 +53,23 @@ export const commandTemplateConfigsCache = createEntityCache<CommandTemplateConf
|
||||
/** Command trackers — used by Command Trackers page. */
|
||||
export const commandTrackersCache = createEntityCache<CommandTracker>('/command-trackers');
|
||||
|
||||
/** Provider capabilities — used by Template Configs, Command Configs. */
|
||||
export const capabilitiesCache = (() => {
|
||||
let data = $state<Record<string, any>>({});
|
||||
let fetchedAt = $state(0);
|
||||
const TTL = 60_000; // 1 minute
|
||||
return {
|
||||
get items() { return data; },
|
||||
async fetch(force = false): Promise<Record<string, any>> {
|
||||
if (!force && Object.keys(data).length > 0 && Date.now() - fetchedAt < TTL) return data;
|
||||
const { api } = await import('$lib/api');
|
||||
data = await api('/providers/capabilities');
|
||||
fetchedAt = Date.now();
|
||||
return data;
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* All caches keyed by entity type — for search palette and crosslink resolution.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user