ZaStoGram/TMessagesProj/build.gradle
loop-uh ecbb199867 Add bundled Python deps for plugin runtime
Bundle Python packages (Pillow, pyfiglet) that external plugins expect at runtime. Since Chaquopy cannot install packages at runtime on Android devices, these must be declared at build time and included in the APK.

Adds a guard script to verify the dependencies are properly configured, updates the CI workflow to run the check, and documents the available packages in README.
2026-06-30 23:25:11 +03:00

315 lines
14 KiB
Groovy

import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
apply plugin: 'com.android.library'
// ZaStoGram plugin engine: embed CPython so .plugin scripts (exteraGram-compatible)
// can run. Chaquopy may be applied to exactly one module per app; TMessagesProj is the
// shared library, so every app flavor (Standalone/App/Huawei/...) inherits plugin support.
apply plugin: 'com.chaquo.python'
repositories {
mavenCentral()
google()
}
configurations {
compile.exclude module: 'support-v4'
}
configurations.all {
exclude group: 'com.google.firebase', module: 'firebase-core'
exclude group: 'androidx.recyclerview', module: 'recyclerview'
}
dependencies {
implementation 'androidx.core:core:1.16.0'
implementation 'androidx.webkit:webkit:1.14.0'
implementation 'androidx.palette:palette:1.0.0'
implementation 'androidx.exifinterface:exifinterface:1.3.6'
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
implementation "androidx.sharetarget:sharetarget:1.2.0"
implementation 'androidx.interpolator:interpolator:1.0.0'
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'com.google.android.gms:play-services-cast-framework:21.4.0'
implementation "androidx.mediarouter:mediarouter:1.7.0"
implementation 'androidx.car.app:app:1.4.0'
implementation 'androidx.car.app:app-projected:1.4.0'
implementation 'org.nanohttpd:nanohttpd:2.3.1'
compileOnly 'org.checkerframework:checker-qual:2.5.2'
compileOnly 'org.checkerframework:checker-compat-qual:2.5.0'
implementation 'com.google.firebase:firebase-messaging:22.0.0'
implementation 'com.google.firebase:firebase-config:21.0.1'
implementation 'com.google.firebase:firebase-datatransport:18.1.0'
implementation 'com.google.firebase:firebase-appindexing:20.0.0'
implementation 'com.google.android.gms:play-services-maps:18.1.0'
implementation 'com.google.android.gms:play-services-auth:20.4.0'
implementation 'com.google.android.gms:play-services-vision:20.1.3'
implementation 'com.google.android.gms:play-services-wearable:18.0.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
implementation 'com.google.android.gms:play-services-wallet:19.1.0'
implementation 'com.googlecode.mp4parser:isoparser:1.0.6'
implementation 'com.stripe:stripe-android:2.0.2'
implementation 'com.google.mlkit:language-id:17.0.6'
implementation 'com.android.billingclient:billing:7.1.1'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.google.guava:guava:31.1-android'
implementation 'com.google.android.play:integrity:1.3.0'
implementation 'com.google.android.gms:play-services-safetynet:18.0.1'
implementation 'com.google.android.gms:play-services-mlkit-subject-segmentation:16.0.0-beta1'
implementation 'com.google.android.gms:play-services-mlkit-image-labeling:16.0.8'
implementation "androidx.credentials:credentials:1.6.0-alpha04"
implementation "androidx.credentials:credentials-play-services-auth:1.6.0-alpha04"
implementation "io.noties.markwon:core:4.6.2"
implementation "io.noties.markwon:ext-strikethrough:4.6.2"
implementation "io.noties.markwon:ext-tables:4.6.2"
implementation "io.noties.markwon:html:4.6.2"
implementation "io.noties.markwon:inline-parser:4.6.2"
implementation "io.noties.markwon:ext-latex:4.6.2"
// implementation 'com.google.mlkit:translate:17.0.3'
constraints {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") {
because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib")
}
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0") {
because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib")
}
}
implementation 'com.google.android.recaptcha:recaptcha:18.7.1'
// ZaStoGram plugin engine: Pine — dynamic ART method hooking (Xposed-compatible API).
// Supports Android 4.4(ART)-15 on arm64/armv7. The :xposed module exposes
// XC_MethodHook (before/afterHookedMethod + MethodHookParam) used by the bridge.
implementation 'top.canyie.pine:core:0.3.0'
// NOTE: the :xposed compat module's latest published version is 0.2.0 (there is no 0.3.0).
// 0.2.0 declares no dependency on :core, so it coexists with core:0.3.0. If runtime ART
// hooking ever misbehaves from version skew, pin core down to 0.2.9 to match.
implementation 'top.canyie.pine:xposed:0.2.0'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}
def isWindows = String.valueOf(DefaultNativePlatform.currentOperatingSystem.toFamilyName() == OperatingSystemFamily.WINDOWS)
android {
compileSdkVersion 35
buildToolsVersion '35.0.0'
ndkVersion "27.2.12479018"
sourceSets.main.jniLibs.srcDirs = ['./jni/']
externalNativeBuild {
cmake {
path 'jni/CMakeLists.txt'
}
}
lintOptions {
disable 'MissingTranslation'
disable 'ExtraTranslation'
disable 'BlockedPrivateApi'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
coreLibraryDesugaringEnabled true
}
defaultConfig {
minSdkVersion 24 // ZaStoGram: Chaquopy (plugin engine) requires minSdk >= 24
targetSdkVersion 35
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']
multiDexEnabled true
// ZaStoGram: Chaquopy (applied to this library module) requires ndk.abiFilters to know
// which ABIs to bundle CPython for. App flavors still narrow each APK to its own ABI;
// 'afat' (the CI authority) uses all four anyway.
ndk {
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
externalNativeBuild {
cmake {
version '3.10.2'
def cmakeArgs = ['-DANDROID_STL=c++_static', '-DANDROID_PLATFORM=android-21'] //, '-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON'
// CI speedup: route NDK compiles through ccache so unchanged native sources
// (webrtc/openh264/ffmpeg/boringssl) reuse cached object files across runs.
// Enabled only when USE_CCACHE=1 (GitHub Actions); local builds are unaffected.
if (System.getenv('USE_CCACHE') == '1') {
cmakeArgs << '-DCMAKE_C_COMPILER_LAUNCHER=ccache' << '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache'
}
arguments(*cmakeArgs)
}
}
}
buildTypes {
debug {
jniDebuggable true
minifyEnabled false
shrinkResources false
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro'
ndk.debugSymbolLevel = 'FULL'
buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\""
buildConfigField "String", "APP_CENTER_HASH", "\"\""
buildConfigField "String", "BETA_URL", "\"" + getProps("BETA_PRIVATE_URL") + "\""
buildConfigField "boolean", "DEBUG_VERSION", "true"
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "true"
buildConfigField "boolean", "BUNDLE", "false"
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
buildConfigField "int", "VERSION_NUM", "0"
}
HA_private {
jniDebuggable false
minifyEnabled true
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro'
ndk.debugSymbolLevel = 'FULL'
buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\""
buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_PRIVATE") + "\""
buildConfigField "String", "BETA_URL", "\"" + getProps("BETA_PRIVATE_URL") + "\""
buildConfigField "boolean", "DEBUG_VERSION", "true"
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "true"
buildConfigField "boolean", "BUNDLE", "false"
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
buildConfigField "int", "VERSION_NUM", "1"
}
HA_public {
jniDebuggable false
minifyEnabled true
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro'
ndk.debugSymbolLevel = 'FULL'
buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\""
buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_PUBLIC") + "\""
buildConfigField "String", "BETA_URL", "\"" + getProps("BETA_PUBLIC_URL") + "\""
buildConfigField "boolean", "DEBUG_VERSION", "true"
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "false"
buildConfigField "boolean", "BUNDLE", "false"
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
buildConfigField "int", "VERSION_NUM", "4"
}
HA_hardcore {
jniDebuggable false
minifyEnabled true
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro', '../TMessagesProj/proguard-rules-beta.pro'
ndk.debugSymbolLevel = 'FULL'
buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\""
buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_HARDCORE") + "\""
buildConfigField "String", "BETA_URL", "\"" + getProps("BETA_HARDCORE_URL") + "\""
buildConfigField "boolean", "DEBUG_VERSION", "true"
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "true"
buildConfigField "boolean", "BUNDLE", "false"
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
buildConfigField "int", "VERSION_NUM", "5"
}
standalone {
jniDebuggable false
minifyEnabled true
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro'
ndk.debugSymbolLevel = 'FULL'
buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\""
buildConfigField "String", "APP_CENTER_HASH", "\"\""
buildConfigField "String", "BETA_URL", "\"\""
buildConfigField "boolean", "DEBUG_VERSION", "false"
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "false"
buildConfigField "boolean", "BUNDLE", "false"
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
buildConfigField "int", "VERSION_NUM", "6"
}
release {
jniDebuggable false
minifyEnabled true
shrinkResources false
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro'
ndk.debugSymbolLevel = 'FULL'
buildConfigField "String", "BUILD_VERSION_STRING", "\"" + APP_VERSION_NAME + "\""
buildConfigField "String", "APP_CENTER_HASH", "\"\""
buildConfigField "String", "BETA_URL", "\"\""
buildConfigField "boolean", "DEBUG_VERSION", "false"
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "false"
buildConfigField "boolean", "BUNDLE", "false"
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
buildConfigField "int", "VERSION_NUM", "7"
}
}
namespace 'org.telegram.messenger'
}
// ZaStoGram plugin engine — Python runtime configuration.
// Host API modules live in src/main/python (base_plugin, client_utils, ui.*, ...).
// User .plugin scripts are loaded at runtime from the data dir, not bundled here.
chaquopy {
defaultConfig {
version "3.11" // matches exteraGram (Chaquopy 16, CPython 3.11)
// The build machine needs a CPython 3.11 on PATH. If Android Studio can't find
// it (common on Windows), uncomment and point at it explicitly:
// buildPython "C:/Users/<you>/AppData/Local/Programs/Python/Python311/python.exe"
pyc {
src false // ship readable .py so plugin tracebacks map to real lines
}
pip {
// Common third-party libs community plugins expect at runtime. Chaquopy can only
// install these at BUILD time (there is no runtime pip), so they must be declared
// here once and shipped in the APK — mirrors what exteraGram bundles.
install "Pillow" // exposes PIL for image-processing plugins
install "pyfiglet" // ASCIIGenerator and ASCII art plugins
install "requests" // th3_proxy_tools (country flags via ip-api, URL import) + many others
}
}
}
def getProps(String propName) {
def propsFile = rootProject.file('local.properties')
if (propsFile.exists()) {
def props = new Properties()
props.load(new FileInputStream(propsFile))
return props[propName]
} else {
return "";
}
}
apply plugin: 'com.google.gms.google-services'
task checkVisibility {
doFirst {
def isPrivateBuild = project.gradle.startParameter.taskNames.find {
it.contains("HA_private") || it.contains("HA_hardcore") || it.contains("Debug") || it.contains("Release")
}
def isPublicAllowed = !project.hasProperty("IS_PRIVATE") || !project.property("IS_PRIVATE").toBoolean()
if (!isPrivateBuild && !isPublicAllowed) {
throw new GradleException("Building public version of private code!")
}
}
doLast {
if (project.gradle.startParameter.taskNames.find { it.contains("HA_public") }) {
def privateBuild = file("${projectDir}_AppHockeyApp/afat/HA_private/Telegram-Beta.apk")
if (privateBuild.exists()) {
privateBuild.delete()
}
}
}
}
preBuild.dependsOn checkVisibility