mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Refactoring
This commit is contained in:
285
submodules/TelegramCore/Sources/State/Serialization.swift
Normal file
285
submodules/TelegramCore/Sources/State/Serialization.swift
Normal file
@@ -0,0 +1,285 @@
|
||||
import Foundation
|
||||
import MtProtoKit
|
||||
import TelegramApi
|
||||
|
||||
private let apiPrefix: String = {
|
||||
let type = _typeName(Api.User.self)
|
||||
let userType = "User"
|
||||
if type.hasSuffix(userType) {
|
||||
return String(type[type.startIndex ..< type.index(type.endIndex, offsetBy: -userType.count)])
|
||||
} else {
|
||||
return "TelegramApi.Api."
|
||||
}
|
||||
}()
|
||||
|
||||
private let apiPrefixLength = apiPrefix.count
|
||||
|
||||
private let redactChildrenOfType: [String: Set<String>] = [
|
||||
"Message.message": Set(["message"]),
|
||||
"Updates.updateShortMessage": Set(["message"]),
|
||||
"Updates.updateShortChatMessage": Set(["message"]),
|
||||
"BotInlineMessage.botInlineMessageText": Set(["message"]),
|
||||
"DraftMessage.draftMessage": Set(["message"]),
|
||||
"InputSingleMedia.inputSingleMedia": Set(["message"]),
|
||||
"InputContact.inputPhoneContact": Set(["phone"]),
|
||||
"User.user": Set(["phone"]),
|
||||
"Update.updateUserPhone": Set(["phone"])
|
||||
]
|
||||
|
||||
private let redactFunctionParameters: [String: Set<String>] = [
|
||||
"messages.sendMessage": Set(["message"]),
|
||||
"messages.sendMedia": Set(["message"]),
|
||||
"messages.saveDraft": Set(["message"]),
|
||||
"messages.getWebPagePreview": Set(["message"])
|
||||
]
|
||||
|
||||
func apiFunctionDescription(of desc: FunctionDescription) -> String {
|
||||
var result = desc.name
|
||||
if !desc.parameters.isEmpty {
|
||||
result.append("(")
|
||||
var first = true
|
||||
for param in desc.parameters {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
result.append(", ")
|
||||
}
|
||||
result.append(param.0)
|
||||
result.append(": ")
|
||||
|
||||
var redactParam = false
|
||||
if let redactParams = redactFunctionParameters[desc.name] {
|
||||
redactParam = redactParams.contains(param.0)
|
||||
}
|
||||
|
||||
if redactParam, Logger.shared.redactSensitiveData {
|
||||
result.append("[[redacted]]")
|
||||
} else {
|
||||
result.append(recursiveDescription(redact: Logger.shared.redactSensitiveData, of: param.1))
|
||||
}
|
||||
}
|
||||
result.append(")")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func apiShortFunctionDescription(of desc: FunctionDescription) -> String {
|
||||
return desc.name
|
||||
}
|
||||
|
||||
private func recursiveDescription(redact: Bool, of value: Any) -> String {
|
||||
let mirror = Mirror(reflecting: value)
|
||||
var result = ""
|
||||
if let displayStyle = mirror.displayStyle {
|
||||
switch displayStyle {
|
||||
case .enum:
|
||||
result.append(_typeName(mirror.subjectType))
|
||||
if result.hasPrefix(apiPrefix) {
|
||||
result.removeSubrange(result.startIndex ..< result.index(result.startIndex, offsetBy: apiPrefixLength))
|
||||
}
|
||||
|
||||
if let value = value as? TypeConstructorDescription {
|
||||
let (consName, fields) = value.descriptionFields()
|
||||
result.append(".")
|
||||
result.append(consName)
|
||||
|
||||
let redactChildren: Set<String>?
|
||||
if redact {
|
||||
redactChildren = redactChildrenOfType[result]
|
||||
} else {
|
||||
redactChildren = nil
|
||||
}
|
||||
|
||||
if !fields.isEmpty {
|
||||
result.append("(")
|
||||
var first = true
|
||||
for (fieldName, fieldValue) in fields {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
result.append(", ")
|
||||
}
|
||||
var redactValue: Bool = false
|
||||
if let redactChildren = redactChildren, redactChildren.contains("*") {
|
||||
redactValue = true
|
||||
}
|
||||
|
||||
result.append(fieldName)
|
||||
result.append(": ")
|
||||
if let redactChildren = redactChildren, redactChildren.contains(fieldName) {
|
||||
redactValue = true
|
||||
}
|
||||
|
||||
if redactValue {
|
||||
result.append("[[redacted]]")
|
||||
} else {
|
||||
result.append(recursiveDescription(redact: redact, of: fieldValue))
|
||||
}
|
||||
}
|
||||
result.append(")")
|
||||
}
|
||||
} else {
|
||||
inner: for child in mirror.children {
|
||||
if let label = child.label {
|
||||
result.append(".")
|
||||
result.append(label)
|
||||
}
|
||||
let redactChildren: Set<String>?
|
||||
if redact {
|
||||
redactChildren = redactChildrenOfType[result]
|
||||
} else {
|
||||
redactChildren = nil
|
||||
}
|
||||
let valueMirror = Mirror(reflecting: child.value)
|
||||
if let displayStyle = valueMirror.displayStyle {
|
||||
switch displayStyle {
|
||||
case .tuple:
|
||||
var hadChildren = false
|
||||
for child in valueMirror.children {
|
||||
if !hadChildren {
|
||||
hadChildren = true
|
||||
result.append("(")
|
||||
} else {
|
||||
result.append(", ")
|
||||
}
|
||||
var redactValue: Bool = false
|
||||
if let redactChildren = redactChildren, redactChildren.contains("*") {
|
||||
redactValue = true
|
||||
}
|
||||
if let label = child.label {
|
||||
result.append(label)
|
||||
result.append(": ")
|
||||
if let redactChildren = redactChildren, redactChildren.contains(label) {
|
||||
redactValue = true
|
||||
}
|
||||
}
|
||||
|
||||
if redactValue {
|
||||
result.append("[[redacted]]")
|
||||
} else {
|
||||
result.append(recursiveDescription(redact: redact, of: child.value))
|
||||
}
|
||||
}
|
||||
if hadChildren {
|
||||
result.append(")")
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
} else {
|
||||
result.append("(")
|
||||
result.append(String(describing: child.value))
|
||||
result.append(")")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
case .collection:
|
||||
result.append("[")
|
||||
var isFirst = true
|
||||
for child in mirror.children {
|
||||
if isFirst {
|
||||
isFirst = false
|
||||
} else {
|
||||
result.append(", ")
|
||||
}
|
||||
result.append(recursiveDescription(redact: redact, of: child.value))
|
||||
}
|
||||
result.append("]")
|
||||
default:
|
||||
result.append("\(value)")
|
||||
}
|
||||
} else {
|
||||
result.append("\(value)")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public class BoxedMessage: NSObject {
|
||||
public let body: Any
|
||||
public init(_ body: Any) {
|
||||
self.body = body
|
||||
}
|
||||
|
||||
override public var description: String {
|
||||
get {
|
||||
return recursiveDescription(redact: Logger.shared.redactSensitiveData, of: self.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 128
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
if let body = Api.parse(Buffer(data: data)) {
|
||||
return BoxedMessage(body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
public func exportAuthorization(_ datacenterId: Int32, data: AutoreleasingUnsafeMutablePointer<NSData?>) -> MTExportAuthorizationResponseParser!
|
||||
{
|
||||
let functionContext = Api.functions.auth.exportAuthorization(dcId: datacenterId)
|
||||
data.pointee = functionContext.1.makeData() as NSData
|
||||
return { data -> MTExportedAuthorizationData? in
|
||||
if let exported = functionContext.2.parse(Buffer(data: data)) {
|
||||
switch exported {
|
||||
case let .exportedAuthorization(id, bytes):
|
||||
return MTExportedAuthorizationData(authorizationBytes: bytes.makeData(), authorizationId: id)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func importAuthorization(_ authId: Int32, bytes: Data!) -> Data! {
|
||||
return Api.functions.auth.importAuthorization(id: authId, bytes: Buffer(data: bytes)).1.makeData()
|
||||
}
|
||||
|
||||
public func requestDatacenterAddress(with data: AutoreleasingUnsafeMutablePointer<NSData?>) -> MTRequestDatacenterAddressListParser! {
|
||||
let (_, buffer, parser) = Api.functions.help.getConfig()
|
||||
data.pointee = buffer.makeData() as NSData
|
||||
return { response -> MTDatacenterAddressListData? in
|
||||
if let config = parser.parse(Buffer(data: response)) {
|
||||
switch config {
|
||||
case let .config(config):
|
||||
var addressDict: [NSNumber: [Any]] = [:]
|
||||
for option in config.dcOptions {
|
||||
switch option {
|
||||
case let .dcOption(flags, id, ipAddress, port, secret):
|
||||
if addressDict[id as NSNumber] == nil {
|
||||
addressDict[id as NSNumber] = []
|
||||
}
|
||||
let preferForMedia = (flags & (1 << 1)) != 0
|
||||
let restrictToTcp = (flags & (1 << 2)) != 0
|
||||
let isCdn = (flags & (1 << 3)) != 0
|
||||
let preferForProxy = (flags & (1 << 4)) != 0
|
||||
addressDict[id as NSNumber]!.append(MTDatacenterAddress(ip: ipAddress, port: UInt16(port), preferForMedia: preferForMedia, restrictToTcp: restrictToTcp, cdn: isCdn, preferForProxy: preferForProxy, secret: secret?.makeData())!)
|
||||
break
|
||||
}
|
||||
}
|
||||
return MTDatacenterAddressListData(addressList: addressDict)
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public func requestNoop(_ data: AutoreleasingUnsafeMutablePointer<NSData?>!) -> MTRequestNoopParser! {
|
||||
let (_, buffer, parser) = Api.functions.help.test()
|
||||
data.pointee = buffer.makeData() as NSData
|
||||
|
||||
return { response -> AnyObject? in
|
||||
if let _ = parser.parse(Buffer(data: response)) {
|
||||
return true as NSNumber
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user