feat: telegram commands, app settings, bot polling, webhook handling, UI improvements
Adds telegram bot command system with 13 commands (search, latest, random, etc.), webhook/polling handlers, rate limiting, app settings page, and various UI/UX improvements across all entity pages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -67,7 +67,7 @@
|
||||
},
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
function buildExtensions(isDark: boolean) {
|
||||
const extensions = [
|
||||
jinjaLang,
|
||||
errorLineField,
|
||||
@@ -88,17 +88,14 @@
|
||||
'.ͼ5': { color: '#6b7280' },
|
||||
}),
|
||||
];
|
||||
if (isDark) extensions.push(oneDark);
|
||||
if (placeholder) extensions.push(cmPlaceholder(placeholder));
|
||||
return extensions;
|
||||
}
|
||||
|
||||
if (theme.isDark) {
|
||||
extensions.push(oneDark);
|
||||
}
|
||||
|
||||
if (placeholder) {
|
||||
extensions.push(cmPlaceholder(placeholder));
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
view = new EditorView({
|
||||
state: EditorState.create({ doc: value, extensions }),
|
||||
state: EditorState.create({ doc: value, extensions: buildExtensions(theme.isDark) }),
|
||||
parent: container,
|
||||
});
|
||||
|
||||
@@ -127,31 +124,8 @@
|
||||
const currentDoc = view.state.doc.toString();
|
||||
view.destroy();
|
||||
|
||||
const extensions = [
|
||||
jinjaLang,
|
||||
errorLineField,
|
||||
EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged) {
|
||||
onchange(update.state.doc.toString());
|
||||
}
|
||||
}),
|
||||
EditorView.lineWrapping,
|
||||
EditorView.theme({
|
||||
'&': { fontSize: '13px', fontFamily: "'Consolas', 'Monaco', 'Courier New', monospace" },
|
||||
'.cm-content': { minHeight: `${rows * 1.5}em`, padding: '8px' },
|
||||
'.cm-editor': { borderRadius: '0.375rem', border: '1px solid var(--color-border)' },
|
||||
'.cm-focused': { outline: '2px solid var(--color-primary)', outlineOffset: '0px' },
|
||||
'.cm-error-line': { backgroundColor: 'rgba(239, 68, 68, 0.2)', outline: '1px solid rgba(239, 68, 68, 0.4)' },
|
||||
'.ͼc': { color: '#e879f9' },
|
||||
'.ͼd': { color: '#38bdf8' },
|
||||
'.ͼ5': { color: '#6b7280' },
|
||||
}),
|
||||
];
|
||||
if (isDark) extensions.push(oneDark);
|
||||
if (placeholder) extensions.push(cmPlaceholder(placeholder));
|
||||
|
||||
view = new EditorView({
|
||||
state: EditorState.create({ doc: currentDoc, extensions }),
|
||||
state: EditorState.create({ doc: currentDoc, extensions: buildExtensions(isDark) }),
|
||||
parent: container,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"telegramBots": "Bots",
|
||||
"targets": "Targets",
|
||||
"users": "Users",
|
||||
"settings": "Settings",
|
||||
"logout": "Logout"
|
||||
},
|
||||
"auth": {
|
||||
@@ -62,6 +63,7 @@
|
||||
"assets": "assets",
|
||||
"eventActivity": "Event Activity",
|
||||
"last14days": "Last 14 days",
|
||||
"event": "event",
|
||||
"events": "events",
|
||||
"noChartData": "No event data yet"
|
||||
},
|
||||
@@ -85,7 +87,11 @@
|
||||
"checking": "Checking...",
|
||||
"loadError": "Failed to load providers.",
|
||||
"externalDomain": "External Domain",
|
||||
"optional": "optional"
|
||||
"optional": "optional",
|
||||
"urlApiKeyRequired": "URL and API Key are required",
|
||||
"externalDomainHint": "Public-facing URL for notification links. Falls back to server URL.",
|
||||
"testAndSave": "Test & Save",
|
||||
"saveWithoutTest": "Save without testing"
|
||||
},
|
||||
"trackers": {
|
||||
"title": "Trackers",
|
||||
@@ -134,7 +140,16 @@
|
||||
"testBasic": "Send test message",
|
||||
"testPeriodic": "Test periodic summary",
|
||||
"testScheduled": "Test scheduled assets",
|
||||
"testMemory": "Test memory / On This Day"
|
||||
"testMemory": "Test memory / On This Day",
|
||||
"checkingLinks": "Checking links...",
|
||||
"missingLinksTitle": "Albums Missing Public Links",
|
||||
"missingLinksDesc": "The following albums don't have public shared links. Without links, notification recipients won't be able to view photos.",
|
||||
"expired": "Expired",
|
||||
"passwordProtected": "Password Protected",
|
||||
"noLink": "No Link",
|
||||
"saveWithoutLinks": "Save without links",
|
||||
"createLinks": "Create {count} link(s)",
|
||||
"linksNote": "You can also create links manually in Immich."
|
||||
},
|
||||
"templates": {
|
||||
"title": "Templates",
|
||||
@@ -198,7 +213,8 @@
|
||||
"create": "Create User",
|
||||
"delete": "Delete",
|
||||
"confirmDelete": "Delete this user?",
|
||||
"joined": "joined"
|
||||
"joined": "joined",
|
||||
"noUsers": "No users found"
|
||||
},
|
||||
"telegramBot": {
|
||||
"title": "Telegram Bots",
|
||||
@@ -220,21 +236,48 @@
|
||||
"channel": "Channel",
|
||||
"confirmDelete": "Delete this bot?",
|
||||
"commands": "Commands",
|
||||
"enabledCommands": "Enabled Commands",
|
||||
"defaultCount": "Default result count",
|
||||
"enabledCommands": "Enabled commands",
|
||||
"defaultCount": "Default count",
|
||||
"responseMode": "Response mode",
|
||||
"modeMedia": "Media (send photos)",
|
||||
"modeText": "Text (send links)",
|
||||
"modeMedia": "Media (photos)",
|
||||
"modeText": "Text only",
|
||||
"botLocale": "Bot language",
|
||||
"rateLimits": "Rate Limits",
|
||||
"rateSearch": "Search cooldown",
|
||||
"rateFind": "Find cooldown",
|
||||
"rateDefault": "Default cooldown",
|
||||
"syncCommands": "Sync to Telegram",
|
||||
"syncCommands": "Sync with Telegram",
|
||||
"discoverChats": "Discover chats from Telegram",
|
||||
"clickToCopy": "Click to copy chat ID",
|
||||
"chatsDiscovered": "Chats discovered",
|
||||
"chatDeleted": "Chat removed"
|
||||
"chatDeleted": "Chat removed",
|
||||
"cmdLocale": "Bot language",
|
||||
"searchCooldown": "Search cooldown (s)",
|
||||
"saveConfig": "Save config",
|
||||
"commandsSynced": "Commands synced with Telegram",
|
||||
"registerWebhook": "Register webhook",
|
||||
"unregisterWebhook": "Unregister webhook",
|
||||
"webhookRegistered": "Webhook registered",
|
||||
"webhookUnregistered": "Webhook unregistered",
|
||||
"updateMode": "Update mode",
|
||||
"polling": "Polling",
|
||||
"webhook": "Webhook",
|
||||
"webhookStatus": "Webhook status",
|
||||
"webhookActive": "Webhook active",
|
||||
"webhookNotSet": "No webhook set",
|
||||
"webhookVerified": "Webhook verified",
|
||||
"webhookError": "Last error",
|
||||
"pendingUpdates": "pending updates",
|
||||
"pollingActive": "Polling active",
|
||||
"telegramSettings": "Telegram Settings",
|
||||
"externalUrl": "External URL",
|
||||
"externalUrlHint": "Public URL of this Notify Bridge instance. Required for webhook mode.",
|
||||
"webhookSecret": "Webhook secret",
|
||||
"webhookSecretHint": "Optional secret token to verify webhook requests from Telegram",
|
||||
"cacheTtl": "Media cache TTL (hours)",
|
||||
"cacheTtlHint": "How long to cache uploaded Telegram file_ids before re-uploading (default: 48h)",
|
||||
"settingsSaved": "Settings saved",
|
||||
"noExternalDomain": "External domain URL not configured"
|
||||
},
|
||||
"trackingConfig": {
|
||||
"title": "Tracking Configs",
|
||||
@@ -269,6 +312,9 @@
|
||||
"assetType": "Asset type",
|
||||
"minRating": "Min rating",
|
||||
"memoryMode": "Memory Mode (On This Day)",
|
||||
"memorySource": "Memory source",
|
||||
"memorySourceAlbums": "Scan tracked albums",
|
||||
"memorySourceNative": "Immich native memories",
|
||||
"test": "Test",
|
||||
"confirmDelete": "Delete this tracking config?",
|
||||
"sortNone": "None",
|
||||
@@ -282,7 +328,14 @@
|
||||
"albumModeRandom": "Random",
|
||||
"assetTypeAll": "All",
|
||||
"assetTypePhoto": "Photo",
|
||||
"assetTypeVideo": "Video"
|
||||
"assetTypeVideo": "Video",
|
||||
"periodic": "periodic",
|
||||
"scheduled": "scheduled",
|
||||
"memory": "memory",
|
||||
"added": "added",
|
||||
"removed": "removed",
|
||||
"renamed": "renamed",
|
||||
"deleted": "deleted"
|
||||
},
|
||||
"templateConfig": {
|
||||
"title": "Template Configs",
|
||||
@@ -324,7 +377,8 @@
|
||||
"variables": "Variables",
|
||||
"assetFields": "Asset fields (in {% for asset in added_assets %})",
|
||||
"albumFields": "Album fields (in {% for album in albums %})",
|
||||
"confirmDelete": "Delete this template config?"
|
||||
"confirmDelete": "Delete this template config?",
|
||||
"invalidFormat": "Invalid format string"
|
||||
},
|
||||
"templateVars": {
|
||||
"message_assets_added": { "description": "Notification when new assets are added to an album" },
|
||||
@@ -378,10 +432,24 @@
|
||||
"album_url_field": "Album share URL",
|
||||
"album_shared": "Whether album is shared"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"description": "Global application settings",
|
||||
"general": "General",
|
||||
"externalUrl": "External URL",
|
||||
"externalUrlHint": "Public URL of this Notify Bridge instance (e.g. https://notify.example.com)",
|
||||
"telegram": "Telegram",
|
||||
"webhookSecret": "Webhook Secret",
|
||||
"webhookSecretHint": "Secret token to verify webhook requests from Telegram",
|
||||
"cacheTtl": "Media Cache TTL (hours)",
|
||||
"cacheTtlHint": "How long to cache uploaded Telegram file_ids before re-uploading",
|
||||
"saved": "Settings saved"
|
||||
},
|
||||
"hints": {
|
||||
"periodicSummary": "Sends a scheduled summary of all tracked albums at specified times. Great for daily/weekly digests.",
|
||||
"scheduledAssets": "Sends random or selected photos from tracked albums on a schedule. Like a daily photo pick.",
|
||||
"memoryMode": "\"On This Day\" — sends photos taken on this date in previous years. Nostalgic flashbacks.",
|
||||
"memorySource": "Albums: scans tracked albums for date-matching assets. Native: uses Immich's built-in memories (covers entire library, optionally filtered by tracked albums).",
|
||||
"favoritesOnly": "Only include assets marked as favorites.",
|
||||
"maxAssets": "Maximum number of asset details to include in a single notification message.",
|
||||
"periodicStartDate": "The reference date for calculating periodic intervals. Summaries are sent every N days from this date.",
|
||||
@@ -406,6 +474,10 @@
|
||||
"botLocale": "Language for command descriptions in Telegram's menu and bot response messages.",
|
||||
"rateLimits": "Cooldown in seconds between uses of each command category per chat. 0 = no limit."
|
||||
},
|
||||
"snackbar": {
|
||||
"showDetails": "Show details",
|
||||
"hideDetails": "Hide details"
|
||||
},
|
||||
"snack": {
|
||||
"providerSaved": "Provider saved",
|
||||
"providerDeleted": "Provider deleted",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"telegramBots": "Боты",
|
||||
"targets": "Получатели",
|
||||
"users": "Пользователи",
|
||||
"settings": "Настройки",
|
||||
"logout": "Выход"
|
||||
},
|
||||
"auth": {
|
||||
@@ -62,6 +63,7 @@
|
||||
"assets": "файлов",
|
||||
"eventActivity": "Активность событий",
|
||||
"last14days": "Последние 14 дней",
|
||||
"event": "событие",
|
||||
"events": "событий",
|
||||
"noChartData": "Нет данных о событиях"
|
||||
},
|
||||
@@ -85,7 +87,11 @@
|
||||
"checking": "Проверка...",
|
||||
"loadError": "Не удалось загрузить провайдеры.",
|
||||
"externalDomain": "Внешний домен",
|
||||
"optional": "необязательно"
|
||||
"optional": "необязательно",
|
||||
"urlApiKeyRequired": "URL и API ключ обязательны",
|
||||
"externalDomainHint": "Публичный URL для ссылок в уведомлениях. По умолчанию используется URL сервера.",
|
||||
"testAndSave": "Проверить и сохранить",
|
||||
"saveWithoutTest": "Сохранить без проверки"
|
||||
},
|
||||
"trackers": {
|
||||
"title": "Трекеры",
|
||||
@@ -134,7 +140,16 @@
|
||||
"testBasic": "Отправить тестовое сообщение",
|
||||
"testPeriodic": "Тест периодической сводки",
|
||||
"testScheduled": "Тест запланированных фото",
|
||||
"testMemory": "Тест воспоминаний"
|
||||
"testMemory": "Тест воспоминаний",
|
||||
"checkingLinks": "Проверка ссылок...",
|
||||
"missingLinksTitle": "Альбомы без публичных ссылок",
|
||||
"missingLinksDesc": "У следующих альбомов нет публичных ссылок. Без ссылок получатели уведомлений не смогут просматривать фото.",
|
||||
"expired": "Истёк",
|
||||
"passwordProtected": "Защищён паролем",
|
||||
"noLink": "Нет ссылки",
|
||||
"saveWithoutLinks": "Сохранить без ссылок",
|
||||
"createLinks": "Создать {count} ссылку(и)",
|
||||
"linksNote": "Вы также можете создать ссылки вручную в Immich."
|
||||
},
|
||||
"templates": {
|
||||
"title": "Шаблоны",
|
||||
@@ -198,7 +213,8 @@
|
||||
"create": "Создать",
|
||||
"delete": "Удалить",
|
||||
"confirmDelete": "Удалить этого пользователя?",
|
||||
"joined": "зарегистрирован"
|
||||
"joined": "зарегистрирован",
|
||||
"noUsers": "Пользователи не найдены"
|
||||
},
|
||||
"telegramBot": {
|
||||
"title": "Telegram боты",
|
||||
@@ -221,10 +237,10 @@
|
||||
"confirmDelete": "Удалить этого бота?",
|
||||
"commands": "Команды",
|
||||
"enabledCommands": "Включённые команды",
|
||||
"defaultCount": "Кол-во результатов",
|
||||
"defaultCount": "Кол-во по умолчанию",
|
||||
"responseMode": "Режим ответа",
|
||||
"modeMedia": "Медиа (отправка фото)",
|
||||
"modeText": "Текст (ссылки)",
|
||||
"modeMedia": "Медиа (фото)",
|
||||
"modeText": "Только текст",
|
||||
"botLocale": "Язык бота",
|
||||
"rateLimits": "Ограничения частоты",
|
||||
"rateSearch": "Кулдаун поиска",
|
||||
@@ -234,7 +250,34 @@
|
||||
"discoverChats": "Обнаружить чаты из Telegram",
|
||||
"clickToCopy": "Нажмите, чтобы скопировать ID чата",
|
||||
"chatsDiscovered": "Чаты обнаружены",
|
||||
"chatDeleted": "Чат удалён"
|
||||
"chatDeleted": "Чат удалён",
|
||||
"cmdLocale": "Язык бота",
|
||||
"searchCooldown": "Кулдаун поиска (с)",
|
||||
"saveConfig": "Сохранить настройки",
|
||||
"commandsSynced": "Команды синхронизированы с Telegram",
|
||||
"registerWebhook": "Зарегистрировать вебхук",
|
||||
"unregisterWebhook": "Удалить вебхук",
|
||||
"webhookRegistered": "Вебхук зарегистрирован",
|
||||
"webhookUnregistered": "Вебхук удалён",
|
||||
"updateMode": "Режим обновлений",
|
||||
"polling": "Опрос",
|
||||
"webhook": "Вебхук",
|
||||
"webhookStatus": "Статус вебхука",
|
||||
"webhookActive": "Вебхук активен",
|
||||
"webhookNotSet": "Вебхук не установлен",
|
||||
"webhookVerified": "Вебхук проверен",
|
||||
"webhookError": "Последняя ошибка",
|
||||
"pendingUpdates": "ожидающих обновлений",
|
||||
"pollingActive": "Опрос активен",
|
||||
"telegramSettings": "Настройки Telegram",
|
||||
"externalUrl": "Внешний URL",
|
||||
"externalUrlHint": "Публичный URL этого экземпляра Notify Bridge. Необходим для режима вебхука.",
|
||||
"webhookSecret": "Секрет вебхука",
|
||||
"webhookSecretHint": "Секретный токен для проверки запросов вебхука от Telegram (необязательно)",
|
||||
"cacheTtl": "TTL кэша медиа (часы)",
|
||||
"cacheTtlHint": "Сколько хранить кэш Telegram file_id перед повторной загрузкой (по умолчанию: 48ч)",
|
||||
"settingsSaved": "Настройки сохранены",
|
||||
"noExternalDomain": "Внешний URL домена не настроен"
|
||||
},
|
||||
"trackingConfig": {
|
||||
"title": "Конфигурации отслеживания",
|
||||
@@ -269,6 +312,9 @@
|
||||
"assetType": "Тип файлов",
|
||||
"minRating": "Мин. рейтинг",
|
||||
"memoryMode": "Воспоминания (В этот день)",
|
||||
"memorySource": "Источник воспоминаний",
|
||||
"memorySourceAlbums": "Сканировать альбомы",
|
||||
"memorySourceNative": "Встроенные воспоминания Immich",
|
||||
"test": "Тест",
|
||||
"confirmDelete": "Удалить эту конфигурацию отслеживания?",
|
||||
"sortNone": "Нет",
|
||||
@@ -282,7 +328,14 @@
|
||||
"albumModeRandom": "Случайный",
|
||||
"assetTypeAll": "Все",
|
||||
"assetTypePhoto": "Фото",
|
||||
"assetTypeVideo": "Видео"
|
||||
"assetTypeVideo": "Видео",
|
||||
"periodic": "периодический",
|
||||
"scheduled": "запланированный",
|
||||
"memory": "воспоминания",
|
||||
"added": "добавление",
|
||||
"removed": "удаление",
|
||||
"renamed": "переименование",
|
||||
"deleted": "удалён"
|
||||
},
|
||||
"templateConfig": {
|
||||
"title": "Конфигурации шаблонов",
|
||||
@@ -324,7 +377,8 @@
|
||||
"variables": "Переменные",
|
||||
"assetFields": "Поля файла (в {% for asset in added_assets %})",
|
||||
"albumFields": "Поля альбома (в {% for album in albums %})",
|
||||
"confirmDelete": "Удалить эту конфигурацию шаблона?"
|
||||
"confirmDelete": "Удалить эту конфигурацию шаблона?",
|
||||
"invalidFormat": "Некорректная строка формата"
|
||||
},
|
||||
"templateVars": {
|
||||
"message_assets_added": { "description": "Уведомление о добавлении файлов в альбом" },
|
||||
@@ -378,10 +432,24 @@
|
||||
"album_url_field": "Ссылка на альбом",
|
||||
"album_shared": "Общий альбом"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройки",
|
||||
"description": "Глобальные настройки приложения",
|
||||
"general": "Общие",
|
||||
"externalUrl": "Внешний URL",
|
||||
"externalUrlHint": "Публичный URL этого экземпляра Notify Bridge (напр. https://notify.example.com)",
|
||||
"telegram": "Telegram",
|
||||
"webhookSecret": "Секрет вебхука",
|
||||
"webhookSecretHint": "Секретный токен для проверки запросов вебхука от Telegram",
|
||||
"cacheTtl": "TTL кэша медиа (часы)",
|
||||
"cacheTtlHint": "Сколько хранить кэш Telegram file_id перед повторной загрузкой",
|
||||
"saved": "Настройки сохранены"
|
||||
},
|
||||
"hints": {
|
||||
"periodicSummary": "Отправляет плановую сводку по всем отслеживаемым альбомам в указанное время. Подходит для ежедневных/еженедельных дайджестов.",
|
||||
"scheduledAssets": "Отправляет случайные или выбранные фото из альбомов по расписанию. Как ежедневная подборка фото.",
|
||||
"memoryMode": "\"В этот день\" — отправляет фото, сделанные в этот день в прошлые годы. Ностальгические воспоминания.",
|
||||
"memorySource": "Альбомы: сканирует отслеживаемые альбомы по дате. Встроенные: использует воспоминания Immich (вся библиотека, с фильтрацией по альбомам).",
|
||||
"favoritesOnly": "Включать только ассеты, отмеченные как избранные.",
|
||||
"maxAssets": "Максимальное количество ассетов в одном уведомлении.",
|
||||
"periodicStartDate": "Опорная дата для расчёта интервалов. Сводки отправляются каждые N дней от этой даты.",
|
||||
@@ -406,6 +474,10 @@
|
||||
"botLocale": "Язык описаний команд в меню Telegram и ответов бота.",
|
||||
"rateLimits": "Кулдаун в секундах между использованиями команд в каждом чате. 0 = без ограничений."
|
||||
},
|
||||
"snackbar": {
|
||||
"showDetails": "Показать детали",
|
||||
"hideDetails": "Скрыть детали"
|
||||
},
|
||||
"snack": {
|
||||
"providerSaved": "Провайдер сохранён",
|
||||
"providerDeleted": "Провайдер удалён",
|
||||
|
||||
Reference in New Issue
Block a user