Add Telegram bot integration and related features
ci / build-backend (push) Successful in 2m38s
ci / build-frontend (push) Successful in 1m16s
ci / tests (push) Successful in 2m33s
ci / sonar (push) Successful in 3m48s

Implemented Telegram bot functionality, including settings management, subscriber tracking, and link generation for user interaction. Updated the backend to support new Telegram-related services and database entities. Enhanced the frontend to display Telegram options and allow users to open a chat with the bot. Localization strings were added for both English and Russian to support the new features. This integration aims to improve user engagement through Telegram notifications and interactions.
This commit is contained in:
Leonid Pershin
2026-07-31 07:58:18 +03:00
parent bd3ced3637
commit 2b03e43a83
53 changed files with 6566 additions and 2 deletions
+28 -1
View File
@@ -1,7 +1,7 @@
import { useQuery } from '@tanstack/react-query'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Download, Radio, RotateCw } from 'lucide-react'
import { Download, Send, Radio, RotateCw } from 'lucide-react'
import { qk } from '@/shared/api/query-keys'
import type { PublicEpgEntryDto } from '@/shared/api/types'
import { cn } from '@/shared/lib/cn'
@@ -11,6 +11,8 @@ import { toast } from '@/shared/ui/toast-store'
import { ChannelPlayer } from './ChannelPlayer'
import {
downloadIptvPlaylist,
getTelegramStatus,
issueTelegramLink,
getEpg,
getViewerFeatures,
imageUrl,
@@ -80,6 +82,25 @@ export function AirPage() {
})
const { data: features } = useQuery({ queryKey: qk.air.features, queryFn: getViewerFeatures })
// Настройки бота читаем публичной частью: кнопка нужна только когда бот действительно настроен.
const { data: telegram } = useQuery({
queryKey: qk.air.telegram,
queryFn: getTelegramStatus,
})
/**
* Ссылка на чат выдаётся по нажатию, а не заранее: в ней одноразовый код привязки, и держать
* его в разметке страницы всё время незачем.
*/
const openBot = async () => {
try {
const { url } = await issueTelegramLink()
window.open(url, '_blank', 'noopener')
} catch {
toast.error(t('admin.telegram.linkFailed'))
}
}
const numbersEnabled = features?.channelNumbersEnabled ?? false
const currentChannel = channels?.find((c) => c.slug === selected)
@@ -193,6 +214,12 @@ export function AirPage() {
{numbersEnabled && (
<span className="text-xs text-muted-foreground">{t('air.numbersHint')}</span>
)}
{telegram?.isConfigured && (
<Button size="sm" variant="outline" onClick={() => void openBot()}>
<Send className="h-4 w-4" />
{t('admin.telegram.openChat')}
</Button>
)}
<Button
size="sm"
variant="outline"