GLEGram 12.5 — Initial public release

Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
This commit is contained in:
Leeksov
2026-04-06 09:48:12 +03:00
commit 4647310322
39685 changed files with 11052678 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ConvertOpusToAAC",
module_name = "ConvertOpusToAAC",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/FFMpegBinding:FFMpegBinding",
"//submodules/MediaPlayer:UniversalMediaPlayer",
],
visibility = [
"//visibility:public",
],
)
@@ -0,0 +1,69 @@
import Foundation
import UniversalMediaPlayer
import AVFoundation
import SwiftSignalKit
public func convertOpusToAAC(sourcePath: String, allocateTempFile: @escaping () -> String) -> Signal<String?, NoError> {
return Signal { subscriber in
var isCancelled = false
let queue = Queue()
queue.async {
do {
let audioSource = SoftwareAudioSource(path: sourcePath)
let outputPath = allocateTempFile()
let assetWriter = try AVAssetWriter(outputURL: URL(fileURLWithPath: outputPath), fileType: .m4a)
var channelLayout = AudioChannelLayout()
memset(&channelLayout, 0, MemoryLayout<AudioChannelLayout>.size)
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono
let outputSettings: [String: Any] = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 48000,
AVEncoderBitRateKey: 32000,
AVNumberOfChannelsKey: 1,
AVChannelLayoutKey: NSData(bytes: &channelLayout, length: MemoryLayout<AudioChannelLayout>.size)
]
let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: outputSettings)
assetWriter.add(audioInput)
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: .zero)
let finishWriting: () -> Void = {
assetWriter.finishWriting(completionHandler: {
subscriber.putNext(outputPath)
subscriber.putCompletion()
})
}
audioInput.requestMediaDataWhenReady(on: queue.queue, using: {
if audioInput.isReadyForMoreMediaData {
if !isCancelled, let sampleBuffer = audioSource.readSampleBuffer() {
if !audioInput.append(sampleBuffer) {
audioInput.markAsFinished()
finishWriting()
return
}
} else {
audioInput.markAsFinished()
finishWriting()
}
}
})
} catch let e {
print("Error: \(e)")
subscriber.putNext(nil)
subscriber.putCompletion()
}
}
return ActionDisposable {
isCancelled = true
}
}
}
@@ -0,0 +1,22 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
sgdeps = [
"//Swiftgram/SGLogging:SGLogging"
]
swift_library(
name = "LocalAudioTranscription",
module_name = "LocalAudioTranscription",
srcs = glob([
"Sources/**/*.swift",
]),
copts = [
"-warnings-as-errors",
],
deps = sgdeps +[
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
],
visibility = [
"//visibility:public",
],
)
@@ -0,0 +1,176 @@
import SGLogging
import Foundation
import SwiftSignalKit
import Speech
private var sharedRecognizers: [String: NSObject] = [:]
private struct TranscriptionResult {
var text: String
var confidence: Float
var isFinal: Bool
var locale: String
}
private func transcribeAudio(path: String, locale: String) -> Signal<TranscriptionResult?, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
if #available(iOS 13.0, *) {
SFSpeechRecognizer.requestAuthorization { status in
Queue.mainQueue().async {
switch status {
case .notDetermined:
SGLogger.shared.log("LocalTranscription", "Authorization status: notDetermined")
subscriber.putNext(nil)
subscriber.putCompletion()
case .restricted:
SGLogger.shared.log("LocalTranscription", "Authorization status: restricted")
subscriber.putNext(nil)
subscriber.putCompletion()
case .denied:
SGLogger.shared.log("LocalTranscription", "Authorization status: denied")
subscriber.putNext(nil)
subscriber.putCompletion()
case .authorized:
let speechRecognizer: SFSpeechRecognizer
if let sharedRecognizer = sharedRecognizers[locale] as? SFSpeechRecognizer {
speechRecognizer = sharedRecognizer
} else {
guard let speechRecognizerValue = SFSpeechRecognizer(locale: Locale(identifier: locale)), speechRecognizerValue.isAvailable else {
SGLogger.shared.log("LocalTranscription", "Recognizer not available for locale: \(locale)")
subscriber.putNext(nil)
subscriber.putCompletion()
return
}
speechRecognizerValue.defaultTaskHint = .dictation
sharedRecognizers[locale] = speechRecognizerValue
speechRecognizer = speechRecognizerValue
if locale == "en-US" {
speechRecognizer.supportsOnDeviceRecognition = true
} else {
speechRecognizer.supportsOnDeviceRecognition = false
}
speechRecognizer.supportsOnDeviceRecognition = true
}
speechRecognizer.defaultTaskHint = .dictation
let tempFilePath = NSTemporaryDirectory() + "/\(UInt64.random(in: 0 ... UInt64.max)).m4a"
let _ = try? FileManager.default.copyItem(atPath: path, toPath: tempFilePath)
let request = SFSpeechURLRecognitionRequest(url: URL(fileURLWithPath: tempFilePath))
if #available(iOS 16.0, *) {
request.addsPunctuation = true
}
request.requiresOnDeviceRecognition = speechRecognizer.supportsOnDeviceRecognition
request.shouldReportPartialResults = false
let task = speechRecognizer.recognitionTask(with: request, resultHandler: { result, error in
if let result = result {
var confidence: Float = 0.0
var segmentsCount = 0
for segment in result.bestTranscription.segments {
confidence += segment.confidence
segmentsCount += 1
}
confidence /= Float(result.bestTranscription.segments.count)
subscriber.putNext(TranscriptionResult(text: result.bestTranscription.formattedString, confidence: confidence, isFinal: result.isFinal, locale: locale))
if result.isFinal {
SGLogger.shared.log("LocalTranscription", "Transcription finalized. locale: \(locale), segments: \(segmentsCount), confidence: \(confidence)")
subscriber.putCompletion()
}
} else {
SGLogger.shared.log("LocalTranscription", "Transcription failed. locale: \(locale), error: \(String(describing: error))")
subscriber.putNext(nil)
subscriber.putCompletion()
}
})
disposable.set(ActionDisposable {
task.cancel()
})
@unknown default:
SGLogger.shared.log("LocalTranscription", "Unknown authorization status")
subscriber.putNext(nil)
subscriber.putCompletion()
}
}
}
} else {
subscriber.putNext(nil)
subscriber.putCompletion()
}
return disposable
}
|> runOn(.mainQueue())
}
public struct LocallyTranscribedAudio {
public var text: String
public var isFinal: Bool
}
public func transcribeAudio(path: String, appLocale: String) -> Signal<LocallyTranscribedAudio?, NoError> {
var signals: [Signal<TranscriptionResult?, NoError>] = []
let locales: [String] = [appLocale]
// Device can effectivelly transcribe only one language at a time. So it will be wise to run language recognition once for each popular language, check the confidence, start over with most confident language and output something it has already generated
// if !locales.contains(Locale.current.identifier) {
// locales.append(Locale.current.identifier)
// }
// if locales.isEmpty {
// locales.append("en-US")
// }
// Dictionary to hold accumulated transcriptions and confidences for each locale
var accumulatedTranscription: [String: (confidence: Float, text: [String])] = [:]
for locale in locales {
signals.append(transcribeAudio(path: path, locale: locale))
}
// We need to combine results per-language and compare their total confidence, (instead of outputting everything we have to the signal)
// return the one with the most confidence
let resultSignal: Signal<[TranscriptionResult?], NoError> = signals.reduce(.single([])) { (accumulator, signal) in
return accumulator
|> mapToSignal { results in
return signal
|> map { next in
return results + [next]
}
}
}
return resultSignal
|> map { results -> LocallyTranscribedAudio? in
for result in results {
if let result = result {
var result = result
if result.text.isEmpty {
result.text = "..."
}
if var existing = accumulatedTranscription[result.locale] {
existing.text.append(result.text)
existing.confidence += result.confidence
accumulatedTranscription[result.locale] = existing
} else {
accumulatedTranscription[result.locale] = (result.confidence, [result.text])
}
}
}
// Find the locale with the highest accumulated confidence
guard let bestLocale = accumulatedTranscription.max(by: { $0.value.confidence < $1.value.confidence }) else {
SGLogger.shared.log("LocalTranscription", "No valid transcription results found")
return nil
}
let combinedText = bestLocale.value.text.joined(separator: ". ")
// Assume 'isFinal' is true if the last result in 'results' is final. Adjust if needed.
let isFinal = results.compactMap({ $0 }).last?.isFinal ?? false
return LocallyTranscribedAudio(text: combinedText, isFinal: isFinal)
}
}