mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-03 13:13:55 +00:00
Merge branch 'master' into gift-resale
# Conflicts: # submodules/TelegramUI/Sources/SharedAccountContext.swift
This commit is contained in:
commit
27a2f38ff6
76
.vscode/settings.json
vendored
76
.vscode/settings.json
vendored
@ -1,5 +1,79 @@
|
||||
{
|
||||
"sweetpad.build.xcodeWorkspacePath": "Telegram/Telegram.xcodeproj/project.xcworkspace",
|
||||
"lldb.library": "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB",
|
||||
"lldb.launch.expressions": "native"
|
||||
"lldb.launch.expressions": "native",
|
||||
"files.associations": {
|
||||
"__bit_reference": "cpp",
|
||||
"__hash_table": "cpp",
|
||||
"__locale": "cpp",
|
||||
"__node_handle": "cpp",
|
||||
"__split_buffer": "cpp",
|
||||
"__threading_support": "cpp",
|
||||
"__tree": "cpp",
|
||||
"__verbose_abort": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"bitset": "cpp",
|
||||
"cctype": "cpp",
|
||||
"cfenv": "cpp",
|
||||
"charconv": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"complex": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"execution": "cpp",
|
||||
"memory": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"fstream": "cpp",
|
||||
"future": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"ios": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"list": "cpp",
|
||||
"locale": "cpp",
|
||||
"map": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"print": "cpp",
|
||||
"queue": "cpp",
|
||||
"ratio": "cpp",
|
||||
"regex": "cpp",
|
||||
"scoped_allocator": "cpp",
|
||||
"set": "cpp",
|
||||
"span": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stack": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"string": "cpp",
|
||||
"string_view": "cpp",
|
||||
"tuple": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp",
|
||||
"vector": "cpp",
|
||||
"algorithm": "cpp"
|
||||
}
|
||||
}
|
||||
@ -14182,3 +14182,9 @@ Sorry for the inconvenience.";
|
||||
"Call.IncomingGroupCallTitle.Multiple_any" = "{} and %d others";
|
||||
|
||||
"GroupCall.RevokeLinkText" = "Are you sure you want to revoke this link? Once you do, no one will be able to join the call using it.";
|
||||
|
||||
|
||||
"SendInviteLink.TextCallsRestrictedOneUser" = "%@ does not accept calls.";
|
||||
"SendInviteLink.TextCallsRestrictedMultipleUsers_1" = "{user_list}, and **%d** more person do not accept calls.";
|
||||
"SendInviteLink.TextCallsRestrictedMultipleUsers_any" = "{user_list}, and **%d** more people do not accept calls.";
|
||||
"SendInviteLink.TextCallsRestrictedSendInviteLink" = "You can try to send an invite link instead.";
|
||||
|
||||
@ -988,6 +988,11 @@ public enum OldChannelsControllerIntent {
|
||||
case upgrade
|
||||
}
|
||||
|
||||
public enum SendInviteLinkScreenSubject {
|
||||
case chat(peer: EnginePeer, link: String?)
|
||||
case groupCall(link: String)
|
||||
}
|
||||
|
||||
public protocol SharedAccountContext: AnyObject {
|
||||
var sharedContainerPath: String { get }
|
||||
var basePath: String { get }
|
||||
@ -1206,6 +1211,8 @@ public protocol SharedAccountContext: AnyObject {
|
||||
|
||||
func makeAccountFreezeInfoScreen(context: AccountContext) -> ViewController
|
||||
|
||||
func makeSendInviteLinkScreen(context: AccountContext, subject: SendInviteLinkScreenSubject, peers: [TelegramForbiddenInvitePeer], theme: PresentationTheme?) -> ViewController
|
||||
|
||||
func makeDebugSettingsController(context: AccountContext?) -> ViewController?
|
||||
|
||||
func openCreateGroupCallUI(context: AccountContext, peerIds: [EnginePeer.Id], parentController: ViewController)
|
||||
|
||||
@ -700,10 +700,6 @@ public final class CallListController: TelegramBaseController {
|
||||
guard case let .conferenceCall(conferenceCall) = action?.action else {
|
||||
return
|
||||
}
|
||||
if conferenceCall.duration != nil {
|
||||
self.context.sharedContext.openCreateGroupCallUI(context: self.context, peerIds: conferenceCall.otherParticipants, parentController: self)
|
||||
return
|
||||
}
|
||||
|
||||
if let currentGroupCallController = self.context.sharedContext as? VoiceChatController, case let .group(groupCall) = currentGroupCallController.call, let currentCallId = groupCall.callId, currentCallId == conferenceCall.callId {
|
||||
self.context.sharedContext.navigateToCurrentCall()
|
||||
|
||||
@ -126,7 +126,7 @@ private func mappedInsertEntries(context: AccountContext, presentationData: Item
|
||||
case let .displayTabInfo(_, text):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: 0), directionHint: entry.directionHint)
|
||||
case .openNewCall:
|
||||
let item = ItemListPeerActionItem(presentationData: presentationData, style: showSettings ? .blocks : .plain, icon: PresentationResourcesRootController.callListCallIcon(presentationData.theme), title: presentationData.strings.CallList_NewCall, hasSeparator: false, sectionId: 1, height: .generic, noInsets: true, editing: false, action: {
|
||||
let item = ItemListPeerActionItem(presentationData: presentationData, style: showSettings ? .blocks : .plain, icon: PresentationResourcesRootController.callListCallIcon(presentationData.theme), title: presentationData.strings.CallList_NewCall, hasSeparator: false, sectionId: 1, height: .generic, noInsets: !showSettings, editing: false, action: {
|
||||
nodeInteraction.openNewCall()
|
||||
})
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
|
||||
@ -150,7 +150,7 @@ private func mappedUpdateEntries(context: AccountContext, presentationData: Item
|
||||
case let .displayTabInfo(_, text):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: 0), directionHint: entry.directionHint)
|
||||
case .openNewCall:
|
||||
let item = ItemListPeerActionItem(presentationData: presentationData, style: showSettings ? .blocks : .plain, icon: PresentationResourcesRootController.callListCallIcon(presentationData.theme), title: presentationData.strings.CallList_NewCall, hasSeparator: false, sectionId: 1, height: .generic, noInsets: true, editing: false, action: {
|
||||
let item = ItemListPeerActionItem(presentationData: presentationData, style: showSettings ? .blocks : .plain, icon: PresentationResourcesRootController.callListCallIcon(presentationData.theme), title: presentationData.strings.CallList_NewCall, hasSeparator: false, sectionId: 1, height: .generic, noInsets: !showSettings, editing: false, action: {
|
||||
nodeInteraction.openNewCall()
|
||||
})
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
|
||||
@ -525,7 +525,7 @@ final class CallListControllerNode: ASDisplayNode {
|
||||
|> mapToQueue { (updateAndType, state, groupCalls, showCallsTab, currentGroupCallPeerId) -> Signal<CallListNodeListViewTransition, NoError> in
|
||||
let (update, type) = updateAndType
|
||||
|
||||
let processedView = CallListNodeView(originalView: update.view, filteredEntries: callListNodeEntriesForView(view: update.view, displayOpenNewCall: mode == .tab && type == .all, groupCalls: groupCalls, state: state, showSettings: showSettings, showCallsTab: showCallsTab, isRecentCalls: type == .all, currentGroupCallPeerId: currentGroupCallPeerId), presentationData: state.presentationData)
|
||||
let processedView = CallListNodeView(originalView: update.view, filteredEntries: callListNodeEntriesForView(view: update.view, displayOpenNewCall: type == .all, groupCalls: groupCalls, state: state, showSettings: showSettings, showCallsTab: showCallsTab, isRecentCalls: type == .all, currentGroupCallPeerId: currentGroupCallPeerId), presentationData: state.presentationData)
|
||||
let previous = previousView.swap(processedView)
|
||||
let previousType = previousType.swap(type)
|
||||
|
||||
|
||||
@ -44,14 +44,14 @@ enum CallListNodeEntry: Comparable, Identifiable {
|
||||
case .openNewCall:
|
||||
switch rhs {
|
||||
case .displayTab, .displayTabInfo:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
case let .groupCall(lhsPeerId, lhsTitle):
|
||||
switch rhs {
|
||||
case .displayTab, .displayTabInfo, .openNewCall:
|
||||
return false
|
||||
return true
|
||||
case let .groupCall(rhsPeerId, rhsTitle):
|
||||
if lhsTitle == rhsTitle {
|
||||
return lhsPeerId < rhsPeerId
|
||||
@ -64,7 +64,7 @@ enum CallListNodeEntry: Comparable, Identifiable {
|
||||
case let .hole(lhsIndex):
|
||||
switch rhs {
|
||||
case .displayTab, .displayTabInfo, .groupCall, .openNewCall:
|
||||
return false
|
||||
return true
|
||||
case let .hole(rhsIndex):
|
||||
return lhsIndex < rhsIndex
|
||||
case let .message(rhsIndex):
|
||||
@ -73,7 +73,7 @@ enum CallListNodeEntry: Comparable, Identifiable {
|
||||
case let .message(lhsIndex):
|
||||
switch rhs {
|
||||
case .displayTab, .displayTabInfo, .groupCall, .openNewCall:
|
||||
return false
|
||||
return true
|
||||
case let .hole(rhsIndex):
|
||||
return lhsIndex < rhsIndex
|
||||
case let .message(rhsIndex):
|
||||
|
||||
@ -306,10 +306,8 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
|
||||
|
||||
if conferenceCall.flags.contains(.isMissed) {
|
||||
messageText = strings.Chat_CallMessage_DeclinedGroupCall
|
||||
} else if message.timestamp < currentTime - missedTimeout {
|
||||
} else if conferenceCall.duration == nil && message.timestamp < currentTime - missedTimeout {
|
||||
messageText = strings.Chat_CallMessage_MissedGroupCall
|
||||
} else if conferenceCall.duration != nil {
|
||||
messageText = strings.Chat_CallMessage_CancelledGroupCall
|
||||
} else {
|
||||
if incoming {
|
||||
messageText = strings.Chat_CallMessage_IncomingGroupCall
|
||||
|
||||
@ -1247,7 +1247,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
|
||||
}
|
||||
|
||||
if let adminPeer, case let .restricted(forbiddenPeer) = error {
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, peer: channelPeer, link: exportedInvitation?.link, peers: [forbiddenPeer ?? TelegramForbiddenInvitePeer(peer: adminPeer, canInviteWithPremium: false, premiumRequiredToContact: false)])
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, subject: .chat(peer: channelPeer, link: exportedInvitation?.link), peers: [forbiddenPeer ?? TelegramForbiddenInvitePeer(peer: adminPeer, canInviteWithPremium: false, premiumRequiredToContact: false)])
|
||||
pushControllerImpl?(inviteScreen)
|
||||
|
||||
dismissImpl?()
|
||||
@ -1437,7 +1437,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { error in
|
||||
if case let .addMemberError(addMemberError) = error, case let .restricted(forbiddenPeer) = addMemberError, let admin = adminPeer {
|
||||
if let channelPeer {
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, peer: channelPeer, link: exportedInvitation?.link, peers: [forbiddenPeer ?? TelegramForbiddenInvitePeer(peer: admin, canInviteWithPremium: false, premiumRequiredToContact: false)])
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, subject: .chat(peer: channelPeer, link: exportedInvitation?.link), peers: [forbiddenPeer ?? TelegramForbiddenInvitePeer(peer: admin, canInviteWithPremium: false, premiumRequiredToContact: false)])
|
||||
pushControllerImpl?(inviteScreen)
|
||||
|
||||
dismissImpl?()
|
||||
@ -1519,7 +1519,7 @@ public func channelAdminController(context: AccountContext, updatedPresentationD
|
||||
)
|
||||
|> deliverOnMainQueue).startStandalone(next: { exportedInvitation in
|
||||
let _ = exportedInvitation
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, peer: .legacyGroup(group), link: exportedInvitation?.link, peers: [failedPeer])
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, subject: .chat(peer: .legacyGroup(group), link: exportedInvitation?.link), peers: [failedPeer])
|
||||
pushControllerImpl?(inviteScreen)
|
||||
})
|
||||
} else {
|
||||
|
||||
@ -560,7 +560,7 @@ public func channelMembersController(context: AccountContext, updatedPresentatio
|
||||
if !failedPeers.isEmpty, let contactsController, let navigationController = contactsController.navigationController as? NavigationController {
|
||||
var viewControllers = navigationController.viewControllers
|
||||
if let index = viewControllers.firstIndex(where: { $0 === contactsController }) {
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, peer: chatPeer, link: exportedInvitation?.link, peers: failedPeers)
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, subject: .chat(peer: chatPeer, link: exportedInvitation?.link), peers: failedPeers)
|
||||
viewControllers.remove(at: index)
|
||||
viewControllers.append(inviteScreen)
|
||||
navigationController.setViewControllers(viewControllers, animated: true)
|
||||
|
||||
@ -356,8 +356,8 @@ private final class ConferenceCallE2EContextStateImpl: ConferenceCallE2EContextS
|
||||
return self.call.takeOutgoingBroadcastBlocks()
|
||||
}
|
||||
|
||||
func encrypt(message: Data, channelId: Int32) -> Data? {
|
||||
return self.call.encrypt(message, channelId: channelId)
|
||||
func encrypt(message: Data, channelId: Int32, plaintextPrefixLength: Int) -> Data? {
|
||||
return self.call.encrypt(message, channelId: channelId, plaintextPrefixLength: plaintextPrefixLength)
|
||||
}
|
||||
|
||||
func decrypt(message: Data, userId: Int64) -> Data? {
|
||||
@ -374,9 +374,9 @@ class OngoingGroupCallEncryptionContextImpl: OngoingGroupCallEncryptionContext {
|
||||
self.channelId = channelId
|
||||
}
|
||||
|
||||
func encrypt(message: Data) -> Data? {
|
||||
func encrypt(message: Data, plaintextPrefixLength: Int) -> Data? {
|
||||
let channelId = self.channelId
|
||||
return self.e2eCall.with({ $0.state?.encrypt(message: message, channelId: channelId) })
|
||||
return self.e2eCall.with({ $0.state?.encrypt(message: message, channelId: channelId, plaintextPrefixLength: plaintextPrefixLength) })
|
||||
}
|
||||
|
||||
func decrypt(message: Data, userId: Int64) -> Data? {
|
||||
@ -3620,14 +3620,24 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
let presentationData = self.accountContext.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||
|
||||
var errorText = presentationData.strings.Login_UnknownError
|
||||
|
||||
switch error {
|
||||
case let .privacy(peer):
|
||||
if let peer {
|
||||
errorText = presentationData.strings.Call_PrivacyErrorMessage(peer.compactDisplayTitle).string
|
||||
if let currentInviteLinks = self.currentInviteLinks {
|
||||
let inviteLinkScreen = self.accountContext.sharedContext.makeSendInviteLinkScreen(context: self.accountContext, subject: .groupCall(link: currentInviteLinks.listenerLink), peers: [TelegramForbiddenInvitePeer(peer: peer, canInviteWithPremium: false, premiumRequiredToContact: false)], theme: defaultDarkColorPresentationTheme)
|
||||
if let navigationController = self.accountContext.sharedContext.mainWindow?.viewController as? NavigationController {
|
||||
navigationController.pushViewController(inviteLinkScreen)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
errorText = presentationData.strings.Call_PrivacyErrorMessage(peer.compactDisplayTitle).string
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
self.accountContext.sharedContext.mainWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [
|
||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {})
|
||||
]), on: .root, blockInteraction: false, completion: {})
|
||||
@ -3752,6 +3762,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
}
|
||||
|
||||
public var currentInviteLinks: GroupCallInviteLinks?
|
||||
|
||||
private var currentMyAudioLevel: Float = 0.0
|
||||
private var currentMyAudioLevelTimestamp: Double = 0.0
|
||||
private var isSendingTyping: Bool = false
|
||||
|
||||
@ -1530,6 +1530,9 @@ final class VideoChatScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
self.inviteLinks = value
|
||||
if case let .group(groupCall) = self.currentCall, let groupCall = groupCall as? PresentationGroupCallImpl {
|
||||
groupCall.currentInviteLinks = value
|
||||
}
|
||||
})
|
||||
|
||||
self.reconnectedAsEventsDisposable?.dispose()
|
||||
|
||||
@ -13,7 +13,7 @@ public protocol ConferenceCallE2EContextState: AnyObject {
|
||||
|
||||
func takeOutgoingBroadcastBlocks() -> [Data]
|
||||
|
||||
func encrypt(message: Data, channelId: Int32) -> Data?
|
||||
func encrypt(message: Data, channelId: Int32, plaintextPrefixLength: Int) -> Data?
|
||||
func decrypt(message: Data, userId: Int64) -> Data?
|
||||
}
|
||||
|
||||
@ -379,7 +379,7 @@ public final class ConferenceCallE2EContext {
|
||||
// Peer ids that are in the blockchain but not in the server list
|
||||
var removedPeerIds = blockchainPeerIds.filter { blockchainPeerId in
|
||||
return !result.participants.contains(where: { participant in
|
||||
if case let .peer(id) = participant.id, id.namespace == Namespaces.Peer.CloudChannel, id.id._internalGetInt64Value() == blockchainPeerId {
|
||||
if case let .peer(id) = participant.id, id.namespace == Namespaces.Peer.CloudUser, id.id._internalGetInt64Value() == blockchainPeerId {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
||||
@ -200,7 +200,7 @@ func _internal_joinCallInvitationInformation(account: Account, messageId: Messag
|
||||
}
|
||||
var members: [EnginePeer] = []
|
||||
for participant in call.topParticipants {
|
||||
if let peer = participant.peer {
|
||||
if let peer = participant.peer, peer.id != account.peerId {
|
||||
members.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
@ -625,10 +625,8 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
|
||||
if conferenceCall.flags.contains(.isMissed) {
|
||||
titleString = strings.Chat_CallMessage_DeclinedGroupCall
|
||||
} else if message.timestamp < currentTime - missedTimeout {
|
||||
} else if conferenceCall.duration == nil && message.timestamp < currentTime - missedTimeout {
|
||||
titleString = strings.Chat_CallMessage_MissedGroupCall
|
||||
} else if conferenceCall.duration != nil {
|
||||
titleString = strings.Chat_CallMessage_CancelledGroupCall
|
||||
} else {
|
||||
if incoming {
|
||||
titleString = strings.Chat_CallMessage_IncomingGroupCall
|
||||
|
||||
@ -174,10 +174,8 @@ public class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let currentTime = Int32(Date().timeIntervalSince1970)
|
||||
if conferenceCall.flags.contains(.isMissed) {
|
||||
titleString = item.presentationData.strings.Chat_CallMessage_DeclinedGroupCall
|
||||
} else if item.message.timestamp < currentTime - missedTimeout {
|
||||
} else if conferenceCall.duration == nil && item.message.timestamp < currentTime - missedTimeout {
|
||||
titleString = item.presentationData.strings.Chat_CallMessage_MissedGroupCall
|
||||
} else if conferenceCall.duration != nil {
|
||||
titleString = item.presentationData.strings.Chat_CallMessage_CancelledGroupCall
|
||||
} else {
|
||||
if incoming {
|
||||
titleString = item.presentationData.strings.Chat_CallMessage_IncomingGroupCall
|
||||
|
||||
@ -14182,7 +14182,7 @@ public func presentAddMembersImpl(context: AccountContext, updatedPresentationDa
|
||||
if !failedPeers.isEmpty, let contactsController, let navigationController = contactsController.navigationController as? NavigationController {
|
||||
var viewControllers = navigationController.viewControllers
|
||||
if let index = viewControllers.firstIndex(where: { $0 === contactsController }) {
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, peer: EnginePeer(groupPeer), link: exportedInvitation?.link, peers: failedPeers)
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, subject: .chat(peer: EnginePeer(groupPeer), link: exportedInvitation?.link), peers: failedPeers)
|
||||
viewControllers.remove(at: index)
|
||||
viewControllers.append(inviteScreen)
|
||||
navigationController.setViewControllers(viewControllers, animated: true)
|
||||
|
||||
@ -23,23 +23,20 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
|
||||
let context: AccountContext
|
||||
let peer: EnginePeer
|
||||
let link: String?
|
||||
let subject: SendInviteLinkScreenSubject
|
||||
let peers: [TelegramForbiddenInvitePeer]
|
||||
let peerPresences: [EnginePeer.Id: EnginePeer.Presence]
|
||||
let sendPaidMessageStars: [EnginePeer.Id: StarsAmount]
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
peer: EnginePeer,
|
||||
link: String?,
|
||||
subject: SendInviteLinkScreenSubject,
|
||||
peers: [TelegramForbiddenInvitePeer],
|
||||
peerPresences: [EnginePeer.Id: EnginePeer.Presence],
|
||||
sendPaidMessageStars: [EnginePeer.Id: StarsAmount]
|
||||
) {
|
||||
self.context = context
|
||||
self.peer = peer
|
||||
self.link = link
|
||||
self.subject = subject
|
||||
self.peers = peers
|
||||
self.peerPresences = peerPresences
|
||||
self.sendPaidMessageStars = sendPaidMessageStars
|
||||
@ -49,9 +46,6 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
if lhs.link != rhs.link {
|
||||
return false
|
||||
}
|
||||
if lhs.peers != rhs.peers {
|
||||
return false
|
||||
}
|
||||
@ -315,7 +309,12 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
|
||||
if self.component == nil {
|
||||
for peer in component.peers {
|
||||
if component.link != nil && !peer.premiumRequiredToContact {
|
||||
switch component.subject {
|
||||
case let .chat(_, link):
|
||||
if link != nil && !peer.premiumRequiredToContact {
|
||||
self.selectedItems.insert(peer.peer.id)
|
||||
}
|
||||
case .groupCall:
|
||||
self.selectedItems.insert(peer.peer.id)
|
||||
}
|
||||
}
|
||||
@ -329,10 +328,15 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
return peer.canInviteWithPremium
|
||||
}
|
||||
var hasInviteLink = true
|
||||
if premiumRestrictedUsers.count == component.peers.count && component.link == nil {
|
||||
hasInviteLink = false
|
||||
} else if component.link != nil && !premiumRestrictedUsers.isEmpty && component.peers.allSatisfy({ $0.premiumRequiredToContact }) {
|
||||
hasInviteLink = false
|
||||
switch component.subject {
|
||||
case let .chat(_, link):
|
||||
if premiumRestrictedUsers.count == component.peers.count && link == nil {
|
||||
hasInviteLink = false
|
||||
} else if link != nil && !premiumRestrictedUsers.isEmpty && component.peers.allSatisfy({ $0.premiumRequiredToContact }) {
|
||||
hasInviteLink = false
|
||||
}
|
||||
case .groupCall:
|
||||
hasInviteLink = true
|
||||
}
|
||||
|
||||
if themeUpdated {
|
||||
@ -453,48 +457,85 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
contentHeight += 8.0
|
||||
|
||||
let text: String
|
||||
if premiumRestrictedUsers.count == 1 {
|
||||
if case let .channel(channel) = component.peer, case .broadcast = channel.info {
|
||||
text = environment.strings.SendInviteLink_ChannelTextContactsAndPremiumOneUser(premiumRestrictedUsers[0].peer.compactDisplayTitle).string
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextContactsAndPremiumOneUser(premiumRestrictedUsers[0].peer.compactDisplayTitle).string
|
||||
}
|
||||
} else {
|
||||
let extraCount = premiumRestrictedUsers.count - 3
|
||||
|
||||
var peersTextArray: [String] = []
|
||||
for i in 0 ..< min(3, premiumRestrictedUsers.count) {
|
||||
peersTextArray.append("**\(premiumRestrictedUsers[i].peer.compactDisplayTitle)**")
|
||||
}
|
||||
|
||||
var peersText = ""
|
||||
if #available(iOS 13.0, *) {
|
||||
let listFormatter = ListFormatter()
|
||||
listFormatter.locale = localeWithStrings(environment.strings)
|
||||
if let value = listFormatter.string(from: peersTextArray) {
|
||||
peersText = value
|
||||
switch component.subject {
|
||||
case let .chat(peer, _):
|
||||
if premiumRestrictedUsers.count == 1 {
|
||||
if case let .channel(channel) = peer, case .broadcast = channel.info {
|
||||
text = environment.strings.SendInviteLink_ChannelTextContactsAndPremiumOneUser(premiumRestrictedUsers[0].peer.compactDisplayTitle).string
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextContactsAndPremiumOneUser(premiumRestrictedUsers[0].peer.compactDisplayTitle).string
|
||||
}
|
||||
}
|
||||
if peersText.isEmpty {
|
||||
for i in 0 ..< peersTextArray.count {
|
||||
if i != 0 {
|
||||
peersText.append(", ")
|
||||
} else {
|
||||
let extraCount = premiumRestrictedUsers.count - 3
|
||||
|
||||
var peersTextArray: [String] = []
|
||||
for i in 0 ..< min(3, premiumRestrictedUsers.count) {
|
||||
peersTextArray.append("**\(premiumRestrictedUsers[i].peer.compactDisplayTitle)**")
|
||||
}
|
||||
|
||||
var peersText = ""
|
||||
if #available(iOS 13.0, *) {
|
||||
let listFormatter = ListFormatter()
|
||||
listFormatter.locale = localeWithStrings(environment.strings)
|
||||
if let value = listFormatter.string(from: peersTextArray) {
|
||||
peersText = value
|
||||
}
|
||||
}
|
||||
if peersText.isEmpty {
|
||||
for i in 0 ..< peersTextArray.count {
|
||||
if i != 0 {
|
||||
peersText.append(", ")
|
||||
}
|
||||
peersText.append(peersTextArray[i])
|
||||
}
|
||||
}
|
||||
|
||||
if extraCount >= 1 {
|
||||
if case let .channel(channel) = peer, case .broadcast = channel.info {
|
||||
text = environment.strings.SendInviteLink_ChannelTextContactsAndPremiumMultipleUsers(Int32(extraCount)).replacingOccurrences(of: "{user_list}", with: peersText)
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextContactsAndPremiumMultipleUsers(Int32(extraCount)).replacingOccurrences(of: "{user_list}", with: peersText)
|
||||
}
|
||||
} else {
|
||||
if case let .channel(channel) = peer, case .broadcast = channel.info {
|
||||
text = environment.strings.SendInviteLink_ChannelTextContactsAndPremiumOneUser(peersText).string
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextContactsAndPremiumOneUser(peersText).string
|
||||
}
|
||||
peersText.append(peersTextArray[i])
|
||||
}
|
||||
}
|
||||
|
||||
if extraCount >= 1 {
|
||||
if case let .channel(channel) = component.peer, case .broadcast = channel.info {
|
||||
text = environment.strings.SendInviteLink_ChannelTextContactsAndPremiumMultipleUsers(Int32(extraCount)).replacingOccurrences(of: "{user_list}", with: peersText)
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextContactsAndPremiumMultipleUsers(Int32(extraCount)).replacingOccurrences(of: "{user_list}", with: peersText)
|
||||
}
|
||||
case .groupCall:
|
||||
if premiumRestrictedUsers.count == 1 {
|
||||
text = environment.strings.SendInviteLink_TextCallsRestrictedOneUser(premiumRestrictedUsers[0].peer.compactDisplayTitle).string
|
||||
} else {
|
||||
if case let .channel(channel) = component.peer, case .broadcast = channel.info {
|
||||
text = environment.strings.SendInviteLink_ChannelTextContactsAndPremiumOneUser(peersText).string
|
||||
let extraCount = premiumRestrictedUsers.count - 3
|
||||
|
||||
var peersTextArray: [String] = []
|
||||
for i in 0 ..< min(3, premiumRestrictedUsers.count) {
|
||||
peersTextArray.append("**\(premiumRestrictedUsers[i].peer.compactDisplayTitle)**")
|
||||
}
|
||||
|
||||
var peersText = ""
|
||||
if #available(iOS 13.0, *) {
|
||||
let listFormatter = ListFormatter()
|
||||
listFormatter.locale = localeWithStrings(environment.strings)
|
||||
if let value = listFormatter.string(from: peersTextArray) {
|
||||
peersText = value
|
||||
}
|
||||
}
|
||||
if peersText.isEmpty {
|
||||
for i in 0 ..< peersTextArray.count {
|
||||
if i != 0 {
|
||||
peersText.append(", ")
|
||||
}
|
||||
peersText.append(peersTextArray[i])
|
||||
}
|
||||
}
|
||||
|
||||
if extraCount >= 1 {
|
||||
text = environment.strings.SendInviteLink_TextCallsRestrictedMultipleUsers(Int32(extraCount)).replacingOccurrences(of: "{user_list}", with: peersText)
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextContactsAndPremiumOneUser(peersText).string
|
||||
text = environment.strings.SendInviteLink_TextCallsRestrictedOneUser(peersText).string
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -693,11 +734,19 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
actionButton = ComponentView()
|
||||
self.actionButton = actionButton
|
||||
}
|
||||
|
||||
let titleText: String
|
||||
switch component.subject {
|
||||
case let .chat(_, link):
|
||||
titleText = link != nil ? environment.strings.SendInviteLink_InviteTitle : environment.strings.SendInviteLink_LinkUnavailableTitle
|
||||
case .groupCall:
|
||||
titleText = environment.strings.SendInviteLink_InviteTitle
|
||||
}
|
||||
|
||||
let titleSize = title.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: component.link != nil ? environment.strings.SendInviteLink_InviteTitle : environment.strings.SendInviteLink_LinkUnavailableTitle, font: Font.semibold(24.0), textColor: environment.theme.list.itemPrimaryTextColor))
|
||||
text: .plain(NSAttributedString(string: titleText, font: Font.semibold(24.0), textColor: environment.theme.list.itemPrimaryTextColor))
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - leftButtonFrame.maxX * 2.0, height: 100.0)
|
||||
@ -714,30 +763,35 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
contentHeight += 8.0
|
||||
|
||||
let text: String
|
||||
if !premiumRestrictedUsers.isEmpty {
|
||||
if component.link != nil {
|
||||
text = environment.strings.SendInviteLink_TextSendInviteLink
|
||||
} else {
|
||||
if component.peers.count == 1 {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableSingleUser(component.peers[0].peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)).string
|
||||
switch component.subject {
|
||||
case let .chat(_, link):
|
||||
if !premiumRestrictedUsers.isEmpty {
|
||||
if link != nil {
|
||||
text = environment.strings.SendInviteLink_TextSendInviteLink
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableMultipleUsers(Int32(component.peers.count))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if component.link != nil {
|
||||
if component.peers.count == 1 {
|
||||
text = environment.strings.SendInviteLink_TextAvailableSingleUser(component.peers[0].peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)).string
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextAvailableMultipleUsers(Int32(component.peers.count))
|
||||
if component.peers.count == 1 {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableSingleUser(component.peers[0].peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)).string
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableMultipleUsers(Int32(component.peers.count))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if component.peers.count == 1 {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableSingleUser(component.peers[0].peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)).string
|
||||
if link != nil {
|
||||
if component.peers.count == 1 {
|
||||
text = environment.strings.SendInviteLink_TextAvailableSingleUser(component.peers[0].peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)).string
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextAvailableMultipleUsers(Int32(component.peers.count))
|
||||
}
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableMultipleUsers(Int32(component.peers.count))
|
||||
if component.peers.count == 1 {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableSingleUser(component.peers[0].peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)).string
|
||||
} else {
|
||||
text = environment.strings.SendInviteLink_TextUnavailableMultipleUsers(Int32(component.peers.count))
|
||||
}
|
||||
}
|
||||
}
|
||||
case .groupCall:
|
||||
text = environment.strings.SendInviteLink_TextCallsRestrictedSendInviteLink
|
||||
}
|
||||
|
||||
let body = MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemPrimaryTextColor)
|
||||
@ -793,7 +847,13 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
}
|
||||
|
||||
let itemSubtitle: PeerListItemComponent.Subtitle
|
||||
let canBeSelected = component.link != nil && !peer.premiumRequiredToContact
|
||||
let canBeSelected : Bool
|
||||
switch component.subject {
|
||||
case let .chat(_, link):
|
||||
canBeSelected = link != nil && !peer.premiumRequiredToContact
|
||||
case .groupCall:
|
||||
canBeSelected = true
|
||||
}
|
||||
if peer.premiumRequiredToContact {
|
||||
itemSubtitle = .text(text: environment.strings.SendInviteLink_StatusAvailableToPremiumOnly, icon: .lock)
|
||||
} else {
|
||||
@ -862,16 +922,24 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
initialContentHeight += 24.0
|
||||
|
||||
let actionButtonTitle: String
|
||||
if component.link != nil {
|
||||
actionButtonTitle = self.selectedItems.isEmpty ? environment.strings.SendInviteLink_ActionSkip : environment.strings.SendInviteLink_ActionInvite
|
||||
} else {
|
||||
actionButtonTitle = environment.strings.SendInviteLink_ActionClose
|
||||
let actionButtonBadge: String?
|
||||
switch component.subject {
|
||||
case let.chat(_, link):
|
||||
if link != nil {
|
||||
actionButtonTitle = self.selectedItems.isEmpty ? environment.strings.SendInviteLink_ActionSkip : environment.strings.SendInviteLink_ActionInvite
|
||||
} else {
|
||||
actionButtonTitle = environment.strings.SendInviteLink_ActionClose
|
||||
}
|
||||
actionButtonBadge = (self.selectedItems.isEmpty || link == nil) ? nil : "\(self.selectedItems.count)"
|
||||
case .groupCall:
|
||||
actionButtonTitle = environment.strings.SendInviteLink_ActionInvite
|
||||
actionButtonBadge = self.selectedItems.isEmpty ? nil : "\(self.selectedItems.count)"
|
||||
}
|
||||
let actionButtonSize = actionButton.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(SolidRoundedButtonComponent(
|
||||
title: actionButtonTitle,
|
||||
badge: (self.selectedItems.isEmpty || component.link == nil) ? nil : "\(self.selectedItems.count)",
|
||||
badge: actionButtonBadge,
|
||||
theme: SolidRoundedButtonComponent.Theme(theme: environment.theme),
|
||||
font: .bold,
|
||||
fontSize: 17.0,
|
||||
@ -885,9 +953,18 @@ private final class SendInviteLinkScreenComponent: Component {
|
||||
guard let self, let component = self.component, let controller = self.environment?.controller() else {
|
||||
return
|
||||
}
|
||||
|
||||
let link: String?
|
||||
switch component.subject {
|
||||
case let .chat(_, linkValue):
|
||||
link = linkValue
|
||||
case let .groupCall(linkValue):
|
||||
link = linkValue
|
||||
}
|
||||
|
||||
if self.selectedItems.isEmpty {
|
||||
controller.dismiss()
|
||||
} else if let link = component.link {
|
||||
} else if let link {
|
||||
let selectedPeers = component.peers.filter { self.selectedItems.contains($0.peer.id) }
|
||||
|
||||
self.presentPaidMessageAlertIfNeeded(
|
||||
@ -1012,15 +1089,21 @@ public class SendInviteLinkScreen: ViewControllerComponentContainer {
|
||||
|
||||
private var presenceDisposable: Disposable?
|
||||
|
||||
public init(context: AccountContext, peer: EnginePeer, link: String?, peers: [TelegramForbiddenInvitePeer]) {
|
||||
public init(context: AccountContext, subject: SendInviteLinkScreenSubject, peers: [TelegramForbiddenInvitePeer], theme: PresentationTheme? = nil) {
|
||||
self.context = context
|
||||
|
||||
var link = link
|
||||
if link == nil, let addressName = peer.addressName {
|
||||
link = "https://t.me/\(addressName)"
|
||||
switch subject {
|
||||
case let .chat(peer, link):
|
||||
var link = link
|
||||
if link == nil, let addressName = peer.addressName {
|
||||
link = "https://t.me/\(addressName)"
|
||||
}
|
||||
self.link = link
|
||||
case let .groupCall(link):
|
||||
self.link = link
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG && false
|
||||
var peers = peers
|
||||
|
||||
if !"".isEmpty {
|
||||
@ -1136,10 +1219,9 @@ public class SendInviteLinkScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
#endif
|
||||
|
||||
self.link = link
|
||||
self.peers = peers
|
||||
|
||||
super.init(context: context, component: SendInviteLinkScreenComponent(context: context, peer: peer, link: link, peers: peers, peerPresences: [:], sendPaidMessageStars: [:]), navigationBarAppearance: .none)
|
||||
super.init(context: context, component: SendInviteLinkScreenComponent(context: context, subject: subject, peers: peers, peerPresences: [:], sendPaidMessageStars: [:]), navigationBarAppearance: .none, theme: theme.flatMap { .custom($0) } ?? .default)
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
self.navigationPresentation = .flatModal
|
||||
@ -1169,7 +1251,7 @@ public class SendInviteLinkScreen: ViewControllerComponentContainer {
|
||||
parsedSendPaidMessageStars[id] = sendPaidMessageStars
|
||||
}
|
||||
}
|
||||
self.updateComponent(component: AnyComponent(SendInviteLinkScreenComponent(context: context, peer: peer, link: link, peers: peers, peerPresences: parsedPresences, sendPaidMessageStars: parsedSendPaidMessageStars)), transition: .immediate)
|
||||
self.updateComponent(component: AnyComponent(SendInviteLinkScreenComponent(context: context, subject: subject, peers: peers, peerPresences: parsedPresences, sendPaidMessageStars: parsedSendPaidMessageStars)), transition: .immediate)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -2893,10 +2893,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard case let .conferenceCall(conferenceCall) = action?.action else {
|
||||
return
|
||||
}
|
||||
if conferenceCall.duration != nil {
|
||||
self.context.sharedContext.openCreateGroupCallUI(context: self.context, peerIds: conferenceCall.otherParticipants, parentController: self)
|
||||
return
|
||||
}
|
||||
|
||||
if let currentGroupCallController = self.context.sharedContext.currentGroupCallController as? VoiceChatController, case let .group(groupCall) = currentGroupCallController.call, let currentCallId = groupCall.callId, currentCallId == conferenceCall.callId {
|
||||
self.context.sharedContext.navigateToCurrentCall()
|
||||
|
||||
@ -2733,7 +2733,6 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
var messageIdsWithUnseenPersonalMention: [MessageId] = []
|
||||
var messageIdsWithUnseenReactions: [MessageId] = []
|
||||
var messageIdsWithInactiveExtendedMedia = Set<MessageId>()
|
||||
var messageIdsWithGroupCalls: [MessageId] = []
|
||||
var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = []
|
||||
var allVisibleAnchorMessageIds: [(MessageId, Int)] = []
|
||||
var visibleAdOpaqueIds: [Data] = []
|
||||
@ -2832,13 +2831,6 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
storiesRequiredValidation = true
|
||||
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, let _ = content.story {
|
||||
storiesRequiredValidation = true
|
||||
} else if let media = media as? TelegramMediaAction {
|
||||
if case let .conferenceCall(conferenceCall) = media.action {
|
||||
if conferenceCall.duration != nil {
|
||||
} else {
|
||||
messageIdsWithGroupCalls.append(message.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if contentRequiredValidation {
|
||||
@ -3096,9 +3088,6 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
if !peerIdsWithRefreshStories.isEmpty {
|
||||
self.context.account.viewTracker.refreshStoryStatsForPeerIds(peerIds: peerIdsWithRefreshStories)
|
||||
}
|
||||
if !messageIdsWithGroupCalls.isEmpty {
|
||||
self.inlineGroupCallsProcessingManager.add(messageIdsWithGroupCalls.map { MessageAndThreadId(messageId: $0, threadId: nil) })
|
||||
}
|
||||
|
||||
self.currentEarlierPrefetchMessages = toEarlierMediaMessages
|
||||
self.currentLaterPrefetchMessages = toLaterMediaMessages
|
||||
|
||||
@ -850,7 +850,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
|
||||
|> deliverOnMainQueue).start(next: { peer in
|
||||
if let peer, let exportedInvitation, let link = exportedInvitation.link {
|
||||
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, peer: peer, link: link, peers: result.result.forbiddenPeers)
|
||||
let inviteScreen = SendInviteLinkScreen(context: context, subject: .chat(peer: peer, link: link), peers: result.result.forbiddenPeers)
|
||||
controller?.push(inviteScreen)
|
||||
}
|
||||
})
|
||||
|
||||
@ -82,6 +82,8 @@ import JoinSubjectScreen
|
||||
import OldChannelsController
|
||||
import InviteLinksUI
|
||||
import GiftStoreScreen
|
||||
import SendInviteLinkScreen
|
||||
|
||||
|
||||
private final class AccountUserInterfaceInUseContext {
|
||||
let subscribers = Bag<(Bool) -> Void>()
|
||||
@ -3833,6 +3835,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
public func makeAccountFreezeInfoScreen(context: AccountContext) -> ViewController {
|
||||
return AccountFreezeInfoScreen(context: context)
|
||||
}
|
||||
|
||||
public func makeSendInviteLinkScreen(context: AccountContext, subject: SendInviteLinkScreenSubject, peers: [TelegramForbiddenInvitePeer], theme: PresentationTheme?) -> ViewController {
|
||||
return SendInviteLinkScreen(context: context, subject: subject, peers: peers, theme: theme)
|
||||
}
|
||||
}
|
||||
|
||||
private func peerInfoControllerImpl(context: AccountContext, updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, requestsContext: PeerInvitationImportersContext? = nil) -> ViewController? {
|
||||
|
||||
@ -217,7 +217,7 @@ final class OngoingGroupCallBroadcastPartTaskImpl: NSObject, OngoingGroupCallBro
|
||||
}
|
||||
|
||||
public protocol OngoingGroupCallEncryptionContext: AnyObject {
|
||||
func encrypt(message: Data) -> Data?
|
||||
func encrypt(message: Data, plaintextPrefixLength: Int) -> Data?
|
||||
func decrypt(message: Data, userId: Int64) -> Data?
|
||||
}
|
||||
|
||||
@ -645,9 +645,9 @@ public final class OngoingGroupCallContext {
|
||||
isConference: isConference,
|
||||
isActiveByDefault: audioIsActiveByDefault,
|
||||
encryptDecrypt: encryptionContext.flatMap { encryptionContext in
|
||||
return { data, userId, isEncrypt in
|
||||
return { data, userId, isEncrypt, plaintextPrefixLength in
|
||||
if isEncrypt {
|
||||
return encryptionContext.encrypt(message: data)
|
||||
return encryptionContext.encrypt(message: data, plaintextPrefixLength: Int(plaintextPrefixLength))
|
||||
} else {
|
||||
return encryptionContext.decrypt(message: data, userId: userId)
|
||||
}
|
||||
@ -755,9 +755,9 @@ public final class OngoingGroupCallContext {
|
||||
isConference: isConference,
|
||||
isActiveByDefault: audioIsActiveByDefault,
|
||||
encryptDecrypt: encryptionContext.flatMap { encryptionContext in
|
||||
return { data, userId, isEncrypt in
|
||||
return { data, userId, isEncrypt, plaintextPrefixLength in
|
||||
if isEncrypt {
|
||||
return encryptionContext.encrypt(message: data)
|
||||
return encryptionContext.encrypt(message: data, plaintextPrefixLength: Int(plaintextPrefixLength))
|
||||
} else {
|
||||
return encryptionContext.decrypt(message: data, userId: userId)
|
||||
}
|
||||
|
||||
@ -457,7 +457,7 @@ onMutedSpeechActivityDetected:(void (^ _Nullable)(bool))onMutedSpeechActivityDet
|
||||
audioDevice:(SharedCallAudioDevice * _Nullable)audioDevice
|
||||
isConference:(bool)isConference
|
||||
isActiveByDefault:(bool)isActiveByDefault
|
||||
encryptDecrypt:(NSData * _Nullable (^ _Nullable)(NSData * _Nonnull, int64_t, bool))encryptDecrypt;
|
||||
encryptDecrypt:(NSData * _Nullable (^ _Nullable)(NSData * _Nonnull, int64_t, bool, int32_t))encryptDecrypt;
|
||||
|
||||
- (void)stop:(void (^ _Nullable)())completion;
|
||||
|
||||
|
||||
@ -2389,7 +2389,7 @@ onMutedSpeechActivityDetected:(void (^ _Nullable)(bool))onMutedSpeechActivityDet
|
||||
audioDevice:(SharedCallAudioDevice * _Nullable)audioDevice
|
||||
isConference:(bool)isConference
|
||||
isActiveByDefault:(bool)isActiveByDefault
|
||||
encryptDecrypt:(NSData * _Nullable (^ _Nullable)(NSData * _Nonnull, int64_t, bool))encryptDecrypt {
|
||||
encryptDecrypt:(NSData * _Nullable (^ _Nullable)(NSData * _Nonnull, int64_t, bool, int32_t))encryptDecrypt {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queue = queue;
|
||||
@ -2458,12 +2458,12 @@ encryptDecrypt:(NSData * _Nullable (^ _Nullable)(NSData * _Nonnull, int64_t, boo
|
||||
|
||||
std::string statsLogPathValue(statsLogPath.length == 0 ? "" : statsLogPath.UTF8String);
|
||||
|
||||
std::function<std::vector<uint8_t>(std::vector<uint8_t> const &, int64_t, bool)> mappedEncryptDecrypt;
|
||||
std::function<std::vector<uint8_t>(std::vector<uint8_t> const &, int64_t, bool, int32_t)> mappedEncryptDecrypt;
|
||||
if (encryptDecrypt) {
|
||||
NSData * _Nullable (^encryptDecryptBlock)(NSData * _Nonnull, int64_t, bool) = [encryptDecrypt copy];
|
||||
mappedEncryptDecrypt = [encryptDecryptBlock](std::vector<uint8_t> const &message, int64_t userId, bool isEncrypt) -> std::vector<uint8_t> {
|
||||
NSData * _Nullable (^encryptDecryptBlock)(NSData * _Nonnull, int64_t, bool, int32_t) = [encryptDecrypt copy];
|
||||
mappedEncryptDecrypt = [encryptDecryptBlock](std::vector<uint8_t> const &message, int64_t userId, bool isEncrypt, int32_t plaintextPrefixLength) -> std::vector<uint8_t> {
|
||||
NSData *mappedMessage = [[NSData alloc] initWithBytes:message.data() length:message.size()];
|
||||
NSData *result = encryptDecryptBlock(mappedMessage, userId, isEncrypt);
|
||||
NSData *result = encryptDecryptBlock(mappedMessage, userId, isEncrypt, plaintextPrefixLength);
|
||||
if (!result) {
|
||||
return std::vector<uint8_t>();
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (nullable NSData *)generateRemoveParticipantsBlock:(NSArray<NSNumber *> *)participantIds;
|
||||
|
||||
- (nullable NSData *)encrypt:(NSData *)message channelId:(int32_t)channelId;
|
||||
- (nullable NSData *)encrypt:(NSData *)message channelId:(int32_t)channelId plaintextPrefixLength:(NSInteger)plaintextPrefixLength;
|
||||
- (nullable NSData *)decrypt:(NSData *)message userId:(int64_t)userId;
|
||||
|
||||
@end
|
||||
|
||||
@ -101,6 +101,42 @@ class ok final : public Object {
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class e2e_callPacket final : public Object {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static const std::int32_t ID = 1084669673;
|
||||
|
||||
static object_ptr<e2e_callPacket> fetch(TlParser &p);
|
||||
|
||||
void store(TlStorerCalcLength &s) const final;
|
||||
|
||||
void store(TlStorerUnsafe &s) const final;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class e2e_callPacketLargeMsgId final : public Object {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static const std::int32_t ID = 484797485;
|
||||
|
||||
static object_ptr<e2e_callPacketLargeMsgId> fetch(TlParser &p);
|
||||
|
||||
void store(TlStorerCalcLength &s) const final;
|
||||
|
||||
void store(TlStorerUnsafe &s) const final;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class e2e_HandshakePrivate: public Object {
|
||||
public:
|
||||
|
||||
|
||||
@ -852,6 +852,23 @@ class authorizationStateWaitPhoneNumber final : public AuthorizationState {
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class authorizationStateWaitPremiumPurchase final : public AuthorizationState {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
string store_product_id_;
|
||||
|
||||
authorizationStateWaitPremiumPurchase();
|
||||
|
||||
explicit authorizationStateWaitPremiumPurchase(string const &store_product_id_);
|
||||
|
||||
static const std::int32_t ID = -862487743;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class authorizationStateWaitEmailAddress final : public AuthorizationState {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
@ -8687,6 +8704,7 @@ class forumTopic final : public Object {
|
||||
public:
|
||||
object_ptr<forumTopicInfo> info_;
|
||||
object_ptr<message> last_message_;
|
||||
int64 order_;
|
||||
bool is_pinned_;
|
||||
int32 unread_count_;
|
||||
int53 last_read_inbox_message_id_;
|
||||
@ -8698,9 +8716,9 @@ class forumTopic final : public Object {
|
||||
|
||||
forumTopic();
|
||||
|
||||
forumTopic(object_ptr<forumTopicInfo> &&info_, object_ptr<message> &&last_message_, bool is_pinned_, int32 unread_count_, int53 last_read_inbox_message_id_, int53 last_read_outbox_message_id_, int32 unread_mention_count_, int32 unread_reaction_count_, object_ptr<chatNotificationSettings> &¬ification_settings_, object_ptr<draftMessage> &&draft_message_);
|
||||
forumTopic(object_ptr<forumTopicInfo> &&info_, object_ptr<message> &&last_message_, int64 order_, bool is_pinned_, int32 unread_count_, int53 last_read_inbox_message_id_, int53 last_read_outbox_message_id_, int32 unread_mention_count_, int32 unread_reaction_count_, object_ptr<chatNotificationSettings> &¬ification_settings_, object_ptr<draftMessage> &&draft_message_);
|
||||
|
||||
static const std::int32_t ID = 303279334;
|
||||
static const std::int32_t ID = -2094608976;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
@ -8733,6 +8751,7 @@ class forumTopicInfo final : public Object {
|
||||
}
|
||||
|
||||
public:
|
||||
int53 chat_id_;
|
||||
int53 message_thread_id_;
|
||||
string name_;
|
||||
object_ptr<forumTopicIcon> icon_;
|
||||
@ -8745,9 +8764,9 @@ class forumTopicInfo final : public Object {
|
||||
|
||||
forumTopicInfo();
|
||||
|
||||
forumTopicInfo(int53 message_thread_id_, string const &name_, object_ptr<forumTopicIcon> &&icon_, int32 creation_date_, object_ptr<MessageSender> &&creator_id_, bool is_general_, bool is_outgoing_, bool is_closed_, bool is_hidden_);
|
||||
forumTopicInfo(int53 chat_id_, int53 message_thread_id_, string const &name_, object_ptr<forumTopicIcon> &&icon_, int32 creation_date_, object_ptr<MessageSender> &&creator_id_, bool is_general_, bool is_outgoing_, bool is_closed_, bool is_hidden_);
|
||||
|
||||
static const std::int32_t ID = -1879842914;
|
||||
static const std::int32_t ID = -654857606;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
@ -26213,6 +26232,46 @@ class storePaymentPurposeGiftedStars final : public StorePaymentPurpose {
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class StoreTransaction: public Object {
|
||||
public:
|
||||
};
|
||||
|
||||
class storeTransactionAppStore final : public StoreTransaction {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
bytes receipt_;
|
||||
|
||||
storeTransactionAppStore();
|
||||
|
||||
explicit storeTransactionAppStore(bytes const &receipt_);
|
||||
|
||||
static const std::int32_t ID = 1625562441;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class storeTransactionGooglePlay final : public StoreTransaction {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
string package_name_;
|
||||
string store_product_id_;
|
||||
string purchase_token_;
|
||||
|
||||
storeTransactionGooglePlay();
|
||||
|
||||
storeTransactionGooglePlay(string const &package_name_, string const &store_product_id_, string const &purchase_token_);
|
||||
|
||||
static const std::int32_t ID = 1094018617;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class story;
|
||||
|
||||
class stories final : public Object {
|
||||
@ -29909,14 +29968,34 @@ class updateForumTopicInfo final : public Update {
|
||||
}
|
||||
|
||||
public:
|
||||
int53 chat_id_;
|
||||
object_ptr<forumTopicInfo> info_;
|
||||
|
||||
updateForumTopicInfo();
|
||||
|
||||
updateForumTopicInfo(int53 chat_id_, object_ptr<forumTopicInfo> &&info_);
|
||||
explicit updateForumTopicInfo(object_ptr<forumTopicInfo> &&info_);
|
||||
|
||||
static const std::int32_t ID = 1802448073;
|
||||
static const std::int32_t ID = 1420762696;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class updateForumTopic final : public Update {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
int53 chat_id_;
|
||||
int53 message_thread_id_;
|
||||
bool is_pinned_;
|
||||
int53 last_read_outbox_message_id_;
|
||||
object_ptr<chatNotificationSettings> notification_settings_;
|
||||
|
||||
updateForumTopic();
|
||||
|
||||
updateForumTopic(int53 chat_id_, int53 message_thread_id_, bool is_pinned_, int53 last_read_outbox_message_id_, object_ptr<chatNotificationSettings> &¬ification_settings_);
|
||||
|
||||
static const std::int32_t ID = 807069971;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
@ -33817,48 +33896,24 @@ class applyPremiumGiftCode final : public Function {
|
||||
|
||||
class StorePaymentPurpose;
|
||||
|
||||
class StoreTransaction;
|
||||
|
||||
class ok;
|
||||
|
||||
class assignAppStoreTransaction final : public Function {
|
||||
class assignStoreTransaction final : public Function {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
bytes receipt_;
|
||||
object_ptr<StoreTransaction> transaction_;
|
||||
object_ptr<StorePaymentPurpose> purpose_;
|
||||
|
||||
assignAppStoreTransaction();
|
||||
assignStoreTransaction();
|
||||
|
||||
assignAppStoreTransaction(bytes const &receipt_, object_ptr<StorePaymentPurpose> &&purpose_);
|
||||
assignStoreTransaction(object_ptr<StoreTransaction> &&transaction_, object_ptr<StorePaymentPurpose> &&purpose_);
|
||||
|
||||
static const std::int32_t ID = -2030892112;
|
||||
|
||||
using ReturnType = object_ptr<ok>;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class StorePaymentPurpose;
|
||||
|
||||
class ok;
|
||||
|
||||
class assignGooglePlayTransaction final : public Function {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
string package_name_;
|
||||
string store_product_id_;
|
||||
string purchase_token_;
|
||||
object_ptr<StorePaymentPurpose> purpose_;
|
||||
|
||||
assignGooglePlayTransaction();
|
||||
|
||||
assignGooglePlayTransaction(string const &package_name_, string const &store_product_id_, string const &purchase_token_, object_ptr<StorePaymentPurpose> &&purpose_);
|
||||
|
||||
static const std::int32_t ID = -1992704860;
|
||||
static const std::int32_t ID = -2046202900;
|
||||
|
||||
using ReturnType = object_ptr<ok>;
|
||||
|
||||
@ -34274,6 +34329,28 @@ class checkAuthenticationPasswordRecoveryCode final : public Function {
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class ok;
|
||||
|
||||
class checkAuthenticationPremiumPurchase final : public Function {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
string currency_;
|
||||
int53 amount_;
|
||||
|
||||
checkAuthenticationPremiumPurchase();
|
||||
|
||||
checkAuthenticationPremiumPurchase(string const ¤cy_, int53 amount_);
|
||||
|
||||
static const std::int32_t ID = 1588959934;
|
||||
|
||||
using ReturnType = object_ptr<ok>;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class chatFolderInviteLinkInfo;
|
||||
|
||||
class checkChatFolderInviteLink final : public Function {
|
||||
@ -47427,6 +47504,32 @@ class setAuthenticationPhoneNumber final : public Function {
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class StoreTransaction;
|
||||
|
||||
class ok;
|
||||
|
||||
class setAuthenticationPremiumPurchaseTransaction final : public Function {
|
||||
std::int32_t get_id() const final {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
object_ptr<StoreTransaction> transaction_;
|
||||
bool is_restore_;
|
||||
string currency_;
|
||||
int53 amount_;
|
||||
|
||||
setAuthenticationPremiumPurchaseTransaction();
|
||||
|
||||
setAuthenticationPremiumPurchaseTransaction(object_ptr<StoreTransaction> &&transaction_, bool is_restore_, string const ¤cy_, int53 amount_);
|
||||
|
||||
static const std::int32_t ID = -450986887;
|
||||
|
||||
using ReturnType = object_ptr<ok>;
|
||||
|
||||
void store(TlStorerToString &s, const char *field_name) const final;
|
||||
};
|
||||
|
||||
class NetworkType;
|
||||
|
||||
class autoDownloadSettings;
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
namespace td {
|
||||
namespace td_api {
|
||||
|
||||
void to_json(JsonValueScope &jv, const tl_object_ptr<Object> &value);
|
||||
void to_json(JsonValueScope &jv, const td_api::object_ptr<Object> &value);
|
||||
|
||||
Status from_json(tl_object_ptr<Function> &to, td::JsonValue from);
|
||||
Status from_json(td_api::object_ptr<Function> &to, td::JsonValue from);
|
||||
|
||||
void to_json(JsonValueScope &jv, const Object &object);
|
||||
|
||||
@ -166,6 +166,8 @@ Result<int32> tl_constructor_from_string(td_api::StickerType *object, const std:
|
||||
|
||||
Result<int32> tl_constructor_from_string(td_api::StorePaymentPurpose *object, const std::string &str);
|
||||
|
||||
Result<int32> tl_constructor_from_string(td_api::StoreTransaction *object, const std::string &str);
|
||||
|
||||
Result<int32> tl_constructor_from_string(td_api::StoryList *object, const std::string &str);
|
||||
|
||||
Result<int32> tl_constructor_from_string(td_api::StoryPrivacySettings *object, const std::string &str);
|
||||
@ -1294,6 +1296,10 @@ Status from_json(td_api::storePaymentPurposeStars &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::storePaymentPurposeGiftedStars &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::storeTransactionAppStore &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::storeTransactionGooglePlay &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::storyAreaPosition &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::storyFullId &to, JsonObject &from);
|
||||
@ -1580,9 +1586,7 @@ Status from_json(td_api::answerWebAppQuery &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::applyPremiumGiftCode &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::assignAppStoreTransaction &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::assignGooglePlayTransaction &to, JsonObject &from);
|
||||
Status from_json(td_api::assignStoreTransaction &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::banChatMember &to, JsonObject &from);
|
||||
|
||||
@ -1622,6 +1626,8 @@ Status from_json(td_api::checkAuthenticationPassword &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::checkAuthenticationPasswordRecoveryCode &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::checkAuthenticationPremiumPurchase &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::checkChatFolderInviteLink &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::checkChatInviteLink &to, JsonObject &from);
|
||||
@ -2800,6 +2806,8 @@ Status from_json(td_api::setAuthenticationEmailAddress &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::setAuthenticationPhoneNumber &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::setAuthenticationPremiumPurchaseTransaction &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::setAutoDownloadSettings &to, JsonObject &from);
|
||||
|
||||
Status from_json(td_api::setAutosaveSettings &to, JsonObject &from);
|
||||
@ -3264,6 +3272,8 @@ void to_json(JsonValueScope &jv, const td_api::authorizationStateWaitTdlibParame
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::authorizationStateWaitPhoneNumber &object);
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::authorizationStateWaitPremiumPurchase &object);
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::authorizationStateWaitEmailAddress &object);
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::authorizationStateWaitEmailCode &object);
|
||||
@ -6140,6 +6150,8 @@ void to_json(JsonValueScope &jv, const td_api::updateQuickReplyShortcutMessages
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::updateForumTopicInfo &object);
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::updateForumTopic &object);
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::updateScopeNotificationSettings &object);
|
||||
|
||||
void to_json(JsonValueScope &jv, const td_api::updateReactionNotificationSettings &object);
|
||||
|
||||
@ -33,31 +33,57 @@ class AuthManager final : public NetActor {
|
||||
}
|
||||
|
||||
bool is_authorized() const;
|
||||
|
||||
bool was_authorized() const;
|
||||
|
||||
void get_state(uint64 query_id);
|
||||
|
||||
void set_phone_number(uint64 query_id, string phone_number,
|
||||
td_api::object_ptr<td_api::phoneNumberAuthenticationSettings> settings);
|
||||
|
||||
void check_premium_purchase(uint64 query_id, string currency, int64 amount);
|
||||
|
||||
void set_premium_purchase_transaction(uint64 query_id, td_api::object_ptr<td_api::StoreTransaction> &&transaction,
|
||||
bool is_restore, string currency, int64 amount);
|
||||
|
||||
void set_firebase_token(uint64 query_id, string token);
|
||||
|
||||
void report_missing_code(uint64 query_id, string mobile_network_code);
|
||||
|
||||
void set_email_address(uint64 query_id, string email_address);
|
||||
|
||||
void resend_authentication_code(uint64 query_id, td_api::object_ptr<td_api::ResendCodeReason> &&reason);
|
||||
|
||||
void check_email_code(uint64 query_id, EmailVerification &&code);
|
||||
|
||||
void reset_email_address(uint64 query_id);
|
||||
|
||||
void check_code(uint64 query_id, string code);
|
||||
|
||||
void register_user(uint64 query_id, string first_name, string last_name, bool disable_notification);
|
||||
|
||||
void request_qr_code_authentication(uint64 query_id, vector<UserId> other_user_ids);
|
||||
|
||||
void check_bot_token(uint64 query_id, string bot_token);
|
||||
|
||||
void check_password(uint64 query_id, string password);
|
||||
|
||||
void request_password_recovery(uint64 query_id);
|
||||
|
||||
void check_password_recovery_code(uint64 query_id, string code);
|
||||
|
||||
void recover_password(uint64 query_id, string code, string new_password, string new_hint);
|
||||
|
||||
void log_out(uint64 query_id);
|
||||
|
||||
void delete_account(uint64 query_id, string reason, string password);
|
||||
|
||||
void on_update_login_token();
|
||||
|
||||
void on_update_sent_code(telegram_api::object_ptr<telegram_api::auth_SentCode> &&sent_code_ptr);
|
||||
|
||||
void on_authorization_lost(string source);
|
||||
|
||||
void on_closing(bool destroy_flag);
|
||||
|
||||
// can return nullptr if state isn't initialized yet
|
||||
@ -69,6 +95,7 @@ class AuthManager final : public NetActor {
|
||||
enum class State : int32 {
|
||||
None,
|
||||
WaitPhoneNumber,
|
||||
WaitPremiumPurchase,
|
||||
WaitCode,
|
||||
WaitQrCodeConfirmation,
|
||||
WaitPassword,
|
||||
@ -86,6 +113,8 @@ class AuthManager final : public NetActor {
|
||||
SignIn,
|
||||
SignUp,
|
||||
SendCode,
|
||||
CheckPremiumPurchase,
|
||||
SetPremiumPurchaseTransaction,
|
||||
SendEmailCode,
|
||||
VerifyEmailAddress,
|
||||
ResetEmailAddress,
|
||||
@ -133,6 +162,9 @@ class AuthManager final : public NetActor {
|
||||
int32 api_id_;
|
||||
string api_hash_;
|
||||
|
||||
// State::WaitPremiumPurchase
|
||||
string store_product_id_;
|
||||
|
||||
// State::WaitEmailAddress
|
||||
bool allow_apple_id_ = false;
|
||||
bool allow_google_id_ = false;
|
||||
@ -204,6 +236,8 @@ class AuthManager final : public NetActor {
|
||||
void on_sent_code(telegram_api::object_ptr<telegram_api::auth_SentCode> &&sent_code_ptr);
|
||||
|
||||
void on_send_code_result(NetQueryPtr &&net_query);
|
||||
void on_check_premium_purchase_result(NetQueryPtr &&net_query);
|
||||
void on_set_premium_purchase_transaction_result(NetQueryPtr &&net_query);
|
||||
void on_send_email_code_result(NetQueryPtr &&net_query);
|
||||
void on_verify_email_address_result(NetQueryPtr &&net_query);
|
||||
void on_reset_email_address_result(NetQueryPtr &&net_query);
|
||||
|
||||
@ -222,8 +222,9 @@ class BusinessConnectionManager final : public Actor {
|
||||
|
||||
void do_send_message_album(int64 request_id, BusinessConnectionId business_connection_id, DialogId dialog_id,
|
||||
MessageInputReplyTo &&input_reply_to, bool disable_notification, bool protect_content,
|
||||
MessageEffectId effect_id, vector<InputMessageContent> &&message_contents,
|
||||
Promise<td_api::object_ptr<td_api::businessMessages>> &&promise);
|
||||
MessageEffectId effect_id, vector<InputMessageContent> &&message_contents);
|
||||
|
||||
void fail_send_message_album(int64 request_id, Status error);
|
||||
|
||||
void on_upload_message_album_media(int64 request_id, size_t media_pos, Result<UploadMediaResult> &&result);
|
||||
|
||||
|
||||
@ -183,7 +183,7 @@ class CallActor final : public NetQueryCallback {
|
||||
Status do_update_call(const telegram_api::phoneCallWaiting &call);
|
||||
Status do_update_call(const telegram_api::phoneCallRequested &call);
|
||||
Status do_update_call(const telegram_api::phoneCallAccepted &call);
|
||||
Status do_update_call(const telegram_api::phoneCall &call);
|
||||
Status do_update_call(telegram_api::phoneCall &call);
|
||||
Status do_update_call(const telegram_api::phoneCallDiscarded &call);
|
||||
|
||||
void on_get_call_id();
|
||||
|
||||
@ -45,15 +45,24 @@ class DialogDate {
|
||||
int64 get_order() const {
|
||||
return order;
|
||||
}
|
||||
|
||||
DialogId get_dialog_id() const {
|
||||
return dialog_id;
|
||||
}
|
||||
|
||||
int32 get_date() const {
|
||||
return static_cast<int32>((order >> 32) & 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
MessageId get_message_id() const {
|
||||
return MessageId(ServerMessageId(static_cast<int32>(order & 0x7FFFFFFF)));
|
||||
}
|
||||
|
||||
static int64 get_dialog_order(MessageId message_id, int32 message_date) {
|
||||
CHECK(!message_id.is_scheduled());
|
||||
return (static_cast<int64>(message_date) << 32) +
|
||||
message_id.get_prev_server_message_id().get_server_message_id().get();
|
||||
}
|
||||
};
|
||||
|
||||
const DialogDate MIN_DIALOG_DATE(std::numeric_limits<int64>::max(), DialogId());
|
||||
|
||||
@ -117,7 +117,7 @@ class DialogInviteLinkManager final : public Actor {
|
||||
vector<UserId> participant_user_ids;
|
||||
string description;
|
||||
StarSubscriptionPricing subscription_pricing;
|
||||
int64 subscription_form_id;
|
||||
int64 subscription_form_id = 0;
|
||||
CustomEmojiId bot_verification_icon;
|
||||
bool creates_join_request = false;
|
||||
bool can_refulfill_subscription = false;
|
||||
|
||||
@ -32,6 +32,8 @@ class ForumTopic {
|
||||
DialogNotificationSettings notification_settings_;
|
||||
unique_ptr<DraftMessage> draft_message_;
|
||||
|
||||
int64 get_forum_topic_order(Td *td, DialogId dialog_id) const;
|
||||
|
||||
public:
|
||||
ForumTopic() = default;
|
||||
|
||||
@ -65,6 +67,9 @@ class ForumTopic {
|
||||
td_api::object_ptr<td_api::forumTopic> get_forum_topic_object(Td *td, DialogId dialog_id,
|
||||
const ForumTopicInfo &info) const;
|
||||
|
||||
td_api::object_ptr<td_api::updateForumTopic> get_update_forum_topic_object(Td *td, DialogId dialog_id,
|
||||
MessageId top_thread_message_id) const;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ class ForumTopicInfo {
|
||||
|
||||
bool apply_edited_data(const ForumTopicEditedData &edited_data);
|
||||
|
||||
td_api::object_ptr<td_api::forumTopicInfo> get_forum_topic_info_object(Td *td) const;
|
||||
td_api::object_ptr<td_api::forumTopicInfo> get_forum_topic_info_object(Td *td, DialogId dialog_id) const;
|
||||
|
||||
template <class StorerT>
|
||||
void store(StorerT &storer) const;
|
||||
|
||||
@ -177,11 +177,18 @@ class ForumTopicManager final : public Actor {
|
||||
|
||||
void on_delete_forum_topic(DialogId dialog_id, MessageId top_thread_message_id, Promise<Unit> &&promise);
|
||||
|
||||
td_api::object_ptr<td_api::updateForumTopicInfo> get_update_forum_topic_info(DialogId dialog_id,
|
||||
const ForumTopicInfo *topic_info) const;
|
||||
td_api::object_ptr<td_api::updateForumTopicInfo> get_update_forum_topic_info_object(
|
||||
DialogId dialog_id, const ForumTopicInfo *topic_info) const;
|
||||
|
||||
void send_update_forum_topic_info(DialogId dialog_id, const ForumTopicInfo *topic_info) const;
|
||||
|
||||
td_api::object_ptr<td_api::updateForumTopic> get_update_forum_topic_object(DialogId dialog_id,
|
||||
const Topic *topic) const;
|
||||
|
||||
void send_update_forum_topic(DialogId dialog_id, const Topic *topic) const;
|
||||
|
||||
void on_forum_topic_changed(DialogId dialog_id, Topic *topic);
|
||||
|
||||
void save_topic_to_database(DialogId dialog_id, const Topic *topic);
|
||||
|
||||
void delete_topic_from_database(DialogId dialog_id, MessageId top_thread_message_id, Promise<Unit> &&promise);
|
||||
|
||||
@ -87,8 +87,8 @@ struct InputMessageContent {
|
||||
struct InlineMessageContent {
|
||||
unique_ptr<MessageContent> message_content;
|
||||
unique_ptr<ReplyMarkup> message_reply_markup;
|
||||
bool disable_web_page_preview;
|
||||
bool invert_media;
|
||||
bool disable_web_page_preview = false;
|
||||
bool invert_media = false;
|
||||
};
|
||||
|
||||
void store_message_content(const MessageContent *content, LogEventStorerCalcLength &storer);
|
||||
|
||||
@ -533,6 +533,8 @@ class MessagesManager final : public Actor {
|
||||
|
||||
vector<DialogId> sort_dialogs_by_order(const vector<DialogId> &dialog_ids, int32 limit) const;
|
||||
|
||||
int64 get_message_order(DialogId dialog_id, MessageId message_id) const;
|
||||
|
||||
void block_message_sender_from_replies(MessageId message_id, bool need_delete_message, bool need_delete_all_messages,
|
||||
bool report_spam, Promise<Unit> &&promise);
|
||||
|
||||
@ -562,10 +564,10 @@ class MessagesManager final : public Actor {
|
||||
void get_messages(DialogId dialog_id, const vector<MessageId> &message_ids, Promise<Unit> &&promise);
|
||||
|
||||
void get_message_from_server(MessageFullId message_full_id, Promise<Unit> &&promise, const char *source,
|
||||
tl_object_ptr<telegram_api::InputMessage> input_message = nullptr);
|
||||
telegram_api::object_ptr<telegram_api::InputMessage> input_message = nullptr);
|
||||
|
||||
void get_messages_from_server(vector<MessageFullId> &&message_ids, Promise<Unit> &&promise, const char *source,
|
||||
tl_object_ptr<telegram_api::InputMessage> input_message = nullptr);
|
||||
telegram_api::object_ptr<telegram_api::InputMessage> input_message = nullptr);
|
||||
|
||||
void get_message_properties(DialogId dialog_id, MessageId message_id,
|
||||
Promise<td_api::object_ptr<td_api::messageProperties>> &&promise);
|
||||
@ -1816,9 +1818,9 @@ class MessagesManager final : public Actor {
|
||||
bool drop_author = false;
|
||||
bool drop_media_captions = false;
|
||||
|
||||
Dialog *from_dialog;
|
||||
Dialog *from_dialog = nullptr;
|
||||
MessageId top_thread_message_id;
|
||||
Dialog *to_dialog;
|
||||
Dialog *to_dialog = nullptr;
|
||||
MessageSendOptions message_send_options;
|
||||
};
|
||||
|
||||
@ -2841,8 +2843,6 @@ class MessagesManager final : public Actor {
|
||||
|
||||
static NotificationInfo *add_dialog_notification_info(Dialog *d);
|
||||
|
||||
static int64 get_dialog_order(MessageId message_id, int32 message_date);
|
||||
|
||||
bool is_dialog_sponsored(const Dialog *d) const;
|
||||
|
||||
int64 get_dialog_base_order(const Dialog *d) const;
|
||||
@ -3255,9 +3255,9 @@ class MessagesManager final : public Actor {
|
||||
|
||||
struct GetDialogsTask {
|
||||
DialogListId dialog_list_id;
|
||||
int64 dialog_list_unique_id;
|
||||
int32 limit;
|
||||
int32 retry_count;
|
||||
int64 dialog_list_unique_id = 0;
|
||||
int32 limit = 0;
|
||||
int32 retry_count = 5;
|
||||
DialogDate last_dialog_date = MIN_DIALOG_DATE;
|
||||
Promise<td_api::object_ptr<td_api::chats>> promise;
|
||||
};
|
||||
|
||||
@ -38,7 +38,7 @@ class PhoneNumberManager final : public Actor {
|
||||
void check_code(string code, Promise<Unit> &&promise);
|
||||
|
||||
private:
|
||||
enum class Type : int32 { ChangePhone, VerifyPhone, ConfirmPhone };
|
||||
enum class Type : int32 { None, ChangePhone, VerifyPhone, ConfirmPhone };
|
||||
enum class State : int32 { Ok, WaitCode } state_ = State::Ok;
|
||||
|
||||
void tear_down() final;
|
||||
@ -56,7 +56,7 @@ class PhoneNumberManager final : public Actor {
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
|
||||
Type type_;
|
||||
Type type_ = Type::None;
|
||||
SendCodeHelper send_code_helper_;
|
||||
int64 generation_ = 0;
|
||||
};
|
||||
|
||||
@ -67,11 +67,7 @@ void get_premium_giveaway_info(Td *td, MessageFullId message_full_id,
|
||||
|
||||
void can_purchase_premium(Td *td, td_api::object_ptr<td_api::StorePaymentPurpose> &&purpose, Promise<Unit> &&promise);
|
||||
|
||||
void assign_app_store_transaction(Td *td, const string &receipt,
|
||||
td_api::object_ptr<td_api::StorePaymentPurpose> &&purpose, Promise<Unit> &&promise);
|
||||
|
||||
void assign_play_market_transaction(Td *td, const string &package_name, const string &store_product_id,
|
||||
const string &purchase_token,
|
||||
td_api::object_ptr<td_api::StorePaymentPurpose> &&purpose, Promise<Unit> &&promise);
|
||||
void assign_store_transaction(Td *td, td_api::object_ptr<td_api::StoreTransaction> &&transaction,
|
||||
td_api::object_ptr<td_api::StorePaymentPurpose> &&purpose, Promise<Unit> &&promise);
|
||||
|
||||
} // namespace td
|
||||
|
||||
@ -105,6 +105,10 @@ class Requests {
|
||||
|
||||
void on_request(uint64 id, td_api::setAuthenticationPhoneNumber &request);
|
||||
|
||||
void on_request(uint64 id, td_api::checkAuthenticationPremiumPurchase &request);
|
||||
|
||||
void on_request(uint64 id, td_api::setAuthenticationPremiumPurchaseTransaction &request);
|
||||
|
||||
void on_request(uint64 id, td_api::sendAuthenticationFirebaseSms &request);
|
||||
|
||||
void on_request(uint64 id, td_api::reportAuthenticationCodeMissing &request);
|
||||
@ -1661,9 +1665,7 @@ class Requests {
|
||||
|
||||
void on_request(uint64 id, td_api::canPurchaseFromStore &request);
|
||||
|
||||
void on_request(uint64 id, td_api::assignAppStoreTransaction &request);
|
||||
|
||||
void on_request(uint64 id, td_api::assignGooglePlayTransaction &request);
|
||||
void on_request(uint64 id, td_api::assignStoreTransaction &request);
|
||||
|
||||
void on_request(uint64 id, const td_api::getBusinessFeatures &request);
|
||||
|
||||
|
||||
@ -642,6 +642,8 @@ class UpdatesManager final : public Actor {
|
||||
|
||||
void on_update(tl_object_ptr<telegram_api::updateLoginToken> update, Promise<Unit> &&promise);
|
||||
|
||||
void on_update(tl_object_ptr<telegram_api::updateSentPhoneCode> update, Promise<Unit> &&promise);
|
||||
|
||||
void on_update(tl_object_ptr<telegram_api::updateBotStopped> update, Promise<Unit> &&promise);
|
||||
void on_update(tl_object_ptr<telegram_api::updateChatParticipant> update, Promise<Unit> &&promise);
|
||||
void on_update(tl_object_ptr<telegram_api::updateChannelParticipant> update, Promise<Unit> &&promise);
|
||||
@ -704,8 +706,6 @@ class UpdatesManager final : public Actor {
|
||||
// unsupported updates
|
||||
|
||||
void on_update(tl_object_ptr<telegram_api::updateNewStoryReaction> update, Promise<Unit> &&promise);
|
||||
|
||||
void on_update(tl_object_ptr<telegram_api::updateSentPhoneCode> update, Promise<Unit> &&promise);
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
||||
@ -239,14 +239,14 @@ class UserManager final : public Actor {
|
||||
|
||||
struct BotData {
|
||||
string username;
|
||||
bool can_be_edited;
|
||||
bool can_join_groups;
|
||||
bool can_read_all_group_messages;
|
||||
bool has_main_app;
|
||||
bool is_inline;
|
||||
bool is_business;
|
||||
bool need_location;
|
||||
bool can_be_added_to_attach_menu;
|
||||
bool can_be_edited = false;
|
||||
bool can_join_groups = false;
|
||||
bool can_read_all_group_messages = false;
|
||||
bool has_main_app = false;
|
||||
bool is_inline = false;
|
||||
bool is_business = false;
|
||||
bool need_location = false;
|
||||
bool can_be_added_to_attach_menu = false;
|
||||
};
|
||||
Result<BotData> get_bot_data(UserId user_id) const TD_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
@ -180,7 +180,7 @@ class ConnectionCreator final : public NetQueryCallback {
|
||||
|
||||
struct TestProxyRequest {
|
||||
Proxy proxy_;
|
||||
int16 dc_id_;
|
||||
int16 dc_id_ = -1;
|
||||
ActorOwn<> child_;
|
||||
Promise<Unit> promise_;
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ class DcAuthManager final : public NetQueryCallback {
|
||||
struct DcInfo {
|
||||
DcId dc_id;
|
||||
std::shared_ptr<AuthDataShared> shared_auth_data;
|
||||
AuthKeyState auth_key_state;
|
||||
AuthKeyState auth_key_state = AuthKeyState::Empty;
|
||||
|
||||
enum class State : int32 { Waiting, Export, Import, BeforeOk, Ok };
|
||||
State state = State::Waiting;
|
||||
|
||||
@ -162,7 +162,7 @@ class Session final
|
||||
double created_at_ = 0;
|
||||
};
|
||||
|
||||
ConnectionInfo *current_info_;
|
||||
ConnectionInfo *current_info_ = nullptr;
|
||||
ConnectionInfo main_connection_;
|
||||
ConnectionInfo long_poll_connection_;
|
||||
mtproto::ConnectionManager::ConnectionToken connection_token_;
|
||||
@ -195,7 +195,7 @@ class Session final
|
||||
enum HandshakeId : int32 { MainAuthKeyHandshake = 0, TmpAuthKeyHandshake = 1 };
|
||||
std::array<HandshakeInfo, 2> handshake_info_;
|
||||
|
||||
double wakeup_at_;
|
||||
double wakeup_at_ = 0.0;
|
||||
|
||||
// mtproto::AuthData should be the last field, because it's size is about 32 KB
|
||||
mtproto::AuthData auth_data_;
|
||||
|
||||
@ -320,6 +320,9 @@ class ClientBlockchain {
|
||||
td::UInt256 get_last_block_hash() const {
|
||||
return blockchain_.last_block_hash_;
|
||||
}
|
||||
td::UInt256 get_previous_block_hash() const {
|
||||
return blockchain_.last_block_.prev_block_hash_;
|
||||
}
|
||||
|
||||
td::Status add_proof(td::Slice proof);
|
||||
|
||||
|
||||
@ -55,7 +55,7 @@ struct CallVerificationChain {
|
||||
friend td::StringBuilder &operator<<(td::StringBuilder &sb, const CallVerificationChain &chain);
|
||||
|
||||
private:
|
||||
td::Status process_broadcast(std::string message, e2e::object_ptr<e2e::e2e_chain_GroupBroadcast> broadcast);
|
||||
td::Status process_broadcast(td::Slice message, e2e::object_ptr<e2e::e2e_chain_GroupBroadcast> broadcast);
|
||||
td::Status process_broadcast(e2e::e2e_chain_groupBroadcastNonceCommit &nonce_commit);
|
||||
td::Status process_broadcast(e2e::e2e_chain_groupBroadcastNonceReveal &nonce_reveal);
|
||||
|
||||
@ -88,11 +88,11 @@ struct CallVerificationChain {
|
||||
class CallEncryption {
|
||||
public:
|
||||
CallEncryption(td::int64 user_id, PrivateKey private_key);
|
||||
td::Status add_shared_key(td::int32 epoch, td::SecureString key, GroupStateRef group_state);
|
||||
void forget_shared_key(td::int32 epoch);
|
||||
td::Status add_shared_key(td::int32 epoch, td::UInt256 epoch_hash, td::SecureString key, GroupStateRef group_state);
|
||||
void forget_shared_key(td::int32 epoch, td::UInt256 epoch_hash);
|
||||
|
||||
td::Result<std::string> decrypt(td::int64 expected_user_id, td::int32 expected_channel_id, td::Slice encrypted_data);
|
||||
td::Result<std::string> encrypt(td::int32 channel_id, td::Slice decrypted_data);
|
||||
td::Result<std::string> decrypt(td::int64 expected_user_id, td::int32 expected_channel_id, td::Slice packet);
|
||||
td::Result<std::string> encrypt(td::int32 channel_id, td::Slice data, size_t unencrypted_header_length);
|
||||
|
||||
private:
|
||||
static constexpr double FORGET_EPOCH_DELAY = 10;
|
||||
@ -101,11 +101,17 @@ class CallEncryption {
|
||||
PrivateKey private_key_;
|
||||
|
||||
struct EpochInfo {
|
||||
EpochInfo(td::int32 epoch, td::int64 user_id, td::SecureString secret, GroupStateRef group_state)
|
||||
: epoch_(epoch), user_id_(user_id), secret_(std::move(secret)), group_state_(std::move(group_state)) {
|
||||
EpochInfo(td::int32 epoch, td::UInt256 epoch_hash, td::int64 user_id, td::SecureString secret,
|
||||
GroupStateRef group_state)
|
||||
: epoch_(epoch)
|
||||
, epoch_hash_(epoch_hash)
|
||||
, user_id_(user_id)
|
||||
, secret_(std::move(secret))
|
||||
, group_state_(std::move(group_state)) {
|
||||
}
|
||||
|
||||
td::int32 epoch_{};
|
||||
td::UInt256 epoch_hash_{};
|
||||
td::int64 user_id_{};
|
||||
td::SecureString secret_;
|
||||
GroupStateRef group_state_;
|
||||
@ -113,6 +119,7 @@ class CallEncryption {
|
||||
|
||||
std::map<td::int32, td::uint32> seqno_;
|
||||
std::map<td::int32, EpochInfo> epochs_;
|
||||
std::map<td::UInt256, td::int32> epoch_by_hash_;
|
||||
td::VectorQueue<std::pair<td::Timestamp, td::int32>> epochs_to_forget_;
|
||||
std::map<std::pair<PublicKey, td::int32>, std::set<td::uint32>> seen_;
|
||||
|
||||
@ -121,8 +128,9 @@ class CallEncryption {
|
||||
td::Result<std::string> encrypt_packet_with_secret(td::int32 channel_id, td::Slice header, td::Slice packet,
|
||||
td::Slice one_time_secret);
|
||||
td::Result<std::string> decrypt_packet_with_secret(td::int64 expected_user_id, td::int32 expected_channel_id,
|
||||
td::Slice unencrypted_packet, td::Slice encrypted_packet,
|
||||
td::Slice one_time_secret, const GroupStateRef &group_state);
|
||||
td::Slice unencrypted_header, td::Slice unencrypted_prefix,
|
||||
td::Slice encrypted_packet, td::Slice one_time_secret,
|
||||
const GroupStateRef &group_state);
|
||||
td::Status check_not_seen(const PublicKey &public_key, td::int32 channel_id, td::uint32 seqno);
|
||||
void mark_as_seen(const PublicKey &public_key, td::int32 channel_id, td::uint32 seqno);
|
||||
static td::Status validate_channel_id(td::int32 channel_id);
|
||||
@ -182,9 +190,9 @@ struct Call {
|
||||
TRY_STATUS(get_status());
|
||||
return call_encryption_.decrypt(user_id, channel_id, encrypted_data);
|
||||
}
|
||||
td::Result<std::string> encrypt(td::int32 channel_id, td::Slice decrypted_data) {
|
||||
td::Result<std::string> encrypt(td::int32 channel_id, td::Slice decrypted_data, size_t unencrypted_prefix_size) {
|
||||
TRY_STATUS(get_status());
|
||||
return call_encryption_.encrypt(channel_id, decrypted_data);
|
||||
return call_encryption_.encrypt(channel_id, decrypted_data, unencrypted_prefix_size);
|
||||
}
|
||||
|
||||
td::Result<std::vector<std::string>> pull_outbound_messages() {
|
||||
|
||||
@ -165,10 +165,10 @@ class Container {
|
||||
auto id = next_id.fetch_add(1, std::memory_order_relaxed);
|
||||
if constexpr (TI::is_mutable) {
|
||||
auto value_ptr = std::make_shared<MutableValue<T>>(std::move(value));
|
||||
storage.values.emplace(id, std::move(o_hash), value_ptr);
|
||||
storage.values.emplace(id, o_hash, value_ptr);
|
||||
} else {
|
||||
auto value_ptr = std::make_shared<T>(std::move(value));
|
||||
storage.values.emplace(id, std::move(o_hash), value_ptr);
|
||||
storage.values.emplace(id, o_hash, value_ptr);
|
||||
}
|
||||
|
||||
if constexpr (TI::has_hash) {
|
||||
@ -243,6 +243,7 @@ td::Result<SharedRef<T>> convert(SharedRef<S> from) {
|
||||
}
|
||||
return td::Status::Error(static_cast<int>(tde2e_api::ErrorCode::UnknownError), "TODO");
|
||||
}
|
||||
|
||||
template <class T, class S>
|
||||
td::Result<UniqueRef<T>> convert(UniqueRef<S> from) {
|
||||
if (std::holds_alternative<T>(*from)) {
|
||||
|
||||
@ -365,7 +365,7 @@ struct EncryptedStorage {
|
||||
|
||||
// current blockchain height
|
||||
td::int64 get_height() const;
|
||||
// one must only apply blocks from server (TODO: signature from server)
|
||||
// one should only apply blocks from server (TODO: signature from server?)
|
||||
td::Result<KeyValueUpdates> apply_block(td::Slice block);
|
||||
|
||||
// proof must be from block of current height
|
||||
|
||||
@ -10,14 +10,19 @@
|
||||
#include "td/utils/SharedSlice.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/UInt.h"
|
||||
|
||||
namespace tde2e_core {
|
||||
|
||||
class MessageEncryption {
|
||||
public:
|
||||
static td::SecureString encrypt_data(td::Slice data, td::Slice secret);
|
||||
static td::Result<td::SecureString> decrypt_data(td::Slice encrypted_data, td::Slice secret);
|
||||
static td::SecureString encrypt_data(td::Slice data, td::Slice secret, td::Slice additional_data = {},
|
||||
td::UInt256 *save_large_msg_id = nullptr);
|
||||
static td::Result<td::SecureString> decrypt_data(td::Slice encrypted_data, td::Slice secret,
|
||||
td::Slice additional_data = {},
|
||||
td::UInt256 *save_large_msg_id = nullptr);
|
||||
static td::SecureString hmac_sha512(td::Slice key, td::Slice message);
|
||||
static td::SecureString hmac_sha256(td::Slice key, td::Slice message);
|
||||
static td::SecureString kdf(td::Slice secret, td::Slice password, int iterations);
|
||||
static td::Result<td::SecureString> encrypt_header(td::Slice decrypted_header, td::Slice encrypted_message,
|
||||
td::Slice secret);
|
||||
@ -29,7 +34,8 @@ class MessageEncryption {
|
||||
static td::SecureString gen_random_prefix(td::int64 data_size, td::int64 min_padding);
|
||||
static td::SecureString gen_deterministic_prefix(td::int64 data_size, td::int64 min_padding);
|
||||
|
||||
static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret);
|
||||
static td::SecureString encrypt_data_with_prefix(td::Slice data, td::Slice secret, td::Slice additional_data = {},
|
||||
td::UInt256 *save_large_msg_id = nullptr);
|
||||
|
||||
static td::SecureString kdf_expand(td::Slice random_secret, td::Slice info);
|
||||
|
||||
|
||||
@ -22,13 +22,16 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Define a custom verbosity name for blockchain-specific logging
|
||||
extern int VERBOSITY_NAME(blkch);
|
||||
|
||||
namespace tde2e_core {
|
||||
|
||||
struct Height {
|
||||
td::int64 height;
|
||||
td::int64 broadcast_height;
|
||||
};
|
||||
|
||||
// Simple blockchain operation logger that writes to a file
|
||||
class BlockchainLogger {
|
||||
public:
|
||||
@ -57,8 +60,6 @@ class BlockchainLogger {
|
||||
std::string base64_encode(td::Slice data);
|
||||
};
|
||||
|
||||
// Define a custom verbosity name for blockchain-specific logging
|
||||
|
||||
class ServerBlockchain {
|
||||
public:
|
||||
ServerBlockchain() = default;
|
||||
@ -128,6 +129,7 @@ struct BlockBuilder {
|
||||
bool in_proof = true, td::int32 external_permissions = 0);
|
||||
BlockBuilder &skip_group_state_proof();
|
||||
BlockBuilder &with_shared_key(const std::vector<td::int64> &user_ids, bool in_changes = true, bool in_proof = true);
|
||||
BlockBuilder &with_shared_key(GroupSharedKeyRef shared_key, bool in_changes, bool in_proof);
|
||||
BlockBuilder &skip_shared_key_proof();
|
||||
|
||||
private:
|
||||
|
||||
@ -80,16 +80,21 @@ struct TrieNode {
|
||||
};
|
||||
|
||||
td::Result<TrieRef> set(const TrieRef &n, BitString key, td::Slice value, td::Slice snapshot = {});
|
||||
|
||||
td::Result<std::string> get(const TrieRef &n, const BitString &key, td::Slice snapshot = {});
|
||||
|
||||
td::Result<TrieRef> generate_pruned_tree(const TrieRef &n, td::Span<td::Slice> keys, td::Slice snapshot = {});
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const td::UInt256 &hash);
|
||||
|
||||
void print_tree(const TrieRef &node, const std::string &prefix = "", bool is_root = true);
|
||||
|
||||
BitString to_key(td::Slice key);
|
||||
|
||||
inline td::Result<TrieRef> set(const TrieRef &n, td::Slice key, td::Slice value) {
|
||||
return set(n, to_key(key), value);
|
||||
}
|
||||
|
||||
inline td::Result<std::string> get(const TrieRef &n, td::Slice key, td::Slice snapshot = {}) {
|
||||
return get(n, to_key(key), snapshot);
|
||||
}
|
||||
|
||||
@ -175,7 +175,6 @@ Result<Ok> login_destroy(LoginId login_id);
|
||||
Result<Ok> login_destroy_all();
|
||||
|
||||
// Personal info
|
||||
// TODO: UserId
|
||||
|
||||
// 1. Each entry stored and signed separately
|
||||
// 2. Signature is never stored, but always is verified
|
||||
@ -304,7 +303,8 @@ Result<std::string> call_describe_block(Slice block);
|
||||
Result<std::string> call_describe_message(Slice message);
|
||||
|
||||
Result<Bytes> call_create_change_state_block(CallId call_id, const CallState &new_state);
|
||||
Result<Bytes> call_encrypt(CallId call_id, CallChannelId channel_id, SecureSlice message);
|
||||
Result<Bytes> call_encrypt(CallId call_id, CallChannelId channel_id, SecureSlice message,
|
||||
size_t unencrypted_prefix_size);
|
||||
Result<SecureBytes> call_decrypt(CallId call_id, UserId user_id, CallChannelId channel_id, Slice message);
|
||||
|
||||
Result<int> call_get_height(CallId call_id);
|
||||
@ -329,7 +329,9 @@ struct CallVerificationWords {
|
||||
int height{};
|
||||
std::vector<std::string> words;
|
||||
};
|
||||
|
||||
Result<CallVerificationWords> call_get_verification_words(CallId call_id);
|
||||
Result<Ok> call_destroy(CallId call_id);
|
||||
Result<Ok> call_destroy_all();
|
||||
|
||||
} // namespace tde2e_api
|
||||
|
||||
@ -25,6 +25,7 @@ enum class ErrorCode : int {
|
||||
InvalidBlock_InvalidStateProof_Secret = 206,
|
||||
InvalidBlock_NoPermissions = 207,
|
||||
InvalidBlock_InvalidGroupState = 208,
|
||||
InvalidBlock_InvalidSharedSecret = 209,
|
||||
InvalidCallGroupState_NotParticipant = 300,
|
||||
InvalidCallGroupState_WrongUserId = 301,
|
||||
Decrypt_UnknownEpoch = 400,
|
||||
@ -37,7 +38,8 @@ enum class ErrorCode : int {
|
||||
InvalidBroadcast_InvalidReveal = 505,
|
||||
InvalidBroadcast_InvalidBlockHash = 506,
|
||||
InvalidCallChannelId = 600,
|
||||
CallFailed = 601
|
||||
CallFailed = 601,
|
||||
CallKeyAlreadyUsed = 602
|
||||
};
|
||||
inline std::string_view error_string(ErrorCode error_code) {
|
||||
switch (error_code) {
|
||||
@ -67,6 +69,8 @@ inline std::string_view error_string(ErrorCode error_code) {
|
||||
return "INVALID_BLOCK__INVALID_STATE_PROOF__SECRET";
|
||||
case ErrorCode::InvalidBlock_InvalidGroupState:
|
||||
return "INVALID_BLOCK__INVALID_GROUP_STATE";
|
||||
case ErrorCode::InvalidBlock_InvalidSharedSecret:
|
||||
return "INVALID_BLOCK__INVALID_SHARED_SECRET";
|
||||
case ErrorCode::InvalidBlock_NoPermissions:
|
||||
return "INVALID_BLOCK__NO_PERMISSIONS";
|
||||
case ErrorCode::InvalidCallGroupState_NotParticipant:
|
||||
@ -93,6 +97,8 @@ inline std::string_view error_string(ErrorCode error_code) {
|
||||
return "INVALID_BROADCAST__INVALID_BLOCK_HASH";
|
||||
case ErrorCode::CallFailed:
|
||||
return "CALL_FAILED";
|
||||
case ErrorCode::CallKeyAlreadyUsed:
|
||||
return "CALL_KEY_ALREADY_USED";
|
||||
case ErrorCode::InvalidCallChannelId:
|
||||
return "INVALID_CALL_CHANNEL_ID";
|
||||
}
|
||||
|
||||
@ -23,7 +23,9 @@
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace tde2e_api {
|
||||
|
||||
inline Error to_error(const td::Status &status) {
|
||||
auto error_code = ErrorCode(status.code());
|
||||
if (error_string(error_code) == "UNKNOWN_ERROR") {
|
||||
@ -39,6 +41,7 @@ Result<T> to_result(td::Result<T> &value) {
|
||||
}
|
||||
return Result<T>(to_error(value.error()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Result<T>::Result(td::Result<T> &&value) : Result(to_result(value)) {
|
||||
}
|
||||
@ -50,11 +53,14 @@ Result<T>::Result(td::Status &&status) : Result(to_error(status)) {
|
||||
} // namespace tde2e_api
|
||||
|
||||
namespace tde2e_core {
|
||||
|
||||
using E = tde2e_api::ErrorCode;
|
||||
|
||||
inline td::Status Error(E error_code) {
|
||||
auto msg = tde2e_api::error_string(error_code);
|
||||
return td::Status::Error(static_cast<int>(error_code), td::Slice(msg.data(), msg.size()));
|
||||
}
|
||||
|
||||
inline td::Status Error(E error_code, td::Slice message) {
|
||||
auto msg = tde2e_api::error_string(error_code);
|
||||
return td::Status::Error(static_cast<int>(error_code), PSLICE()
|
||||
|
||||
@ -15,6 +15,7 @@ struct TestVector {
|
||||
std::string name;
|
||||
std::string secret;
|
||||
std::string data;
|
||||
std::string extra;
|
||||
std::string header;
|
||||
std::string encrypted;
|
||||
std::string encrypted_header;
|
||||
@ -22,59 +23,65 @@ struct TestVector {
|
||||
|
||||
inline std::vector<TestVector> get_test_vectors() {
|
||||
return {
|
||||
{"empty_message", "5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a", "",
|
||||
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
|
||||
"9e2476ad849d22a44d9135c5c3c5e8b52d4f88473ae8745f3a9cec4d54780caf",
|
||||
"de3539a5e10b20a3a0cffc24dbbd76b3a7e0eeab402cb38396d64785a3ab7c25"},
|
||||
{"simple_message", "5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
|
||||
"48656c6c6f2c20576f726c6421", "a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
|
||||
"872b141f6d1e3554ead471dffd0fee5c04a0b04260eafcca9187158ce84c4487e9429df876706753913de61029402478",
|
||||
"013037e02dc8dbf13598d96eb333a69a930efe043bac7dce0d6edfd1abc6bd2f"},
|
||||
{"long_message", "5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
|
||||
{"empty_message", "f9fb473b9887e50ea38eef7380c82361432cd4b22c5f9b3700809990d8ed344c", "", "",
|
||||
"bd29703cf44551710ca14d091a6c98ee347931b2b8140faaaef2dbb40719df12",
|
||||
"d28eb3e3d1328f06dafedabd67a353d5ea6e164d2f34c162a16f8a1164663a03",
|
||||
"4060edd7bcacca6dd0f4fe81d6ec63a8859fa9d520598043bc4748919f3fdeda"},
|
||||
{"simple_message", "f9fb473b9887e50ea38eef7380c82361432cd4b22c5f9b3700809990d8ed344c",
|
||||
"48656c6c6f2c20576f726c6421", "", "bd29703cf44551710ca14d091a6c98ee347931b2b8140faaaef2dbb40719df12",
|
||||
"967f5245b03e07ab7be6044174306a4af811e96708ae3ad2ab427aa5495508b1c319ca0353531c0a2921e307f2455856",
|
||||
"9e7910949e526b6ad51a59aad8022c826b00f379e28592ed3216aabc6be252e0"},
|
||||
{"long_message", "f9fb473b9887e50ea38eef7380c82361432cd4b22c5f9b3700809990d8ed344c",
|
||||
"787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787"
|
||||
"878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878"
|
||||
"787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787"
|
||||
"8787878787878787878787878787878787878787878787878787878787878787878",
|
||||
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
|
||||
"0fd497802c755b9c6fb9d58d38b9fb5fbd7dc9ccf78af3eb003a22d46bfa38894135d976bbec0f3cadc2b61a4d8648120dada26b2c3153d"
|
||||
"ef20fb9e370def31c802e202846946b5cb1bc2c01a7b46605292d6043ffb8f4040aaf18914e1c93fe9e683f088e23ee5e1551f00068a23f"
|
||||
"a3ebb8d6b9dcbf7a9072b12323b1a64247ba9bc7d277b08cfcc37387a0d24afca170dc027d8f0212eb62bccd9555de98936047c9bfc6a03"
|
||||
"aa539073f458795bd94b9b43003fe2299805f90c1d30ca631c8054242687e41e890bf4d744b529d7e96ea48a5bcec700993b5e980173049"
|
||||
"cf9df6f93d62ccc06d933fd6d7063890fa2d",
|
||||
"697558ba60e789622ee90dffc55f1f1148cfea568c573b257fcf2083cf8aad0a"},
|
||||
{"random_message", "5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
|
||||
"e61d2b05302c49faa9fac6a893957a846a2b30801dc171cf62ffec92297b10bfc4a82445839ecb4c5800ffb37c5356d4b95fc565ddb2e7f"
|
||||
"3e21f2936a952373c",
|
||||
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
|
||||
"515f0223f27302ca5e952ec978ec66bcdf04e7f72ae3a8e011e21457b355891d12e158c9b2dfb921520a0e5f531e6a20e95d42635b084a0"
|
||||
"b38a6e658f4a4181f85ea83756d316cea538cc34592491eef3e3530c34c63a693e3372cbdd0076628",
|
||||
"b5bdfe6a3400c5d299d94756af4c18bbb8cca4a2635beeba3d89bbaa0025d9d3"},
|
||||
{"very_long_message", "5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
|
||||
"de6e0dbde23e04b6be3d4c46868a1171c6b879227b19e370765823390501b195783c356af2156e828e511473d5698c9bd1cb4a70b7e209b"
|
||||
"bb02f8dda044af02ab6869478b211e3a17d72fbe6289c1b2e6132cb141e89cf72cf70defd67a23fbfe8e718a09a9c6a345565ebdc73e1f5"
|
||||
"9927744801eb4e6f0b30d2705ea181e02a4030252330ac73bc4a4d51d2ccafb2f3f62abe3e81163be325ac823571c8dfae739f70bff3916"
|
||||
"4e3cec7f53b88f97735dc25ac0c0630b1b41a131a979ba5164ab92e103716e9096e2fb5a6434b31d2c3673fca7e54dcdcce3807bfd43ee7"
|
||||
"bc3422868094305a9847ce7666bf57e49fb3c2009cb30eb3ba955942b923ec2c2a4e0341d86b524b198974bdce9cf863ab3526e9e03e533"
|
||||
"99dad20fc218554567c440536a31e05573f4cb930ba6a",
|
||||
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
|
||||
"e296a98cd96154b27d4b94cc520a8f028c61bd5ea69d22f0c3c13658c4bd5db0bd6661d0d17fac791c5cc06b3a54a853916bd7bf8a00644"
|
||||
"acc53cca43b6f51c66bc6a6cb98cf8d9f23dcd639089d1d9d3dfbc8829a1a81638317bbd3edb070c1dae181d97605eb42a6111b8696a16c"
|
||||
"c3e42639e38e93f872111fd67e934740f73a57df0e6edc6726c9aff99682bfcb7ddd99a3bef30da70d3c21e590fd02defc23be9f7f243e4"
|
||||
"5a56b13562b8ecea09a14ac5af3a0500cb52f73f1bffea4a6624644da0bc4d112e5ee684b13a2ae8dbf401a5a8e581295a9dc876eaeb8ae"
|
||||
"4d732fb78d50a92c302d15c0a2308e43fc6e147ec162b28a534d6c95a2020fa141f3ce7f7dd25ff000d35f732a145abf31b3ff4d0da015d"
|
||||
"39da3b0fc70e692b567a9507be59e8c91a63fe809c495d76e70ec857cc24978771fc9314251e2bc4b1b24e0448514f97a6d438255cba8c1"
|
||||
"854019",
|
||||
"8dab56b50ce6a4315b6e0b4eb32c39dfe817cb462ee9e070e2a60bb843c16107"},
|
||||
{"message_with_special_chars", "5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
|
||||
"2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f",
|
||||
"a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
|
||||
"2014d1125081316a334896cbe5aed251d9fba6f3422afbc7e7bc9019e10e184241d18f71ef86603b5ce03e1c351e3dfff8adfb8f3498300"
|
||||
"a712ec134b367c533",
|
||||
"6f5a5de410db3606ff94fa14d0e084a6ba5a51241a2abf45ac593e4748c477ce"},
|
||||
{"message_with_unicode", "5a08a19b447df98136a4502e01b286011b2d148084a7ca17e3a93616d279eb2a",
|
||||
"48656c6c6f2c20e4b896e7958c21", "a36c57ad5e8d6a30e80e010ab903b60da0206db1b4fd981cd61e059bbd8c0d4f",
|
||||
"7ae70cb905f23109477b4d758d3907238ff4c37e2f351f086268ba3e85cef0257af58a70d8838c7b9c044f30382c2ccf",
|
||||
"7dfb2d2e76df39b2fafdf01de009088a7e4d045b8630941986111ef2010d7c4a"},
|
||||
"", "bd29703cf44551710ca14d091a6c98ee347931b2b8140faaaef2dbb40719df12",
|
||||
"8202a46a19de7111166f6c244127c84dbdc1c3a63ca6526dc699c6cbbc6f8236ee82a0172ed1115cb4a2ba8e27cfa8089822c7e9070ec2f"
|
||||
"5c7cee77cc979447c1db9758119ad28a05b2edfc1c98b486985bb60fb6f1fefb4b5f7ecea19d59b8018f865a7be3771c7f6fe6092b34b78"
|
||||
"a1bddefc8d07f2f61351a4247c41a58cb068ebe9110245de4fda076f0ff73aede4e9811678424f648b8054b921b53f0612dfbdb7173a86b"
|
||||
"ce3eba73955afef435599ae34825d295e8d298d6d3a1fc07084740c0b1c3a24cebedbd26b631cbbd1a352c1a499ba3576a628a74ab14eb1"
|
||||
"d180e5af7e9eac4020b889fafc4f7bfb2e24",
|
||||
"641620351a1e4d76711385d5cf3b0eed07308c9cafc06ef09ed0c1f57ebb5f42"},
|
||||
{"random_message", "f9fb473b9887e50ea38eef7380c82361432cd4b22c5f9b3700809990d8ed344c",
|
||||
"fed306c137017ab008c22d1f74bc104e5138d3c19b42fb303c768b083912a1102d06ac1e0f4440e3b32b9144a50e6fc0f190273bd4dec7e"
|
||||
"f847bf7d46680bb67",
|
||||
"736d616c6c206578747261", "bd29703cf44551710ca14d091a6c98ee347931b2b8140faaaef2dbb40719df12",
|
||||
"ee198e4860c888ab18bcecba5083eb539f402be1fbde51e0c49e398145d40ebb7b5a52bdc83d6200e63a70c47cc6a5e6fa7a71f6e24b722"
|
||||
"b5f0314b6b52768dbd2e438a582d1cf2a54d4de7ba30e36e68afd8379b63a345483dbcc33380fd07f",
|
||||
"f282da8a41f17a5fa7f793c6c134c5bb2b960a2fea43bdc15b58a69cb7dafb43"},
|
||||
{"very_long_message", "f9fb473b9887e50ea38eef7380c82361432cd4b22c5f9b3700809990d8ed344c",
|
||||
"d16554889d83850ffb42d119e0c69d8b68ee07ff021f0a2cb7beb70d0b1cc62e3d8fe2dff95e674893393b5da015a965108c785d8935a3e"
|
||||
"e58e3df9505016020b558687ee535f9bcfa94450ded18ac3e8145879af43e66eeacfee1d9f9c9c78824cf34639af50fb0b93de73aa9362c"
|
||||
"f2732e2d8c652111ec1246c8ded3b19e93d154d04cc8a4bd927332136d7627e71e6be2c97dd62235dfd998d1e630588d10beeab791e0919"
|
||||
"9bfa8bab3b9e6dbcdfba9f9dd76110f7f6c7fd1fbccc421e7ad093e8fd385e53e3c03f7f0a79296962de1e752eea5f8c5e6325ef406aef5"
|
||||
"62d8ef0b9431defeb46fb93ee3c3409af0e3a4f7e63af4efbfb5f4b61a104c1158247877a28f9538d6cf8c5e243ece977cc2a0a0bcf602c"
|
||||
"d16df445cb71a4f6a0494a3b6a1149725c169dc40eb10",
|
||||
"ebc6b1176ca69b8bb769bcc68add44fbba1c79d2771ef412eccad3ee4f7afe595f8fd2052f8d1d8b8fea209c568eb6a4c6aea6d88c583df"
|
||||
"25ed3f38260c2f95c1f0244219d55e658498b34f7e7a527c60723b6806fe28275337b0c9b64c158825a3c14d8cec6a40bbf8c5a5a8009ca"
|
||||
"75f2c6f2e7f3ab612ff5d675f2c3b801d4d4e0408b49d8543d8621de0df26a65a49d1fc7a21584d5495a24b2090479870e852766f6de34b"
|
||||
"724e5941097d19153f4f4d035ae0c978ec6354ba452cf465581cd4afd7045bfa4c54383796587d19e981da220cd9ca5230161eaf64d8a1b"
|
||||
"406a2f8afc7faeb0ec7634c3c14aa63736c955b56c48c61ba58b109775ac252f3837e8bcebdb40f4ca2ce32609619b0063cb421a268f80c"
|
||||
"60ffc7c99963f74033d22283a6d2ab3095f65cb49a17e",
|
||||
"bd29703cf44551710ca14d091a6c98ee347931b2b8140faaaef2dbb40719df12",
|
||||
"c96e7fadcf4e51f5c0dc03aeed33352d7f984c2d49791d173caad17d724b98155ff6b3dc6e082b90063434e9f85941c085dd8573fb4f23d"
|
||||
"d0867615249e8e8c567ba74d4e6739919c46afc0a6b19b26c0e37e1810952dcb859b8a2df9ed322da89c4e7821166939809d2561980ff77"
|
||||
"d3b797f1ecb1ed78e39614e096c72bed4587ac3229929ae4e164da9b00323410f8b17abed5cc8455656ee73114119e20b529294f8c578f7"
|
||||
"f9492327ff40f9f1255abe84f7445c87c8b048e98eac746f6d58fb3261f61eb039e5e88da46c9fc5e35baeb0c1180e9913f49ab7aac5f59"
|
||||
"76be1e384071470d80ddbf77c52e781f954d77978697cf555d1586469ce21ccd45f43283eeec3b976d6bd897f436ef9ccacde5da73f298b"
|
||||
"d1b99c10e988befeb2988f8f03f96215a746590d35ff0a6a85fa1102d63a00cd71e3cb80753bfe98bf6744f2aec697993dab51cce21f823"
|
||||
"656870",
|
||||
"97b6b5b2082a66182783c0be6940ca9d63e931195b6cc84dbf9158e9b39834ac"},
|
||||
{"message_with_special_chars", "f9fb473b9887e50ea38eef7380c82361432cd4b22c5f9b3700809990d8ed344c",
|
||||
"2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", "",
|
||||
"bd29703cf44551710ca14d091a6c98ee347931b2b8140faaaef2dbb40719df12",
|
||||
"b862c41221e3242c07c375dfded48e302aaebed7fbc91bbfe3b7c88345a58d3a13d83cfb87f08250b2d66f4590b5dd2bb2b08fabd4328d1"
|
||||
"04f7b4e1bad80931c",
|
||||
"7557d10f233e47a56f74a57458b5169e8cce5c4c98e3a3da02f6e49a3db4c2b3"},
|
||||
{"message_with_unicode", "f9fb473b9887e50ea38eef7380c82361432cd4b22c5f9b3700809990d8ed344c",
|
||||
"48656c6c6f2c20e4b896e7958c21", "", "bd29703cf44551710ca14d091a6c98ee347931b2b8140faaaef2dbb40719df12",
|
||||
"cb0d460ca3daf8e3fd5623965b39b5c1de840e92d39f6caf4662b7a7983c53b29fe644bf45acea2644507ac01f0617a2",
|
||||
"ebe8636326b11d90f9a670e63086e2fcd02b78c0aa5cacdb4f887e511d1ae4c9"},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -138,7 +138,7 @@ class ChainScheduler final : public ChainSchedulerBase {
|
||||
struct Task {
|
||||
enum class State { Pending, Active, Paused } state{State::Pending};
|
||||
vector<TaskChainInfo> chains;
|
||||
ExtraT extra;
|
||||
ExtraT extra{};
|
||||
};
|
||||
FlatHashMap<ChainId, unique_ptr<ChainInfo>> chains_;
|
||||
FlatHashMap<ChainId, TaskId> limited_tasks_;
|
||||
|
||||
@ -209,12 +209,15 @@ class ConcurrentHashMap {
|
||||
int migrate_generation_{0};
|
||||
HashMap *migrate_from_hash_map_{nullptr};
|
||||
HashMap *migrate_to_hash_map_{nullptr};
|
||||
|
||||
struct Task {
|
||||
size_t begin;
|
||||
size_t end;
|
||||
|
||||
bool empty() const {
|
||||
return begin >= end;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
if (empty()) {
|
||||
return 0;
|
||||
@ -224,9 +227,10 @@ class ConcurrentHashMap {
|
||||
};
|
||||
|
||||
struct TaskCreator {
|
||||
size_t chunk_size;
|
||||
size_t size;
|
||||
size_t chunk_size{0};
|
||||
size_t size{0};
|
||||
std::atomic<size_t> pos{0};
|
||||
|
||||
Task create() {
|
||||
auto i = pos++;
|
||||
auto begin = i * chunk_size;
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
#include "td/utils/Status.h"
|
||||
#include "td/utils/UInt.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if TD_HAVE_OPENSSL
|
||||
|
||||
namespace td {
|
||||
@ -45,7 +47,7 @@ class Ed25519 {
|
||||
}
|
||||
|
||||
static Result<PublicKey> from_slice(Slice slice) {
|
||||
if (slice.size() != 32) {
|
||||
if (slice.size() != LENGTH) {
|
||||
return Status::Error("Invalid slice size");
|
||||
}
|
||||
return PublicKey(SecureString(slice));
|
||||
@ -65,18 +67,24 @@ class Ed25519 {
|
||||
SecureString octet_string_;
|
||||
};
|
||||
|
||||
struct PreparedPrivateKey;
|
||||
|
||||
class PrivateKey {
|
||||
public:
|
||||
static constexpr size_t LENGTH = 32;
|
||||
|
||||
explicit PrivateKey(SecureString octet_string);
|
||||
|
||||
Result<std::shared_ptr<const PreparedPrivateKey>> prepare() const;
|
||||
|
||||
SecureString as_octet_string() const;
|
||||
|
||||
Result<PublicKey> get_public_key() const;
|
||||
|
||||
Result<SecureString> sign(Slice data) const;
|
||||
|
||||
static Result<SecureString> sign(const PreparedPrivateKey &prepared_private_key, Slice data);
|
||||
|
||||
Result<SecureString> as_pem(Slice password) const;
|
||||
|
||||
static Result<PrivateKey> from_pem(Slice pem, Slice password);
|
||||
|
||||
@ -68,7 +68,7 @@ struct MaskPortable {
|
||||
static MaskIterator<1> equal_mask(uint8 *bytes, uint8 needle) {
|
||||
uint64 res = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
res |= (bytes[i] == needle) << i;
|
||||
res |= static_cast<int>(bytes[i] == needle) << i;
|
||||
}
|
||||
return {res & ((1u << 14) - 1)};
|
||||
}
|
||||
|
||||
@ -287,9 +287,9 @@ static NSString *hexStringFromData(NSData *data) {
|
||||
return [[NSData alloc] initWithBytes:result.value().data() length:result.value().size()];
|
||||
}
|
||||
|
||||
- (nullable NSData *)encrypt:(NSData *)message channelId:(int32_t)channelId {
|
||||
- (nullable NSData *)encrypt:(NSData *)message channelId:(int32_t)channelId plaintextPrefixLength:(NSInteger)plaintextPrefixLength {
|
||||
std::string mappedMessage((uint8_t *)message.bytes, ((uint8_t *)message.bytes) + message.length);
|
||||
auto result = tde2e_api::call_encrypt(_callId, channelId, mappedMessage);
|
||||
auto result = tde2e_api::call_encrypt(_callId, channelId, mappedMessage, (size_t)plaintextPrefixLength);
|
||||
if (!result.is_ok()) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user