mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 19:10:47 +02:00
Add Telegram bot integration for pipeline processing (#5185)
# Description of Changes This pull request introduces Telegram bot integration to the application, enabling users to send files via Telegram for processing through the pipeline. The main changes add configuration options, dependency management, and a new service for handling Telegram interactions. **Telegram bot integration:** * Added a new `TelegramPipelineBot` service (`TelegramPipelineBot.java`) that listens for incoming Telegram messages, downloads attached files or photos, places them in a pipeline inbox folder, waits for processing results, and sends the output files back to the user. The service includes error handling and status messaging. * Introduced a `TelegramBotConfig` configuration class to initialize and register the Telegram bot only when enabled via application properties. * Added a new `Telegram` configuration section to `ApplicationProperties` and the `settings.yml.template`, supporting options like enabling/disabling the bot, bot token/username, pipeline folder, processing timeout, and polling interval. [[1]](diffhunk://#diff-1c357db0a3e88cf5bedd4a5852415fadad83b8b3b9eb56e67059d8b9d8b10702R63) [[2]](diffhunk://#diff-1c357db0a3e88cf5bedd4a5852415fadad83b8b3b9eb56e67059d8b9d8b10702R580-R589) [[3]](diffhunk://#diff-12f23603ae35319a3ea08f91b6340d5d935216941fda2e69d2df1b6cd22a63f2R108-R115) **Dependency management:** * Added the `org.telegram:telegrambots` library to the project dependencies to support Telegram bot functionality. --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: Anthony Stirling <[email protected]>
This commit is contained in:
co-authored by
Copilot
Anthony Stirling
parent
83e96a9aa3
commit
e7b030e6b5
@@ -1,5 +1,18 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Paper, Group, Text, Button, Collapse, Stack, TextInput, Textarea, Switch, PasswordInput } from '@mantine/core';
|
||||
import {
|
||||
Paper,
|
||||
Group,
|
||||
Text,
|
||||
Button,
|
||||
Collapse,
|
||||
Stack,
|
||||
TextInput,
|
||||
Textarea,
|
||||
Switch,
|
||||
PasswordInput,
|
||||
NumberInput,
|
||||
TagsInput,
|
||||
} from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import LocalIcon from '@app/components/shared/LocalIcon';
|
||||
import { Provider, ProviderField } from '@app/components/shared/config/configSections/providerDefinitions';
|
||||
@@ -105,6 +118,36 @@ export default function ProviderCard({
|
||||
/>
|
||||
);
|
||||
|
||||
case 'number':
|
||||
return (
|
||||
<NumberInput
|
||||
key={field.key}
|
||||
label={field.label}
|
||||
description={field.description}
|
||||
placeholder={field.placeholder}
|
||||
value={value}
|
||||
onChange={(num) => handleFieldChange(field.key, num)}
|
||||
disabled={disabled}
|
||||
allowDecimal={false}
|
||||
/>
|
||||
);
|
||||
|
||||
case 'tags': {
|
||||
const tagValue = Array.isArray(value) ? value.map((val) => `${val}`) : [];
|
||||
|
||||
return (
|
||||
<TagsInput
|
||||
key={field.key}
|
||||
label={field.label}
|
||||
description={field.description}
|
||||
placeholder={field.placeholder}
|
||||
value={tagValue}
|
||||
onChange={(vals) => handleFieldChange(field.key, vals)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
default:
|
||||
return (
|
||||
<TextInput
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
export type ProviderType = 'oauth2' | 'saml2';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export type ProviderType = 'oauth2' | 'saml2' | 'telegram';
|
||||
|
||||
export interface ProviderField {
|
||||
key: string;
|
||||
type: 'text' | 'password' | 'switch' | 'textarea';
|
||||
type: 'text' | 'password' | 'switch' | 'textarea' | 'number' | 'tags';
|
||||
label: string;
|
||||
description: string;
|
||||
placeholder?: string;
|
||||
@@ -231,7 +233,7 @@ export const SMTP_PROVIDER: Provider = {
|
||||
},
|
||||
{
|
||||
key: 'port',
|
||||
type: 'text',
|
||||
type: 'number',
|
||||
label: 'SMTP Port',
|
||||
description: 'The port number for SMTP connection (typically 25, 465, or 587)',
|
||||
placeholder: '587',
|
||||
@@ -258,6 +260,216 @@ export const SMTP_PROVIDER: Provider = {
|
||||
},
|
||||
],
|
||||
};
|
||||
const useTelegramProvider = (): Provider => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return {
|
||||
id: 'telegram',
|
||||
name: t('admin.settings.telegram.title', 'Telegram Bot'),
|
||||
icon: 'send-rounded',
|
||||
type: 'telegram',
|
||||
scope: t(
|
||||
'admin.settings.telegram.description',
|
||||
'Configure Telegram bot connectivity, access controls, and feedback behavior.'
|
||||
),
|
||||
fields: [
|
||||
{
|
||||
key: 'enabled',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.enabled.label', 'Enable Telegram Bot'),
|
||||
description: t(
|
||||
'admin.settings.telegram.enabled.description',
|
||||
'Allow users to interact with Stirling PDF through your configured Telegram bot.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'botUsername',
|
||||
type: 'text',
|
||||
label: t('admin.settings.telegram.botUsername.label', 'Bot Username'),
|
||||
description: t(
|
||||
'admin.settings.telegram.botUsername.description',
|
||||
'The public username of your Telegram bot.'
|
||||
),
|
||||
placeholder: 'my_pdf_bot',
|
||||
},
|
||||
{
|
||||
key: 'botToken',
|
||||
type: 'password',
|
||||
label: t('admin.settings.telegram.botToken.label', 'Bot Token'),
|
||||
description: t(
|
||||
'admin.settings.telegram.botToken.description',
|
||||
'API token provided by BotFather for your Telegram bot.'
|
||||
),
|
||||
placeholder: '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
|
||||
},
|
||||
{
|
||||
key: 'pipelineInboxFolder',
|
||||
type: 'text',
|
||||
label: t('admin.settings.telegram.pipelineInboxFolder.label', 'Inbox Folder'),
|
||||
description: t(
|
||||
'admin.settings.telegram.pipelineInboxFolder.description',
|
||||
'Folder under the pipeline directory where incoming Telegram files are stored.'
|
||||
),
|
||||
placeholder: 'telegram',
|
||||
},
|
||||
{
|
||||
key: 'customFolderSuffix',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.customFolderSuffix.label', 'Use Custom Folder Suffix'),
|
||||
description: t(
|
||||
'admin.settings.telegram.customFolderSuffix.description',
|
||||
'Append the chat ID to incoming file folders to isolate uploads per chat.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'enableAllowUserIDs',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.enableAllowUserIDs.label', 'Allow Specific User IDs'),
|
||||
description: t(
|
||||
'admin.settings.telegram.enableAllowUserIDs.description',
|
||||
'When enabled, only listed user IDs can use the bot.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'allowUserIDs',
|
||||
type: 'tags',
|
||||
label: t('admin.settings.telegram.allowUserIDs.label', 'Allowed User IDs'),
|
||||
description: t(
|
||||
'admin.settings.telegram.allowUserIDs.description',
|
||||
'Enter Telegram user IDs allowed to interact with the bot.'
|
||||
),
|
||||
placeholder: t('admin.settings.telegram.allowUserIDs.placeholder', 'Add user ID and press enter'),
|
||||
defaultValue: [],
|
||||
},
|
||||
{
|
||||
key: 'enableAllowChannelIDs',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.enableAllowChannelIDs.label', 'Allow Specific Channel IDs'),
|
||||
description: t(
|
||||
'admin.settings.telegram.enableAllowChannelIDs.description',
|
||||
'When enabled, only listed channel IDs can use the bot.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'allowChannelIDs',
|
||||
type: 'tags',
|
||||
label: t('admin.settings.telegram.allowChannelIDs.label', 'Allowed Channel IDs'),
|
||||
description: t(
|
||||
'admin.settings.telegram.allowChannelIDs.description',
|
||||
'Enter Telegram channel IDs allowed to interact with the bot.'
|
||||
),
|
||||
placeholder: t('admin.settings.telegram.allowChannelIDs.placeholder', 'Add channel ID and press enter'),
|
||||
defaultValue: [],
|
||||
},
|
||||
{
|
||||
key: 'processingTimeoutSeconds',
|
||||
type: 'number',
|
||||
label: t(
|
||||
'admin.settings.telegram.processingTimeoutSeconds.label',
|
||||
'Processing Timeout (seconds)'
|
||||
),
|
||||
description: t(
|
||||
'admin.settings.telegram.processingTimeoutSeconds.description',
|
||||
'Maximum time to wait for a processing job before reporting an error.'
|
||||
),
|
||||
defaultValue: 180,
|
||||
},
|
||||
{
|
||||
key: 'pollingIntervalMillis',
|
||||
type: 'number',
|
||||
label: t('admin.settings.telegram.pollingIntervalMillis.label', 'Polling Interval (ms)'),
|
||||
description: t(
|
||||
'admin.settings.telegram.pollingIntervalMillis.description',
|
||||
'Interval between checks for new Telegram updates.'
|
||||
),
|
||||
defaultValue: 2000,
|
||||
},
|
||||
{
|
||||
key: 'feedback.general.enabled',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.feedback.general.enabled.label', 'Enable Feedback'),
|
||||
description: t(
|
||||
'admin.settings.telegram.feedback.general.enabled.description',
|
||||
'Control whether the bot sends feedback messages at all.'
|
||||
),
|
||||
defaultValue: true,
|
||||
},
|
||||
{
|
||||
key: 'feedback.channel.noValidDocument',
|
||||
type: 'switch',
|
||||
label: t(
|
||||
'admin.settings.telegram.feedback.channel.noValidDocument.label',
|
||||
'Show "No valid document" (Channel)'
|
||||
),
|
||||
description: t(
|
||||
'admin.settings.telegram.feedback.channel.noValidDocument.description',
|
||||
'Suppress the no valid document response for channel uploads.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'feedback.channel.errorProcessing',
|
||||
type: 'switch',
|
||||
label: t(
|
||||
'admin.settings.telegram.feedback.channel.errorProcessing.label',
|
||||
'Show processing errors (Channel)'
|
||||
),
|
||||
description: t(
|
||||
'admin.settings.telegram.feedback.channel.errorProcessing.description',
|
||||
'Send processing error messages to channels.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'feedback.channel.errorMessage',
|
||||
type: 'switch',
|
||||
label: t(
|
||||
'admin.settings.telegram.feedback.channel.errorMessage.label',
|
||||
'Show error messages (Channel)'
|
||||
),
|
||||
description: t(
|
||||
'admin.settings.telegram.feedback.channel.errorMessage.description',
|
||||
'Show detailed error messages for channels.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'feedback.user.noValidDocument',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.feedback.user.noValidDocument.label', 'Show "No valid document" (User)'),
|
||||
description: t(
|
||||
'admin.settings.telegram.feedback.user.noValidDocument.description',
|
||||
'Suppress the no valid document response for user uploads.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'feedback.user.errorProcessing',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.feedback.user.errorProcessing.label', 'Show processing errors (User)'),
|
||||
description: t(
|
||||
'admin.settings.telegram.feedback.user.errorProcessing.description',
|
||||
'Send processing error messages to users.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
key: 'feedback.user.errorMessage',
|
||||
type: 'switch',
|
||||
label: t('admin.settings.telegram.feedback.user.errorMessage.label', 'Show error messages (User)'),
|
||||
description: t(
|
||||
'admin.settings.telegram.feedback.user.errorMessage.description',
|
||||
'Show detailed error messages for users.'
|
||||
),
|
||||
defaultValue: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
export const SAML2_PROVIDER: Provider = {
|
||||
id: 'saml2',
|
||||
@@ -352,4 +564,14 @@ export const SAML2_PROVIDER: Provider = {
|
||||
],
|
||||
};
|
||||
|
||||
export const ALL_PROVIDERS = [...OAUTH2_PROVIDERS, GENERIC_OAUTH2_PROVIDER, SAML2_PROVIDER, SMTP_PROVIDER];
|
||||
export const useAllProviders = (): Provider[] => {
|
||||
const telegramProvider = useTelegramProvider();
|
||||
|
||||
return [
|
||||
...OAUTH2_PROVIDERS,
|
||||
GENERIC_OAUTH2_PROVIDER,
|
||||
SAML2_PROVIDER,
|
||||
SMTP_PROVIDER,
|
||||
telegramProvider,
|
||||
];
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ export const VALID_NAV_KEYS = [
|
||||
'adminGeneral',
|
||||
'adminSecurity',
|
||||
'adminConnections',
|
||||
'adminTelegram',
|
||||
'adminPrivacy',
|
||||
'adminDatabase',
|
||||
'adminAdvanced',
|
||||
@@ -33,4 +34,4 @@ export const VALID_NAV_KEYS = [
|
||||
// Derive the type from the array
|
||||
export type NavKey = typeof VALID_NAV_KEYS[number];
|
||||
|
||||
// some of these are not used yet, but appear in figma designs
|
||||
// some of these are not used yet, but appear in figma designs
|
||||
|
||||
Reference in New Issue
Block a user