mirror of
https://github.com/GLEGram/GLEGram-iOS.git
synced 2026-04-23 11:26:54 +02:00
4647310322
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.
99 lines
4.8 KiB
Swift
Executable File
99 lines
4.8 KiB
Swift
Executable File
// MARK: Swiftgram – Plugin metadata (exteraGram-compatible .plugin file format)
|
||
import Foundation
|
||
|
||
/// Metadata parsed from a .plugin file (exteraGram plugin format).
|
||
public struct PluginMetadata: Codable, Equatable {
|
||
public let id: String
|
||
public let name: String
|
||
public let description: String
|
||
public let version: String
|
||
public let author: String
|
||
/// Icon reference e.g. "ApplicationEmoji/141" or "glePlugins/1".
|
||
public let iconRef: String?
|
||
public let minVersion: String?
|
||
/// If true, plugin modifies profile display (Fake Profile–style). App reads settings and applies via userDisplayRunner.
|
||
public let hasUserDisplay: Bool
|
||
|
||
public init(id: String, name: String, description: String, version: String, author: String, iconRef: String? = nil, minVersion: String? = nil, hasUserDisplay: Bool = false) {
|
||
self.id = id
|
||
self.name = name
|
||
self.description = description
|
||
self.version = version
|
||
self.author = author
|
||
self.iconRef = iconRef
|
||
self.minVersion = minVersion
|
||
self.hasUserDisplay = hasUserDisplay
|
||
}
|
||
|
||
public init(from decoder: Decoder) throws {
|
||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||
id = try c.decode(String.self, forKey: .id)
|
||
name = try c.decode(String.self, forKey: .name)
|
||
description = try c.decode(String.self, forKey: .description)
|
||
version = try c.decode(String.self, forKey: .version)
|
||
author = try c.decode(String.self, forKey: .author)
|
||
iconRef = try c.decodeIfPresent(String.self, forKey: .iconRef)
|
||
minVersion = try c.decodeIfPresent(String.self, forKey: .minVersion)
|
||
hasUserDisplay = try c.decodeIfPresent(Bool.self, forKey: .hasUserDisplay) ?? false
|
||
}
|
||
}
|
||
|
||
/// Installed plugin info (stored in settings).
|
||
public struct PluginInfo: Codable, Equatable {
|
||
public var metadata: PluginMetadata
|
||
public var path: String
|
||
public var enabled: Bool
|
||
public var hasSettings: Bool
|
||
|
||
public init(metadata: PluginMetadata, path: String, enabled: Bool, hasSettings: Bool) {
|
||
self.metadata = metadata
|
||
self.path = path
|
||
self.enabled = enabled
|
||
self.hasSettings = hasSettings
|
||
}
|
||
}
|
||
|
||
/// Parses exteraGram-style metadata from .plugin file content (Python script with __name__, __description__, etc.).
|
||
public enum PluginMetadataParser {
|
||
private static let namePattern = #"__name__\s*=\s*["']([^"']+)["']"#
|
||
private static let descriptionPattern = #"__description__\s*=\s*["']([^"']+)["']"#
|
||
private static let versionPattern = #"__version__\s*=\s*["']([^"']+)["']"#
|
||
private static let authorPattern = #"__author__\s*=\s*["']([^"']+)["']"#
|
||
private static let idPattern = #"__id__\s*=\s*["']([^"']+)["']"#
|
||
private static let iconPattern = #"__icon__\s*=\s*["']([^"']+)["']"#
|
||
private static let minVersionPattern = #"__min_version__\s*=\s*["']([^"']+)["']"#
|
||
private static let createSettingsPattern = #"def\s+create_settings\s*\("#
|
||
/// Some plugins set __settings__ = True (e.g. panic_passcode_pro).
|
||
private static let settingsFlagPattern = #"__settings__\s*=\s*True"#
|
||
/// Plugins that modify profile display (Fake Profile–style) set __user_display__ = True.
|
||
private static let userDisplayPattern = #"__user_display__\s*=\s*True"#
|
||
|
||
public static func parse(content: String) -> PluginMetadata? {
|
||
guard let name = firstMatch(in: content, pattern: namePattern),
|
||
let id = firstMatch(in: content, pattern: idPattern) else {
|
||
return nil
|
||
}
|
||
let description = firstMatch(in: content, pattern: descriptionPattern) ?? ""
|
||
let version = firstMatch(in: content, pattern: versionPattern) ?? "1.0"
|
||
let author = firstMatch(in: content, pattern: authorPattern) ?? ""
|
||
let iconRef = firstMatch(in: content, pattern: iconPattern)
|
||
let minVersion = firstMatch(in: content, pattern: minVersionPattern)
|
||
let hasUserDisplay = content.range(of: userDisplayPattern, options: .regularExpression) != nil
|
||
return PluginMetadata(id: id, name: name, description: description, version: version, author: author, iconRef: iconRef, minVersion: minVersion, hasUserDisplay: hasUserDisplay)
|
||
}
|
||
|
||
public static func hasCreateSettings(content: String) -> Bool {
|
||
content.range(of: createSettingsPattern, options: .regularExpression) != nil
|
||
|| content.range(of: settingsFlagPattern, options: .regularExpression) != nil
|
||
}
|
||
|
||
private static func firstMatch(in string: String, pattern: String) -> String? {
|
||
guard let regex = try? NSRegularExpression(pattern: pattern),
|
||
let match = regex.firstMatch(in: string, range: NSRange(string.startIndex..., in: string)),
|
||
let range = Range(match.range(at: 1), in: string) else {
|
||
return nil
|
||
}
|
||
return String(string[range])
|
||
}
|
||
}
|