mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-02-17 13:52:14 +01:00
# 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 <175728472+Copilot@users.noreply.github.com> Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
307 lines
11 KiB
Groovy
307 lines
11 KiB
Groovy
apply plugin: 'org.springframework.boot'
|
|
|
|
import org.apache.tools.ant.taskdefs.condition.Os
|
|
|
|
repositories {
|
|
maven { url = 'https://build.shibboleth.net/maven/releases' }
|
|
maven { url = 'https://maven.pkg.github.com/jcefmaven/jcefmaven' }
|
|
}
|
|
|
|
configurations {
|
|
developmentOnly
|
|
runtimeClasspath {
|
|
extendsFrom developmentOnly
|
|
}
|
|
}
|
|
|
|
spotless {
|
|
java {
|
|
target 'src/**/java/**/*.java'
|
|
targetExclude 'src/main/resources/static/**'
|
|
googleJavaFormat(googleJavaFormatVersion).aosp().reorderImports(false)
|
|
|
|
importOrder("java", "javax", "org", "com", "net", "io", "jakarta", "lombok", "me", "stirling")
|
|
toggleOffOn()
|
|
trimTrailingWhitespace()
|
|
leadingTabsToSpaces()
|
|
endWithNewline()
|
|
}
|
|
yaml {
|
|
target '**/*.yml', '**/*.yaml'
|
|
targetExclude 'src/main/resources/static/**'
|
|
trimTrailingWhitespace()
|
|
leadingTabsToSpaces()
|
|
endWithNewline()
|
|
}
|
|
format 'gradle', {
|
|
target '**/gradle/*.gradle', '**/*.gradle'
|
|
targetExclude 'src/main/resources/static/**'
|
|
trimTrailingWhitespace()
|
|
leadingTabsToSpaces()
|
|
endWithNewline()
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') != 'false'
|
|
|| (project.hasProperty('STIRLING_PDF_DESKTOP_UI')
|
|
&& project.getProperty('STIRLING_PDF_DESKTOP_UI') != 'false')) {
|
|
implementation 'org.openjfx:javafx-controls:21'
|
|
implementation 'org.openjfx:javafx-swing:21'
|
|
}
|
|
|
|
if (System.getenv('DISABLE_ADDITIONAL_FEATURES') != 'true'
|
|
|| (project.hasProperty('DISABLE_ADDITIONAL_FEATURES')
|
|
&& System.getProperty('DISABLE_ADDITIONAL_FEATURES') != 'true')) {
|
|
implementation project(':proprietary')
|
|
}
|
|
|
|
implementation project(':common')
|
|
implementation 'org.springframework.boot:spring-boot-starter-jetty'
|
|
implementation 'com.posthog.java:posthog:1.2.0'
|
|
implementation 'org.telegram:telegrambots:6.9.7.1'
|
|
implementation 'commons-io:commons-io:2.21.0'
|
|
implementation "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion"
|
|
implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion"
|
|
implementation 'io.micrometer:micrometer-core:1.16.1'
|
|
implementation 'com.google.zxing:core:3.5.4'
|
|
implementation "org.commonmark:commonmark:$commonmarkVersion" // https://mvnrepository.com/artifact/org.commonmark/commonmark
|
|
implementation "org.commonmark:commonmark-ext-gfm-tables:$commonmarkVersion"
|
|
|
|
// General PDF dependencies
|
|
implementation "org.apache.pdfbox:preflight:$pdfboxVersion"
|
|
implementation "org.apache.pdfbox:xmpbox:$pdfboxVersion"
|
|
|
|
implementation 'org.verapdf:validation-model:1.28.2'
|
|
|
|
// veraPDF still uses javax.xml.bind, not the new jakarta namespace
|
|
implementation 'javax.xml.bind:jaxb-api:2.3.1'
|
|
implementation 'com.sun.xml.bind:jaxb-impl:2.3.9'
|
|
implementation 'com.sun.xml.bind:jaxb-core:2.3.0.1'
|
|
|
|
// https://mvnrepository.com/artifact/technology.tabula/tabula
|
|
implementation ('technology.tabula:tabula:1.0.5') {
|
|
exclude group: 'org.slf4j', module: 'slf4j-simple'
|
|
exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
|
|
exclude group: 'com.google.code.gson', module: 'gson'
|
|
}
|
|
implementation 'org.apache.pdfbox:jbig2-imageio:3.0.4'
|
|
implementation 'com.opencsv:opencsv:5.12.0' // https://mvnrepository.com/artifact/com.opencsv/opencsv
|
|
|
|
// Batik
|
|
implementation 'org.apache.xmlgraphics:batik-all:1.19'
|
|
|
|
// TwelveMonkeys
|
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
|
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
|
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
|
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
|
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
|
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-psd:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
|
|
// runtimeOnly "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
|
|
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
|
}
|
|
|
|
sourceSets {
|
|
main {
|
|
resources {
|
|
srcDirs += ['../configs']
|
|
}
|
|
java {
|
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
|
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
|
}
|
|
|
|
}
|
|
}
|
|
test {
|
|
java {
|
|
if (System.getenv('STIRLING_PDF_DESKTOP_UI') == 'false') {
|
|
exclude 'stirling/software/SPDF/UI/impl/**'
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Disable regular jar
|
|
jar {
|
|
enabled = false
|
|
}
|
|
|
|
// Configure and enable bootJar for this project
|
|
bootJar {
|
|
enabled = true
|
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
zip64 = true
|
|
|
|
// Don't include all dependencies directly like the old jar task did
|
|
// from {
|
|
// configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
|
// }
|
|
|
|
// Exclude signature files to prevent "Invalid signature file digest" errors
|
|
exclude 'META-INF/*.SF'
|
|
exclude 'META-INF/*.DSA'
|
|
exclude 'META-INF/*.RSA'
|
|
exclude 'META-INF/*.EC'
|
|
|
|
manifest {
|
|
attributes(
|
|
'Implementation-Title': 'Stirling-PDF',
|
|
'Implementation-Version': project.version
|
|
)
|
|
}
|
|
}
|
|
|
|
// Configure main class for Spring Boot
|
|
springBoot {
|
|
mainClass = 'stirling.software.SPDF.SPDFApplication'
|
|
}
|
|
|
|
// Frontend build tasks - only enabled with -PbuildWithFrontend=true
|
|
def buildWithFrontend = project.hasProperty('buildWithFrontend') && project.property('buildWithFrontend') == 'true'
|
|
def frontendDir = file('../../frontend')
|
|
def frontendDistDir = file('../../frontend/dist')
|
|
def resourcesStaticDir = file('src/main/resources/static')
|
|
def generatedFrontendPaths = [
|
|
'assets',
|
|
'index.html',
|
|
'locales',
|
|
'Login',
|
|
'classic-logo',
|
|
'modern-logo',
|
|
'og_images',
|
|
'samples',
|
|
'manifest-classic.json'
|
|
]
|
|
|
|
tasks.register('npmInstall', Exec) {
|
|
enabled = buildWithFrontend
|
|
group = 'frontend'
|
|
description = 'Install frontend dependencies'
|
|
workingDir frontendDir
|
|
commandLine = Os.isFamily(Os.FAMILY_WINDOWS) ? ['cmd', '/c', 'npm', 'ci', '--prefer-offline'] : ['npm', 'ci', '--prefer-offline']
|
|
inputs.file(new File(frontendDir, 'package.json'))
|
|
inputs.file(new File(frontendDir, 'package-lock.json'))
|
|
outputs.dir(new File(frontendDir, 'node_modules'))
|
|
|
|
// Show live output
|
|
standardOutput = System.out
|
|
errorOutput = System.err
|
|
|
|
// Skip if node_modules exists and is up-to-date
|
|
onlyIf {
|
|
def nodeModules = new File(frontendDir, 'node_modules')
|
|
if (!nodeModules.exists()) {
|
|
println "node_modules not found, will install..."
|
|
return true
|
|
}
|
|
def packageJson = new File(frontendDir, 'package.json')
|
|
def packageLock = new File(frontendDir, 'package-lock.json')
|
|
def isOutdated = nodeModules.lastModified() < packageJson.lastModified() ||
|
|
nodeModules.lastModified() < packageLock.lastModified()
|
|
if (isOutdated) {
|
|
println "package.json or package-lock.json changed, will reinstall..."
|
|
} else {
|
|
println "node_modules is up-to-date, skipping npm install"
|
|
}
|
|
return isOutdated
|
|
}
|
|
|
|
doFirst {
|
|
println "Installing npm dependencies in ${frontendDir}..."
|
|
}
|
|
}
|
|
|
|
tasks.register('npmBuild', Exec) {
|
|
enabled = buildWithFrontend
|
|
group = 'frontend'
|
|
description = 'Build frontend application'
|
|
workingDir frontendDir
|
|
commandLine = Os.isFamily(Os.FAMILY_WINDOWS) ? ['cmd', '/c', 'npm', 'run', 'build'] : ['npm', 'run', 'build']
|
|
dependsOn npmInstall
|
|
inputs.dir(new File(frontendDir, 'src'))
|
|
inputs.file(new File(frontendDir, 'package.json'))
|
|
outputs.dir(frontendDistDir)
|
|
|
|
// Show live output
|
|
standardOutput = System.out
|
|
errorOutput = System.err
|
|
|
|
// Override VITE_API_BASE_URL to use relative paths for production builds
|
|
// This ensures JARs work regardless of how they're deployed (direct, proxied, etc.)
|
|
environment 'VITE_API_BASE_URL', '/'
|
|
|
|
doFirst {
|
|
println "Building frontend application for production (VITE_API_BASE_URL=/)"
|
|
}
|
|
}
|
|
|
|
tasks.register('copyFrontendAssets', Copy) {
|
|
enabled = buildWithFrontend
|
|
group = 'frontend'
|
|
description = 'Copy frontend build to static resources'
|
|
dependsOn npmBuild
|
|
from(frontendDistDir) {
|
|
// Exclude files that conflict with backend static resources
|
|
exclude 'robots.txt' // Backend already has this
|
|
exclude 'favicon.ico' // Backend already has this
|
|
}
|
|
into resourcesStaticDir
|
|
duplicatesStrategy = DuplicatesStrategy.INCLUDE // Let frontend overwrite when needed
|
|
doFirst {
|
|
println "Copying frontend build from ${frontendDistDir} to ${resourcesStaticDir}..."
|
|
println "Backend static resources will be preserved"
|
|
}
|
|
doLast {
|
|
println "Frontend assets copied successfully!"
|
|
}
|
|
}
|
|
|
|
tasks.register('cleanFrontendAssets', Delete) {
|
|
group = 'frontend'
|
|
description = 'Remove previously generated frontend assets from static resources'
|
|
delete generatedFrontendPaths.collect { new File(resourcesStaticDir, it) }
|
|
}
|
|
|
|
tasks.register('copyApiLandingPage', Copy) {
|
|
group = 'frontend'
|
|
description = 'Copy API landing page to index.html for backend-only mode'
|
|
from(new File(resourcesStaticDir, 'api-landing.html'))
|
|
into(resourcesStaticDir)
|
|
rename('api-landing.html', 'index.html')
|
|
dependsOn cleanFrontendAssets
|
|
doFirst {
|
|
println "Copying API landing page to index.html for backend-only mode..."
|
|
}
|
|
}
|
|
|
|
// Ensure copyFrontendAssets runs after spotless tasks
|
|
tasks.named('copyFrontendAssets').configure {
|
|
mustRunAfter tasks.matching { it.name.startsWith('spotless') }
|
|
}
|
|
|
|
if (buildWithFrontend) {
|
|
println "Frontend build enabled - JAR will include React frontend"
|
|
processResources.dependsOn copyFrontendAssets
|
|
} else {
|
|
println "Frontend build disabled - JAR will be backend-only with API landing page"
|
|
// When not building the UI, ensure any stale frontend assets are removed and use API landing page
|
|
processResources.dependsOn copyApiLandingPage
|
|
}
|
|
|
|
bootJar.dependsOn ':common:jar'
|
|
bootJar.dependsOn ':proprietary:jar'
|