Stars subscriptions API [skip ci]

This commit is contained in:
Ilya Laktyushin 2024-07-22 20:45:32 +04:00
parent 31ba87fb0f
commit ea1e9e797f
21 changed files with 639 additions and 155 deletions

View File

@ -1,4 +1,4 @@
import Foundation wimport Foundation
import UIKit import UIKit
import AsyncDisplayKit import AsyncDisplayKit
import Display import Display
@ -460,7 +460,7 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
let actionsDisposable = DisposableSet() let actionsDisposable = DisposableSet()
let initialState: InviteLinkEditControllerState let initialState: InviteLinkEditControllerState
if let invite = invite, case let .link(_, title, _, requestApproval, _, _, _, _, expireDate, usageLimit, count, _) = invite { if let invite = invite, case let .link(_, title, _, requestApproval, _, _, _, _, expireDate, usageLimit, count, _, _) = invite {
var usageLimit = usageLimit var usageLimit = usageLimit
if let limit = usageLimit, let count = count, count > 0 { if let limit = usageLimit, let count = count, count > 0 {
usageLimit = limit - count usageLimit = limit - count
@ -593,7 +593,7 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
let requestNeeded = state.requestApproval && !isPublic let requestNeeded = state.requestApproval && !isPublic
if invite == nil { if invite == nil {
let _ = (context.engine.peers.createPeerExportedInvitation(peerId: peerId, title: title, expireDate: expireDate, usageLimit: requestNeeded ? 0 : usageLimit, requestNeeded: requestNeeded) let _ = (context.engine.peers.createPeerExportedInvitation(peerId: peerId, title: title, expireDate: expireDate, usageLimit: requestNeeded ? 0 : usageLimit, requestNeeded: requestNeeded, subscriptionPricing: nil)
|> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic)) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic))
|> deliverOnMainQueue).start(next: { invite in |> deliverOnMainQueue).start(next: { invite in
completion?(invite) completion?(invite)
@ -606,7 +606,7 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
} }
presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}) })
} else if let initialInvite = invite, case let .link(link, _, _, initialRequestApproval, _, _, _, _, initialExpireDate, initialUsageLimit, _, _) = initialInvite { } else if let initialInvite = invite, case let .link(link, _, _, initialRequestApproval, _, _, _, _, initialExpireDate, initialUsageLimit, _, _, _) = initialInvite {
if initialExpireDate == expireDate && initialUsageLimit == usageLimit && initialRequestApproval == requestNeeded { if initialExpireDate == expireDate && initialUsageLimit == usageLimit && initialRequestApproval == requestNeeded {
completion?(initialInvite) completion?(initialInvite)
dismissImpl?() dismissImpl?()

View File

@ -284,7 +284,7 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
let mainInvite: ExportedInvitation? let mainInvite: ExportedInvitation?
var isPublic = false var isPublic = false
if let peer = peer, let address = peer.addressName, !address.isEmpty && admin == nil { if let peer = peer, let address = peer.addressName, !address.isEmpty && admin == nil {
mainInvite = .link(link: "t.me/\(address)", title: nil, isPermanent: true, requestApproval: false, isRevoked: false, adminId: EnginePeer.Id(0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil, requestedCount: nil) mainInvite = .link(link: "t.me/\(address)", title: nil, isPermanent: true, requestApproval: false, isRevoked: false, adminId: EnginePeer.Id(0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil, requestedCount: nil, pricing: nil)
isPublic = true isPublic = true
} else if let invites = invites, let invite = invites.first(where: { $0.isPermanent && !$0.isRevoked }) { } else if let invites = invites, let invite = invites.first(where: { $0.isPermanent && !$0.isRevoked }) {
mainInvite = invite mainInvite = invite
@ -299,7 +299,7 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
let importersCount: Int32 let importersCount: Int32
if let count = importers?.count { if let count = importers?.count {
importersCount = count importersCount = count
} else if let mainInvite = mainInvite, case let .link(_, _, _, _, _, _, _, _, _, _, count, _) = mainInvite, let count = count { } else if let mainInvite = mainInvite, case let .link(_, _, _, _, _, _, _, _, _, _, count, _, _) = mainInvite, let count = count {
importersCount = count importersCount = count
} else { } else {
importersCount = 0 importersCount = 0
@ -338,7 +338,7 @@ private func inviteLinkListControllerEntries(presentationData: PresentationData,
if let additionalInvites = additionalInvites { if let additionalInvites = additionalInvites {
var index: Int32 = 0 var index: Int32 = 0
for invite in additionalInvites { for invite in additionalInvites {
if case let .link(_, _, _, _, _, _, _, _, expireDate, _, _, _) = invite { if case let .link(_, _, _, _, _, _, _, _, expireDate, _, _, _, _) = invite {
entries.append(.link(index, presentationData.theme, invite, canEditLinks, expireDate != nil ? tick : nil)) entries.append(.link(index, presentationData.theme, invite, canEditLinks, expireDate != nil ? tick : nil))
index += 1 index += 1
} }
@ -533,7 +533,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio
}) })
}))) })))
if case let .link(_, _, _, _, _, adminId, _, _, _, _, _, _) = invite, adminId.toInt64() != 0 { if case let .link(_, _, _, _, _, adminId, _, _, _, _, _, _, _) = invite, adminId.toInt64() != 0 {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.InviteLink_ContextRevoke, textColor: .destructive, icon: { theme in items.append(.action(ContextMenuActionItem(text: presentationData.strings.InviteLink_ContextRevoke, textColor: .destructive, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor)
}, action: { _, f in }, action: { _, f in

View File

@ -425,7 +425,7 @@ public final class InviteLinkViewController: ViewController {
self.controller = controller self.controller = controller
self.importersContext = importersContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: false)) self.importersContext = importersContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: false))
if case let .link(_, _, _, requestApproval, _, _, _, _, _, _, _, _) = invite, requestApproval { if case let .link(_, _, _, requestApproval, _, _, _, _, _, _, _, _, _) = invite, requestApproval {
self.requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: true)) self.requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: true))
} else { } else {
self.requestsContext = nil self.requestsContext = nil
@ -568,7 +568,7 @@ public final class InviteLinkViewController: ViewController {
} }
var creatorIsBot: Signal<Bool, NoError> var creatorIsBot: Signal<Bool, NoError>
if case let .link(_, _, _, _, _, adminId, _, _, _, _, _, _) = invite { if case let .link(_, _, _, _, _, adminId, _, _, _, _, _, _, _) = invite {
creatorIsBot = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: adminId)) creatorIsBot = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: adminId))
|> map { peer -> Bool in |> map { peer -> Bool in
if let peer, case let .user(user) = peer, user.botInfo != nil { if let peer, case let .user(user) = peer, user.botInfo != nil {
@ -716,7 +716,7 @@ public final class InviteLinkViewController: ViewController {
requestsState = .single(PeerInvitationImportersState.Empty) requestsState = .single(PeerInvitationImportersState.Empty)
} }
if case let .link(_, _, _, _, _, adminId, date, _, _, usageLimit, _, _) = invite { if case let .link(_, _, _, _, _, adminId, date, _, _, usageLimit, _, _, _) = invite {
self.disposable = (combineLatest( self.disposable = (combineLatest(
self.presentationDataPromise.get(), self.presentationDataPromise.get(),
self.importersContext.state, self.importersContext.state,
@ -1002,7 +1002,7 @@ public final class InviteLinkViewController: ViewController {
var subtitleText = "" var subtitleText = ""
var subtitleColor = self.presentationData.theme.list.itemSecondaryTextColor var subtitleColor = self.presentationData.theme.list.itemSecondaryTextColor
if case let .link(_, title, _, _, isRevoked, _, _, _, expireDate, usageLimit, count, _) = self.invite { if case let .link(_, title, _, _, isRevoked, _, _, _, expireDate, usageLimit, count, _, _) = self.invite {
if isRevoked { if isRevoked {
subtitleText = self.presentationData.strings.InviteLink_Revoked subtitleText = self.presentationData.strings.InviteLink_Revoked
} else if let usageLimit = usageLimit, let count = count, count >= usageLimit { } else if let usageLimit = usageLimit, let count = count, count >= usageLimit {

View File

@ -9,7 +9,7 @@ import ShimmerEffect
import TelegramCore import TelegramCore
func invitationAvailability(_ invite: ExportedInvitation) -> CGFloat { func invitationAvailability(_ invite: ExportedInvitation) -> CGFloat {
if case let .link(_, _, _, _, isRevoked, _, date, startDate, expireDate, usageLimit, count, _) = invite { if case let .link(_, _, _, _, isRevoked, _, date, startDate, expireDate, usageLimit, count, _, _) = invite {
if isRevoked { if isRevoked {
return 0.0 return 0.0
} }
@ -299,7 +299,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
let color: ItemBackgroundColor let color: ItemBackgroundColor
let nextColor: ItemBackgroundColor let nextColor: ItemBackgroundColor
let transitionFraction: CGFloat let transitionFraction: CGFloat
if let invite = item.invite, case let .link(_, _, _, _, isRevoked, _, _, _, expireDate, usageLimit, _, _) = invite { if let invite = item.invite, case let .link(_, _, _, _, isRevoked, _, _, _, expireDate, usageLimit, _, _, _) = invite {
if isRevoked { if isRevoked {
color = .gray color = .gray
nextColor = .gray nextColor = .gray
@ -346,7 +346,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
var timerValue: TimerNode.Value? var timerValue: TimerNode.Value?
if let invite = item.invite, case let .link(_, title, _, _, _, _, date, startDate, expireDate, usageLimit, count, requestedCount) = invite { if let invite = item.invite, case let .link(_, title, _, _, _, _, date, startDate, expireDate, usageLimit, count, requestedCount, _) = invite {
if let title = title, !title.isEmpty { if let title = title, !title.isEmpty {
titleText = title titleText = title
} }

View File

@ -1024,7 +1024,7 @@ private enum StatsEntry: ItemListNodeEntry {
case let .boostOverview(_, stats, isGroup): case let .boostOverview(_, stats, isGroup):
return StatsOverviewItem(context: arguments.context, presentationData: presentationData, isGroup: isGroup, stats: stats, sectionId: self.section, style: .blocks) return StatsOverviewItem(context: arguments.context, presentationData: presentationData, isGroup: isGroup, stats: stats, sectionId: self.section, style: .blocks)
case let .boostLink(_, link): case let .boostLink(_, link):
let invite: ExportedInvitation = .link(link: link, title: nil, isPermanent: false, requestApproval: false, isRevoked: false, adminId: PeerId(0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil, requestedCount: nil) let invite: ExportedInvitation = .link(link: link, title: nil, isPermanent: false, requestApproval: false, isRevoked: false, adminId: PeerId(0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil, requestedCount: nil, pricing: nil)
return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: invite, count: 0, peers: [], displayButton: true, displayImporters: false, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: { return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: invite, count: 0, peers: [], displayButton: true, displayImporters: false, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: {
arguments.copyBoostLink(link) arguments.copyBoostLink(link)
}, shareAction: { }, shareAction: {

View File

@ -201,7 +201,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) } dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
dict[-1146407795] = { return Api.ChatFull.parse_channelFull($0) } dict[-1146407795] = { return Api.ChatFull.parse_channelFull($0) }
dict[640893467] = { return Api.ChatFull.parse_chatFull($0) } dict[640893467] = { return Api.ChatFull.parse_chatFull($0) }
dict[-840897472] = { return Api.ChatInvite.parse_chatInvite($0) } dict[-1965998484] = { return Api.ChatInvite.parse_chatInvite($0) }
dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) } dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) }
dict[1634294960] = { return Api.ChatInvite.parse_chatInvitePeek($0) } dict[1634294960] = { return Api.ChatInvite.parse_chatInvitePeek($0) }
dict[-1940201511] = { return Api.ChatInviteImporter.parse_chatInviteImporter($0) } dict[-1940201511] = { return Api.ChatInviteImporter.parse_chatInviteImporter($0) }
@ -273,7 +273,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1038136962] = { return Api.EncryptedFile.parse_encryptedFileEmpty($0) } dict[-1038136962] = { return Api.EncryptedFile.parse_encryptedFileEmpty($0) }
dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) } dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) }
dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) } dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) }
dict[179611673] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) } dict[-1812799720] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[-317687113] = { return Api.ExportedChatInvite.parse_chatInvitePublicJoinRequests($0) } dict[-317687113] = { return Api.ExportedChatInvite.parse_chatInvitePublicJoinRequests($0) }
dict[206668204] = { return Api.ExportedChatlistInvite.parse_exportedChatlistInvite($0) } dict[206668204] = { return Api.ExportedChatlistInvite.parse_exportedChatlistInvite($0) }
dict[1103040667] = { return Api.ExportedContactToken.parse_exportedContactToken($0) } dict[1103040667] = { return Api.ExportedContactToken.parse_exportedContactToken($0) }
@ -370,6 +370,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) } dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) } dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
dict[-659913713] = { return Api.InputGroupCall.parse_inputGroupCall($0) } dict[-659913713] = { return Api.InputGroupCall.parse_inputGroupCall($0) }
dict[887591921] = { return Api.InputInvoice.parse_inputInvoiceChatInviteSubscription($0) }
dict[-977967015] = { return Api.InputInvoice.parse_inputInvoiceMessage($0) } dict[-977967015] = { return Api.InputInvoice.parse_inputInvoiceMessage($0) }
dict[-1734841331] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftCode($0) } dict[-1734841331] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftCode($0) }
dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) } dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) }
@ -879,8 +880,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) } dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
dict[1577421297] = { return Api.StarsGiftOption.parse_starsGiftOption($0) } dict[1577421297] = { return Api.StarsGiftOption.parse_starsGiftOption($0) }
dict[2033461574] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) } dict[2033461574] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) }
dict[-797707802] = { return Api.StarsSubscription.parse_starsSubscription($0) }
dict[88173912] = { return Api.StarsSubscriptionPricing.parse_starsSubscriptionPricing($0) }
dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) } dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) }
dict[766853519] = { return Api.StarsTransaction.parse_starsTransaction($0) } dict[455361027] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) } dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) }
dict[1617438738] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAds($0) } dict[1617438738] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAds($0) }
dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) } dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) }
@ -1325,7 +1328,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[961445665] = { return Api.payments.StarsRevenueAdsAccountUrl.parse_starsRevenueAdsAccountUrl($0) } dict[961445665] = { return Api.payments.StarsRevenueAdsAccountUrl.parse_starsRevenueAdsAccountUrl($0) }
dict[-919881925] = { return Api.payments.StarsRevenueStats.parse_starsRevenueStats($0) } dict[-919881925] = { return Api.payments.StarsRevenueStats.parse_starsRevenueStats($0) }
dict[497778871] = { return Api.payments.StarsRevenueWithdrawalUrl.parse_starsRevenueWithdrawalUrl($0) } dict[497778871] = { return Api.payments.StarsRevenueWithdrawalUrl.parse_starsRevenueWithdrawalUrl($0) }
dict[-1930105248] = { return Api.payments.StarsStatus.parse_starsStatus($0) } dict[-2064727699] = { return Api.payments.StarsStatus.parse_starsStatus($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) } dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[541839704] = { return Api.phone.ExportedGroupCallInvite.parse_exportedGroupCallInvite($0) } dict[541839704] = { return Api.phone.ExportedGroupCallInvite.parse_exportedGroupCallInvite($0) }
dict[-1636664659] = { return Api.phone.GroupCall.parse_groupCall($0) } dict[-1636664659] = { return Api.phone.GroupCall.parse_groupCall($0) }
@ -1996,6 +1999,10 @@ public extension Api {
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsRevenueStatus: case let _1 as Api.StarsRevenueStatus:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsSubscription:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsSubscriptionPricing:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsTopupOption: case let _1 as Api.StarsTopupOption:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsTransaction: case let _1 as Api.StarsTransaction:

View File

@ -670,6 +670,102 @@ public extension Api {
} }
} }
public extension Api {
enum StarsSubscription: TypeConstructorDescription {
case starsSubscription(flags: Int32, id: String, peer: Api.Peer, untilDate: Int32, pricing: Api.StarsSubscriptionPricing)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing):
if boxed {
buffer.appendInt32(-797707802)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(untilDate, buffer: buffer, boxed: false)
pricing.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing):
return ("starsSubscription", [("flags", flags as Any), ("id", id as Any), ("peer", peer as Any), ("untilDate", untilDate as Any), ("pricing", pricing as Any)])
}
}
public static func parse_starsSubscription(_ reader: BufferReader) -> StarsSubscription? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Api.Peer?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _4: Int32?
_4 = reader.readInt32()
var _5: Api.StarsSubscriptionPricing?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StarsSubscription.starsSubscription(flags: _1!, id: _2!, peer: _3!, untilDate: _4!, pricing: _5!)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsSubscriptionPricing: TypeConstructorDescription {
case starsSubscriptionPricing(period: Int32, amount: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsSubscriptionPricing(let period, let amount):
if boxed {
buffer.appendInt32(88173912)
}
serializeInt32(period, buffer: buffer, boxed: false)
serializeInt64(amount, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsSubscriptionPricing(let period, let amount):
return ("starsSubscriptionPricing", [("period", period as Any), ("amount", amount as Any)])
}
}
public static func parse_starsSubscriptionPricing(_ reader: BufferReader) -> StarsSubscriptionPricing? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.StarsSubscriptionPricing.starsSubscriptionPricing(period: _1!, amount: _2!)
}
else {
return nil
}
}
}
}
public extension Api { public extension Api {
enum StarsTopupOption: TypeConstructorDescription { enum StarsTopupOption: TypeConstructorDescription {
case starsTopupOption(flags: Int32, stars: Int64, storeProduct: String?, currency: String, amount: Int64) case starsTopupOption(flags: Int32, stars: Int64, storeProduct: String?, currency: String, amount: Int64)
@ -724,13 +820,13 @@ public extension Api {
} }
public extension Api { public extension Api {
enum StarsTransaction: TypeConstructorDescription { enum StarsTransaction: TypeConstructorDescription {
case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?, transactionDate: Int32?, transactionUrl: String?, botPayload: Buffer?, msgId: Int32?, extendedMedia: [Api.MessageMedia]?) case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?, transactionDate: Int32?, transactionUrl: String?, botPayload: Buffer?, msgId: Int32?, extendedMedia: [Api.MessageMedia]?, subscriptionPeriod: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia): case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod):
if boxed { if boxed {
buffer.appendInt32(766853519) buffer.appendInt32(455361027)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false) serializeString(id, buffer: buffer, boxed: false)
@ -749,14 +845,15 @@ public extension Api {
for item in extendedMedia! { for item in extendedMedia! {
item.serialize(buffer, true) item.serialize(buffer, true)
}} }}
if Int(flags) & Int(1 << 11) != 0 {serializeInt32(subscriptionPeriod!, buffer: buffer, boxed: false)}
break break
} }
} }
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia): case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod):
return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("transactionDate", transactionDate as Any), ("transactionUrl", transactionUrl as Any), ("botPayload", botPayload as Any), ("msgId", msgId as Any), ("extendedMedia", extendedMedia as Any)]) return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("transactionDate", transactionDate as Any), ("transactionUrl", transactionUrl as Any), ("botPayload", botPayload as Any), ("msgId", msgId as Any), ("extendedMedia", extendedMedia as Any), ("subscriptionPeriod", subscriptionPeriod as Any)])
} }
} }
@ -793,6 +890,8 @@ public extension Api {
if Int(_1!) & Int(1 << 9) != 0 {if let _ = reader.readInt32() { if Int(_1!) & Int(1 << 9) != 0 {if let _ = reader.readInt32() {
_13 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageMedia.self) _13 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageMedia.self)
} } } }
var _14: Int32?
if Int(_1!) & Int(1 << 11) != 0 {_14 = reader.readInt32() }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
@ -806,8 +905,9 @@ public extension Api {
let _c11 = (Int(_1!) & Int(1 << 7) == 0) || _11 != nil let _c11 = (Int(_1!) & Int(1 << 7) == 0) || _11 != nil
let _c12 = (Int(_1!) & Int(1 << 8) == 0) || _12 != nil let _c12 = (Int(_1!) & Int(1 << 8) == 0) || _12 != nil
let _c13 = (Int(_1!) & Int(1 << 9) == 0) || _13 != nil let _c13 = (Int(_1!) & Int(1 << 9) == 0) || _13 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 { let _c14 = (Int(_1!) & Int(1 << 11) == 0) || _14 != nil
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10, botPayload: _11, msgId: _12, extendedMedia: _13) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 {
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10, botPayload: _11, msgId: _12, extendedMedia: _13, subscriptionPeriod: _14)
} }
else { else {
return nil return nil

View File

@ -1246,21 +1246,27 @@ public extension Api.payments {
} }
public extension Api.payments { public extension Api.payments {
enum StarsStatus: TypeConstructorDescription { enum StarsStatus: TypeConstructorDescription {
case starsStatus(flags: Int32, balance: Int64, history: [Api.StarsTransaction], nextOffset: String?, chats: [Api.Chat], users: [Api.User]) case starsStatus(flags: Int32, balance: Int64, subscriptions: [Api.StarsSubscription]?, subscriptionsNextOffset: String?, history: [Api.StarsTransaction]?, nextOffset: String?, chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .starsStatus(let flags, let balance, let history, let nextOffset, let chats, let users): case .starsStatus(let flags, let balance, let subscriptions, let subscriptionsNextOffset, let history, let nextOffset, let chats, let users):
if boxed { if boxed {
buffer.appendInt32(-1930105248) buffer.appendInt32(-2064727699)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(balance, buffer: buffer, boxed: false) serializeInt64(balance, buffer: buffer, boxed: false)
buffer.appendInt32(481674261) if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(history.count)) buffer.appendInt32(Int32(subscriptions!.count))
for item in history { for item in subscriptions! {
item.serialize(buffer, true) item.serialize(buffer, true)
} }}
if Int(flags) & Int(1 << 2) != 0 {serializeString(subscriptionsNextOffset!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(history!.count))
for item in history! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261) buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count)) buffer.appendInt32(Int32(chats.count))
@ -1278,8 +1284,8 @@ public extension Api.payments {
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .starsStatus(let flags, let balance, let history, let nextOffset, let chats, let users): case .starsStatus(let flags, let balance, let subscriptions, let subscriptionsNextOffset, let history, let nextOffset, let chats, let users):
return ("starsStatus", [("flags", flags as Any), ("balance", balance as Any), ("history", history as Any), ("nextOffset", nextOffset as Any), ("chats", chats as Any), ("users", users as Any)]) return ("starsStatus", [("flags", flags as Any), ("balance", balance as Any), ("subscriptions", subscriptions as Any), ("subscriptionsNextOffset", subscriptionsNextOffset as Any), ("history", history as Any), ("nextOffset", nextOffset as Any), ("chats", chats as Any), ("users", users as Any)])
} }
} }
@ -1288,28 +1294,36 @@ public extension Api.payments {
_1 = reader.readInt32() _1 = reader.readInt32()
var _2: Int64? var _2: Int64?
_2 = reader.readInt64() _2 = reader.readInt64()
var _3: [Api.StarsTransaction]? var _3: [Api.StarsSubscription]?
if let _ = reader.readInt32() { if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsTransaction.self) _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsSubscription.self)
} } }
var _4: String? var _4: String?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } if Int(_1!) & Int(1 << 2) != 0 {_4 = parseString(reader) }
var _5: [Api.Chat]? var _5: [Api.StarsTransaction]?
if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsTransaction.self)
} }
var _6: String?
if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) }
var _7: [Api.Chat]?
if let _ = reader.readInt32() { if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
} }
var _6: [Api.User]? var _8: [Api.User]?
if let _ = reader.readInt32() { if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
} }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
let _c5 = _5 != nil let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
let _c6 = _6 != nil let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { let _c7 = _7 != nil
return Api.payments.StarsStatus.starsStatus(flags: _1!, balance: _2!, history: _3!, nextOffset: _4, chats: _5!, users: _6!) let _c8 = _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.payments.StarsStatus.starsStatus(flags: _1!, balance: _2!, subscriptions: _3, subscriptionsNextOffset: _4, history: _5, nextOffset: _6, chats: _7!, users: _8!)
} }
else { else {
return nil return nil

View File

@ -5439,15 +5439,16 @@ public extension Api.functions.messages {
} }
} }
public extension Api.functions.messages { public extension Api.functions.messages {
static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?, title: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) { static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?, title: String?, subscriptionPricing: Api.StarsSubscriptionPricing?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(-1607670315) buffer.appendInt32(-1537876336)
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in if Int(flags) & Int(1 << 5) != 0 {subscriptionPricing!.serialize(buffer, true)}
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("title", String(describing: title)), ("subscriptionPricing", String(describing: subscriptionPricing))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
let reader = BufferReader(buffer) let reader = BufferReader(buffer)
var result: Api.ExportedChatInvite? var result: Api.ExportedChatInvite?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
@ -8735,6 +8736,24 @@ public extension Api.functions.payments {
}) })
} }
} }
public extension Api.functions.payments {
static func changeStarsSubscription(flags: Int32, peer: Api.InputPeer, subscriptionId: String, canceled: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-948500360)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeString(subscriptionId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {canceled!.serialize(buffer, true)}
return (FunctionDescription(name: "payments.changeStarsSubscription", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("subscriptionId", String(describing: subscriptionId)), ("canceled", String(describing: canceled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
}
public extension Api.functions.payments { public extension Api.functions.payments {
static func checkGiftCode(slug: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.CheckedGiftCode>) { static func checkGiftCode(slug: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.CheckedGiftCode>) {
let buffer = Buffer() let buffer = Buffer()
@ -8954,6 +8973,22 @@ public extension Api.functions.payments {
}) })
} }
} }
public extension Api.functions.payments {
static func getStarsSubscriptions(peer: Api.InputPeer, offset: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
let buffer = Buffer()
buffer.appendInt32(-2145547570)
peer.serialize(buffer, true)
serializeString(offset, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getStarsSubscriptions", parameters: [("peer", String(describing: peer)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
let reader = BufferReader(buffer)
var result: Api.payments.StarsStatus?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.StarsStatus
}
return result
})
}
}
public extension Api.functions.payments { public extension Api.functions.payments {
static func getStarsTopupOptions() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.StarsTopupOption]>) { static func getStarsTopupOptions() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.StarsTopupOption]>) {
let buffer = Buffer() let buffer = Buffer()

View File

@ -1280,15 +1280,15 @@ public extension Api {
} }
public extension Api { public extension Api {
indirect enum ChatInvite: TypeConstructorDescription { indirect enum ChatInvite: TypeConstructorDescription {
case chatInvite(flags: Int32, title: String, about: String?, photo: Api.Photo, participantsCount: Int32, participants: [Api.User]?, color: Int32) case chatInvite(flags: Int32, title: String, about: String?, photo: Api.Photo, participantsCount: Int32, participants: [Api.User]?, color: Int32, subscriptionPricing: Api.StarsSubscriptionPricing?, subscriptionFormId: Int64?)
case chatInviteAlready(chat: Api.Chat) case chatInviteAlready(chat: Api.Chat)
case chatInvitePeek(chat: Api.Chat, expires: Int32) case chatInvitePeek(chat: Api.Chat, expires: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color): case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color, let subscriptionPricing, let subscriptionFormId):
if boxed { if boxed {
buffer.appendInt32(-840897472) buffer.appendInt32(-1965998484)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(title, buffer: buffer, boxed: false) serializeString(title, buffer: buffer, boxed: false)
@ -1301,6 +1301,8 @@ public extension Api {
item.serialize(buffer, true) item.serialize(buffer, true)
}} }}
serializeInt32(color, buffer: buffer, boxed: false) serializeInt32(color, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 10) != 0 {subscriptionPricing!.serialize(buffer, true)}
if Int(flags) & Int(1 << 10) != 0 {serializeInt64(subscriptionFormId!, buffer: buffer, boxed: false)}
break break
case .chatInviteAlready(let chat): case .chatInviteAlready(let chat):
if boxed { if boxed {
@ -1320,8 +1322,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color): case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color, let subscriptionPricing, let subscriptionFormId):
return ("chatInvite", [("flags", flags as Any), ("title", title as Any), ("about", about as Any), ("photo", photo as Any), ("participantsCount", participantsCount as Any), ("participants", participants as Any), ("color", color as Any)]) return ("chatInvite", [("flags", flags as Any), ("title", title as Any), ("about", about as Any), ("photo", photo as Any), ("participantsCount", participantsCount as Any), ("participants", participants as Any), ("color", color as Any), ("subscriptionPricing", subscriptionPricing as Any), ("subscriptionFormId", subscriptionFormId as Any)])
case .chatInviteAlready(let chat): case .chatInviteAlready(let chat):
return ("chatInviteAlready", [("chat", chat as Any)]) return ("chatInviteAlready", [("chat", chat as Any)])
case .chatInvitePeek(let chat, let expires): case .chatInvitePeek(let chat, let expires):
@ -1348,6 +1350,12 @@ public extension Api {
} } } }
var _7: Int32? var _7: Int32?
_7 = reader.readInt32() _7 = reader.readInt32()
var _8: Api.StarsSubscriptionPricing?
if Int(_1!) & Int(1 << 10) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
} }
var _9: Int64?
if Int(_1!) & Int(1 << 10) != 0 {_9 = reader.readInt64() }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _3 != nil let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _3 != nil
@ -1355,8 +1363,10 @@ public extension Api {
let _c5 = _5 != nil let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil
let _c7 = _7 != nil let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { let _c8 = (Int(_1!) & Int(1 << 10) == 0) || _8 != nil
return Api.ChatInvite.chatInvite(flags: _1!, title: _2!, about: _3, photo: _4!, participantsCount: _5!, participants: _6, color: _7!) let _c9 = (Int(_1!) & Int(1 << 10) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.ChatInvite.chatInvite(flags: _1!, title: _2!, about: _3, photo: _4!, participantsCount: _5!, participants: _6, color: _7!, subscriptionPricing: _8, subscriptionFormId: _9)
} }
else { else {
return nil return nil

View File

@ -1012,14 +1012,14 @@ public extension Api {
} }
public extension Api { public extension Api {
enum ExportedChatInvite: TypeConstructorDescription { enum ExportedChatInvite: TypeConstructorDescription {
case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, requested: Int32?, title: String?) case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, requested: Int32?, title: String?, subscriptionPricing: Api.StarsSubscriptionPricing?)
case chatInvitePublicJoinRequests case chatInvitePublicJoinRequests
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title): case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title, let subscriptionPricing):
if boxed { if boxed {
buffer.appendInt32(179611673) buffer.appendInt32(-1812799720)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(link, buffer: buffer, boxed: false) serializeString(link, buffer: buffer, boxed: false)
@ -1031,6 +1031,7 @@ public extension Api {
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(requested!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 7) != 0 {serializeInt32(requested!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 8) != 0 {serializeString(title!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 8) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 9) != 0 {subscriptionPricing!.serialize(buffer, true)}
break break
case .chatInvitePublicJoinRequests: case .chatInvitePublicJoinRequests:
if boxed { if boxed {
@ -1043,8 +1044,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title): case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title, let subscriptionPricing):
return ("chatInviteExported", [("flags", flags as Any), ("link", link as Any), ("adminId", adminId as Any), ("date", date as Any), ("startDate", startDate as Any), ("expireDate", expireDate as Any), ("usageLimit", usageLimit as Any), ("usage", usage as Any), ("requested", requested as Any), ("title", title as Any)]) return ("chatInviteExported", [("flags", flags as Any), ("link", link as Any), ("adminId", adminId as Any), ("date", date as Any), ("startDate", startDate as Any), ("expireDate", expireDate as Any), ("usageLimit", usageLimit as Any), ("usage", usage as Any), ("requested", requested as Any), ("title", title as Any), ("subscriptionPricing", subscriptionPricing as Any)])
case .chatInvitePublicJoinRequests: case .chatInvitePublicJoinRequests:
return ("chatInvitePublicJoinRequests", []) return ("chatInvitePublicJoinRequests", [])
} }
@ -1071,6 +1072,10 @@ public extension Api {
if Int(_1!) & Int(1 << 7) != 0 {_9 = reader.readInt32() } if Int(_1!) & Int(1 << 7) != 0 {_9 = reader.readInt32() }
var _10: String? var _10: String?
if Int(_1!) & Int(1 << 8) != 0 {_10 = parseString(reader) } if Int(_1!) & Int(1 << 8) != 0 {_10 = parseString(reader) }
var _11: Api.StarsSubscriptionPricing?
if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
} }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
@ -1081,8 +1086,9 @@ public extension Api {
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil
let _c10 = (Int(_1!) & Int(1 << 8) == 0) || _10 != nil let _c10 = (Int(_1!) & Int(1 << 8) == 0) || _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { let _c11 = (Int(_1!) & Int(1 << 9) == 0) || _11 != nil
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, requested: _9, title: _10) if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, requested: _9, title: _10, subscriptionPricing: _11)
} }
else { else {
return nil return nil

View File

@ -1004,6 +1004,7 @@ public extension Api {
} }
public extension Api { public extension Api {
indirect enum InputInvoice: TypeConstructorDescription { indirect enum InputInvoice: TypeConstructorDescription {
case inputInvoiceChatInviteSubscription(hash: String)
case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32) case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32)
case inputInvoicePremiumGiftCode(purpose: Api.InputStorePaymentPurpose, option: Api.PremiumGiftCodeOption) case inputInvoicePremiumGiftCode(purpose: Api.InputStorePaymentPurpose, option: Api.PremiumGiftCodeOption)
case inputInvoiceSlug(slug: String) case inputInvoiceSlug(slug: String)
@ -1011,6 +1012,12 @@ public extension Api {
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .inputInvoiceChatInviteSubscription(let hash):
if boxed {
buffer.appendInt32(887591921)
}
serializeString(hash, buffer: buffer, boxed: false)
break
case .inputInvoiceMessage(let peer, let msgId): case .inputInvoiceMessage(let peer, let msgId):
if boxed { if boxed {
buffer.appendInt32(-977967015) buffer.appendInt32(-977967015)
@ -1042,6 +1049,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .inputInvoiceChatInviteSubscription(let hash):
return ("inputInvoiceChatInviteSubscription", [("hash", hash as Any)])
case .inputInvoiceMessage(let peer, let msgId): case .inputInvoiceMessage(let peer, let msgId):
return ("inputInvoiceMessage", [("peer", peer as Any), ("msgId", msgId as Any)]) return ("inputInvoiceMessage", [("peer", peer as Any), ("msgId", msgId as Any)])
case .inputInvoicePremiumGiftCode(let purpose, let option): case .inputInvoicePremiumGiftCode(let purpose, let option):
@ -1053,6 +1062,17 @@ public extension Api {
} }
} }
public static func parse_inputInvoiceChatInviteSubscription(_ reader: BufferReader) -> InputInvoice? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputInvoice.inputInvoiceChatInviteSubscription(hash: _1!)
}
else {
return nil
}
}
public static func parse_inputInvoiceMessage(_ reader: BufferReader) -> InputInvoice? { public static func parse_inputInvoiceMessage(_ reader: BufferReader) -> InputInvoice? {
var _1: Api.InputPeer? var _1: Api.InputPeer?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {

View File

@ -6,8 +6,8 @@ import TelegramApi
extension ExportedInvitation { extension ExportedInvitation {
init(apiExportedInvite: Api.ExportedChatInvite) { init(apiExportedInvite: Api.ExportedChatInvite) {
switch apiExportedInvite { switch apiExportedInvite {
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, title): case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, title, pricing):
self = .link(link: link, title: title, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, requestedCount: requested) self = .link(link: link, title: title, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, requestedCount: requested, pricing: pricing.flatMap { StarsSubscriptionPricing(apiStarsSubscriptionPricing: $0) })
case .chatInvitePublicJoinRequests: case .chatInvitePublicJoinRequests:
self = .publicJoinRequest self = .publicJoinRequest
} }
@ -17,7 +17,7 @@ extension ExportedInvitation {
public extension ExportedInvitation { public extension ExportedInvitation {
var link: String? { var link: String? {
switch self { switch self {
case let .link(link, _, _, _, _, _, _, _, _, _, _, _): case let .link(link, _, _, _, _, _, _, _, _, _, _, _, _):
return link return link
case .publicJoinRequest: case .publicJoinRequest:
return nil return nil
@ -26,7 +26,7 @@ public extension ExportedInvitation {
var date: Int32? { var date: Int32? {
switch self { switch self {
case let .link(_, _, _, _, _, _, date, _, _, _, _, _): case let .link(_, _, _, _, _, _, date, _, _, _, _, _, _):
return date return date
case .publicJoinRequest: case .publicJoinRequest:
return nil return nil
@ -35,7 +35,7 @@ public extension ExportedInvitation {
var isPermanent: Bool { var isPermanent: Bool {
switch self { switch self {
case let .link(_, _, isPermanent, _, _, _, _, _, _, _, _, _): case let .link(_, _, isPermanent, _, _, _, _, _, _, _, _, _, _):
return isPermanent return isPermanent
case .publicJoinRequest: case .publicJoinRequest:
return false return false
@ -44,10 +44,19 @@ public extension ExportedInvitation {
var isRevoked: Bool { var isRevoked: Bool {
switch self { switch self {
case let .link(_, _, _, _, isRevoked, _, _, _, _, _, _, _): case let .link(_, _, _, _, isRevoked, _, _, _, _, _, _, _, _):
return isRevoked return isRevoked
case .publicJoinRequest: case .publicJoinRequest:
return false return false
} }
} }
var pricing: StarsSubscriptionPricing? {
switch self {
case let .link(_, _, _, _, _, _, _, _, _, _, _, _, pricing):
return pricing
case .publicJoinRequest:
return nil
}
}
} }

View File

@ -1,7 +1,7 @@
import Postbox import Postbox
public enum ExportedInvitation: Codable, Equatable { public enum ExportedInvitation: Codable, Equatable {
case link(link: String, title: String?, isPermanent: Bool, requestApproval: Bool, isRevoked: Bool, adminId: PeerId, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, count: Int32?, requestedCount: Int32?) case link(link: String, title: String?, isPermanent: Bool, requestApproval: Bool, isRevoked: Bool, adminId: PeerId, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, count: Int32?, requestedCount: Int32?, pricing: StarsSubscriptionPricing?)
case publicJoinRequest case publicJoinRequest
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
@ -21,8 +21,9 @@ public enum ExportedInvitation: Codable, Equatable {
let usageLimit = try container.decodeIfPresent(Int32.self, forKey: "usageLimit") let usageLimit = try container.decodeIfPresent(Int32.self, forKey: "usageLimit")
let count = try container.decodeIfPresent(Int32.self, forKey: "count") let count = try container.decodeIfPresent(Int32.self, forKey: "count")
let requestedCount = try? container.decodeIfPresent(Int32.self, forKey: "requestedCount") let requestedCount = try? container.decodeIfPresent(Int32.self, forKey: "requestedCount")
let pricing = try? container.decodeIfPresent(StarsSubscriptionPricing.self, forKey: "pricing")
self = .link(link: link, title: title, isPermanent: isPermanent, requestApproval: requestApproval, isRevoked: isRevoked, adminId: adminId, date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: count, requestedCount: requestedCount) self = .link(link: link, title: title, isPermanent: isPermanent, requestApproval: requestApproval, isRevoked: isRevoked, adminId: adminId, date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: count, requestedCount: requestedCount, pricing: pricing)
} else { } else {
self = .publicJoinRequest self = .publicJoinRequest
} }
@ -32,7 +33,7 @@ public enum ExportedInvitation: Codable, Equatable {
var container = encoder.container(keyedBy: StringCodingKey.self) var container = encoder.container(keyedBy: StringCodingKey.self)
switch self { switch self {
case let .link(link, title, isPermanent, requestApproval, isRevoked, adminId, date, startDate, expireDate, usageLimit, count, requestedCount): case let .link(link, title, isPermanent, requestApproval, isRevoked, adminId, date, startDate, expireDate, usageLimit, count, requestedCount, pricing):
let type: Int32 = 0 let type: Int32 = 0
try container.encode(type, forKey: "t") try container.encode(type, forKey: "t")
try container.encode(link, forKey: "l") try container.encode(link, forKey: "l")
@ -47,6 +48,7 @@ public enum ExportedInvitation: Codable, Equatable {
try container.encodeIfPresent(usageLimit, forKey: "usageLimit") try container.encodeIfPresent(usageLimit, forKey: "usageLimit")
try container.encodeIfPresent(count, forKey: "count") try container.encodeIfPresent(count, forKey: "count")
try container.encodeIfPresent(requestedCount, forKey: "requestedCount") try container.encodeIfPresent(requestedCount, forKey: "requestedCount")
try container.encodeIfPresent(pricing, forKey: "pricing")
case .publicJoinRequest: case .publicJoinRequest:
let type: Int32 = 1 let type: Int32 = 1
try container.encode(type, forKey: "t") try container.encode(type, forKey: "t")
@ -55,8 +57,8 @@ public enum ExportedInvitation: Codable, Equatable {
public static func ==(lhs: ExportedInvitation, rhs: ExportedInvitation) -> Bool { public static func ==(lhs: ExportedInvitation, rhs: ExportedInvitation) -> Bool {
switch lhs { switch lhs {
case let .link(link, title, isPermanent, requestApproval, isRevoked, adminId, date, startDate, expireDate, usageLimit, count, requestedCount): case let .link(link, title, isPermanent, requestApproval, isRevoked, adminId, date, startDate, expireDate, usageLimit, count, requestedCount, pricing):
if case .link(link, title, isPermanent, requestApproval, isRevoked, adminId, date, startDate, expireDate, usageLimit, count, requestedCount) = rhs { if case .link(link, title, isPermanent, requestApproval, isRevoked, adminId, date, startDate, expireDate, usageLimit, count, requestedCount, pricing) = rhs {
return true return true
} else { } else {
return false return false
@ -72,8 +74,8 @@ public enum ExportedInvitation: Codable, Equatable {
public func withUpdated(isRevoked: Bool) -> ExportedInvitation { public func withUpdated(isRevoked: Bool) -> ExportedInvitation {
switch self { switch self {
case let .link(link, title, isPermanent, requestApproval, _, adminId, date, startDate, expireDate, usageLimit, count, requestedCount): case let .link(link, title, isPermanent, requestApproval, _, adminId, date, startDate, expireDate, usageLimit, count, requestedCount, pricing):
return .link(link: link, title: title, isPermanent: isPermanent, requestApproval: requestApproval, isRevoked: isRevoked, adminId: adminId, date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: count, requestedCount: requestedCount) return .link(link: link, title: title, isPermanent: isPermanent, requestApproval: requestApproval, isRevoked: isRevoked, adminId: adminId, date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: count, requestedCount: requestedCount, pricing: pricing)
case .publicJoinRequest: case .publicJoinRequest:
return .publicJoinRequest return .publicJoinRequest
} }

View File

@ -11,6 +11,7 @@ public enum BotPaymentInvoiceSource {
case giftCode(users: [PeerId], currency: String, amount: Int64, option: PremiumGiftCodeOption) case giftCode(users: [PeerId], currency: String, amount: Int64, option: PremiumGiftCodeOption)
case stars(option: StarsTopUpOption) case stars(option: StarsTopUpOption)
case starsGift(peerId: EnginePeer.Id, count: Int64, currency: String, amount: Int64) case starsGift(peerId: EnginePeer.Id, count: Int64, currency: String, amount: Int64)
case starsChatSubscription(hash: String)
} }
public struct BotPaymentInvoiceFields: OptionSet { public struct BotPaymentInvoiceFields: OptionSet {
@ -314,6 +315,8 @@ func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInv
return nil return nil
} }
return .inputInvoiceStars(purpose: .inputStorePaymentStarsGift(userId: inputUser, stars: count, currency: currency, amount: amount)) return .inputInvoiceStars(purpose: .inputStorePaymentStarsGift(userId: inputUser, stars: count, currency: currency, amount: amount))
case let .starsChatSubscription(hash):
return .inputInvoiceChatInviteSubscription(hash: hash)
} }
} }
@ -612,7 +615,7 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
receiptMessageId = id receiptMessageId = id
} }
} }
case .giftCode, .stars, .starsGift: case .giftCode, .stars, .starsGift, .starsChatSubscription:
receiptMessageId = nil receiptMessageId = nil
} }
} }

View File

@ -147,8 +147,10 @@ func _internal_starsGiftOptions(account: Account, peerId: EnginePeer.Id?) -> Sig
struct InternalStarsStatus { struct InternalStarsStatus {
let balance: Int64 let balance: Int64
let subscriptions: [StarsContext.State.Subscription]
let nextSubscriptionsOffset: String?
let transactions: [StarsContext.State.Transaction] let transactions: [StarsContext.State.Transaction]
let nextOffset: String? let nextTransactionsOffset: String?
} }
private enum RequestStarsStateError { private enum RequestStarsStateError {
@ -187,17 +189,25 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
|> mapToSignal { result -> Signal<InternalStarsStatus, RequestStarsStateError> in |> mapToSignal { result -> Signal<InternalStarsStatus, RequestStarsStateError> in
return account.postbox.transaction { transaction -> InternalStarsStatus in return account.postbox.transaction { transaction -> InternalStarsStatus in
switch result { switch result {
case let .starsStatus(_, balance, history, nextOffset, chats, users): case let .starsStatus(_, balance, _, _, transactions, nextTransactionsOffset, chats, users):
let peers = AccumulatedPeers(chats: chats, users: users) let peers = AccumulatedPeers(chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers) updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers)
var parsedTransactions: [StarsContext.State.Transaction] = [] var parsedTransactions: [StarsContext.State.Transaction] = []
for entry in history { if let transactions {
if let parsedTransaction = StarsContext.State.Transaction(apiTransaction: entry, peerId: peerId != account.peerId ? peerId : nil, transaction: transaction) { for entry in transactions {
parsedTransactions.append(parsedTransaction) if let parsedTransaction = StarsContext.State.Transaction(apiTransaction: entry, peerId: peerId != account.peerId ? peerId : nil, transaction: transaction) {
parsedTransactions.append(parsedTransaction)
}
} }
} }
return InternalStarsStatus(balance: balance, transactions: parsedTransactions, nextOffset: nextOffset) return InternalStarsStatus(
balance: balance,
subscriptions: [],
nextSubscriptionsOffset: nil,
transactions: parsedTransactions,
nextTransactionsOffset: nextTransactionsOffset
)
} }
} }
|> castError(RequestStarsStateError.self) |> castError(RequestStarsStateError.self)
@ -205,6 +215,51 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
} }
} }
private enum RequestStarsSubscriptionsError {
case generic
}
private func _internal_requestStarsSubscriptions(account: Account, peerId: EnginePeer.Id, offset: String) -> Signal<InternalStarsStatus, RequestStarsSubscriptionsError> {
return account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
|> castError(RequestStarsSubscriptionsError.self)
|> mapToSignal { peer -> Signal<InternalStarsStatus, RequestStarsSubscriptionsError> in
guard let peer, let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
return account.network.request(Api.functions.payments.getStarsSubscriptions(peer: inputPeer, offset: offset))
|> retryRequest
|> castError(RequestStarsSubscriptionsError.self)
|> mapToSignal { result -> Signal<InternalStarsStatus, RequestStarsSubscriptionsError> in
return account.postbox.transaction { transaction -> InternalStarsStatus in
switch result {
case let .starsStatus(_, balance, subscriptions, subscriptionsNextOffset, _, _, chats, users):
let peers = AccumulatedPeers(chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers)
var parsedSubscriptions: [StarsContext.State.Subscription] = []
if let subscriptions {
for entry in subscriptions {
if let parsedSubscription = StarsContext.State.Subscription(apiSubscription: entry, transaction: transaction) {
parsedSubscriptions.append(parsedSubscription)
}
}
}
return InternalStarsStatus(
balance: balance,
subscriptions: parsedSubscriptions,
nextSubscriptionsOffset: subscriptionsNextOffset,
transactions: [],
nextTransactionsOffset: nil
)
}
}
|> castError(RequestStarsSubscriptionsError.self)
}
}
}
private final class StarsContextImpl { private final class StarsContextImpl {
private let account: Account private let account: Account
fileprivate let peerId: EnginePeer.Id fileprivate let peerId: EnginePeer.Id
@ -214,7 +269,6 @@ private final class StarsContextImpl {
var state: Signal<StarsContext.State?, NoError> { var state: Signal<StarsContext.State?, NoError> {
return self._statePromise.get() return self._statePromise.get()
} }
private var nextOffset: String?
private let disposable = MetaDisposable() private let disposable = MetaDisposable()
private var updateDisposable: Disposable? private var updateDisposable: Disposable?
@ -235,7 +289,7 @@ private final class StarsContextImpl {
guard let self, let state = self._state, let balance = balances[peerId] else { guard let self, let state = self._state, let balance = balances[peerId] else {
return return
} }
self.updateState(StarsContext.State(flags: [], balance: balance, transactions: state.transactions, canLoadMore: nextOffset != nil, isLoading: false)) self.updateState(StarsContext.State(flags: [], balance: balance, subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: state.transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: false))
self.load(force: true) self.load(force: true)
}) })
} }
@ -261,8 +315,7 @@ private final class StarsContextImpl {
guard let self else { guard let self else {
return return
} }
self.updateState(StarsContext.State(flags: [], balance: status.balance, transactions: status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false)) self.updateState(StarsContext.State(flags: [], balance: status.balance, subscriptions: status.subscriptions, canLoadMoreSubscriptions: status.nextSubscriptionsOffset != nil, transactions: status.transactions, canLoadMoreTransactions: status.nextTransactionsOffset != nil, isLoading: false))
self.nextOffset = status.nextOffset
}, error: { [weak self] _ in }, error: { [weak self] _ in
guard let self else { guard let self else {
return return
@ -280,32 +333,14 @@ private final class StarsContextImpl {
var transactions = state.transactions var transactions = state.transactions
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, media: []), at: 0) transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, media: []), at: 0)
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: state.balance + balance, transactions: transactions, canLoadMore: state.canLoadMore, isLoading: state.isLoading)) self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: state.balance + balance, subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
} }
fileprivate func updateBalance(_ balance: Int64, transactions: [StarsContext.State.Transaction]?) { fileprivate func updateBalance(_ balance: Int64, transactions: [StarsContext.State.Transaction]?) {
guard let state = self._state else { guard let state = self._state else {
return return
} }
self.updateState(StarsContext.State(flags: [], balance: balance, transactions: transactions ?? state.transactions, canLoadMore: state.canLoadMore, isLoading: state.isLoading)) self.updateState(StarsContext.State(flags: [], balance: balance, subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions ?? state.transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
}
func loadMore() {
assert(Queue.mainQueue().isCurrent())
guard let currentState = self._state, let nextOffset = self.nextOffset else {
return
}
self._state?.isLoading = true
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, mode: .all, offset: nextOffset, limit: 10)
|> deliverOnMainQueue).start(next: { [weak self] status in
if let self {
self.updateState(StarsContext.State(flags: [], balance: status.balance, transactions: currentState.transactions + status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false))
self.nextOffset = status.nextOffset
}
}))
} }
private func updateState(_ state: StarsContext.State) { private func updateState(_ state: StarsContext.State) {
@ -317,7 +352,7 @@ private final class StarsContextImpl {
private extension StarsContext.State.Transaction { private extension StarsContext.State.Transaction {
init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) { init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) {
switch apiTransaction { switch apiTransaction {
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia): case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod):
let parsedPeer: StarsContext.State.Transaction.Peer let parsedPeer: StarsContext.State.Transaction.Peer
var paidMessageId: MessageId? var paidMessageId: MessageId?
switch transactionPeer { switch transactionPeer {
@ -362,11 +397,28 @@ private extension StarsContext.State.Transaction {
} }
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? [] let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
let _ = subscriptionPeriod
self.init(flags: flags, id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, media: media) self.init(flags: flags, id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, media: media)
} }
} }
} }
private extension StarsContext.State.Subscription {
init?(apiSubscription: Api.StarsSubscription, transaction: Transaction) {
switch apiSubscription {
case let .starsSubscription(apiFlags, id, apiPeer, untilDate, pricing):
guard let peer = transaction.getPeer(apiPeer.peerId) else {
return nil
}
var flags: Flags = []
if (apiFlags & (1 << 0)) != 0 {
flags.insert(.isCancelled)
}
self.init(flags: flags, id: id, peer: EnginePeer(peer), untilDate: untilDate, pricing: StarsSubscriptionPricing(apiStarsSubscriptionPricing: pricing))
}
}
}
public final class StarsContext { public final class StarsContext {
public struct State: Equatable { public struct State: Equatable {
public struct Transaction: Equatable { public struct Transaction: Equatable {
@ -476,6 +528,57 @@ public final class StarsContext {
} }
} }
public struct Subscription: Equatable {
public struct Flags: OptionSet {
public var rawValue: Int32
public init(rawValue: Int32) {
self.rawValue = rawValue
}
public static let isCancelled = Flags(rawValue: 1 << 0)
}
public let flags: Flags
public let id: String
public let peer: EnginePeer
public let untilDate: Int32
public let pricing: StarsSubscriptionPricing
public init(
flags: Flags,
id: String,
peer: EnginePeer,
untilDate: Int32,
pricing: StarsSubscriptionPricing
) {
self.flags = flags
self.id = id
self.peer = peer
self.untilDate = untilDate
self.pricing = pricing
}
public static func == (lhs: Subscription, rhs: Subscription) -> Bool {
if lhs.flags != rhs.flags {
return false
}
if lhs.id != rhs.id {
return false
}
if lhs.peer != rhs.peer {
return false
}
if lhs.untilDate != rhs.untilDate {
return false
}
if lhs.pricing != rhs.pricing {
return false
}
return true
}
}
public struct Flags: OptionSet { public struct Flags: OptionSet {
public var rawValue: Int32 public var rawValue: Int32
@ -488,15 +591,19 @@ public final class StarsContext {
public var flags: Flags public var flags: Flags
public var balance: Int64 public var balance: Int64
public var subscriptions: [Subscription]
public var canLoadMoreSubscriptions: Bool
public var transactions: [Transaction] public var transactions: [Transaction]
public var canLoadMore: Bool public var canLoadMoreTransactions: Bool
public var isLoading: Bool public var isLoading: Bool
init(flags: Flags, balance: Int64, transactions: [Transaction], canLoadMore: Bool, isLoading: Bool) { init(flags: Flags, balance: Int64, subscriptions: [Subscription], canLoadMoreSubscriptions: Bool, transactions: [Transaction], canLoadMoreTransactions: Bool, isLoading: Bool) {
self.flags = flags self.flags = flags
self.balance = balance self.balance = balance
self.subscriptions = subscriptions
self.canLoadMoreSubscriptions = canLoadMoreSubscriptions
self.transactions = transactions self.transactions = transactions
self.canLoadMore = canLoadMore self.canLoadMoreTransactions = canLoadMoreTransactions
self.isLoading = isLoading self.isLoading = isLoading
} }
@ -510,7 +617,10 @@ public final class StarsContext {
if lhs.transactions != rhs.transactions { if lhs.transactions != rhs.transactions {
return false return false
} }
if lhs.canLoadMore != rhs.canLoadMore { if lhs.subscriptions != rhs.subscriptions {
return false
}
if lhs.canLoadMoreTransactions != rhs.canLoadMoreTransactions {
return false return false
} }
if lhs.isLoading != rhs.isLoading { if lhs.isLoading != rhs.isLoading {
@ -569,11 +679,6 @@ public final class StarsContext {
} }
} }
public func loadMore() {
self.impl.with {
$0.loadMore()
}
}
init(account: Account) { init(account: Account) {
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: { self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
@ -690,7 +795,7 @@ private final class StarsTransactionsContextImpl {
guard let self else { guard let self else {
return return
} }
self.nextOffset = status.nextOffset self.nextOffset = status.nextTransactionsOffset
var updatedState = self._state var updatedState = self._state
updatedState.transactions = nextOffset.isEmpty ? status.transactions : updatedState.transactions + status.transactions updatedState.transactions = nextOffset.isEmpty ? status.transactions : updatedState.transactions + status.transactions
@ -769,6 +874,112 @@ public final class StarsTransactionsContext {
} }
} }
private final class StarsSubscriptionsContextImpl {
private let account: Account
private weak var starsContext: StarsContext?
private var _state: StarsSubscriptionsContext.State
private let _statePromise = Promise<StarsSubscriptionsContext.State>()
var state: Signal<StarsSubscriptionsContext.State, NoError> {
return self._statePromise.get()
}
private var nextOffset: String? = ""
private let disposable = MetaDisposable()
private var stateDisposable: Disposable?
init(account: Account, starsContext: StarsContext) {
assert(Queue.mainQueue().isCurrent())
self.account = account
self.starsContext = starsContext
let currentSubscriptions = starsContext.currentState?.subscriptions ?? []
let canLoadMore = starsContext.currentState?.canLoadMoreSubscriptions ?? true
self._state = StarsSubscriptionsContext.State(subscriptions: currentSubscriptions, canLoadMore: canLoadMore, isLoading: false)
self._statePromise.set(.single(self._state))
}
deinit {
assert(Queue.mainQueue().isCurrent())
self.disposable.dispose()
self.stateDisposable?.dispose()
}
func loadMore() {
assert(Queue.mainQueue().isCurrent())
guard !self._state.isLoading, let nextOffset = self.nextOffset else {
return
}
var updatedState = self._state
updatedState.isLoading = true
self.updateState(updatedState)
self.disposable.set((_internal_requestStarsSubscriptions(account: self.account, peerId: self.account.peerId, offset: nextOffset)
|> deliverOnMainQueue).start(next: { [weak self] status in
guard let self else {
return
}
self.nextOffset = status.nextSubscriptionsOffset
var updatedState = self._state
updatedState.subscriptions = nextOffset.isEmpty ? status.subscriptions : updatedState.subscriptions + status.subscriptions
updatedState.isLoading = false
updatedState.canLoadMore = self.nextOffset != nil
self.updateState(updatedState)
}))
}
private func updateState(_ state: StarsSubscriptionsContext.State) {
self._state = state
self._statePromise.set(.single(state))
}
}
public final class StarsSubscriptionsContext {
public struct State: Equatable {
public var subscriptions: [StarsContext.State.Subscription]
public var canLoadMore: Bool
public var isLoading: Bool
init(subscriptions: [StarsContext.State.Subscription], canLoadMore: Bool, isLoading: Bool) {
self.subscriptions = subscriptions
self.canLoadMore = canLoadMore
self.isLoading = isLoading
}
}
fileprivate let impl: QueueLocalObject<StarsSubscriptionsContextImpl>
public var state: Signal<StarsSubscriptionsContext.State, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.state.start(next: { value in
subscriber.putNext(value)
}))
}
return disposable
}
}
public func loadMore() {
self.impl.with {
$0.loadMore()
}
}
init(account: Account, starsContext: StarsContext) {
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
return StarsSubscriptionsContextImpl(account: account, starsContext: starsContext)
})
}
}
func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> { func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
return account.postbox.transaction { transaction -> Api.InputInvoice? in return account.postbox.transaction { transaction -> Api.InputInvoice? in
return _internal_parseInputInvoice(transaction: transaction, source: source) return _internal_parseInputInvoice(transaction: transaction, source: source)
@ -819,6 +1030,8 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
} }
case .giftCode, .stars, .starsGift: case .giftCode, .stars, .starsGift:
receiptMessageId = nil receiptMessageId = nil
case .starsChatSubscription:
receiptMessageId = nil
} }
} }
} }
@ -889,7 +1102,7 @@ func _internal_getStarsTransaction(accountPeerId: PeerId, postbox: Postbox, netw
} }
|> mapToSignal { result -> Signal<StarsContext.State.Transaction?, NoError> in |> mapToSignal { result -> Signal<StarsContext.State.Transaction?, NoError> in
return postbox.transaction { transaction -> StarsContext.State.Transaction? in return postbox.transaction { transaction -> StarsContext.State.Transaction? in
guard let result, case let .starsStatus(_, _, transactions, _, chats, users) = result, let matchingTransaction = transactions.first else { guard let result, case let .starsStatus(_, _, _, _, transactions, _, chats, users) = result, let matchingTransaction = transactions?.first else {
return nil return nil
} }
let peers = AccumulatedPeers(chats: chats, users: users) let peers = AccumulatedPeers(chats: chats, users: users)
@ -900,3 +1113,70 @@ func _internal_getStarsTransaction(accountPeerId: PeerId, postbox: Postbox, netw
} }
} }
} }
public struct StarsSubscriptionPricing: Codable, Equatable {
private enum CodingKeys: String, CodingKey {
case period
case amount
}
public let period: Int32
public let amount: Int64
public init(period: Int32, amount: Int64) {
self.period = period
self.amount = amount
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.period = try container.decode(Int32.self, forKey: .period)
self.amount = try container.decode(Int64.self, forKey: .amount)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.period, forKey: .period)
try container.encode(self.amount, forKey: .amount)
}
public static let monthPeriod = 2592000
public static let testPeriod = 300
}
extension StarsSubscriptionPricing {
init(apiStarsSubscriptionPricing: Api.StarsSubscriptionPricing) {
switch apiStarsSubscriptionPricing {
case let .starsSubscriptionPricing(period, amount):
self = .init(period: period, amount: amount)
}
}
var apiStarsSubscriptionPricing: Api.StarsSubscriptionPricing {
return .starsSubscriptionPricing(period: self.period, amount: self.amount)
}
}
public enum CancelStarsSubsciptionError {
case generic
}
func _internal_cancelStarsSubscription(account: Account, subscriptionId: String, reason: String) -> Signal<Never, CancelStarsSubsciptionError> {
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(account.peerId).flatMap(apiInputPeer)
}
|> castError(CancelStarsSubsciptionError.self)
|> mapToSignal { inputPeer -> Signal<Never, CancelStarsSubsciptionError> in
guard let inputPeer else {
return .complete()
}
let flags: Int32 = (1 << 0)
return account.network.request(Api.functions.payments.changeStarsSubscription(flags: flags, peer: inputPeer, subscriptionId: subscriptionId, canceled: .boolTrue))
|> mapError { _ -> CancelStarsSubsciptionError in
return .generic
}
|> ignoreValues
}
}

View File

@ -5,11 +5,11 @@ import Postbox
public extension TelegramEngine { public extension TelegramEngine {
final class Payments { final class Payments {
private let account: Account private let account: Account
init(account: Account) { init(account: Account) {
self.account = account self.account = account
} }
public func getBankCardInfo(cardNumber: String) -> Signal<BankCardInfo?, NoError> { public func getBankCardInfo(cardNumber: String) -> Signal<BankCardInfo?, NoError> {
return _internal_getBankCardInfo(account: self.account, cardNumber: cardNumber) return _internal_getBankCardInfo(account: self.account, cardNumber: cardNumber)
} }
@ -25,7 +25,7 @@ public extension TelegramEngine {
public func validateBotPaymentForm(saveInfo: Bool, source: BotPaymentInvoiceSource, formInfo: BotPaymentRequestedInfo) -> Signal<BotPaymentValidatedFormInfo, ValidateBotPaymentFormError> { public func validateBotPaymentForm(saveInfo: Bool, source: BotPaymentInvoiceSource, formInfo: BotPaymentRequestedInfo) -> Signal<BotPaymentValidatedFormInfo, ValidateBotPaymentFormError> {
return _internal_validateBotPaymentForm(account: self.account, saveInfo: saveInfo, source: source, formInfo: formInfo) return _internal_validateBotPaymentForm(account: self.account, saveInfo: saveInfo, source: source, formInfo: formInfo)
} }
public func sendBotPaymentForm(source: BotPaymentInvoiceSource, formId: Int64, validatedInfoId: String?, shippingOptionId: String?, tipAmount: Int64?, credentials: BotPaymentCredentials) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> { public func sendBotPaymentForm(source: BotPaymentInvoiceSource, formId: Int64, validatedInfoId: String?, shippingOptionId: String?, tipAmount: Int64?, credentials: BotPaymentCredentials) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
return _internal_sendBotPaymentForm(account: self.account, formId: formId, source: source, validatedInfoId: validatedInfoId, shippingOptionId: shippingOptionId, tipAmount: tipAmount, credentials: credentials) return _internal_sendBotPaymentForm(account: self.account, formId: formId, source: source, validatedInfoId: validatedInfoId, shippingOptionId: shippingOptionId, tipAmount: tipAmount, credentials: credentials)
} }
@ -33,7 +33,7 @@ public extension TelegramEngine {
public func requestBotPaymentReceipt(messageId: MessageId) -> Signal<BotPaymentReceipt, RequestBotPaymentReceiptError> { public func requestBotPaymentReceipt(messageId: MessageId) -> Signal<BotPaymentReceipt, RequestBotPaymentReceiptError> {
return _internal_requestBotPaymentReceipt(account: self.account, messageId: messageId) return _internal_requestBotPaymentReceipt(account: self.account, messageId: messageId)
} }
public func clearBotPaymentInfo(info: BotPaymentInfo) -> Signal<Void, NoError> { public func clearBotPaymentInfo(info: BotPaymentInfo) -> Signal<Void, NoError> {
return _internal_clearBotPaymentInfo(network: self.account.network, info: info) return _internal_clearBotPaymentInfo(network: self.account.network, info: info)
} }
@ -89,5 +89,9 @@ public extension TelegramEngine {
public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> { public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
return _internal_sendStarsPaymentForm(account: self.account, formId: formId, source: source) return _internal_sendStarsPaymentForm(account: self.account, formId: formId, source: source)
} }
public func cancelStarsSubscription(subscriptionId: String, reason: String) -> Signal<Never, CancelStarsSubsciptionError> {
return _internal_cancelStarsSubscription(account: self.account, subscriptionId: subscriptionId, reason: reason)
}
} }
} }

View File

@ -44,7 +44,7 @@ func _internal_revokePersistentPeerExportedInvitation(account: Account, peerId:
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
let flags: Int32 = (1 << 2) let flags: Int32 = (1 << 2)
if let _ = peer as? TelegramChannel { if let _ = peer as? TelegramChannel {
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil)) return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil, subscriptionPricing: nil))
|> retryRequest |> retryRequest
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in |> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
return account.postbox.transaction { transaction -> ExportedInvitation? in return account.postbox.transaction { transaction -> ExportedInvitation? in
@ -61,7 +61,7 @@ func _internal_revokePersistentPeerExportedInvitation(account: Account, peerId:
} }
} }
} else if let _ = peer as? TelegramGroup { } else if let _ = peer as? TelegramGroup {
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil)) return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil, subscriptionPricing: nil))
|> retryRequest |> retryRequest
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in |> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
return account.postbox.transaction { transaction -> ExportedInvitation? in return account.postbox.transaction { transaction -> ExportedInvitation? in
@ -90,7 +90,7 @@ public enum CreatePeerExportedInvitationError {
case generic case generic
} }
func _internal_createPeerExportedInvitation(account: Account, peerId: PeerId, title: String?, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Bool?) -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> { func _internal_createPeerExportedInvitation(account: Account, peerId: PeerId, title: String?, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Bool?, subscriptionPricing: StarsSubscriptionPricing?) -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> {
return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> in return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 0 var flags: Int32 = 0
@ -106,7 +106,10 @@ func _internal_createPeerExportedInvitation(account: Account, peerId: PeerId, ti
if let _ = title { if let _ = title {
flags |= (1 << 4) flags |= (1 << 4)
} }
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: expireDate, usageLimit: usageLimit, title: title)) if let _ = subscriptionPricing {
flags |= (1 << 5)
}
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: expireDate, usageLimit: usageLimit, title: title, subscriptionPricing: subscriptionPricing?.apiStarsSubscriptionPricing))
|> mapError { _ in return CreatePeerExportedInvitationError.generic } |> mapError { _ in return CreatePeerExportedInvitationError.generic }
|> map { result -> ExportedInvitation? in |> map { result -> ExportedInvitation? in
return ExportedInvitation(apiExportedInvite: result) return ExportedInvitation(apiExportedInvite: result)
@ -817,7 +820,7 @@ private final class PeerInvitationImportersContextImpl {
var link: String? var link: String?
var count: Int32 = 0 var count: Int32 = 0
if let invite = invite, case let .link(inviteLink, _, _, _, _, _, _, _, _, _, inviteCount, _) = invite { if let invite = invite, case let .link(inviteLink, _, _, _, _, _, _, _, _, _, inviteCount, _, _) = invite {
link = inviteLink link = inviteLink
if let inviteCount = inviteCount { if let inviteCount = inviteCount {
count = inviteCount count = inviteCount

View File

@ -48,6 +48,8 @@ public enum ExternalJoiningChatState {
public let participantsCount: Int32 public let participantsCount: Int32
public let participants: [EnginePeer]? public let participants: [EnginePeer]?
public let nameColor: PeerNameColor? public let nameColor: PeerNameColor?
public let subscriptionPricing: StarsSubscriptionPricing?
public let subscriptionFormId: Int64?
} }
case invite(Invite) case invite(Invite)
@ -106,10 +108,10 @@ func _internal_joinLinkInformation(_ hash: String, account: Account) -> Signal<E
|> mapToSignal { result -> Signal<ExternalJoiningChatState, JoinLinkInfoError> in |> mapToSignal { result -> Signal<ExternalJoiningChatState, JoinLinkInfoError> in
if let result = result { if let result = result {
switch result { switch result {
case let .chatInvite(flags, title, about, invitePhoto, participantsCount, participants, nameColor): case let .chatInvite(flags, title, about, invitePhoto, participantsCount, participants, nameColor, subscriptionPricing, subscriptionFormId):
let photo = telegramMediaImageFromApiPhoto(invitePhoto).flatMap({ smallestImageRepresentation($0.representations) }) let photo = telegramMediaImageFromApiPhoto(invitePhoto).flatMap({ smallestImageRepresentation($0.representations) })
let flags: ExternalJoiningChatState.Invite.Flags = .init(isChannel: (flags & (1 << 0)) != 0, isBroadcast: (flags & (1 << 1)) != 0, isPublic: (flags & (1 << 2)) != 0, isMegagroup: (flags & (1 << 3)) != 0, requestNeeded: (flags & (1 << 6)) != 0, isVerified: (flags & (1 << 7)) != 0, isScam: (flags & (1 << 8)) != 0, isFake: (flags & (1 << 9)) != 0) let flags: ExternalJoiningChatState.Invite.Flags = .init(isChannel: (flags & (1 << 0)) != 0, isBroadcast: (flags & (1 << 1)) != 0, isPublic: (flags & (1 << 2)) != 0, isMegagroup: (flags & (1 << 3)) != 0, requestNeeded: (flags & (1 << 6)) != 0, isVerified: (flags & (1 << 7)) != 0, isScam: (flags & (1 << 8)) != 0, isFake: (flags & (1 << 9)) != 0)
return .single(.invite(ExternalJoiningChatState.Invite(flags: flags, title: title, about: about, photoRepresentation: photo, participantsCount: participantsCount, participants: participants?.map({ EnginePeer(TelegramUser(user: $0)) }), nameColor: PeerNameColor(rawValue: nameColor)))) return .single(.invite(ExternalJoiningChatState.Invite(flags: flags, title: title, about: about, photoRepresentation: photo, participantsCount: participantsCount, participants: participants?.map({ EnginePeer(TelegramUser(user: $0)) }), nameColor: PeerNameColor(rawValue: nameColor), subscriptionPricing: subscriptionPricing.flatMap { StarsSubscriptionPricing(apiStarsSubscriptionPricing: $0) }, subscriptionFormId: subscriptionFormId)))
case let .chatInviteAlready(chat): case let .chatInviteAlready(chat):
if let peer = parseTelegramGroupOrChannel(chat: chat) { if let peer = parseTelegramGroupOrChannel(chat: chat) {
return account.postbox.transaction({ (transaction) -> ExternalJoiningChatState in return account.postbox.transaction({ (transaction) -> ExternalJoiningChatState in

View File

@ -705,8 +705,8 @@ public extension TelegramEngine {
return _internal_checkPeerChatServiceActions(postbox: self.account.postbox, peerId: peerId) return _internal_checkPeerChatServiceActions(postbox: self.account.postbox, peerId: peerId)
} }
public func createPeerExportedInvitation(peerId: PeerId, title: String?, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Bool?) -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> { public func createPeerExportedInvitation(peerId: PeerId, title: String?, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Bool?, subscriptionPricing: StarsSubscriptionPricing?) -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> {
return _internal_createPeerExportedInvitation(account: self.account, peerId: peerId, title: title, expireDate: expireDate, usageLimit: usageLimit, requestNeeded: requestNeeded) return _internal_createPeerExportedInvitation(account: self.account, peerId: peerId, title: title, expireDate: expireDate, usageLimit: usageLimit, requestNeeded: requestNeeded, subscriptionPricing: subscriptionPricing)
} }
public func editPeerExportedInvitation(peerId: PeerId, link: String, title: String?, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Bool?) -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> { public func editPeerExportedInvitation(peerId: PeerId, link: String, title: String?, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Bool?) -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> {

View File

@ -1460,7 +1460,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
var text: String = "" var text: String = ""
var entities: [MessageTextEntity] = [] var entities: [MessageTextEntity] = []
let rawText: PresentationStrings.FormattedString = self.presentationData.strings.Channel_AdminLog_DeletedInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link_?.replacingOccurrences(of: "https://", with: "") ?? "") let rawText: PresentationStrings.FormattedString = self.presentationData.strings.Channel_AdminLog_DeletedInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link?.replacingOccurrences(of: "https://", with: "") ?? "")
appendAttributedText(text: rawText, generateEntities: { index in appendAttributedText(text: rawText, generateEntities: { index in
if index == 0, let author = author { if index == 0, let author = author {
@ -1486,7 +1486,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
var text: String = "" var text: String = ""
var entities: [MessageTextEntity] = [] var entities: [MessageTextEntity] = []
let rawText: PresentationStrings.FormattedString = self.presentationData.strings.Channel_AdminLog_RevokedInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link_?.replacingOccurrences(of: "https://", with: "") ?? "") let rawText: PresentationStrings.FormattedString = self.presentationData.strings.Channel_AdminLog_RevokedInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link?.replacingOccurrences(of: "https://", with: "") ?? "")
appendAttributedText(text: rawText, generateEntities: { index in appendAttributedText(text: rawText, generateEntities: { index in
if index == 0, let author = author { if index == 0, let author = author {
@ -1512,7 +1512,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
var text: String = "" var text: String = ""
var entities: [MessageTextEntity] = [] var entities: [MessageTextEntity] = []
let rawText: PresentationStrings.FormattedString = self.presentationData.strings.Channel_AdminLog_EditedInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", updatedInvite.link_?.replacingOccurrences(of: "https://", with: "") ?? "") let rawText: PresentationStrings.FormattedString = self.presentationData.strings.Channel_AdminLog_EditedInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", updatedInvite.link?.replacingOccurrences(of: "https://", with: "") ?? "")
appendAttributedText(text: rawText, generateEntities: { index in appendAttributedText(text: rawText, generateEntities: { index in
if index == 0, let author = author { if index == 0, let author = author {
@ -1540,9 +1540,9 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let rawText: PresentationStrings.FormattedString let rawText: PresentationStrings.FormattedString
if joinedViaFolderLink { if joinedViaFolderLink {
rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaFolderInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link_?.replacingOccurrences(of: "https://", with: "") ?? "") rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaFolderInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link?.replacingOccurrences(of: "https://", with: "") ?? "")
} else { } else {
rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link_?.replacingOccurrences(of: "https://", with: "") ?? "") rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaInviteLink(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", invite.link?.replacingOccurrences(of: "https://", with: "") ?? "")
} }
appendAttributedText(text: rawText, generateEntities: { index in appendAttributedText(text: rawText, generateEntities: { index in
@ -1709,7 +1709,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let rawText: PresentationStrings.FormattedString let rawText: PresentationStrings.FormattedString
switch invite { switch invite {
case let .link(link, _, _, _, _, _, _, _, _, _, _, _): case let .link(link, _, _, _, _, _, _, _, _, _, _, _, _):
rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaRequest(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", link.replacingOccurrences(of: "https://", with: ""), approver.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "") rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaRequest(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", link.replacingOccurrences(of: "https://", with: ""), approver.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
case .publicJoinRequest: case .publicJoinRequest:
rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaPublicRequest(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", approver.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "") rawText = self.presentationData.strings.Channel_AdminLog_JoinedViaPublicRequest(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", approver.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
@ -2326,14 +2326,3 @@ func chatRecentActionsHistoryPreparedTransition(from fromEntries: [ChatRecentAct
return ChatRecentActionsHistoryTransition(filteredEntries: toEntries, type: type, deletions: deletions, insertions: insertions, updates: updates, canLoadEarlier: canLoadEarlier, displayingResults: displayingResults, searchResultsState: searchResultsState, synchronous: !toggledDeletedMessageIds.isEmpty, isEmpty: toEntries.isEmpty) return ChatRecentActionsHistoryTransition(filteredEntries: toEntries, type: type, deletions: deletions, insertions: insertions, updates: updates, canLoadEarlier: canLoadEarlier, displayingResults: displayingResults, searchResultsState: searchResultsState, synchronous: !toggledDeletedMessageIds.isEmpty, isEmpty: toEntries.isEmpty)
} }
private extension ExportedInvitation {
var link_: String? {
switch self {
case let .link(link, _, _, _, _, _, _, _, _, _, _, _):
return link
case .publicJoinRequest:
return nil
}
}
}