Update API

This commit is contained in:
Ilya Laktyushin 2025-06-28 17:38:45 +02:00
parent 3b46e1d3d0
commit 8862492480
63 changed files with 1595 additions and 1963 deletions

Binary file not shown.

View file

@ -1565,3 +1565,52 @@ public struct StarsSubscriptionConfiguration {
}
}
}
public struct TranslationConfiguration {
static var defaultValue: TranslationConfiguration {
return TranslationConfiguration(manual: .disabled, auto: .disabled)
}
public enum TranslationAvailability {
case enabled
case system
case alternative
case disabled
init(string: String) {
switch string {
case "enabled":
#if DEBUG
self = .system
#else
self = .enabled
#endif
case "system":
self = .system
case "alternative":
self = .alternative
default:
self = .disabled
}
}
}
public let manual: TranslationAvailability
public let auto: TranslationAvailability
fileprivate init(manual: TranslationAvailability, auto: TranslationAvailability) {
self.manual = manual
self.auto = auto
}
public static func with(appConfiguration: AppConfiguration) -> TranslationConfiguration {
if let data = appConfiguration.data {
let manualValue = data["translations_manual_enabled"] as? String ?? "disabled"
let autoValue = data["translations_auto_enabled"] as? String ?? "disabled"
return TranslationConfiguration(manual: TranslationAvailability(string: manualValue), auto: TranslationAvailability(string: autoValue))
} else {
return .defaultValue
}
}
}

View file

@ -827,7 +827,7 @@ public enum PremiumPerk: CaseIterable {
case .paidMessages:
return "Premium/Perk/PaidMessages"
case .todo:
return "Premium/Perk/PaidMessages"
return "Premium/Perk/Todo"
case .businessLocation:
return "Premium/BusinessPerk/Location"
case .businessHours:
@ -858,6 +858,7 @@ struct PremiumIntroConfiguration {
.voiceToText,
.fasterDownload,
.translation,
.todo,
.animatedEmoji,
.emojiStatus,
.messageEffects,
@ -2172,6 +2173,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
demoSubject = .messageEffects
case .paidMessages:
demoSubject = .paidMessages
case .todo:
demoSubject = .todo
case .business:
demoSubject = .business
let _ = ApplicationSpecificNotice.setDismissedBusinessBadge(accountManager: accountContext.sharedContext.accountManager).startStandalone()
@ -3699,6 +3702,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
let buttonTitle: String
var buttonSubtitle: String?
if case let .auth(price) = context.component.source {
//TODO:localize
buttonTitle = "Sign up for \(price)"
buttonSubtitle = "Get Telegram Premium for 1 week"
} else if isUnusedGift {

View file

@ -431,6 +431,32 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
})
}
let translationConfiguration = TranslationConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
var translateButtonAvailable = false
var chatTranslationAvailable = false
switch translationConfiguration.manual {
case .enabled, .alternative:
translateButtonAvailable = true
case .system:
if #available(iOS 18.0, *) {
translateButtonAvailable = true
}
default:
break
}
switch translationConfiguration.auto {
case .enabled:
chatTranslationAvailable = true
case .system:
if #available(iOS 18.0, *) {
chatTranslationAvailable = true
}
default:
break
}
let previousState = Atomic<LocalizationListState?>(value: nil)
let previousEntriesHolder = Atomic<([LanguageListEntry], PresentationTheme, PresentationStrings)?>(value: nil)
self.listDisposable = combineLatest(
@ -465,7 +491,6 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
if let languages = translationSettings.ignoredLanguages {
ignoredLanguages = languages
} else {
if var activeLanguage = activeLanguageCode {
let rawSuffix = "-raw"
if activeLanguage.hasSuffix(rawSuffix) {
@ -497,12 +522,15 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
if !localizationListState.availableOfficialLocalizations.isEmpty {
strongSelf.currentListState = localizationListState
if #available(iOS 12.0, *) {
if translateButtonAvailable || chatTranslationAvailable {
entries.append(.translateTitle(text: presentationData.strings.Localization_TranslateMessages.uppercased()))
entries.append(.translate(text: presentationData.strings.Localization_ShowTranslate, value: showTranslate))
entries.append(.translateEntire(text: presentationData.strings.Localization_TranslateEntireChat, value: translateChats, locked: !isPremium))
if translateButtonAvailable {
entries.append(.translate(text: presentationData.strings.Localization_ShowTranslate, value: showTranslate))
}
if chatTranslationAvailable {
entries.append(.translateEntire(text: presentationData.strings.Localization_TranslateEntireChat, value: translateChats, locked: !isPremium))
}
var value = ""
if ignoredLanguages.count > 1 {

View file

@ -51,7 +51,7 @@ private final class ChannelStatsControllerArguments {
let buyAds: () -> Void
let openMonetizationIntro: () -> Void
let openMonetizationInfo: () -> Void
let openTonTransaction: (RevenueStatsTransactionsContext.State.Transaction) -> Void
let openTonTransaction: (StarsContext.State.Transaction) -> Void
let openStarsTransaction: (StarsContext.State.Transaction) -> Void
let expandTransactions: (Bool) -> Void
let updateCpmEnabled: (Bool) -> Void
@ -59,7 +59,7 @@ private final class ChannelStatsControllerArguments {
let openEarnStars: () -> Void
let dismissInput: () -> Void
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openPostStats: @escaping (EnginePeer, StatsPostItem) -> Void, openStory: @escaping (EngineStoryItem, UIView) -> Void, contextAction: @escaping (MessageId, ASDisplayNode, ContextGesture?) -> Void, copyBoostLink: @escaping (String) -> Void, shareBoostLink: @escaping (String) -> Void, openBoost: @escaping (ChannelBoostersContext.State.Boost) -> Void, expandBoosters: @escaping () -> Void, openGifts: @escaping () -> Void, createPrepaidGiveaway: @escaping (PrepaidGiveaway) -> Void, updateGiftsSelected: @escaping (Bool) -> Void, updateStarsSelected: @escaping (Bool) -> Void, requestTonWithdraw: @escaping () -> Void, requestStarsWithdraw: @escaping () -> Void, showTimeoutTooltip: @escaping (Int32) -> Void, buyAds: @escaping () -> Void, openMonetizationIntro: @escaping () -> Void, openMonetizationInfo: @escaping () -> Void, openTonTransaction: @escaping (RevenueStatsTransactionsContext.State.Transaction) -> Void, openStarsTransaction: @escaping (StarsContext.State.Transaction) -> Void, expandTransactions: @escaping (Bool) -> Void, updateCpmEnabled: @escaping (Bool) -> Void, presentCpmLocked: @escaping () -> Void, openEarnStars: @escaping () -> Void, dismissInput: @escaping () -> Void) {
init(context: AccountContext, loadDetailedGraph: @escaping (StatsGraph, Int64) -> Signal<StatsGraph?, NoError>, openPostStats: @escaping (EnginePeer, StatsPostItem) -> Void, openStory: @escaping (EngineStoryItem, UIView) -> Void, contextAction: @escaping (MessageId, ASDisplayNode, ContextGesture?) -> Void, copyBoostLink: @escaping (String) -> Void, shareBoostLink: @escaping (String) -> Void, openBoost: @escaping (ChannelBoostersContext.State.Boost) -> Void, expandBoosters: @escaping () -> Void, openGifts: @escaping () -> Void, createPrepaidGiveaway: @escaping (PrepaidGiveaway) -> Void, updateGiftsSelected: @escaping (Bool) -> Void, updateStarsSelected: @escaping (Bool) -> Void, requestTonWithdraw: @escaping () -> Void, requestStarsWithdraw: @escaping () -> Void, showTimeoutTooltip: @escaping (Int32) -> Void, buyAds: @escaping () -> Void, openMonetizationIntro: @escaping () -> Void, openMonetizationInfo: @escaping () -> Void, openTonTransaction: @escaping (StarsContext.State.Transaction) -> Void, openStarsTransaction: @escaping (StarsContext.State.Transaction) -> Void, expandTransactions: @escaping (Bool) -> Void, updateCpmEnabled: @escaping (Bool) -> Void, presentCpmLocked: @escaping () -> Void, openEarnStars: @escaping () -> Void, dismissInput: @escaping () -> Void) {
self.context = context
self.loadDetailedGraph = loadDetailedGraph
self.openPostStats = openPostStats
@ -242,11 +242,11 @@ private enum StatsEntry: ItemListNodeEntry {
case adsStarsRevenueGraph(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, StatsGraph, ChartType, Double)
case adsProceedsTitle(PresentationTheme, String)
case adsProceedsOverview(PresentationTheme, RevenueStats?, StarsRevenueStats?)
case adsProceedsOverview(PresentationTheme, StarsRevenueStats?, StarsRevenueStats?)
case adsProceedsInfo(PresentationTheme, String)
case adsTonBalanceTitle(PresentationTheme, String)
case adsTonBalance(PresentationTheme, RevenueStats, Bool, Bool)
case adsTonBalance(PresentationTheme, StarsRevenueStats, Bool, Bool)
case adsTonBalanceInfo(PresentationTheme, String)
case adsStarsBalanceTitle(PresentationTheme, String)
@ -256,7 +256,7 @@ private enum StatsEntry: ItemListNodeEntry {
case earnStarsInfo
case adsTransactionsTitle(PresentationTheme, String)
case adsTransactionsTabs(PresentationTheme, String, String, Bool)
case adsTransaction(Int32, PresentationTheme, RevenueStatsTransactionsContext.State.Transaction)
case adsTransaction(Int32, PresentationTheme, StarsContext.State.Transaction)
case adsStarsTransaction(Int32, PresentationTheme, StarsContext.State.Transaction)
case adsTransactionsExpand(PresentationTheme, String, Bool)
@ -1155,8 +1155,7 @@ private enum StatsEntry: ItemListNodeEntry {
let detailText: String
var detailColor: ItemListDisclosureItemDetailLabelColor = .generic
switch transaction {
case let .proceeds(_, fromDate, toDate):
if let fromDate = transaction.adsProceedsFromDate, let toDate = transaction.adsProceedsToDate {
title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Proceeds, font: font, textColor: theme.list.itemPrimaryTextColor)
let fromDateString = stringForMediumCompactDate(timestamp: fromDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: false)
let toDateString = stringForMediumCompactDate(timestamp: toDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: false)
@ -1165,24 +1164,26 @@ private enum StatsEntry: ItemListNodeEntry {
} else {
detailText = "\(fromDateString) \(toDateString)"
}
case let .withdrawal(status, _, date, provider, _, _):
title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Withdrawal(provider).string, font: font, textColor: theme.list.itemPrimaryTextColor)
} else if case .fragment = transaction.peer {
title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Withdrawal("Fragment").string, font: font, textColor: theme.list.itemPrimaryTextColor)
labelColor = theme.list.itemDestructiveColor
switch status {
case .succeed:
detailText = stringForMediumCompactDate(timestamp: date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
case .failed:
detailText = stringForMediumCompactDate(timestamp: date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: false) + " \(presentationData.strings.Monetization_Transaction_Failed)"
detailColor = .destructive
case .pending:
if transaction.flags.contains(.isPending) {
detailText = presentationData.strings.Monetization_Transaction_Pending
} else if transaction.flags.contains(.isFailed) {
detailText = stringForMediumCompactDate(timestamp: transaction.date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, withTime: false) + " \(presentationData.strings.Monetization_Transaction_Failed)"
detailColor = .destructive
} else {
detailText = stringForMediumCompactDate(timestamp: transaction.date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
}
case let .refund(_, date, _):
} else if transaction.flags.contains(.isRefund) {
title = NSAttributedString(string: presentationData.strings.Monetization_Transaction_Refund, font: font, textColor: theme.list.itemPrimaryTextColor)
detailText = stringForMediumCompactDate(timestamp: date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
detailText = stringForMediumCompactDate(timestamp: transaction.date, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)
} else {
title = NSAttributedString()
detailText = ""
}
let label = tonAmountAttributedString(formatTonAmountText(transaction.amount, dateTimeFormat: presentationData.dateTimeFormat, showPlus: true), integralFont: font, fractionalFont: smallLabelFont, color: labelColor, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
let label = tonAmountAttributedString(formatTonAmountText(transaction.count.amount.value, dateTimeFormat: presentationData.dateTimeFormat, showPlus: true), integralFont: font, fractionalFont: smallLabelFont, color: labelColor, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
label.insert(NSAttributedString(string: " $ ", font: font, textColor: labelColor), at: 1)
if let range = label.string.range(of: "$"), let icon = generateTintedImage(image: UIImage(bundleImageName: "Ads/TonMedium"), color: labelColor) {
@ -1565,9 +1566,9 @@ private func monetizationEntries(
presentationData: PresentationData,
state: ChannelStatsControllerState,
peer: EnginePeer?,
data: RevenueStats?,
data: StarsRevenueStats?,
boostData: ChannelBoostStatus?,
transactionsInfo: RevenueStatsTransactionsContext.State,
transactionsInfo: StarsTransactionsContext.State,
starsData: StarsRevenueStats?,
starsTransactionsInfo: StarsTransactionsContext.State,
adsRestricted: Bool,
@ -1587,9 +1588,9 @@ private func monetizationEntries(
if canViewRevenue, let data {
entries.append(.adsHeader(presentationData.theme, isBot ? presentationData.strings.Monetization_Bot_Header : presentationData.strings.Monetization_Header))
if !data.topHoursGraph.isEmpty {
if let topHoursGraph = data.topHoursGraph, !topHoursGraph.isEmpty {
entries.append(.adsImpressionsTitle(presentationData.theme, presentationData.strings.Monetization_ImpressionsTitle))
entries.append(.adsImpressionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, data.topHoursGraph, .hourlyStep))
entries.append(.adsImpressionsGraph(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, topHoursGraph, .hourlyStep))
}
if !data.revenueGraph.isEmpty {
@ -1608,8 +1609,8 @@ private func monetizationEntries(
entries.append(.adsProceedsTitle(presentationData.theme, presentationData.strings.Monetization_StarsProceeds_Title))
entries.append(.adsProceedsOverview(presentationData.theme, canViewRevenue ? data : nil, canViewStarsRevenue ? starsData : nil))
let hasTonBalance = (data?.balances.overallRevenue ?? 0) > 0
let hasStarsBalance = (starsData?.balances.overallRevenue ?? StarsAmount.zero) > StarsAmount.zero
let hasTonBalance = (data?.balances.overallRevenue.amount ?? StarsAmount.zero) > StarsAmount.zero
let hasStarsBalance = (starsData?.balances.overallRevenue.amount ?? StarsAmount.zero) > StarsAmount.zero
let proceedsInfo: String
if (canViewStarsRevenue && hasStarsBalance) && (canViewRevenue && hasTonBalance) {
@ -1632,11 +1633,11 @@ private func monetizationEntries(
if canViewRevenue, let data {
entries.append(.adsTonBalanceTitle(presentationData.theme, isBot ? presentationData.strings.Monetization_Bot_BalanceTitle : presentationData.strings.Monetization_TonBalanceTitle))
entries.append(.adsTonBalance(presentationData.theme, data, (isCreator || isBot) && data.balances.availableBalance > 0, data.balances.withdrawEnabled))
entries.append(.adsTonBalance(presentationData.theme, data, (isCreator || isBot) && data.balances.availableBalance.amount > StarsAmount.zero, data.balances.withdrawEnabled))
if isCreator || isBot {
let withdrawalInfoText: String
if data.balances.availableBalance == 0 {
if data.balances.availableBalance.amount == StarsAmount.zero {
withdrawalInfoText = presentationData.strings.Monetization_Balance_ZeroInfo
} else if monetizationConfiguration.withdrawalAvailable {
withdrawalInfoText = presentationData.strings.Monetization_Balance_AvailableInfo
@ -1647,9 +1648,9 @@ private func monetizationEntries(
}
}
if canViewStarsRevenue, let starsData, starsData.balances.overallRevenue > StarsAmount.zero {
if canViewStarsRevenue, let starsData, starsData.balances.overallRevenue.amount > StarsAmount.zero {
entries.append(.adsStarsBalanceTitle(presentationData.theme, presentationData.strings.Monetization_StarsBalanceTitle))
entries.append(.adsStarsBalance(presentationData.theme, starsData, isCreator && starsData.balances.availableBalance > StarsAmount.zero, !isGroup, starsData.balances.withdrawEnabled, starsData.balances.nextWithdrawalTimestamp))
entries.append(.adsStarsBalance(presentationData.theme, starsData, isCreator && starsData.balances.availableBalance.amount > StarsAmount.zero, !isGroup, starsData.balances.withdrawEnabled, starsData.balances.nextWithdrawalTimestamp))
entries.append(.adsStarsBalanceInfo(presentationData.theme, isGroup ? presentationData.strings.Monetization_Balance_StarsInfoGroup : presentationData.strings.Monetization_Balance_StarsInfo))
}
@ -1693,12 +1694,12 @@ private func monetizationEntries(
i += 1
}
if transactions.count < transactionsInfo.count {
if transactionsInfo.canLoadMore || transactionsInfo.transactions.count > transactions.count {
let moreCount: Int32
if !state.transactionsExpanded {
moreCount = min(20, transactionsInfo.count - Int32(transactions.count))
moreCount = min(20, Int32(transactionsInfo.transactions.count - transactions.count))
} else {
moreCount = min(50, transactionsInfo.count - Int32(transactions.count))
moreCount = min(50, Int32(transactionsInfo.transactions.count - transactions.count))
}
entries.append(.adsTransactionsExpand(presentationData.theme, presentationData.strings.Monetization_Transaction_ShowMoreTransactions(moreCount), false))
}
@ -1762,8 +1763,8 @@ private func channelStatsControllerEntries(
giveawayAvailable: Bool,
isGroup: Bool,
boostsOnly: Bool,
revenueState: RevenueStats?,
revenueTransactions: RevenueStatsTransactionsContext.State,
revenueState: StarsRevenueStats?,
revenueTransactions: StarsTransactionsContext.State,
starsState: StarsRevenueStats?,
starsTransactions: StarsTransactionsContext.State,
adsRestricted: Bool,
@ -1826,7 +1827,7 @@ public func channelStatsController(
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
peerId: PeerId,
section: ChannelStatsSection = .stats,
existingRevenueContext: RevenueStatsContext? = nil,
existingRevenueContext: StarsRevenueStatsContext? = nil,
existingStarsRevenueContext: StarsRevenueStatsContext? = nil,
boostStatus: ChannelBoostStatus? = nil,
boostStatusUpdated: ((ChannelBoostStatus) -> Void)? = nil
@ -1887,15 +1888,16 @@ public func channelStatsController(
let boostsContext = ChannelBoostersContext(account: context.account, peerId: peerId, gift: false)
let giftsContext = ChannelBoostersContext(account: context.account, peerId: peerId, gift: true)
let revenueContext = existingRevenueContext ?? RevenueStatsContext(account: context.account, peerId: peerId)
let revenueState = Promise<RevenueStatsContextState?>()
let revenueContext = existingRevenueContext ?? context.engine.payments.peerStarsRevenueContext(peerId: peerId, ton: true)
let revenueState = Promise<StarsRevenueStatsContextState?>()
revenueState.set(.single(nil) |> then(revenueContext.state |> map(Optional.init)))
let starsContext = existingStarsRevenueContext ?? context.engine.payments.peerStarsRevenueContext(peerId: peerId)
let starsContext = existingStarsRevenueContext ?? context.engine.payments.peerStarsRevenueContext(peerId: peerId, ton: false)
let starsState = Promise<StarsRevenueStatsContextState?>()
starsState.set(.single(nil) |> then(starsContext.state |> map(Optional.init)))
let revenueTransactions = RevenueStatsTransactionsContext(account: context.account, peerId: peerId)
let revenueTransactions = context.engine.payments.peerStarsTransactionsContext(subject: .peer(peerId: peerId, ton: true), mode: .all)
revenueTransactions.loadMore()
let starsTransactions = context.engine.payments.peerStarsTransactionsContext(subject: .peer(peerId: peerId, ton: false), mode: .all)
starsTransactions.loadMore()
@ -1906,7 +1908,7 @@ public func channelStatsController(
var navigateToChatImpl: ((EnginePeer) -> Void)?
var navigateToMessageImpl: ((EngineMessage.Id) -> Void)?
var openBoostImpl: ((Bool) -> Void)?
var openTonTransactionImpl: ((RevenueStatsTransactionsContext.State.Transaction) -> Void)?
var openTonTransactionImpl: ((StarsContext.State.Transaction) -> Void)?
var openStarsTransactionImpl: ((StarsContext.State.Transaction) -> Void)?
var requestTonWithdrawImpl: (() -> Void)?
var requestStarsWithdrawImpl: (() -> Void)?
@ -2514,7 +2516,7 @@ public func channelStatsController(
}
}
requestTonWithdrawImpl = {
withdrawalDisposable.set((context.engine.peers.checkChannelRevenueWithdrawalAvailability()
withdrawalDisposable.set((context.engine.peers.checkStarsRevenueWithdrawalAvailability()
|> deliverOnMainQueue).start(error: { error in
let controller = revenueWithdrawalController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, initialError: error, present: { c, _ in
presentImpl?(c)

View file

@ -175,14 +175,17 @@ final class MonetizationBalanceItemNode: ListViewItemNode, ItemListItemNode {
let value: String
var isStars = false
if let stats = item.stats as? RevenueStats {
let cryptoValue = formatTonAmountText(stats.balances.availableBalance, dateTimeFormat: item.presentationData.dateTimeFormat)
amountString = tonAmountAttributedString(cryptoValue, integralFont: integralFont, fractionalFont: fractionalFont, color: item.presentationData.theme.list.itemPrimaryTextColor, decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator)
value = stats.balances.availableBalance == 0 ? "" : "\(formatTonUsdValue(stats.balances.availableBalance, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
} else if let stats = item.stats as? StarsRevenueStats {
amountString = NSAttributedString(string: presentationStringsFormattedNumber(stats.balances.availableBalance, item.presentationData.dateTimeFormat.groupingSeparator), font: integralFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
value = stats.balances.availableBalance == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
isStars = true
if let stats = item.stats as? StarsRevenueStats {
switch stats.balances.availableBalance.currency {
case .ton:
let cryptoValue = formatTonAmountText(stats.balances.availableBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat)
amountString = tonAmountAttributedString(cryptoValue, integralFont: integralFont, fractionalFont: fractionalFont, color: item.presentationData.theme.list.itemPrimaryTextColor, decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator)
value = stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
case .stars:
amountString = NSAttributedString(string: presentationStringsFormattedNumber(stats.balances.availableBalance.amount, item.presentationData.dateTimeFormat.groupingSeparator), font: integralFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
value = stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
isStars = true
}
} else {
fatalError()
}

View file

@ -46,7 +46,7 @@ func confirmRevenueWithdrawalController(context: AccountContext, updatedPresenta
}
contentNode.updateIsChecking(true)
let signal = context.engine.peers.requestChannelRevenueWithdrawalUrl(peerId: peerId, password: contentNode.password)
let signal = context.engine.peers.requestStarsRevenueWithdrawalUrl(peerId: peerId, ton: false, amount: nil, password: contentNode.password)
disposable.set((signal |> deliverOnMainQueue).start(next: { url in
dismissImpl?()
completion(url)
@ -73,7 +73,7 @@ func confirmRevenueWithdrawalController(context: AccountContext, updatedPresenta
}
func revenueWithdrawalController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: EnginePeer.Id, initialError: RequestRevenueWithdrawalError, present: @escaping (ViewController, Any?) -> Void, completion: @escaping (String) -> Void) -> ViewController {
func revenueWithdrawalController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: EnginePeer.Id, initialError: RequestStarsRevenueWithdrawalError, present: @escaping (ViewController, Any?) -> Void, completion: @escaping (String) -> Void) -> ViewController {
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
let theme = AlertControllerTheme(presentationData: presentationData)

View file

@ -36,10 +36,6 @@ extension StoryStats: Stats {
}
extension RevenueStats: Stats {
}
extension StarsRevenueStats: Stats {
}
@ -763,8 +759,8 @@ class StatsOverviewItemNode: ListViewItemNode {
} else {
height += topLeftItemLayoutAndApply!.0.height * 4.0 + verticalSpacing * 3.0
}
} else if let stats = item.stats as? RevenueStats {
if let additionalStats = item.additionalStats as? StarsRevenueStats, additionalStats.balances.overallRevenue > StarsAmount.zero {
} else if let stats = item.stats as? StarsRevenueStats, case .ton = stats.balances.overallRevenue.currency {
if let additionalStats = item.additionalStats as? StarsRevenueStats, additionalStats.balances.overallRevenue.amount > StarsAmount.zero {
twoColumnLayout = true
useMinLeftColumnWidth = true
@ -772,9 +768,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatTonAmountText(stats.balances.availableBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatTonAmountText(stats.balances.availableBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Available,
(stats.balances.availableBalance == 0 ? "" : "\(formatTonUsdValue(stats.balances.availableBalance, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.availableBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -782,9 +778,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatTonAmountText(stats.balances.currentBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatTonAmountText(stats.balances.currentBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Current,
(stats.balances.currentBalance == 0 ? "" : "\(formatTonUsdValue(stats.balances.currentBalance, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.currentBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.currentBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -792,9 +788,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatTonAmountText(stats.balances.overallRevenue, dateTimeFormat: item.presentationData.dateTimeFormat),
formatTonAmountText(stats.balances.overallRevenue.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Total,
(stats.balances.overallRevenue == 0 ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.overallRevenue.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -802,9 +798,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatStarsAmountText(additionalStats.balances.availableBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatStarsAmountText(additionalStats.balances.availableBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
" ",
(additionalStats.balances.availableBalance == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.availableBalance.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(additionalStats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.availableBalance.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -812,9 +808,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatStarsAmountText(additionalStats.balances.currentBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatStarsAmountText(additionalStats.balances.currentBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
" ",
(additionalStats.balances.currentBalance == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.currentBalance.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(additionalStats.balances.currentBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.currentBalance.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -822,9 +818,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatStarsAmountText(additionalStats.balances.overallRevenue, dateTimeFormat: item.presentationData.dateTimeFormat),
formatStarsAmountText(additionalStats.balances.overallRevenue.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
" ",
(additionalStats.balances.overallRevenue == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.overallRevenue.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(additionalStats.balances.overallRevenue.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.overallRevenue.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -836,9 +832,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatTonAmountText(stats.balances.availableBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatTonAmountText(stats.balances.availableBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_Overview_Available,
(stats.balances.availableBalance == 0 ? "" : "\(formatTonUsdValue(stats.balances.availableBalance, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.availableBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -846,9 +842,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatTonAmountText(stats.balances.currentBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatTonAmountText(stats.balances.currentBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_Overview_Current,
(stats.balances.currentBalance == 0 ? "" : "\(formatTonUsdValue(stats.balances.currentBalance, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.currentBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.currentBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -856,9 +852,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatTonAmountText(stats.balances.overallRevenue, dateTimeFormat: item.presentationData.dateTimeFormat),
formatTonAmountText(stats.balances.overallRevenue.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_Overview_Total,
(stats.balances.overallRevenue == 0 ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.overallRevenue.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -871,9 +867,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatStarsAmountText(stats.balances.availableBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatStarsAmountText(stats.balances.availableBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Available,
(stats.balances.availableBalance == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -881,9 +877,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatStarsAmountText(stats.balances.currentBalance, dateTimeFormat: item.presentationData.dateTimeFormat),
formatStarsAmountText(stats.balances.currentBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Current,
(stats.balances.currentBalance == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.currentBalance.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.currentBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.currentBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -891,9 +887,9 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
formatStarsAmountText(stats.balances.overallRevenue, dateTimeFormat: item.presentationData.dateTimeFormat),
formatStarsAmountText(stats.balances.overallRevenue.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Total,
(stats.balances.overallRevenue == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.overallRevenue.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)

View file

@ -23,14 +23,14 @@ private final class SheetContent: CombinedComponent {
let context: AccountContext
let peer: EnginePeer
let transaction: RevenueStatsTransactionsContext.State.Transaction
let transaction: StarsContext.State.Transaction
let openExplorer: (String) -> Void
let dismiss: () -> Void
init(
context: AccountContext,
peer: EnginePeer,
transaction: RevenueStatsTransactionsContext.State.Transaction,
transaction: StarsContext.State.Transaction,
openExplorer: @escaping (String) -> Void,
dismiss: @escaping () -> Void
) {
@ -136,40 +136,45 @@ private final class SheetContent: CombinedComponent {
let labelColor: UIColor
var showPeer = false
switch component.transaction {
case let .proceeds(amount, fromDate, toDate):
if let fromDate = component.transaction.adsProceedsFromDate, let toDate = component.transaction.adsProceedsToDate {
labelColor = theme.list.itemDisclosureActions.constructive.fillColor
amountString = tonAmountAttributedString(formatTonAmountText(amount, dateTimeFormat: dateTimeFormat, showPlus: true), integralFont: integralFont, fractionalFont: fractionalFont, color: labelColor, decimalSeparator: dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
amountString = tonAmountAttributedString(formatTonAmountText(component.transaction.count.amount.value, dateTimeFormat: dateTimeFormat, showPlus: true), integralFont: integralFont, fractionalFont: fractionalFont, color: labelColor, decimalSeparator: dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
dateString = "\(stringForMediumCompactDate(timestamp: fromDate, strings: strings, dateTimeFormat: dateTimeFormat)) \(stringForMediumCompactDate(timestamp: toDate, strings: strings, dateTimeFormat: dateTimeFormat))"
titleString = strings.Monetization_TransactionInfo_Proceeds
buttonTitle = strings.Common_OK
explorerUrl = nil
showPeer = true
case let .withdrawal(status, amount, date, provider, _, transactionUrl):
} else if case .fragment = component.transaction.peer {
labelColor = theme.list.itemDestructiveColor
amountString = tonAmountAttributedString(formatTonAmountText(amount, dateTimeFormat: dateTimeFormat), integralFont: integralFont, fractionalFont: fractionalFont, color: labelColor, decimalSeparator: dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
dateString = stringForFullDate(timestamp: date, strings: strings, dateTimeFormat: dateTimeFormat)
amountString = tonAmountAttributedString(formatTonAmountText(component.transaction.count.amount.value, dateTimeFormat: dateTimeFormat), integralFont: integralFont, fractionalFont: fractionalFont, color: labelColor, decimalSeparator: dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
dateString = stringForFullDate(timestamp: component.transaction.date, strings: strings, dateTimeFormat: dateTimeFormat)
switch status {
case .succeed:
titleString = strings.Monetization_TransactionInfo_Withdrawal(provider).string
buttonTitle = strings.Monetization_TransactionInfo_ViewInExplorer
case .pending:
if component.transaction.flags.contains(.isPending) {
titleString = strings.Monetization_TransactionInfo_Pending
buttonTitle = strings.Common_OK
case .failed:
} else if component.transaction.flags.contains(.isFailed) {
titleString = strings.Monetization_TransactionInfo_Failed
buttonTitle = strings.Common_OK
titleColor = theme.list.itemDestructiveColor
} else {
titleString = strings.Monetization_TransactionInfo_Withdrawal("Fragment").string
buttonTitle = strings.Monetization_TransactionInfo_ViewInExplorer
}
explorerUrl = transactionUrl
case let .refund(amount, date, _):
explorerUrl = component.transaction.transactionUrl
} else if component.transaction.flags.contains(.isRefund) {
labelColor = theme.list.itemDisclosureActions.constructive.fillColor
titleString = strings.Monetization_TransactionInfo_Refund
amountString = tonAmountAttributedString(formatTonAmountText(amount, dateTimeFormat: dateTimeFormat, showPlus: true), integralFont: integralFont, fractionalFont: fractionalFont, color: labelColor, decimalSeparator: dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
dateString = stringForFullDate(timestamp: date, strings: strings, dateTimeFormat: dateTimeFormat)
amountString = tonAmountAttributedString(formatTonAmountText(component.transaction.count.amount.value, dateTimeFormat: dateTimeFormat, showPlus: true), integralFont: integralFont, fractionalFont: fractionalFont, color: labelColor, decimalSeparator: dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
dateString = stringForFullDate(timestamp: component.transaction.date, strings: strings, dateTimeFormat: dateTimeFormat)
buttonTitle = strings.Common_OK
explorerUrl = nil
} else {
labelColor = theme.list.itemDisclosureActions.constructive.fillColor
amountString = tonAmountAttributedString(formatTonAmountText(component.transaction.count.amount.value, dateTimeFormat: dateTimeFormat, showPlus: true), integralFont: integralFont, fractionalFont: fractionalFont, color: labelColor, decimalSeparator: dateTimeFormat.decimalSeparator).mutableCopy() as! NSMutableAttributedString
dateString = ""
titleString = ""
buttonTitle = ""
explorerUrl = nil
}
amountString.insert(NSAttributedString(string: " $ ", font: integralFont, textColor: labelColor), at: 1)
@ -293,13 +298,13 @@ private final class SheetContainerComponent: CombinedComponent {
let context: AccountContext
let peer: EnginePeer
let transaction: RevenueStatsTransactionsContext.State.Transaction
let transaction: StarsContext.State.Transaction
let openExplorer: (String) -> Void
init(
context: AccountContext,
peer: EnginePeer,
transaction: RevenueStatsTransactionsContext.State.Transaction,
transaction: StarsContext.State.Transaction,
openExplorer: @escaping (String) -> Void
) {
self.context = context
@ -410,7 +415,7 @@ final class TransactionInfoScreen: ViewControllerComponentContainer {
init(
context: AccountContext,
peer: EnginePeer,
transaction: RevenueStatsTransactionsContext.State.Transaction,
transaction: StarsContext.State.Transaction,
openExplorer: @escaping (String) -> Void
) {
self.context = context

View file

@ -110,10 +110,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[602479523] = { return Api.BotPreviewMedia.parse_botPreviewMedia($0) }
dict[-113453988] = { return Api.BotVerification.parse_botVerification($0) }
dict[-1328716265] = { return Api.BotVerifierSettings.parse_botVerifierSettings($0) }
dict[-1006669337] = { return Api.BroadcastRevenueBalances.parse_broadcastRevenueBalances($0) }
dict[1434332356] = { return Api.BroadcastRevenueTransaction.parse_broadcastRevenueTransactionProceeds($0) }
dict[1121127726] = { return Api.BroadcastRevenueTransaction.parse_broadcastRevenueTransactionRefund($0) }
dict[1515784568] = { return Api.BroadcastRevenueTransaction.parse_broadcastRevenueTransactionWithdrawal($0) }
dict[-283809188] = { return Api.BusinessAwayMessage.parse_businessAwayMessage($0) }
dict[-910564679] = { return Api.BusinessAwayMessageSchedule.parse_businessAwayMessageScheduleAlways($0) }
dict[-867328308] = { return Api.BusinessAwayMessageSchedule.parse_businessAwayMessageScheduleCustom($0) }
@ -609,6 +605,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[775611918] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
dict[-293988970] = { return Api.MessageAction.parse_messageActionSuggestedPostApproval($0) }
dict[1777932024] = { return Api.MessageAction.parse_messageActionSuggestedPostRefund($0) }
dict[-1780625559] = { return Api.MessageAction.parse_messageActionSuggestedPostSuccess($0) }
dict[-940721021] = { return Api.MessageAction.parse_messageActionTodoAppendTasks($0) }
dict[-864265079] = { return Api.MessageAction.parse_messageActionTodoCompletions($0) }
dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) }
@ -964,7 +962,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[779004698] = { return Api.StarsSubscription.parse_starsSubscription($0) }
dict[88173912] = { return Api.StarsSubscriptionPricing.parse_starsSubscriptionPricing($0) }
dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) }
dict[-1549805238] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[325426864] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) }
dict[-110658899] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAPI($0) }
dict[1617438738] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAds($0) }
@ -1042,7 +1040,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-997782967] = { return Api.Update.parse_updateBotStopped($0) }
dict[-2095595325] = { return Api.Update.parse_updateBotWebhookJSON($0) }
dict[-1684914010] = { return Api.Update.parse_updateBotWebhookJSONQuery($0) }
dict[-539401739] = { return Api.Update.parse_updateBroadcastRevenueTransactions($0) }
dict[513998247] = { return Api.Update.parse_updateBusinessBotCallbackQuery($0) }
dict[1666927625] = { return Api.Update.parse_updateChannel($0) }
dict[-1304443240] = { return Api.Update.parse_updateChannelAvailableMessages($0) }
@ -1436,7 +1433,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1877571094] = { return Api.payments.StarGifts.parse_starGifts($0) }
dict[-1551326360] = { return Api.payments.StarGifts.parse_starGiftsNotModified($0) }
dict[961445665] = { return Api.payments.StarsRevenueAdsAccountUrl.parse_starsRevenueAdsAccountUrl($0) }
dict[-919881925] = { return Api.payments.StarsRevenueStats.parse_starsRevenueStats($0) }
dict[1814066038] = { return Api.payments.StarsRevenueStats.parse_starsRevenueStats($0) }
dict[497778871] = { return Api.payments.StarsRevenueWithdrawalUrl.parse_starsRevenueWithdrawalUrl($0) }
dict[1822222573] = { return Api.payments.StarsStatus.parse_starsStatus($0) }
dict[-1261053863] = { return Api.payments.SuggestedStarRefBots.parse_suggestedStarRefBots($0) }
@ -1457,9 +1454,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1696454430] = { return Api.premium.MyBoosts.parse_myBoosts($0) }
dict[-594852657] = { return Api.smsjobs.EligibilityToJoin.parse_eligibleToJoin($0) }
dict[720277905] = { return Api.smsjobs.Status.parse_status($0) }
dict[1409802903] = { return Api.stats.BroadcastRevenueStats.parse_broadcastRevenueStats($0) }
dict[-2028632986] = { return Api.stats.BroadcastRevenueTransactions.parse_broadcastRevenueTransactions($0) }
dict[-328886473] = { return Api.stats.BroadcastRevenueWithdrawalUrl.parse_broadcastRevenueWithdrawalUrl($0) }
dict[963421692] = { return Api.stats.BroadcastStats.parse_broadcastStats($0) }
dict[-276825834] = { return Api.stats.MegagroupStats.parse_megagroupStats($0) }
dict[2145983508] = { return Api.stats.MessageStats.parse_messageStats($0) }
@ -1620,10 +1614,6 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.BotVerifierSettings:
_1.serialize(buffer, boxed)
case let _1 as Api.BroadcastRevenueBalances:
_1.serialize(buffer, boxed)
case let _1 as Api.BroadcastRevenueTransaction:
_1.serialize(buffer, boxed)
case let _1 as Api.BusinessAwayMessage:
_1.serialize(buffer, boxed)
case let _1 as Api.BusinessAwayMessageSchedule:
@ -2598,12 +2588,6 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.smsjobs.Status:
_1.serialize(buffer, boxed)
case let _1 as Api.stats.BroadcastRevenueStats:
_1.serialize(buffer, boxed)
case let _1 as Api.stats.BroadcastRevenueTransactions:
_1.serialize(buffer, boxed)
case let _1 as Api.stats.BroadcastRevenueWithdrawalUrl:
_1.serialize(buffer, boxed)
case let _1 as Api.stats.BroadcastStats:
_1.serialize(buffer, boxed)
case let _1 as Api.stats.MegagroupStats:

View file

@ -397,6 +397,8 @@ public extension Api {
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, resaleStars: Int64?, canTransferAt: Int32?, canResellAt: Int32?)
case messageActionSuggestProfilePhoto(photo: Api.Photo)
case messageActionSuggestedPostApproval(flags: Int32, rejectComment: String?, scheduleDate: Int32?, price: Api.StarsAmount?)
case messageActionSuggestedPostRefund(flags: Int32)
case messageActionSuggestedPostSuccess(price: Api.StarsAmount)
case messageActionTodoAppendTasks(list: [Api.TodoItem])
case messageActionTodoCompletions(completed: [Int32], incompleted: [Int32])
case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?)
@ -825,6 +827,18 @@ public extension Api {
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {price!.serialize(buffer, true)}
break
case .messageActionSuggestedPostRefund(let flags):
if boxed {
buffer.appendInt32(1777932024)
}
serializeInt32(flags, buffer: buffer, boxed: false)
break
case .messageActionSuggestedPostSuccess(let price):
if boxed {
buffer.appendInt32(-1780625559)
}
price.serialize(buffer, true)
break
case .messageActionTodoAppendTasks(let list):
if boxed {
buffer.appendInt32(-940721021)
@ -985,6 +999,10 @@ public extension Api {
return ("messageActionSuggestProfilePhoto", [("photo", photo as Any)])
case .messageActionSuggestedPostApproval(let flags, let rejectComment, let scheduleDate, let price):
return ("messageActionSuggestedPostApproval", [("flags", flags as Any), ("rejectComment", rejectComment as Any), ("scheduleDate", scheduleDate as Any), ("price", price as Any)])
case .messageActionSuggestedPostRefund(let flags):
return ("messageActionSuggestedPostRefund", [("flags", flags as Any)])
case .messageActionSuggestedPostSuccess(let price):
return ("messageActionSuggestedPostSuccess", [("price", price as Any)])
case .messageActionTodoAppendTasks(let list):
return ("messageActionTodoAppendTasks", [("list", list as Any)])
case .messageActionTodoCompletions(let completed, let incompleted):
@ -1832,6 +1850,30 @@ public extension Api {
return nil
}
}
public static func parse_messageActionSuggestedPostRefund(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.MessageAction.messageActionSuggestedPostRefund(flags: _1!)
}
else {
return nil
}
}
public static func parse_messageActionSuggestedPostSuccess(_ reader: BufferReader) -> MessageAction? {
var _1: Api.StarsAmount?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
let _c1 = _1 != nil
if _c1 {
return Api.MessageAction.messageActionSuggestedPostSuccess(price: _1!)
}
else {
return nil
}
}
public static func parse_messageActionTodoAppendTasks(_ reader: BufferReader) -> MessageAction? {
var _1: [Api.TodoItem]?
if let _ = reader.readInt32() {

View file

@ -914,166 +914,6 @@ public extension Api {
}
}
public extension Api {
enum BroadcastRevenueBalances: TypeConstructorDescription {
case broadcastRevenueBalances(flags: Int32, currentBalance: Int64, availableBalance: Int64, overallRevenue: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastRevenueBalances(let flags, let currentBalance, let availableBalance, let overallRevenue):
if boxed {
buffer.appendInt32(-1006669337)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(currentBalance, buffer: buffer, boxed: false)
serializeInt64(availableBalance, buffer: buffer, boxed: false)
serializeInt64(overallRevenue, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastRevenueBalances(let flags, let currentBalance, let availableBalance, let overallRevenue):
return ("broadcastRevenueBalances", [("flags", flags as Any), ("currentBalance", currentBalance as Any), ("availableBalance", availableBalance as Any), ("overallRevenue", overallRevenue as Any)])
}
}
public static func parse_broadcastRevenueBalances(_ reader: BufferReader) -> BroadcastRevenueBalances? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int64?
_3 = reader.readInt64()
var _4: Int64?
_4 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.BroadcastRevenueBalances.broadcastRevenueBalances(flags: _1!, currentBalance: _2!, availableBalance: _3!, overallRevenue: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum BroadcastRevenueTransaction: TypeConstructorDescription {
case broadcastRevenueTransactionProceeds(amount: Int64, fromDate: Int32, toDate: Int32)
case broadcastRevenueTransactionRefund(amount: Int64, date: Int32, provider: String)
case broadcastRevenueTransactionWithdrawal(flags: Int32, amount: Int64, date: Int32, provider: String, transactionDate: Int32?, transactionUrl: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastRevenueTransactionProceeds(let amount, let fromDate, let toDate):
if boxed {
buffer.appendInt32(1434332356)
}
serializeInt64(amount, buffer: buffer, boxed: false)
serializeInt32(fromDate, buffer: buffer, boxed: false)
serializeInt32(toDate, buffer: buffer, boxed: false)
break
case .broadcastRevenueTransactionRefund(let amount, let date, let provider):
if boxed {
buffer.appendInt32(1121127726)
}
serializeInt64(amount, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeString(provider, buffer: buffer, boxed: false)
break
case .broadcastRevenueTransactionWithdrawal(let flags, let amount, let date, let provider, let transactionDate, let transactionUrl):
if boxed {
buffer.appendInt32(1515784568)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(amount, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeString(provider, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(transactionDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(transactionUrl!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastRevenueTransactionProceeds(let amount, let fromDate, let toDate):
return ("broadcastRevenueTransactionProceeds", [("amount", amount as Any), ("fromDate", fromDate as Any), ("toDate", toDate as Any)])
case .broadcastRevenueTransactionRefund(let amount, let date, let provider):
return ("broadcastRevenueTransactionRefund", [("amount", amount as Any), ("date", date as Any), ("provider", provider as Any)])
case .broadcastRevenueTransactionWithdrawal(let flags, let amount, let date, let provider, let transactionDate, let transactionUrl):
return ("broadcastRevenueTransactionWithdrawal", [("flags", flags as Any), ("amount", amount as Any), ("date", date as Any), ("provider", provider as Any), ("transactionDate", transactionDate as Any), ("transactionUrl", transactionUrl as Any)])
}
}
public static func parse_broadcastRevenueTransactionProceeds(_ reader: BufferReader) -> BroadcastRevenueTransaction? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.BroadcastRevenueTransaction.broadcastRevenueTransactionProceeds(amount: _1!, fromDate: _2!, toDate: _3!)
}
else {
return nil
}
}
public static func parse_broadcastRevenueTransactionRefund(_ reader: BufferReader) -> BroadcastRevenueTransaction? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int32?
_2 = reader.readInt32()
var _3: String?
_3 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.BroadcastRevenueTransaction.broadcastRevenueTransactionRefund(amount: _1!, date: _2!, provider: _3!)
}
else {
return nil
}
}
public static func parse_broadcastRevenueTransactionWithdrawal(_ reader: BufferReader) -> BroadcastRevenueTransaction? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int32?
_3 = reader.readInt32()
var _4: String?
_4 = parseString(reader)
var _5: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
var _6: String?
if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.BroadcastRevenueTransaction.broadcastRevenueTransactionWithdrawal(flags: _1!, amount: _2!, date: _3!, provider: _4!, transactionDate: _5, transactionUrl: _6)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessAwayMessage: TypeConstructorDescription {
case businessAwayMessage(flags: Int32, shortcutId: Int32, schedule: Api.BusinessAwayMessageSchedule, recipients: Api.BusinessRecipients)
@ -1190,3 +1030,203 @@ public extension Api {
}
}
public extension Api {
enum BusinessBotRecipients: TypeConstructorDescription {
case businessBotRecipients(flags: Int32, users: [Int64]?, excludeUsers: [Int64]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessBotRecipients(let flags, let users, let excludeUsers):
if boxed {
buffer.appendInt32(-1198722189)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users!.count))
for item in users! {
serializeInt64(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 6) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(excludeUsers!.count))
for item in excludeUsers! {
serializeInt64(item, buffer: buffer, boxed: false)
}}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessBotRecipients(let flags, let users, let excludeUsers):
return ("businessBotRecipients", [("flags", flags as Any), ("users", users as Any), ("excludeUsers", excludeUsers as Any)])
}
}
public static func parse_businessBotRecipients(_ reader: BufferReader) -> BusinessBotRecipients? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Int64]?
if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
} }
var _3: [Int64]?
if Int(_1!) & Int(1 << 6) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
} }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 4) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 6) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.BusinessBotRecipients.businessBotRecipients(flags: _1!, users: _2, excludeUsers: _3)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessBotRights: TypeConstructorDescription {
case businessBotRights(flags: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessBotRights(let flags):
if boxed {
buffer.appendInt32(-1604170505)
}
serializeInt32(flags, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessBotRights(let flags):
return ("businessBotRights", [("flags", flags as Any)])
}
}
public static func parse_businessBotRights(_ reader: BufferReader) -> BusinessBotRights? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.BusinessBotRights.businessBotRights(flags: _1!)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessChatLink: TypeConstructorDescription {
case businessChatLink(flags: Int32, link: String, message: String, entities: [Api.MessageEntity]?, title: String?, views: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessChatLink(let flags, let link, let message, let entities, let title, let views):
if boxed {
buffer.appendInt32(-1263638929)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(link, buffer: buffer, boxed: false)
serializeString(message, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
serializeInt32(views, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessChatLink(let flags, let link, let message, let entities, let title, let views):
return ("businessChatLink", [("flags", flags as Any), ("link", link as Any), ("message", message as Any), ("entities", entities as Any), ("title", title as Any), ("views", views as Any)])
}
}
public static func parse_businessChatLink(_ reader: BufferReader) -> BusinessChatLink? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
var _5: String?
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
var _6: Int32?
_6 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.BusinessChatLink.businessChatLink(flags: _1!, link: _2!, message: _3!, entities: _4, title: _5, views: _6!)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessGreetingMessage: TypeConstructorDescription {
case businessGreetingMessage(shortcutId: Int32, recipients: Api.BusinessRecipients, noActivityDays: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessGreetingMessage(let shortcutId, let recipients, let noActivityDays):
if boxed {
buffer.appendInt32(-451302485)
}
serializeInt32(shortcutId, buffer: buffer, boxed: false)
recipients.serialize(buffer, true)
serializeInt32(noActivityDays, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessGreetingMessage(let shortcutId, let recipients, let noActivityDays):
return ("businessGreetingMessage", [("shortcutId", shortcutId as Any), ("recipients", recipients as Any), ("noActivityDays", noActivityDays as Any)])
}
}
public static func parse_businessGreetingMessage(_ reader: BufferReader) -> BusinessGreetingMessage? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.BusinessRecipients?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.BusinessRecipients
}
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.BusinessGreetingMessage.businessGreetingMessage(shortcutId: _1!, recipients: _2!, noActivityDays: _3!)
}
else {
return nil
}
}
}
}

View file

@ -504,17 +504,17 @@ public extension Api {
}
public extension Api {
enum StarsTransaction: TypeConstructorDescription {
case starsTransaction(flags: Int32, id: String, stars: Api.StarsAmount, 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?, giveawayPostId: Int32?, stargift: Api.StarGift?, floodskipNumber: Int32?, starrefCommissionPermille: Int32?, starrefPeer: Api.Peer?, starrefAmount: Api.StarsAmount?, paidMessages: Int32?, premiumGiftMonths: Int32?)
case starsTransaction(flags: Int32, id: String, amount: Api.StarsAmount, 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?, giveawayPostId: Int32?, stargift: Api.StarGift?, floodskipNumber: Int32?, starrefCommissionPermille: Int32?, starrefPeer: Api.Peer?, starrefAmount: Api.StarsAmount?, paidMessages: Int32?, premiumGiftMonths: Int32?, adsProceedsFromDate: Int32?, adsProceedsToDate: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
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, let subscriptionPeriod, let giveawayPostId, let stargift, let floodskipNumber, let starrefCommissionPermille, let starrefPeer, let starrefAmount, let paidMessages, let premiumGiftMonths):
case .starsTransaction(let flags, let id, let amount, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod, let giveawayPostId, let stargift, let floodskipNumber, let starrefCommissionPermille, let starrefPeer, let starrefAmount, let paidMessages, let premiumGiftMonths, let adsProceedsFromDate, let adsProceedsToDate):
if boxed {
buffer.appendInt32(-1549805238)
buffer.appendInt32(325426864)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
stars.serialize(buffer, true)
amount.serialize(buffer, true)
serializeInt32(date, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
@ -538,14 +538,16 @@ public extension Api {
if Int(flags) & Int(1 << 17) != 0 {starrefAmount!.serialize(buffer, true)}
if Int(flags) & Int(1 << 19) != 0 {serializeInt32(paidMessages!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 20) != 0 {serializeInt32(premiumGiftMonths!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 23) != 0 {serializeInt32(adsProceedsFromDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 23) != 0 {serializeInt32(adsProceedsToDate!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
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, let subscriptionPeriod, let giveawayPostId, let stargift, let floodskipNumber, let starrefCommissionPermille, let starrefPeer, let starrefAmount, let paidMessages, let premiumGiftMonths):
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), ("giveawayPostId", giveawayPostId as Any), ("stargift", stargift as Any), ("floodskipNumber", floodskipNumber as Any), ("starrefCommissionPermille", starrefCommissionPermille as Any), ("starrefPeer", starrefPeer as Any), ("starrefAmount", starrefAmount as Any), ("paidMessages", paidMessages as Any), ("premiumGiftMonths", premiumGiftMonths as Any)])
case .starsTransaction(let flags, let id, let amount, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod, let giveawayPostId, let stargift, let floodskipNumber, let starrefCommissionPermille, let starrefPeer, let starrefAmount, let paidMessages, let premiumGiftMonths, let adsProceedsFromDate, let adsProceedsToDate):
return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("amount", amount 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), ("giveawayPostId", giveawayPostId as Any), ("stargift", stargift as Any), ("floodskipNumber", floodskipNumber as Any), ("starrefCommissionPermille", starrefCommissionPermille as Any), ("starrefPeer", starrefPeer as Any), ("starrefAmount", starrefAmount as Any), ("paidMessages", paidMessages as Any), ("premiumGiftMonths", premiumGiftMonths as Any), ("adsProceedsFromDate", adsProceedsFromDate as Any), ("adsProceedsToDate", adsProceedsToDate as Any)])
}
}
@ -608,6 +610,10 @@ public extension Api {
if Int(_1!) & Int(1 << 19) != 0 {_21 = reader.readInt32() }
var _22: Int32?
if Int(_1!) & Int(1 << 20) != 0 {_22 = reader.readInt32() }
var _23: Int32?
if Int(_1!) & Int(1 << 23) != 0 {_23 = reader.readInt32() }
var _24: Int32?
if Int(_1!) & Int(1 << 23) != 0 {_24 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -630,8 +636,10 @@ public extension Api {
let _c20 = (Int(_1!) & Int(1 << 17) == 0) || _20 != nil
let _c21 = (Int(_1!) & Int(1 << 19) == 0) || _21 != nil
let _c22 = (Int(_1!) & Int(1 << 20) == 0) || _22 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 {
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, giveawayPostId: _15, stargift: _16, floodskipNumber: _17, starrefCommissionPermille: _18, starrefPeer: _19, starrefAmount: _20, paidMessages: _21, premiumGiftMonths: _22)
let _c23 = (Int(_1!) & Int(1 << 23) == 0) || _23 != nil
let _c24 = (Int(_1!) & Int(1 << 23) == 0) || _24 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 {
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, amount: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10, botPayload: _11, msgId: _12, extendedMedia: _13, subscriptionPeriod: _14, giveawayPostId: _15, stargift: _16, floodskipNumber: _17, starrefCommissionPermille: _18, starrefPeer: _19, starrefAmount: _20, paidMessages: _21, premiumGiftMonths: _22, adsProceedsFromDate: _23, adsProceedsToDate: _24)
}
else {
return nil

View file

@ -73,7 +73,6 @@ public extension Api {
case updateBotStopped(userId: Int64, date: Int32, stopped: Api.Bool, qts: Int32)
case updateBotWebhookJSON(data: Api.DataJSON)
case updateBotWebhookJSONQuery(queryId: Int64, data: Api.DataJSON, timeout: Int32)
case updateBroadcastRevenueTransactions(peer: Api.Peer, balances: Api.BroadcastRevenueBalances)
case updateBusinessBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, connectionId: String, message: Api.Message, replyToMessage: Api.Message?, chatInstance: Int64, data: Buffer?)
case updateChannel(channelId: Int64)
case updateChannelAvailableMessages(channelId: Int64, availableMinId: Int32)
@ -413,13 +412,6 @@ public extension Api {
data.serialize(buffer, true)
serializeInt32(timeout, buffer: buffer, boxed: false)
break
case .updateBroadcastRevenueTransactions(let peer, let balances):
if boxed {
buffer.appendInt32(-539401739)
}
peer.serialize(buffer, true)
balances.serialize(buffer, true)
break
case .updateBusinessBotCallbackQuery(let flags, let queryId, let userId, let connectionId, let message, let replyToMessage, let chatInstance, let data):
if boxed {
buffer.appendInt32(513998247)
@ -1515,8 +1507,6 @@ public extension Api {
return ("updateBotWebhookJSON", [("data", data as Any)])
case .updateBotWebhookJSONQuery(let queryId, let data, let timeout):
return ("updateBotWebhookJSONQuery", [("queryId", queryId as Any), ("data", data as Any), ("timeout", timeout as Any)])
case .updateBroadcastRevenueTransactions(let peer, let balances):
return ("updateBroadcastRevenueTransactions", [("peer", peer as Any), ("balances", balances as Any)])
case .updateBusinessBotCallbackQuery(let flags, let queryId, let userId, let connectionId, let message, let replyToMessage, let chatInstance, let data):
return ("updateBusinessBotCallbackQuery", [("flags", flags as Any), ("queryId", queryId as Any), ("userId", userId as Any), ("connectionId", connectionId as Any), ("message", message as Any), ("replyToMessage", replyToMessage as Any), ("chatInstance", chatInstance as Any), ("data", data as Any)])
case .updateChannel(let channelId):
@ -2242,24 +2232,6 @@ public extension Api {
return nil
}
}
public static func parse_updateBroadcastRevenueTransactions(_ reader: BufferReader) -> Update? {
var _1: Api.Peer?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _2: Api.BroadcastRevenueBalances?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.BroadcastRevenueBalances
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.Update.updateBroadcastRevenueTransactions(peer: _1!, balances: _2!)
}
else {
return nil
}
}
public static func parse_updateBusinessBotCallbackQuery(_ reader: BufferReader) -> Update? {
var _1: Int32?
_1 = reader.readInt32()

View file

@ -1,203 +1,3 @@
public extension Api {
enum BusinessBotRecipients: TypeConstructorDescription {
case businessBotRecipients(flags: Int32, users: [Int64]?, excludeUsers: [Int64]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessBotRecipients(let flags, let users, let excludeUsers):
if boxed {
buffer.appendInt32(-1198722189)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users!.count))
for item in users! {
serializeInt64(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 6) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(excludeUsers!.count))
for item in excludeUsers! {
serializeInt64(item, buffer: buffer, boxed: false)
}}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessBotRecipients(let flags, let users, let excludeUsers):
return ("businessBotRecipients", [("flags", flags as Any), ("users", users as Any), ("excludeUsers", excludeUsers as Any)])
}
}
public static func parse_businessBotRecipients(_ reader: BufferReader) -> BusinessBotRecipients? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Int64]?
if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
} }
var _3: [Int64]?
if Int(_1!) & Int(1 << 6) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
} }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 4) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 6) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.BusinessBotRecipients.businessBotRecipients(flags: _1!, users: _2, excludeUsers: _3)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessBotRights: TypeConstructorDescription {
case businessBotRights(flags: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessBotRights(let flags):
if boxed {
buffer.appendInt32(-1604170505)
}
serializeInt32(flags, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessBotRights(let flags):
return ("businessBotRights", [("flags", flags as Any)])
}
}
public static func parse_businessBotRights(_ reader: BufferReader) -> BusinessBotRights? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.BusinessBotRights.businessBotRights(flags: _1!)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessChatLink: TypeConstructorDescription {
case businessChatLink(flags: Int32, link: String, message: String, entities: [Api.MessageEntity]?, title: String?, views: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessChatLink(let flags, let link, let message, let entities, let title, let views):
if boxed {
buffer.appendInt32(-1263638929)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(link, buffer: buffer, boxed: false)
serializeString(message, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
serializeInt32(views, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessChatLink(let flags, let link, let message, let entities, let title, let views):
return ("businessChatLink", [("flags", flags as Any), ("link", link as Any), ("message", message as Any), ("entities", entities as Any), ("title", title as Any), ("views", views as Any)])
}
}
public static func parse_businessChatLink(_ reader: BufferReader) -> BusinessChatLink? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
var _5: String?
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
var _6: Int32?
_6 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.BusinessChatLink.businessChatLink(flags: _1!, link: _2!, message: _3!, entities: _4, title: _5, views: _6!)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessGreetingMessage: TypeConstructorDescription {
case businessGreetingMessage(shortcutId: Int32, recipients: Api.BusinessRecipients, noActivityDays: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .businessGreetingMessage(let shortcutId, let recipients, let noActivityDays):
if boxed {
buffer.appendInt32(-451302485)
}
serializeInt32(shortcutId, buffer: buffer, boxed: false)
recipients.serialize(buffer, true)
serializeInt32(noActivityDays, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .businessGreetingMessage(let shortcutId, let recipients, let noActivityDays):
return ("businessGreetingMessage", [("shortcutId", shortcutId as Any), ("recipients", recipients as Any), ("noActivityDays", noActivityDays as Any)])
}
}
public static func parse_businessGreetingMessage(_ reader: BufferReader) -> BusinessGreetingMessage? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.BusinessRecipients?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.BusinessRecipients
}
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.BusinessGreetingMessage.businessGreetingMessage(shortcutId: _1!, recipients: _2!, noActivityDays: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum BusinessIntro: TypeConstructorDescription {
case businessIntro(flags: Int32, title: String, description: String, sticker: Api.Document?)

View file

@ -392,14 +392,16 @@ public extension Api.payments {
}
public extension Api.payments {
enum StarsRevenueStats: TypeConstructorDescription {
case starsRevenueStats(revenueGraph: Api.StatsGraph, status: Api.StarsRevenueStatus, usdRate: Double)
case starsRevenueStats(flags: Int32, topHoursGraph: Api.StatsGraph?, revenueGraph: Api.StatsGraph, status: Api.StarsRevenueStatus, usdRate: Double)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsRevenueStats(let revenueGraph, let status, let usdRate):
case .starsRevenueStats(let flags, let topHoursGraph, let revenueGraph, let status, let usdRate):
if boxed {
buffer.appendInt32(-919881925)
buffer.appendInt32(1814066038)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {topHoursGraph!.serialize(buffer, true)}
revenueGraph.serialize(buffer, true)
status.serialize(buffer, true)
serializeDouble(usdRate, buffer: buffer, boxed: false)
@ -409,27 +411,35 @@ public extension Api.payments {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsRevenueStats(let revenueGraph, let status, let usdRate):
return ("starsRevenueStats", [("revenueGraph", revenueGraph as Any), ("status", status as Any), ("usdRate", usdRate as Any)])
case .starsRevenueStats(let flags, let topHoursGraph, let revenueGraph, let status, let usdRate):
return ("starsRevenueStats", [("flags", flags as Any), ("topHoursGraph", topHoursGraph as Any), ("revenueGraph", revenueGraph as Any), ("status", status as Any), ("usdRate", usdRate as Any)])
}
}
public static func parse_starsRevenueStats(_ reader: BufferReader) -> StarsRevenueStats? {
var _1: Api.StatsGraph?
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.StatsGraph?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsGraph
} }
var _3: Api.StatsGraph?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
_3 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _2: Api.StarsRevenueStatus?
var _4: Api.StarsRevenueStatus?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarsRevenueStatus
_4 = Api.parse(reader, signature: signature) as? Api.StarsRevenueStatus
}
var _3: Double?
_3 = reader.readDouble()
var _5: Double?
_5 = reader.readDouble()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.payments.StarsRevenueStats.starsRevenueStats(revenueGraph: _1!, status: _2!, usdRate: _3!)
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.payments.StarsRevenueStats.starsRevenueStats(flags: _1!, topHoursGraph: _2, revenueGraph: _3!, status: _4!, usdRate: _5!)
}
else {
return nil
@ -1561,73 +1571,39 @@ public extension Api.smsjobs {
}
}
public extension Api.stats {
enum BroadcastRevenueStats: TypeConstructorDescription {
case broadcastRevenueStats(topHoursGraph: Api.StatsGraph, revenueGraph: Api.StatsGraph, balances: Api.BroadcastRevenueBalances, usdRate: Double)
enum BroadcastStats: TypeConstructorDescription {
case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, reactionsPerPost: Api.StatsAbsValueAndPrev, viewsPerStory: Api.StatsAbsValueAndPrev, sharesPerStory: Api.StatsAbsValueAndPrev, reactionsPerStory: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph, ivInteractionsGraph: Api.StatsGraph, viewsBySourceGraph: Api.StatsGraph, newFollowersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, reactionsByEmotionGraph: Api.StatsGraph, storyInteractionsGraph: Api.StatsGraph, storyReactionsByEmotionGraph: Api.StatsGraph, recentPostsInteractions: [Api.PostInteractionCounters])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastRevenueStats(let topHoursGraph, let revenueGraph, let balances, let usdRate):
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let reactionsPerPost, let viewsPerStory, let sharesPerStory, let reactionsPerStory, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let reactionsByEmotionGraph, let storyInteractionsGraph, let storyReactionsByEmotionGraph, let recentPostsInteractions):
if boxed {
buffer.appendInt32(1409802903)
buffer.appendInt32(963421692)
}
period.serialize(buffer, true)
followers.serialize(buffer, true)
viewsPerPost.serialize(buffer, true)
sharesPerPost.serialize(buffer, true)
reactionsPerPost.serialize(buffer, true)
viewsPerStory.serialize(buffer, true)
sharesPerStory.serialize(buffer, true)
reactionsPerStory.serialize(buffer, true)
enabledNotifications.serialize(buffer, true)
growthGraph.serialize(buffer, true)
followersGraph.serialize(buffer, true)
muteGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
revenueGraph.serialize(buffer, true)
balances.serialize(buffer, true)
serializeDouble(usdRate, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastRevenueStats(let topHoursGraph, let revenueGraph, let balances, let usdRate):
return ("broadcastRevenueStats", [("topHoursGraph", topHoursGraph as Any), ("revenueGraph", revenueGraph as Any), ("balances", balances as Any), ("usdRate", usdRate as Any)])
}
}
public static func parse_broadcastRevenueStats(_ reader: BufferReader) -> BroadcastRevenueStats? {
var _1: Api.StatsGraph?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _2: Api.StatsGraph?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _3: Api.BroadcastRevenueBalances?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.BroadcastRevenueBalances
}
var _4: Double?
_4 = reader.readDouble()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.stats.BroadcastRevenueStats.broadcastRevenueStats(topHoursGraph: _1!, revenueGraph: _2!, balances: _3!, usdRate: _4!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum BroadcastRevenueTransactions: TypeConstructorDescription {
case broadcastRevenueTransactions(count: Int32, transactions: [Api.BroadcastRevenueTransaction])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastRevenueTransactions(let count, let transactions):
if boxed {
buffer.appendInt32(-2028632986)
}
serializeInt32(count, buffer: buffer, boxed: false)
interactionsGraph.serialize(buffer, true)
ivInteractionsGraph.serialize(buffer, true)
viewsBySourceGraph.serialize(buffer, true)
newFollowersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
reactionsByEmotionGraph.serialize(buffer, true)
storyInteractionsGraph.serialize(buffer, true)
storyReactionsByEmotionGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(transactions.count))
for item in transactions {
buffer.appendInt32(Int32(recentPostsInteractions.count))
for item in recentPostsInteractions {
item.serialize(buffer, true)
}
break
@ -1636,22 +1612,124 @@ public extension Api.stats {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastRevenueTransactions(let count, let transactions):
return ("broadcastRevenueTransactions", [("count", count as Any), ("transactions", transactions as Any)])
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let reactionsPerPost, let viewsPerStory, let sharesPerStory, let reactionsPerStory, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let reactionsByEmotionGraph, let storyInteractionsGraph, let storyReactionsByEmotionGraph, let recentPostsInteractions):
return ("broadcastStats", [("period", period as Any), ("followers", followers as Any), ("viewsPerPost", viewsPerPost as Any), ("sharesPerPost", sharesPerPost as Any), ("reactionsPerPost", reactionsPerPost as Any), ("viewsPerStory", viewsPerStory as Any), ("sharesPerStory", sharesPerStory as Any), ("reactionsPerStory", reactionsPerStory as Any), ("enabledNotifications", enabledNotifications as Any), ("growthGraph", growthGraph as Any), ("followersGraph", followersGraph as Any), ("muteGraph", muteGraph as Any), ("topHoursGraph", topHoursGraph as Any), ("interactionsGraph", interactionsGraph as Any), ("ivInteractionsGraph", ivInteractionsGraph as Any), ("viewsBySourceGraph", viewsBySourceGraph as Any), ("newFollowersBySourceGraph", newFollowersBySourceGraph as Any), ("languagesGraph", languagesGraph as Any), ("reactionsByEmotionGraph", reactionsByEmotionGraph as Any), ("storyInteractionsGraph", storyInteractionsGraph as Any), ("storyReactionsByEmotionGraph", storyReactionsByEmotionGraph as Any), ("recentPostsInteractions", recentPostsInteractions as Any)])
}
}
public static func parse_broadcastRevenueTransactions(_ reader: BufferReader) -> BroadcastRevenueTransactions? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.BroadcastRevenueTransaction]?
public static func parse_broadcastStats(_ reader: BufferReader) -> BroadcastStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _6: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _7: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _8: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _9: Api.StatsPercentValue?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: Api.StatsGraph?
if let signature = reader.readInt32() {
_14 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _15: Api.StatsGraph?
if let signature = reader.readInt32() {
_15 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _16: Api.StatsGraph?
if let signature = reader.readInt32() {
_16 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _17: Api.StatsGraph?
if let signature = reader.readInt32() {
_17 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _18: Api.StatsGraph?
if let signature = reader.readInt32() {
_18 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _19: Api.StatsGraph?
if let signature = reader.readInt32() {
_19 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _20: Api.StatsGraph?
if let signature = reader.readInt32() {
_20 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _21: Api.StatsGraph?
if let signature = reader.readInt32() {
_21 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _22: [Api.PostInteractionCounters]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BroadcastRevenueTransaction.self)
_22 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PostInteractionCounters.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.stats.BroadcastRevenueTransactions.broadcastRevenueTransactions(count: _1!, transactions: _2!)
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
let _c16 = _16 != nil
let _c17 = _17 != nil
let _c18 = _18 != nil
let _c19 = _19 != nil
let _c20 = _20 != nil
let _c21 = _21 != nil
let _c22 = _22 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 {
return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, reactionsPerPost: _5!, viewsPerStory: _6!, sharesPerStory: _7!, reactionsPerStory: _8!, enabledNotifications: _9!, growthGraph: _10!, followersGraph: _11!, muteGraph: _12!, topHoursGraph: _13!, interactionsGraph: _14!, ivInteractionsGraph: _15!, viewsBySourceGraph: _16!, newFollowersBySourceGraph: _17!, languagesGraph: _18!, reactionsByEmotionGraph: _19!, storyInteractionsGraph: _20!, storyReactionsByEmotionGraph: _21!, recentPostsInteractions: _22!)
}
else {
return nil
@ -1661,33 +1739,191 @@ public extension Api.stats {
}
}
public extension Api.stats {
enum BroadcastRevenueWithdrawalUrl: TypeConstructorDescription {
case broadcastRevenueWithdrawalUrl(url: String)
enum MegagroupStats: TypeConstructorDescription {
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastRevenueWithdrawalUrl(let url):
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
if boxed {
buffer.appendInt32(-328886473)
buffer.appendInt32(-276825834)
}
period.serialize(buffer, true)
members.serialize(buffer, true)
messages.serialize(buffer, true)
viewers.serialize(buffer, true)
posters.serialize(buffer, true)
growthGraph.serialize(buffer, true)
membersGraph.serialize(buffer, true)
newMembersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
messagesGraph.serialize(buffer, true)
actionsGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
weekdaysGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topPosters.count))
for item in topPosters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topAdmins.count))
for item in topAdmins {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topInviters.count))
for item in topInviters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
serializeString(url, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastRevenueWithdrawalUrl(let url):
return ("broadcastRevenueWithdrawalUrl", [("url", url as Any)])
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
return ("megagroupStats", [("period", period as Any), ("members", members as Any), ("messages", messages as Any), ("viewers", viewers as Any), ("posters", posters as Any), ("growthGraph", growthGraph as Any), ("membersGraph", membersGraph as Any), ("newMembersBySourceGraph", newMembersBySourceGraph as Any), ("languagesGraph", languagesGraph as Any), ("messagesGraph", messagesGraph as Any), ("actionsGraph", actionsGraph as Any), ("topHoursGraph", topHoursGraph as Any), ("weekdaysGraph", weekdaysGraph as Any), ("topPosters", topPosters as Any), ("topAdmins", topAdmins as Any), ("topInviters", topInviters as Any), ("users", users as Any)])
}
}
public static func parse_broadcastRevenueWithdrawalUrl(_ reader: BufferReader) -> BroadcastRevenueWithdrawalUrl? {
var _1: String?
_1 = parseString(reader)
public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _6: Api.StatsGraph?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _7: Api.StatsGraph?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _8: Api.StatsGraph?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _9: Api.StatsGraph?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: [Api.StatsGroupTopPoster]?
if let _ = reader.readInt32() {
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
}
var _15: [Api.StatsGroupTopAdmin]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
}
var _16: [Api.StatsGroupTopInviter]?
if let _ = reader.readInt32() {
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
}
var _17: [Api.User]?
if let _ = reader.readInt32() {
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.stats.BroadcastRevenueWithdrawalUrl.broadcastRevenueWithdrawalUrl(url: _1!)
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
let _c16 = _16 != nil
let _c17 = _17 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum MessageStats: TypeConstructorDescription {
case messageStats(viewsGraph: Api.StatsGraph, reactionsByEmotionGraph: Api.StatsGraph)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
if boxed {
buffer.appendInt32(2145983508)
}
viewsGraph.serialize(buffer, true)
reactionsByEmotionGraph.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
return ("messageStats", [("viewsGraph", viewsGraph as Any), ("reactionsByEmotionGraph", reactionsByEmotionGraph as Any)])
}
}
public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? {
var _1: Api.StatsGraph?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _2: Api.StatsGraph?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.stats.MessageStats.messageStats(viewsGraph: _1!, reactionsByEmotionGraph: _2!)
}
else {
return nil

View file

@ -1,365 +1,3 @@
public extension Api.stats {
enum BroadcastStats: TypeConstructorDescription {
case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, reactionsPerPost: Api.StatsAbsValueAndPrev, viewsPerStory: Api.StatsAbsValueAndPrev, sharesPerStory: Api.StatsAbsValueAndPrev, reactionsPerStory: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph, ivInteractionsGraph: Api.StatsGraph, viewsBySourceGraph: Api.StatsGraph, newFollowersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, reactionsByEmotionGraph: Api.StatsGraph, storyInteractionsGraph: Api.StatsGraph, storyReactionsByEmotionGraph: Api.StatsGraph, recentPostsInteractions: [Api.PostInteractionCounters])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let reactionsPerPost, let viewsPerStory, let sharesPerStory, let reactionsPerStory, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let reactionsByEmotionGraph, let storyInteractionsGraph, let storyReactionsByEmotionGraph, let recentPostsInteractions):
if boxed {
buffer.appendInt32(963421692)
}
period.serialize(buffer, true)
followers.serialize(buffer, true)
viewsPerPost.serialize(buffer, true)
sharesPerPost.serialize(buffer, true)
reactionsPerPost.serialize(buffer, true)
viewsPerStory.serialize(buffer, true)
sharesPerStory.serialize(buffer, true)
reactionsPerStory.serialize(buffer, true)
enabledNotifications.serialize(buffer, true)
growthGraph.serialize(buffer, true)
followersGraph.serialize(buffer, true)
muteGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
interactionsGraph.serialize(buffer, true)
ivInteractionsGraph.serialize(buffer, true)
viewsBySourceGraph.serialize(buffer, true)
newFollowersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
reactionsByEmotionGraph.serialize(buffer, true)
storyInteractionsGraph.serialize(buffer, true)
storyReactionsByEmotionGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(recentPostsInteractions.count))
for item in recentPostsInteractions {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let reactionsPerPost, let viewsPerStory, let sharesPerStory, let reactionsPerStory, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let reactionsByEmotionGraph, let storyInteractionsGraph, let storyReactionsByEmotionGraph, let recentPostsInteractions):
return ("broadcastStats", [("period", period as Any), ("followers", followers as Any), ("viewsPerPost", viewsPerPost as Any), ("sharesPerPost", sharesPerPost as Any), ("reactionsPerPost", reactionsPerPost as Any), ("viewsPerStory", viewsPerStory as Any), ("sharesPerStory", sharesPerStory as Any), ("reactionsPerStory", reactionsPerStory as Any), ("enabledNotifications", enabledNotifications as Any), ("growthGraph", growthGraph as Any), ("followersGraph", followersGraph as Any), ("muteGraph", muteGraph as Any), ("topHoursGraph", topHoursGraph as Any), ("interactionsGraph", interactionsGraph as Any), ("ivInteractionsGraph", ivInteractionsGraph as Any), ("viewsBySourceGraph", viewsBySourceGraph as Any), ("newFollowersBySourceGraph", newFollowersBySourceGraph as Any), ("languagesGraph", languagesGraph as Any), ("reactionsByEmotionGraph", reactionsByEmotionGraph as Any), ("storyInteractionsGraph", storyInteractionsGraph as Any), ("storyReactionsByEmotionGraph", storyReactionsByEmotionGraph as Any), ("recentPostsInteractions", recentPostsInteractions as Any)])
}
}
public static func parse_broadcastStats(_ reader: BufferReader) -> BroadcastStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _6: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _7: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _8: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _9: Api.StatsPercentValue?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: Api.StatsGraph?
if let signature = reader.readInt32() {
_14 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _15: Api.StatsGraph?
if let signature = reader.readInt32() {
_15 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _16: Api.StatsGraph?
if let signature = reader.readInt32() {
_16 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _17: Api.StatsGraph?
if let signature = reader.readInt32() {
_17 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _18: Api.StatsGraph?
if let signature = reader.readInt32() {
_18 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _19: Api.StatsGraph?
if let signature = reader.readInt32() {
_19 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _20: Api.StatsGraph?
if let signature = reader.readInt32() {
_20 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _21: Api.StatsGraph?
if let signature = reader.readInt32() {
_21 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _22: [Api.PostInteractionCounters]?
if let _ = reader.readInt32() {
_22 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PostInteractionCounters.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
let _c16 = _16 != nil
let _c17 = _17 != nil
let _c18 = _18 != nil
let _c19 = _19 != nil
let _c20 = _20 != nil
let _c21 = _21 != nil
let _c22 = _22 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 {
return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, reactionsPerPost: _5!, viewsPerStory: _6!, sharesPerStory: _7!, reactionsPerStory: _8!, enabledNotifications: _9!, growthGraph: _10!, followersGraph: _11!, muteGraph: _12!, topHoursGraph: _13!, interactionsGraph: _14!, ivInteractionsGraph: _15!, viewsBySourceGraph: _16!, newFollowersBySourceGraph: _17!, languagesGraph: _18!, reactionsByEmotionGraph: _19!, storyInteractionsGraph: _20!, storyReactionsByEmotionGraph: _21!, recentPostsInteractions: _22!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum MegagroupStats: TypeConstructorDescription {
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
if boxed {
buffer.appendInt32(-276825834)
}
period.serialize(buffer, true)
members.serialize(buffer, true)
messages.serialize(buffer, true)
viewers.serialize(buffer, true)
posters.serialize(buffer, true)
growthGraph.serialize(buffer, true)
membersGraph.serialize(buffer, true)
newMembersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
messagesGraph.serialize(buffer, true)
actionsGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
weekdaysGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topPosters.count))
for item in topPosters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topAdmins.count))
for item in topAdmins {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topInviters.count))
for item in topInviters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
return ("megagroupStats", [("period", period as Any), ("members", members as Any), ("messages", messages as Any), ("viewers", viewers as Any), ("posters", posters as Any), ("growthGraph", growthGraph as Any), ("membersGraph", membersGraph as Any), ("newMembersBySourceGraph", newMembersBySourceGraph as Any), ("languagesGraph", languagesGraph as Any), ("messagesGraph", messagesGraph as Any), ("actionsGraph", actionsGraph as Any), ("topHoursGraph", topHoursGraph as Any), ("weekdaysGraph", weekdaysGraph as Any), ("topPosters", topPosters as Any), ("topAdmins", topAdmins as Any), ("topInviters", topInviters as Any), ("users", users as Any)])
}
}
public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _6: Api.StatsGraph?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _7: Api.StatsGraph?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _8: Api.StatsGraph?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _9: Api.StatsGraph?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: [Api.StatsGroupTopPoster]?
if let _ = reader.readInt32() {
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
}
var _15: [Api.StatsGroupTopAdmin]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
}
var _16: [Api.StatsGroupTopInviter]?
if let _ = reader.readInt32() {
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
}
var _17: [Api.User]?
if let _ = reader.readInt32() {
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
let _c16 = _16 != nil
let _c17 = _17 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum MessageStats: TypeConstructorDescription {
case messageStats(viewsGraph: Api.StatsGraph, reactionsByEmotionGraph: Api.StatsGraph)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
if boxed {
buffer.appendInt32(2145983508)
}
viewsGraph.serialize(buffer, true)
reactionsByEmotionGraph.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
return ("messageStats", [("viewsGraph", viewsGraph as Any), ("reactionsByEmotionGraph", reactionsByEmotionGraph as Any)])
}
}
public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? {
var _1: Api.StatsGraph?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _2: Api.StatsGraph?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.stats.MessageStats.messageStats(viewsGraph: _1!, reactionsByEmotionGraph: _2!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum PublicForwards: TypeConstructorDescription {
case publicForwards(flags: Int32, count: Int32, forwards: [Api.PublicForward], nextOffset: String?, chats: [Api.Chat], users: [Api.User])
@ -1596,3 +1234,111 @@ public extension Api.updates {
}
}
public extension Api.updates {
enum State: TypeConstructorDescription {
case state(pts: Int32, qts: Int32, date: Int32, seq: Int32, unreadCount: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .state(let pts, let qts, let date, let seq, let unreadCount):
if boxed {
buffer.appendInt32(-1519637954)
}
serializeInt32(pts, buffer: buffer, boxed: false)
serializeInt32(qts, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(seq, buffer: buffer, boxed: false)
serializeInt32(unreadCount, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .state(let pts, let qts, let date, let seq, let unreadCount):
return ("state", [("pts", pts as Any), ("qts", qts as Any), ("date", date as Any), ("seq", seq as Any), ("unreadCount", unreadCount as Any)])
}
}
public static func parse_state(_ reader: BufferReader) -> State? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
_5 = reader.readInt32()
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.updates.State.state(pts: _1!, qts: _2!, date: _3!, seq: _4!, unreadCount: _5!)
}
else {
return nil
}
}
}
}
public extension Api.upload {
enum CdnFile: TypeConstructorDescription {
case cdnFile(bytes: Buffer)
case cdnFileReuploadNeeded(requestToken: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .cdnFile(let bytes):
if boxed {
buffer.appendInt32(-1449145777)
}
serializeBytes(bytes, buffer: buffer, boxed: false)
break
case .cdnFileReuploadNeeded(let requestToken):
if boxed {
buffer.appendInt32(-290921362)
}
serializeBytes(requestToken, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .cdnFile(let bytes):
return ("cdnFile", [("bytes", bytes as Any)])
case .cdnFileReuploadNeeded(let requestToken):
return ("cdnFileReuploadNeeded", [("requestToken", requestToken as Any)])
}
}
public static func parse_cdnFile(_ reader: BufferReader) -> CdnFile? {
var _1: Buffer?
_1 = parseBytes(reader)
let _c1 = _1 != nil
if _c1 {
return Api.upload.CdnFile.cdnFile(bytes: _1!)
}
else {
return nil
}
}
public static func parse_cdnFileReuploadNeeded(_ reader: BufferReader) -> CdnFile? {
var _1: Buffer?
_1 = parseBytes(reader)
let _c1 = _1 != nil
if _c1 {
return Api.upload.CdnFile.cdnFileReuploadNeeded(requestToken: _1!)
}
else {
return nil
}
}
}
}

View file

@ -1,111 +1,3 @@
public extension Api.updates {
enum State: TypeConstructorDescription {
case state(pts: Int32, qts: Int32, date: Int32, seq: Int32, unreadCount: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .state(let pts, let qts, let date, let seq, let unreadCount):
if boxed {
buffer.appendInt32(-1519637954)
}
serializeInt32(pts, buffer: buffer, boxed: false)
serializeInt32(qts, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(seq, buffer: buffer, boxed: false)
serializeInt32(unreadCount, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .state(let pts, let qts, let date, let seq, let unreadCount):
return ("state", [("pts", pts as Any), ("qts", qts as Any), ("date", date as Any), ("seq", seq as Any), ("unreadCount", unreadCount as Any)])
}
}
public static func parse_state(_ reader: BufferReader) -> State? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
_5 = reader.readInt32()
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.updates.State.state(pts: _1!, qts: _2!, date: _3!, seq: _4!, unreadCount: _5!)
}
else {
return nil
}
}
}
}
public extension Api.upload {
enum CdnFile: TypeConstructorDescription {
case cdnFile(bytes: Buffer)
case cdnFileReuploadNeeded(requestToken: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .cdnFile(let bytes):
if boxed {
buffer.appendInt32(-1449145777)
}
serializeBytes(bytes, buffer: buffer, boxed: false)
break
case .cdnFileReuploadNeeded(let requestToken):
if boxed {
buffer.appendInt32(-290921362)
}
serializeBytes(requestToken, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .cdnFile(let bytes):
return ("cdnFile", [("bytes", bytes as Any)])
case .cdnFileReuploadNeeded(let requestToken):
return ("cdnFileReuploadNeeded", [("requestToken", requestToken as Any)])
}
}
public static func parse_cdnFile(_ reader: BufferReader) -> CdnFile? {
var _1: Buffer?
_1 = parseBytes(reader)
let _c1 = _1 != nil
if _c1 {
return Api.upload.CdnFile.cdnFile(bytes: _1!)
}
else {
return nil
}
}
public static func parse_cdnFileReuploadNeeded(_ reader: BufferReader) -> CdnFile? {
var _1: Buffer?
_1 = parseBytes(reader)
let _c1 = _1 != nil
if _c1 {
return Api.upload.CdnFile.cdnFileReuploadNeeded(requestToken: _1!)
}
else {
return nil
}
}
}
}
public extension Api.upload {
enum File: TypeConstructorDescription {
case file(type: Api.storage.FileType, mtime: Int32, bytes: Buffer)

View file

@ -9674,13 +9674,14 @@ public extension Api.functions.payments {
}
}
public extension Api.functions.payments {
static func getStarsRevenueWithdrawalUrl(peer: Api.InputPeer, stars: Int64, password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsRevenueWithdrawalUrl>) {
static func getStarsRevenueWithdrawalUrl(flags: Int32, peer: Api.InputPeer, amount: Int64?, password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsRevenueWithdrawalUrl>) {
let buffer = Buffer()
buffer.appendInt32(331081907)
buffer.appendInt32(607378578)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt64(stars, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt64(amount!, buffer: buffer, boxed: false)}
password.serialize(buffer, true)
return (FunctionDescription(name: "payments.getStarsRevenueWithdrawalUrl", parameters: [("peer", String(describing: peer)), ("stars", String(describing: stars)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsRevenueWithdrawalUrl? in
return (FunctionDescription(name: "payments.getStarsRevenueWithdrawalUrl", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("amount", String(describing: amount)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsRevenueWithdrawalUrl? in
let reader = BufferReader(buffer)
var result: Api.payments.StarsRevenueWithdrawalUrl?
if let signature = reader.readInt32() {
@ -9758,16 +9759,17 @@ public extension Api.functions.payments {
}
}
public extension Api.functions.payments {
static func getStarsTransactionsByID(peer: Api.InputPeer, id: [Api.InputStarsTransaction]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
static func getStarsTransactionsByID(flags: Int32, peer: Api.InputPeer, id: [Api.InputStarsTransaction]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
let buffer = Buffer()
buffer.appendInt32(662973742)
buffer.appendInt32(768218808)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(id.count))
for item in id {
item.serialize(buffer, true)
}
return (FunctionDescription(name: "payments.getStarsTransactionsByID", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
return (FunctionDescription(name: "payments.getStarsTransactionsByID", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
let reader = BufferReader(buffer)
var result: Api.payments.StarsStatus?
if let signature = reader.readInt32() {
@ -10927,55 +10929,6 @@ public extension Api.functions.smsjobs {
})
}
}
public extension Api.functions.stats {
static func getBroadcastRevenueStats(flags: Int32, peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stats.BroadcastRevenueStats>) {
let buffer = Buffer()
buffer.appendInt32(-142021095)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
return (FunctionDescription(name: "stats.getBroadcastRevenueStats", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.BroadcastRevenueStats? in
let reader = BufferReader(buffer)
var result: Api.stats.BroadcastRevenueStats?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.stats.BroadcastRevenueStats
}
return result
})
}
}
public extension Api.functions.stats {
static func getBroadcastRevenueTransactions(peer: Api.InputPeer, offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stats.BroadcastRevenueTransactions>) {
let buffer = Buffer()
buffer.appendInt32(1889078125)
peer.serialize(buffer, true)
serializeInt32(offset, buffer: buffer, boxed: false)
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "stats.getBroadcastRevenueTransactions", parameters: [("peer", String(describing: peer)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.BroadcastRevenueTransactions? in
let reader = BufferReader(buffer)
var result: Api.stats.BroadcastRevenueTransactions?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.stats.BroadcastRevenueTransactions
}
return result
})
}
}
public extension Api.functions.stats {
static func getBroadcastRevenueWithdrawalUrl(peer: Api.InputPeer, password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stats.BroadcastRevenueWithdrawalUrl>) {
let buffer = Buffer()
buffer.appendInt32(-1644889427)
peer.serialize(buffer, true)
password.serialize(buffer, true)
return (FunctionDescription(name: "stats.getBroadcastRevenueWithdrawalUrl", parameters: [("peer", String(describing: peer)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.BroadcastRevenueWithdrawalUrl? in
let reader = BufferReader(buffer)
var result: Api.stats.BroadcastRevenueWithdrawalUrl?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.stats.BroadcastRevenueWithdrawalUrl
}
return result
})
}
}
public extension Api.functions.stats {
static func getBroadcastStats(flags: Int32, channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stats.BroadcastStats>) {
let buffer = Buffer()

View file

@ -129,7 +129,6 @@ enum AccountStateMutationOperation {
case UpdateStorySentReaction(peerId: PeerId, id: Int32, reaction: Api.Reaction)
case UpdateNewAuthorization(isUnconfirmed: Bool, hash: Int64, date: Int32, device: String, location: String)
case UpdateWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?)
case UpdateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances)
case UpdateStarsBalance(peerId: PeerId, currency: CurrencyAmount.Currency, balance: StarsAmount)
case UpdateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances)
case UpdateStarsReactionsDefaultPrivacy(privacy: TelegramPaidReactionPrivacy)
@ -692,10 +691,6 @@ struct AccountMutableState {
self.addOperation(.UpdateNewAuthorization(isUnconfirmed: isUnconfirmed, hash: hash, date: date, device: device, location: location))
}
mutating func updateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances) {
self.addOperation(.UpdateRevenueBalances(peerId: peerId, balances: balances))
}
mutating func updateStarsBalance(peerId: PeerId, currency: CurrencyAmount.Currency, balance: StarsAmount) {
self.addOperation(.UpdateStarsBalance(peerId: peerId, currency: currency, balance: balance))
}
@ -714,7 +709,7 @@ struct AccountMutableState {
mutating func addOperation(_ operation: AccountStateMutationOperation) {
switch operation {
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .UpdateWallpaper, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateGroupCallChainBlocks, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsDefaultPrivacy, .ReportMessageDelivery:
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .UpdateWallpaper, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateGroupCallChainBlocks, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsDefaultPrivacy, .ReportMessageDelivery:
break
case let .AddMessages(messages, location):
for message in messages {
@ -858,7 +853,6 @@ struct AccountReplayedFinalState {
let updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id]
let updateConfig: Bool
let isPremiumUpdated: Bool
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
let updatedStarsBalance: [PeerId: StarsAmount]
let updatedTonBalance: [PeerId: StarsAmount]
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
@ -892,7 +886,6 @@ struct AccountFinalStateEvents {
let updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id]
let updateConfig: Bool
let isPremiumUpdated: Bool
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
let updatedStarsBalance: [PeerId: StarsAmount]
let updatedTonBalance: [PeerId: StarsAmount]
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
@ -900,10 +893,10 @@ struct AccountFinalStateEvents {
let addedConferenceInvitationMessagesIds: [MessageId]
var isEmpty: Bool {
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.sentScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedRevenueBalances.isEmpty && self.updatedStarsBalance.isEmpty && self.updatedTonBalance.isEmpty && self.updatedStarsRevenueStatus.isEmpty && self.reportMessageDelivery.isEmpty && self.addedConferenceInvitationMessagesIds.isEmpty
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.sentScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedStarsBalance.isEmpty && self.updatedTonBalance.isEmpty && self.updatedStarsRevenueStatus.isEmpty && self.reportMessageDelivery.isEmpty && self.addedConferenceInvitationMessagesIds.isEmpty
}
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:], updatedStarsBalance: [PeerId: StarsAmount] = [:], updatedTonBalance: [PeerId: StarsAmount] = [:], updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:], sentScheduledMessageIds: Set<MessageId> = Set(), reportMessageDelivery: Set<MessageId> = Set(), addedConferenceInvitationMessagesIds: [MessageId] = []) {
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [PeerAndBoundThreadId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedStarsBalance: [PeerId: StarsAmount] = [:], updatedTonBalance: [PeerId: StarsAmount] = [:], updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:], sentScheduledMessageIds: Set<MessageId> = Set(), reportMessageDelivery: Set<MessageId> = Set(), addedConferenceInvitationMessagesIds: [MessageId] = []) {
self.addedIncomingMessageIds = addedIncomingMessageIds
self.addedReactionEvents = addedReactionEvents
self.wasScheduledMessageIds = wasScheduledMessageIds
@ -927,7 +920,6 @@ struct AccountFinalStateEvents {
self.updatedOutgoingThreadReadStates = updatedOutgoingThreadReadStates
self.updateConfig = updateConfig
self.isPremiumUpdated = isPremiumUpdated
self.updatedRevenueBalances = updatedRevenueBalances
self.updatedStarsBalance = updatedStarsBalance
self.updatedTonBalance = updatedTonBalance
self.updatedStarsRevenueStatus = updatedStarsRevenueStatus
@ -960,7 +952,6 @@ struct AccountFinalStateEvents {
self.updatedOutgoingThreadReadStates = state.updatedOutgoingThreadReadStates
self.updateConfig = state.updateConfig
self.isPremiumUpdated = state.isPremiumUpdated
self.updatedRevenueBalances = state.updatedRevenueBalances
self.updatedStarsBalance = state.updatedStarsBalance
self.updatedTonBalance = state.updatedTonBalance
self.updatedStarsRevenueStatus = state.updatedStarsRevenueStatus
@ -1027,7 +1018,6 @@ struct AccountFinalStateEvents {
updatedIncomingThreadReadStates: self.updatedIncomingThreadReadStates.merging(other.updatedIncomingThreadReadStates,uniquingKeysWith: { lhs, _ in lhs }),
updateConfig: updateConfig,
isPremiumUpdated: isPremiumUpdated,
updatedRevenueBalances: self.updatedRevenueBalances.merging(other.updatedRevenueBalances, uniquingKeysWith: { lhs, _ in lhs }),
updatedStarsBalance: self.updatedStarsBalance.merging(other.updatedStarsBalance, uniquingKeysWith: { lhs, _ in lhs }),
updatedTonBalance: self.updatedTonBalance.merging(other.updatedTonBalance, uniquingKeysWith: { lhs, _ in lhs }),
updatedStarsRevenueStatus: self.updatedStarsRevenueStatus.merging(other.updatedStarsRevenueStatus, uniquingKeysWith: { lhs, _ in lhs }),

View file

@ -232,7 +232,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
}
switch action {
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon:
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund:
break
case let .messageActionChannelMigrateFrom(_, chatId):
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)))

View file

@ -264,6 +264,10 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .suggestedPostApprovalStatus(status: status))
case let .messageActionGiftTon(_, currency, amount, cryptoCurrency, cryptoAmount, transactionId):
return TelegramMediaAction(action: .giftTon(currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, transactionId: transactionId))
case .messageActionSuggestedPostSuccess:
return nil
case .messageActionSuggestedPostRefund:
return nil
}
}

View file

@ -1836,8 +1836,6 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
updatedState.updateNewAuthorization(isUnconfirmed: isUnconfirmed, hash: hash, date: date ?? 0, device: device ?? "", location: location ?? "")
case let .updatePeerWallpaper(_, peer, wallpaper):
updatedState.updateWallpaper(peerId: peer.peerId, wallpaper: wallpaper.flatMap { TelegramWallpaper(apiWallpaper: $0) })
case let .updateBroadcastRevenueTransactions(peer, balances):
updatedState.updateRevenueBalances(peerId: peer.peerId, balances: RevenueStats.Balances(apiRevenueBalances: balances))
case let .updateStarsBalance(balance):
let amount = CurrencyAmount(apiAmount: balance)
updatedState.updateStarsBalance(peerId: accountPeerId, currency: amount.currency, balance: amount.amount)
@ -3581,7 +3579,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
var currentAddQuickReplyMessages: OptimizeAddMessagesState?
for operation in operations {
switch operation {
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread, .UpdateMessagesPinned, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateGroupCallChainBlocks, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsDefaultPrivacy, .ReportMessageDelivery:
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread, .UpdateMessagesPinned, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateGroupCallChainBlocks, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsDefaultPrivacy, .ReportMessageDelivery:
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
}
@ -3716,7 +3714,6 @@ func replayFinalState(
var deletedMessageIds: [DeletedMessageId] = []
var syncAttachMenuBots = false
var updateConfig = false
var updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:]
var updatedStarsBalance: [PeerId: StarsAmount] = [:]
var updatedTonBalance: [PeerId: StarsAmount] = [:]
var updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:]
@ -5169,8 +5166,6 @@ func replayFinalState(
} else {
transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.NewSessionReviews, itemId: id.rawValue)
}
case let .UpdateRevenueBalances(peerId, balances):
updatedRevenueBalances[peerId] = balances
case let .UpdateStarsBalance(peerId, currency, balance):
switch currency {
case .ton:
@ -5702,7 +5697,6 @@ func replayFinalState(
updatedOutgoingThreadReadStates: updatedOutgoingThreadReadStates,
updateConfig: updateConfig,
isPremiumUpdated: isPremiumUpdated,
updatedRevenueBalances: updatedRevenueBalances,
updatedStarsBalance: updatedStarsBalance,
updatedTonBalance: updatedTonBalance,
updatedStarsRevenueStatus: updatedStarsRevenueStatus,

View file

@ -44,10 +44,6 @@ private final class UpdatedPeersNearbySubscriberContext {
let subscribers = Bag<([PeerNearby]) -> Void>()
}
private final class UpdatedRevenueBalancesSubscriberContext {
let subscribers = Bag<([PeerId: RevenueStats.Balances]) -> Void>()
}
private final class UpdatedStarsBalanceSubscriberContext {
let subscribers = Bag<([PeerId: StarsAmount]) -> Void>()
}
@ -353,7 +349,6 @@ public final class AccountStateManager {
private var updatedWebpageContexts: [MediaId: UpdatedWebpageSubscriberContext] = [:]
private var updatedPeersNearbyContext = UpdatedPeersNearbySubscriberContext()
private var updatedRevenueBalancesContext = UpdatedRevenueBalancesSubscriberContext()
private var updatedStarsBalanceContext = UpdatedStarsBalanceSubscriberContext()
private var updatedTonBalanceContext = UpdatedStarsBalanceSubscriberContext()
private var updatedStarsRevenueStatusContext = UpdatedStarsRevenueStatusSubscriberContext()
@ -1112,9 +1107,6 @@ public final class AccountStateManager {
if let updatedPeersNearby = events.updatedPeersNearby {
strongSelf.notifyUpdatedPeersNearby(updatedPeersNearby)
}
if !events.updatedRevenueBalances.isEmpty {
strongSelf.notifyUpdatedRevenueBalances(events.updatedRevenueBalances)
}
if !events.updatedStarsBalance.isEmpty {
strongSelf.notifyUpdatedStarsBalance(events.updatedStarsBalance)
}
@ -1708,33 +1700,6 @@ public final class AccountStateManager {
}
}
public func updatedRevenueBalances() -> Signal<[PeerId: RevenueStats.Balances], NoError> {
let queue = self.queue
return Signal { [weak self] subscriber in
let disposable = MetaDisposable()
queue.async {
if let strongSelf = self {
let index = strongSelf.updatedRevenueBalancesContext.subscribers.add({ revenueBalances in
subscriber.putNext(revenueBalances)
})
disposable.set(ActionDisposable {
if let strongSelf = self {
strongSelf.updatedRevenueBalancesContext.subscribers.remove(index)
}
})
}
}
return disposable
}
}
private func notifyUpdatedRevenueBalances(_ updatedRevenueBalances: [PeerId: RevenueStats.Balances]) {
for subscriber in self.updatedRevenueBalancesContext.subscribers.copyItems() {
subscriber(updatedRevenueBalances)
}
}
public func updatedStarsBalance() -> Signal<[PeerId: StarsAmount], NoError> {
let queue = self.queue
return Signal { [weak self] subscriber in
@ -2165,12 +2130,6 @@ public final class AccountStateManager {
}
}
public func updatedRevenueBalances() -> Signal<[PeerId: RevenueStats.Balances], NoError> {
return self.impl.signalWith { impl, subscriber in
return impl.updatedRevenueBalances().start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
}
}
public func updatedStarsBalance() -> Signal<[PeerId: StarsAmount], NoError> {
return self.impl.signalWith { impl, subscriber in
return impl.updatedStarsBalance().start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
@ -2179,7 +2138,7 @@ public final class AccountStateManager {
public func updatedTonBalance() -> Signal<[PeerId: StarsAmount], NoError> {
return self.impl.signalWith { impl, subscriber in
return impl.updatedStarsBalance().start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
return impl.updatedTonBalance().start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
}
}

View file

@ -1,589 +0,0 @@
import Foundation
import SwiftSignalKit
import Postbox
import TelegramApi
import MtProtoKit
public struct RevenueStats: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case topHoursGraph
case revenueGraph
case balances
case usdRate
}
static func key(peerId: PeerId) -> ValueBoxKey {
let key = ValueBoxKey(length: 8 + 4)
key.setInt64(0, value: peerId.toInt64())
return key
}
public struct Balances: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case currentBalance
case availableBalance
case overallRevenue
case withdrawEnabled
}
public let currentBalance: Int64
public let availableBalance: Int64
public let overallRevenue: Int64
public let withdrawEnabled: Bool
init(
currentBalance: Int64,
availableBalance: Int64,
overallRevenue: Int64,
withdrawEnabled: Bool
) {
self.currentBalance = currentBalance
self.availableBalance = availableBalance
self.overallRevenue = overallRevenue
self.withdrawEnabled = withdrawEnabled
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.currentBalance = try container.decode(Int64.self, forKey: .currentBalance)
self.availableBalance = try container.decode(Int64.self, forKey: .availableBalance)
self.overallRevenue = try container.decode(Int64.self, forKey: .overallRevenue)
self.withdrawEnabled = try container.decode(Bool.self, forKey: .withdrawEnabled)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.currentBalance, forKey: .currentBalance)
try container.encode(self.availableBalance, forKey: .availableBalance)
try container.encode(self.overallRevenue, forKey: .overallRevenue)
try container.encode(self.withdrawEnabled, forKey: .withdrawEnabled)
}
}
public let topHoursGraph: StatsGraph
public let revenueGraph: StatsGraph
public let balances: Balances
public let usdRate: Double
init(topHoursGraph: StatsGraph, revenueGraph: StatsGraph, balances: Balances, usdRate: Double) {
self.topHoursGraph = topHoursGraph
self.revenueGraph = revenueGraph
self.balances = balances
self.usdRate = usdRate
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.topHoursGraph = try container.decode(StatsGraph.self, forKey: .topHoursGraph)
self.revenueGraph = try container.decode(StatsGraph.self, forKey: .revenueGraph)
self.balances = try container.decode(Balances.self, forKey: .balances)
self.usdRate = try container.decode(Double.self, forKey: .usdRate)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.topHoursGraph, forKey: .topHoursGraph)
try container.encode(self.revenueGraph, forKey: .revenueGraph)
try container.encode(self.balances, forKey: .balances)
try container.encode(self.usdRate, forKey: .usdRate)
}
public static func == (lhs: RevenueStats, rhs: RevenueStats) -> Bool {
if lhs.topHoursGraph != rhs.topHoursGraph {
return false
}
if lhs.revenueGraph != rhs.revenueGraph {
return false
}
if lhs.balances != rhs.balances {
return false
}
if lhs.usdRate != rhs.usdRate {
return false
}
return true
}
}
public extension RevenueStats {
func withUpdated(balances: RevenueStats.Balances) -> RevenueStats {
return RevenueStats(
topHoursGraph: self.topHoursGraph,
revenueGraph: self.revenueGraph,
balances: balances,
usdRate: self.usdRate
)
}
}
extension RevenueStats {
init(apiRevenueStats: Api.stats.BroadcastRevenueStats, peerId: PeerId) {
switch apiRevenueStats {
case let .broadcastRevenueStats(topHoursGraph, revenueGraph, balances, usdRate):
self.init(topHoursGraph: StatsGraph(apiStatsGraph: topHoursGraph), revenueGraph: StatsGraph(apiStatsGraph: revenueGraph), balances: RevenueStats.Balances(apiRevenueBalances: balances), usdRate: usdRate)
}
}
}
extension RevenueStats.Balances {
init(apiRevenueBalances: Api.BroadcastRevenueBalances) {
switch apiRevenueBalances {
case let .broadcastRevenueBalances(flags, currentBalance, availableBalance, overallRevenue):
self.init(currentBalance: currentBalance, availableBalance: availableBalance, overallRevenue: overallRevenue, withdrawEnabled: ((flags & (1 << 0)) != 0))
}
}
}
public struct RevenueStatsContextState: Equatable {
public var stats: RevenueStats?
}
private func requestRevenueStats(postbox: Postbox, network: Network, peerId: PeerId, dark: Bool = false) -> Signal<RevenueStats?, NoError> {
return postbox.transaction { transaction -> Peer? in
if let peer = transaction.getPeer(peerId) {
return peer
}
return nil
} |> mapToSignal { peer -> Signal<RevenueStats?, NoError> in
guard let peer, let channel = peer as? TelegramChannel, case .broadcast = channel.info, let inputPeer = apiInputPeer(peer) else {
return .never()
}
var flags: Int32 = 0
if dark {
flags |= (1 << 1)
}
return network.request(Api.functions.stats.getBroadcastRevenueStats(flags: flags, peer: inputPeer))
|> map { result -> RevenueStats? in
return RevenueStats(apiRevenueStats: result, peerId: peerId)
}
|> retryRequest
}
}
private final class RevenueStatsContextImpl {
private let account: Account
private let peerId: PeerId
private var _state: RevenueStatsContextState {
didSet {
if self._state != oldValue {
self._statePromise.set(.single(self._state))
}
}
}
private let _statePromise = Promise<RevenueStatsContextState>()
var state: Signal<RevenueStatsContextState, NoError> {
return self._statePromise.get()
}
private let disposable = MetaDisposable()
init(account: Account, peerId: PeerId) {
assert(Queue.mainQueue().isCurrent())
self.account = account
self.peerId = peerId
self._state = RevenueStatsContextState(stats: nil)
self._statePromise.set(.single(self._state))
self.load()
let _ = (account.postbox.transaction { transaction -> RevenueStats? in
return transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedRevenueStats, key: StarsRevenueStats.key(peerId: peerId)))?.get(RevenueStats.self)
}
|> deliverOnMainQueue).start(next: { [weak self] cachedResult in
guard let self, let cachedResult else {
return
}
self._state = RevenueStatsContextState(stats: cachedResult)
self._statePromise.set(.single(self._state))
})
}
deinit {
assert(Queue.mainQueue().isCurrent())
self.disposable.dispose()
}
fileprivate func load() {
assert(Queue.mainQueue().isCurrent())
let account = self.account
let peerId = self.peerId
let signal = requestRevenueStats(postbox: self.account.postbox, network: self.account.network, peerId: self.peerId)
|> mapToSignal { initial -> Signal<RevenueStats?, NoError> in
guard let initial else {
return .single(nil)
}
return .single(initial)
|> then(
account.stateManager.updatedRevenueBalances()
|> mapToSignal { updates in
if let balances = updates[peerId] {
return .single(initial.withUpdated(balances: balances))
}
return .complete()
}
)
}
self.disposable.set((signal
|> deliverOnMainQueue).start(next: { [weak self] stats in
if let self {
self._state = RevenueStatsContextState(stats: stats)
self._statePromise.set(.single(self._state))
if let stats {
let _ = (self.account.postbox.transaction { transaction in
if let entry = CodableEntry(stats) {
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedRevenueStats, key: StarsRevenueStats.key(peerId: peerId)), entry: entry)
}
}).start()
}
}
}))
}
func loadDetailedGraph(_ graph: StatsGraph, x: Int64) -> Signal<StatsGraph?, NoError> {
if let token = graph.token {
return requestGraph(postbox: self.account.postbox, network: self.account.network, peerId: self.peerId, token: token, x: x)
} else {
return .single(nil)
}
}
}
public final class RevenueStatsContext {
private let impl: QueueLocalObject<RevenueStatsContextImpl>
public var state: Signal<RevenueStatsContextState, 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 init(account: Account, peerId: PeerId) {
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
return RevenueStatsContextImpl(account: account, peerId: peerId)
})
}
public func reload() {
self.impl.with { impl in
impl.load()
}
}
public func loadDetailedGraph(_ graph: StatsGraph, x: Int64) -> Signal<StatsGraph?, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.loadDetailedGraph(graph, x: x).start(next: { value in
subscriber.putNext(value)
subscriber.putCompletion()
}))
}
return disposable
}
}
}
private final class RevenueStatsTransactionsContextImpl {
private let queue: Queue
private let account: Account
private let peerId: EnginePeer.Id
private let disposable = MetaDisposable()
private var updateDisposable: Disposable?
private var isLoadingMore: Bool = false
private var hasLoadedOnce: Bool = false
private var canLoadMore: Bool = true
private var results: [RevenueStatsTransactionsContext.State.Transaction] = []
private var count: Int32
private var lastOffset: Int32?
let state = Promise<RevenueStatsTransactionsContext.State>()
init(queue: Queue, account: Account, peerId: EnginePeer.Id) {
self.queue = queue
self.account = account
self.peerId = peerId
self.count = 0
self.loadMore()
self.updateDisposable = (account.stateManager.updatedRevenueBalances()
|> deliverOn(self.queue)).startStrict(next: { [weak self] _ in
self?.reload()
})
}
deinit {
self.disposable.dispose()
self.updateDisposable?.dispose()
}
func reload() {
self.lastOffset = nil
self.loadMore()
}
func loadMore() {
if self.isLoadingMore || !self.canLoadMore {
return
}
self.isLoadingMore = true
let account = self.account
let peerId = self.peerId
let lastOffset = self.lastOffset
self.disposable.set((self.account.postbox.transaction { transaction -> Peer? in
guard let peer = transaction.getPeer(peerId) else {
return nil
}
return peer
}
|> mapToSignal { peer -> Signal<([RevenueStatsTransactionsContext.State.Transaction], Int32, Int32?), NoError> in
if let peer {
guard let channel = peer as? TelegramChannel, case .broadcast = channel.info, let inputPeer = apiInputPeer(peer) else {
return .complete()
}
let offset = lastOffset ?? 0
let limit: Int32 = lastOffset == nil ? 25 : 50
return account.network.request(Api.functions.stats.getBroadcastRevenueTransactions(peer: inputPeer, offset: offset, limit: limit), automaticFloodWait: false)
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.stats.BroadcastRevenueTransactions?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<([RevenueStatsTransactionsContext.State.Transaction], Int32, Int32?), NoError> in
return account.postbox.transaction { transaction -> ([RevenueStatsTransactionsContext.State.Transaction], Int32, Int32?) in
guard let result = result else {
return ([], 0, nil)
}
switch result {
case let .broadcastRevenueTransactions(count, transactions):
let nextOffset = offset + Int32(transactions.count)
var resultTransactions: [RevenueStatsTransactionsContext.State.Transaction] = []
for transaction in transactions {
switch transaction {
case let .broadcastRevenueTransactionProceeds(amount, fromDate, toDate):
resultTransactions.append(.proceeds(amount: amount, fromDate: fromDate, toDate: toDate))
case let .broadcastRevenueTransactionRefund(amount, date, provider):
resultTransactions.append(.refund(amount: amount, date: date, provider: provider))
case let .broadcastRevenueTransactionWithdrawal(flags, amount, date, provider, transactionDate, transactionUrl):
let status: RevenueStatsTransactionsContext.State.Transaction.WithdrawalStatus
if (flags & (1 << 0)) != 0 {
status = .pending
} else if (flags & (1 << 2)) != 0 {
status = .failed
} else {
status = .succeed
}
resultTransactions.append(.withdrawal(status: status, amount: amount, date: date, provider: provider, transactionDate: transactionDate, transactionUrl: transactionUrl))
}
}
return (resultTransactions, count, nextOffset)
}
}
}
} else {
return .single(([], 0, nil))
}
}
|> deliverOn(self.queue)).start(next: { [weak self] transactions, updatedCount, nextOffset in
guard let strongSelf = self else {
return
}
strongSelf.lastOffset = nextOffset
for transaction in transactions {
strongSelf.results.append(transaction)
}
strongSelf.isLoadingMore = false
strongSelf.hasLoadedOnce = true
strongSelf.canLoadMore = !transactions.isEmpty && nextOffset != nil
if strongSelf.canLoadMore {
strongSelf.count = max(updatedCount, Int32(strongSelf.results.count))
} else {
strongSelf.count = Int32(strongSelf.results.count)
}
strongSelf.updateState()
}))
self.updateState()
}
private func updateState() {
self.state.set(.single(RevenueStatsTransactionsContext.State(transactions: self.results, isLoadingMore: self.isLoadingMore, hasLoadedOnce: self.hasLoadedOnce, canLoadMore: self.canLoadMore, count: self.count)))
}
}
public final class RevenueStatsTransactionsContext {
public struct State: Equatable {
public enum Transaction: Equatable {
public enum WithdrawalStatus {
case succeed
case pending
case failed
}
case proceeds(amount: Int64, fromDate: Int32, toDate: Int32)
case withdrawal(status: WithdrawalStatus, amount: Int64, date: Int32, provider: String, transactionDate: Int32?, transactionUrl: String?)
case refund(amount: Int64, date: Int32, provider: String)
public var amount: Int64 {
switch self {
case let .proceeds(amount, _, _), let .withdrawal(_, amount, _, _, _, _), let .refund(amount, _, _):
return amount
}
}
}
public var transactions: [Transaction]
public var isLoadingMore: Bool
public var hasLoadedOnce: Bool
public var canLoadMore: Bool
public var count: Int32
public static var Empty = State(transactions: [], isLoadingMore: false, hasLoadedOnce: true, canLoadMore: false, count: 0)
public static var Loading = State(transactions: [], isLoadingMore: false, hasLoadedOnce: false, canLoadMore: false, count: 0)
}
private let queue: Queue = Queue()
private let impl: QueueLocalObject<RevenueStatsTransactionsContextImpl>
public var state: Signal<State, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.state.get().start(next: { value in
subscriber.putNext(value)
}))
}
return disposable
}
}
public init(account: Account, peerId: EnginePeer.Id) {
let queue = self.queue
self.impl = QueueLocalObject(queue: queue, generate: {
return RevenueStatsTransactionsContextImpl(queue: queue, account: account, peerId: peerId)
})
}
public func loadMore() {
self.impl.with { impl in
impl.loadMore()
}
}
public func reload() {
self.impl.with { impl in
impl.reload()
}
}
}
public enum RequestRevenueWithdrawalError : Equatable {
case generic
case twoStepAuthMissing
case twoStepAuthTooFresh(Int32)
case authSessionTooFresh(Int32)
case limitExceeded
case requestPassword
case invalidPassword
}
func _internal_checkChannelRevenueWithdrawalAvailability(account: Account) -> Signal<Never, RequestRevenueWithdrawalError> {
return account.network.request(Api.functions.stats.getBroadcastRevenueWithdrawalUrl(peer: .inputPeerEmpty, password: .inputCheckPasswordEmpty))
|> mapError { error -> RequestRevenueWithdrawalError in
if error.errorDescription == "PASSWORD_HASH_INVALID" {
return .requestPassword
} else if error.errorDescription == "PASSWORD_MISSING" {
return .twoStepAuthMissing
} else if error.errorDescription.hasPrefix("PASSWORD_TOO_FRESH_") {
let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "PASSWORD_TOO_FRESH_".count)...])
if let value = Int32(timeout) {
return .twoStepAuthTooFresh(value)
}
} else if error.errorDescription.hasPrefix("SESSION_TOO_FRESH_") {
let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "SESSION_TOO_FRESH_".count)...])
if let value = Int32(timeout) {
return .authSessionTooFresh(value)
}
}
return .generic
}
|> ignoreValues
}
func _internal_requestChannelRevenueWithdrawalUrl(account: Account, peerId: PeerId, password: String) -> Signal<String, RequestRevenueWithdrawalError> {
guard !password.isEmpty else {
return .fail(.invalidPassword)
}
return account.postbox.transaction { transaction -> Signal<String, RequestRevenueWithdrawalError> in
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
let checkPassword = _internal_twoStepAuthData(account.network)
|> mapError { error -> RequestRevenueWithdrawalError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic
}
}
|> mapToSignal { authData -> Signal<Api.InputCheckPasswordSRP, RequestRevenueWithdrawalError> in
if let currentPasswordDerivation = authData.currentPasswordDerivation, let srpSessionData = authData.srpSessionData {
guard let kdfResult = passwordKDF(encryptionProvider: account.network.encryptionProvider, password: password, derivation: currentPasswordDerivation, srpSessionData: srpSessionData) else {
return .fail(.generic)
}
return .single(.inputCheckPasswordSRP(srpId: kdfResult.id, A: Buffer(data: kdfResult.A), M1: Buffer(data: kdfResult.M1)))
} else {
return .fail(.twoStepAuthMissing)
}
}
return checkPassword
|> mapToSignal { password -> Signal<String, RequestRevenueWithdrawalError> in
return account.network.request(Api.functions.stats.getBroadcastRevenueWithdrawalUrl(peer: inputPeer, password: password), automaticFloodWait: false)
|> mapError { error -> RequestRevenueWithdrawalError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else if error.errorDescription == "PASSWORD_HASH_INVALID" {
return .invalidPassword
} else if error.errorDescription == "PASSWORD_MISSING" {
return .twoStepAuthMissing
} else if error.errorDescription.hasPrefix("PASSWORD_TOO_FRESH_") {
let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "PASSWORD_TOO_FRESH_".count)...])
if let value = Int32(timeout) {
return .twoStepAuthTooFresh(value)
}
} else if error.errorDescription.hasPrefix("SESSION_TOO_FRESH_") {
let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "SESSION_TOO_FRESH_".count)...])
if let value = Int32(timeout) {
return .authSessionTooFresh(value)
}
}
return .generic
}
|> map { result -> String in
switch result {
case let .broadcastRevenueWithdrawalUrl(url):
return url
}
}
}
}
|> mapError { _ -> RequestRevenueWithdrawalError in }
|> switchToLatest
}

View file

@ -6,6 +6,7 @@ import MtProtoKit
public struct StarsRevenueStats: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case topHoursGraph
case revenueGraph
case balances
case usdRate
@ -24,21 +25,22 @@ public struct StarsRevenueStats: Equatable, Codable {
case overallRevenue
case withdrawEnabled
case nextWithdrawalTimestamp
case currentBalanceStars
case availableBalanceStars
case overallRevenueStars
}
public let currentBalance: StarsAmount
public let availableBalance: StarsAmount
public let overallRevenue: StarsAmount
public let currentBalance: CurrencyAmount
public let availableBalance: CurrencyAmount
public let overallRevenue: CurrencyAmount
public let withdrawEnabled: Bool
public let nextWithdrawalTimestamp: Int32?
public init(
currentBalance: StarsAmount,
availableBalance: StarsAmount,
overallRevenue: StarsAmount,
currentBalance: CurrencyAmount,
availableBalance: CurrencyAmount,
overallRevenue: CurrencyAmount,
withdrawEnabled: Bool,
nextWithdrawalTimestamp: Int32?
) {
@ -52,23 +54,22 @@ public struct StarsRevenueStats: Equatable, Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let legacyCurrentBalance = try container.decodeIfPresent(Int64.self, forKey: .currentBalance) {
self.currentBalance = StarsAmount(value: legacyCurrentBalance, nanos: 0)
if let legacyCurrentBalance = try container.decodeIfPresent(StarsAmount.self, forKey: .currentBalanceStars) {
self.currentBalance = CurrencyAmount(amount: legacyCurrentBalance, currency: .stars)
} else {
self.currentBalance = try container.decode(StarsAmount.self, forKey: .currentBalanceStars)
self.currentBalance = try container.decode(CurrencyAmount.self, forKey: .currentBalance)
}
if let legacyAvailableBalance = try container.decodeIfPresent(Int64.self, forKey: .availableBalance) {
self.availableBalance = StarsAmount(value: legacyAvailableBalance, nanos: 0)
if let legacyAvailableBalance = try container.decodeIfPresent(StarsAmount.self, forKey: .availableBalanceStars) {
self.availableBalance = CurrencyAmount(amount: legacyAvailableBalance, currency: .stars)
} else {
self.availableBalance = try container.decode(StarsAmount.self, forKey: .availableBalanceStars)
self.availableBalance = try container.decode(CurrencyAmount.self, forKey: .availableBalance)
}
if let legacyOverallRevenue = try container.decodeIfPresent(Int64.self, forKey: .overallRevenue) {
self.overallRevenue = StarsAmount(value: legacyOverallRevenue, nanos: 0)
if let legacyOverallRevenue = try container.decodeIfPresent(StarsAmount.self, forKey: .overallRevenueStars) {
self.overallRevenue = CurrencyAmount(amount: legacyOverallRevenue, currency: .stars)
} else {
self.overallRevenue = try container.decode(StarsAmount.self, forKey: .overallRevenueStars)
self.overallRevenue = try container.decode(CurrencyAmount.self, forKey: .overallRevenue)
}
self.withdrawEnabled = try container.decode(Bool.self, forKey: .withdrawEnabled)
@ -77,19 +78,21 @@ public struct StarsRevenueStats: Equatable, Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.currentBalance, forKey: .currentBalanceStars)
try container.encode(self.availableBalance, forKey: .availableBalanceStars)
try container.encode(self.overallRevenue, forKey: .overallRevenueStars)
try container.encode(self.currentBalance, forKey: .currentBalance)
try container.encode(self.availableBalance, forKey: .availableBalance)
try container.encode(self.overallRevenue, forKey: .overallRevenue)
try container.encode(self.withdrawEnabled, forKey: .withdrawEnabled)
try container.encodeIfPresent(self.nextWithdrawalTimestamp, forKey: .nextWithdrawalTimestamp)
}
}
public let topHoursGraph: StatsGraph?
public let revenueGraph: StatsGraph
public let balances: Balances
public let usdRate: Double
init(revenueGraph: StatsGraph, balances: Balances, usdRate: Double) {
init(topHoursGraph: StatsGraph?, revenueGraph: StatsGraph, balances: Balances, usdRate: Double) {
self.topHoursGraph = topHoursGraph
self.revenueGraph = revenueGraph
self.balances = balances
self.usdRate = usdRate
@ -97,6 +100,7 @@ public struct StarsRevenueStats: Equatable, Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.topHoursGraph = try container.decodeIfPresent(StatsGraph.self, forKey: .topHoursGraph)
self.revenueGraph = try container.decode(StatsGraph.self, forKey: .revenueGraph)
self.balances = try container.decode(Balances.self, forKey: .balances)
self.usdRate = try container.decode(Double.self, forKey: .usdRate)
@ -104,12 +108,16 @@ public struct StarsRevenueStats: Equatable, Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(self.topHoursGraph, forKey: .topHoursGraph)
try container.encode(self.revenueGraph, forKey: .revenueGraph)
try container.encode(self.balances, forKey: .balances)
try container.encode(self.usdRate, forKey: .usdRate)
}
public static func == (lhs: StarsRevenueStats, rhs: StarsRevenueStats) -> Bool {
if lhs.topHoursGraph != rhs.topHoursGraph {
return false
}
if lhs.revenueGraph != rhs.revenueGraph {
return false
}
@ -126,6 +134,7 @@ public struct StarsRevenueStats: Equatable, Codable {
public extension StarsRevenueStats {
func withUpdated(balances: StarsRevenueStats.Balances) -> StarsRevenueStats {
return StarsRevenueStats(
topHoursGraph: self.topHoursGraph,
revenueGraph: self.revenueGraph,
balances: balances,
usdRate: self.usdRate
@ -136,8 +145,8 @@ public extension StarsRevenueStats {
extension StarsRevenueStats {
init(apiStarsRevenueStats: Api.payments.StarsRevenueStats, peerId: PeerId) {
switch apiStarsRevenueStats {
case let .starsRevenueStats(revenueGraph, balances, usdRate):
self.init(revenueGraph: StatsGraph(apiStatsGraph: revenueGraph), balances: StarsRevenueStats.Balances(apiStarsRevenueStatus: balances), usdRate: usdRate)
case let .starsRevenueStats(_, topHoursGraph, revenueGraph, balances, usdRate):
self.init(topHoursGraph: topHoursGraph.flatMap { StatsGraph(apiStatsGraph: $0) }, revenueGraph: StatsGraph(apiStatsGraph: revenueGraph), balances: StarsRevenueStats.Balances(apiStarsRevenueStatus: balances), usdRate: usdRate)
}
}
}
@ -146,7 +155,7 @@ extension StarsRevenueStats.Balances {
init(apiStarsRevenueStatus: Api.StarsRevenueStatus) {
switch apiStarsRevenueStatus {
case let .starsRevenueStatus(flags, currentBalance, availableBalance, overallRevenue, nextWithdrawalAt):
self.init(currentBalance: StarsAmount(apiAmount: currentBalance), availableBalance: StarsAmount(apiAmount: availableBalance), overallRevenue: StarsAmount(apiAmount: overallRevenue), withdrawEnabled: ((flags & (1 << 0)) != 0), nextWithdrawalTimestamp: nextWithdrawalAt)
self.init(currentBalance: CurrencyAmount(apiAmount: currentBalance), availableBalance: CurrencyAmount(apiAmount: availableBalance), overallRevenue: CurrencyAmount(apiAmount: overallRevenue), withdrawEnabled: ((flags & (1 << 0)) != 0), nextWithdrawalTimestamp: nextWithdrawalAt)
}
}
}
@ -155,7 +164,7 @@ public struct StarsRevenueStatsContextState: Equatable {
public var stats: StarsRevenueStats?
}
private func requestStarsRevenueStats(postbox: Postbox, network: Network, peerId: PeerId, dark: Bool = false) -> Signal<StarsRevenueStats?, NoError> {
private func requestStarsRevenueStats(postbox: Postbox, network: Network, peerId: PeerId, ton: Bool, dark: Bool = false) -> Signal<StarsRevenueStats?, NoError> {
return postbox.transaction { transaction -> Peer? in
if let peer = transaction.getPeer(peerId) {
return peer
@ -167,9 +176,12 @@ private func requestStarsRevenueStats(postbox: Postbox, network: Network, peerId
}
var flags: Int32 = 0
if dark {
if ton {
flags |= (1 << 1)
}
if dark {
flags |= (1 << 0)
}
return network.request(Api.functions.payments.getStarsRevenueStats(flags: flags, peer: inputPeer))
|> retryRequestIfNotFrozen
@ -186,6 +198,7 @@ private func requestStarsRevenueStats(postbox: Postbox, network: Network, peerId
private final class StarsRevenueStatsContextImpl {
private let account: Account
private let peerId: PeerId
private let ton: Bool
private var _state: StarsRevenueStatsContextState {
didSet {
@ -202,11 +215,12 @@ private final class StarsRevenueStatsContextImpl {
private let disposable = MetaDisposable()
private let updateDisposable = MetaDisposable()
init(account: Account, peerId: PeerId) {
init(account: Account, peerId: PeerId, ton: Bool) {
assert(Queue.mainQueue().isCurrent())
self.account = account
self.peerId = peerId
self.ton = ton
self._state = StarsRevenueStatsContextState(stats: nil)
self._statePromise.set(.single(self._state))
@ -245,7 +259,7 @@ private final class StarsRevenueStatsContextImpl {
let account = self.account
let peerId = self.peerId
let signal = requestStarsRevenueStats(postbox: self.account.postbox, network: self.account.network, peerId: self.peerId)
let signal = requestStarsRevenueStats(postbox: self.account.postbox, network: self.account.network, peerId: self.peerId, ton: self.ton)
|> mapToSignal { initial -> Signal<StarsRevenueStats?, NoError> in
guard let initial else {
return .single(nil)
@ -303,9 +317,9 @@ public final class StarsRevenueStatsContext {
}
}
public init(account: Account, peerId: PeerId) {
public init(account: Account, peerId: PeerId, ton: Bool) {
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
return StarsRevenueStatsContextImpl(account: account, peerId: peerId)
return StarsRevenueStatsContextImpl(account: account, peerId: peerId, ton: ton)
})
}
@ -347,7 +361,7 @@ public enum RequestStarsRevenueWithdrawalError : Equatable {
}
func _internal_checkStarsRevenueWithdrawalAvailability(account: Account) -> Signal<Never, RequestStarsRevenueWithdrawalError> {
return account.network.request(Api.functions.payments.getStarsRevenueWithdrawalUrl(peer: .inputPeerEmpty, stars: 0, password: .inputCheckPasswordEmpty))
return account.network.request(Api.functions.payments.getStarsRevenueWithdrawalUrl(flags: 0, peer: .inputPeerEmpty, amount: nil, password: .inputCheckPasswordEmpty))
|> mapError { error -> RequestStarsRevenueWithdrawalError in
if error.errorDescription == "PASSWORD_HASH_INVALID" {
return .requestPassword
@ -369,7 +383,7 @@ func _internal_checkStarsRevenueWithdrawalAvailability(account: Account) -> Sign
|> ignoreValues
}
func _internal_requestStarsRevenueWithdrawalUrl(account: Account, peerId: PeerId, amount: Int64, password: String) -> Signal<String, RequestStarsRevenueWithdrawalError> {
func _internal_requestStarsRevenueWithdrawalUrl(account: Account, ton: Bool, peerId: PeerId, amount: Int64?, password: String) -> Signal<String, RequestStarsRevenueWithdrawalError> {
guard !password.isEmpty else {
return .fail(.invalidPassword)
}
@ -400,7 +414,13 @@ func _internal_requestStarsRevenueWithdrawalUrl(account: Account, peerId: PeerId
return checkPassword
|> mapToSignal { password -> Signal<String, RequestStarsRevenueWithdrawalError> in
return account.network.request(Api.functions.payments.getStarsRevenueWithdrawalUrl(peer: inputPeer, stars: amount, password: password), automaticFloodWait: false)
var flags: Int32 = 0
if ton {
flags |= 1 << 0
} else {
flags |= 1 << 1
}
return account.network.request(Api.functions.payments.getStarsRevenueWithdrawalUrl(flags: flags, peer: inputPeer, amount: amount, password: password), automaticFloodWait: false)
|> mapError { error -> RequestStarsRevenueWithdrawalError in
if error.errorCode == 406 {
return .serverProvided(text: error.errorDescription)

View file

@ -2405,6 +2405,62 @@ public extension TelegramEngine.EngineData.Item {
}
}
public struct BotGroupAdminRights: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = Optional<TelegramChatAdminRights>
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
return self.id
}
public init(id: EnginePeer.Id) {
self.id = id
}
var key: PostboxViewKey {
return .cachedPeerData(peerId: self.id)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? CachedPeerDataView else {
preconditionFailure()
}
if let cachedData = view.cachedPeerData as? CachedUserData {
return cachedData.botGroupAdminRights
} else {
return nil
}
}
}
public struct BotChannelAdminRights: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem {
public typealias Result = Optional<TelegramChatAdminRights>
fileprivate var id: EnginePeer.Id
public var mapKey: EnginePeer.Id {
return self.id
}
public init(id: EnginePeer.Id) {
self.id = id
}
var key: PostboxViewKey {
return .cachedPeerData(peerId: self.id)
}
func extract(view: PostboxView) -> Result {
guard let view = view as? CachedPeerDataView else {
preconditionFailure()
}
if let cachedData = view.cachedPeerData as? CachedUserData {
return cachedData.botChannelAdminRights
} else {
return nil
}
}
}
public struct StarsReactionDefaultPrivacy: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = TelegramPaidReactionPrivacy

View file

@ -462,7 +462,7 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
|> mapToSignal { result -> Signal<InternalStarsStatus, RequestStarsStateError> in
return account.postbox.transaction { transaction -> InternalStarsStatus in
switch result {
case let .starsStatus(flags: _, balance, _, _, subscriptionsMissingBalance, transactions, nextTransactionsOffset, chats, users):
case let .starsStatus(_, balance, _, _, subscriptionsMissingBalance, transactions, nextTransactionsOffset, chats, users):
let peers = AccumulatedPeers(chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers)
@ -570,9 +570,9 @@ private final class StarsContextImpl {
self.load(force: true)
self.updateDisposable = (account.stateManager.updatedStarsBalance()
self.updateDisposable = ((ton ? account.stateManager.updatedTonBalance() : account.stateManager.updatedStarsBalance())
|> deliverOnMainQueue).startStrict(next: { [weak self] balances in
guard let self, let state = self._state, let balance = balances[peerId] else {
guard let self, let state = self._state, let balance = balances[self.peerId] else {
return
}
self.updateState(StarsContext.State(flags: [], balance: balance, subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: state.transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: false))
@ -619,7 +619,7 @@ private final class StarsContextImpl {
var transactions = state.transactions
if addTransaction {
let count = CurrencyAmount(amount: balance, currency: self.ton ? .ton : .stars)
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: count, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, giveawayMessageId: nil, media: [], subscriptionPeriod: nil, starGift: nil, floodskipNumber: nil, starrefCommissionPermille: nil, starrefPeerId: nil, starrefAmount: nil, paidMessageCount: nil, premiumGiftMonths: nil), at: 0)
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: count, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, giveawayMessageId: nil, media: [], subscriptionPeriod: nil, starGift: nil, floodskipNumber: nil, starrefCommissionPermille: nil, starrefPeerId: nil, starrefAmount: nil, paidMessageCount: nil, premiumGiftMonths: nil, adsProceedsFromDate: nil, adsProceedsToDate: nil), at: 0)
}
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: max(StarsAmount(value: 0, nanos: 0), state.balance + balance), subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
}
@ -655,7 +655,7 @@ private final class StarsContextImpl {
private extension StarsContext.State.Transaction {
init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) {
switch apiTransaction {
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod, giveawayPostId, starGift, floodskipNumber, starrefCommissionPermille, starrefPeer, starrefAmount, paidMessageCount, premiumGiftMonths):
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod, giveawayPostId, starGift, floodskipNumber, starrefCommissionPermille, starrefPeer, starrefAmount, paidMessageCount, premiumGiftMonths, adsProceedsFromDate, adsProceedsToDate):
let parsedPeer: StarsContext.State.Transaction.Peer
var paidMessageId: MessageId?
var giveawayMessageId: MessageId?
@ -724,7 +724,7 @@ private extension StarsContext.State.Transaction {
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
let _ = subscriptionPeriod
self.init(flags: flags, id: id, count: CurrencyAmount(apiAmount: stars), date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, giveawayMessageId: giveawayMessageId, media: media, subscriptionPeriod: subscriptionPeriod, starGift: starGift.flatMap { StarGift(apiStarGift: $0) }, floodskipNumber: floodskipNumber, starrefCommissionPermille: starrefCommissionPermille, starrefPeerId: starrefPeer?.peerId, starrefAmount: starrefAmount.flatMap(StarsAmount.init(apiAmount:)), paidMessageCount: paidMessageCount, premiumGiftMonths: premiumGiftMonths)
self.init(flags: flags, id: id, count: CurrencyAmount(apiAmount: stars), date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, giveawayMessageId: giveawayMessageId, media: media, subscriptionPeriod: subscriptionPeriod, starGift: starGift.flatMap { StarGift(apiStarGift: $0) }, floodskipNumber: floodskipNumber, starrefCommissionPermille: starrefCommissionPermille, starrefPeerId: starrefPeer?.peerId, starrefAmount: starrefAmount.flatMap(StarsAmount.init(apiAmount:)), paidMessageCount: paidMessageCount, premiumGiftMonths: premiumGiftMonths, adsProceedsFromDate: adsProceedsFromDate, adsProceedsToDate: adsProceedsToDate)
}
}
}
@ -808,6 +808,8 @@ public final class StarsContext {
public let starrefAmount: StarsAmount?
public let paidMessageCount: Int32?
public let premiumGiftMonths: Int32?
public let adsProceedsFromDate: Int32?
public let adsProceedsToDate: Int32?
public init(
flags: Flags,
@ -830,7 +832,9 @@ public final class StarsContext {
starrefPeerId: PeerId?,
starrefAmount: StarsAmount?,
paidMessageCount: Int32?,
premiumGiftMonths: Int32?
premiumGiftMonths: Int32?,
adsProceedsFromDate: Int32?,
adsProceedsToDate: Int32?
) {
self.flags = flags
self.id = id
@ -853,6 +857,8 @@ public final class StarsContext {
self.starrefAmount = starrefAmount
self.paidMessageCount = paidMessageCount
self.premiumGiftMonths = premiumGiftMonths
self.adsProceedsFromDate = adsProceedsFromDate
self.adsProceedsToDate = adsProceedsToDate
}
public static func == (lhs: Transaction, rhs: Transaction) -> Bool {
@ -919,6 +925,12 @@ public final class StarsContext {
if lhs.premiumGiftMonths != rhs.premiumGiftMonths {
return false
}
if lhs.adsProceedsFromDate != rhs.adsProceedsFromDate {
return false
}
if lhs.adsProceedsToDate != rhs.adsProceedsToDate {
return false
}
return true
}
}
@ -1663,23 +1675,27 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
public struct StarsTransactionReference: PostboxCoding, Hashable, Equatable {
public let peerId: EnginePeer.Id
public let ton: Bool
public let id: String
public let isRefund: Bool
public init(peerId: EnginePeer.Id, id: String, isRefund: Bool) {
public init(peerId: EnginePeer.Id, ton: Bool, id: String, isRefund: Bool) {
self.peerId = peerId
self.ton = ton
self.id = id
self.isRefund = isRefund
}
public init(decoder: PostboxDecoder) {
self.peerId = EnginePeer.Id(decoder.decodeInt64ForKey("peerId", orElse: 0))
self.ton = decoder.decodeBoolForKey("ton", orElse: false)
self.id = decoder.decodeStringForKey("id", orElse: "")
self.isRefund = decoder.decodeBoolForKey("refund", orElse: false)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt64(self.peerId.toInt64(), forKey: "peerId")
encoder.encodeBool(self.ton, forKey: "ton")
encoder.encodeString(self.id, forKey: "id")
encoder.encodeBool(self.isRefund, forKey: "refund")
}
@ -1695,6 +1711,7 @@ func _internal_getStarsTransaction(accountPeerId: PeerId, postbox: Postbox, netw
}
return network.request(
Api.functions.payments.getStarsTransactionsByID(
flags: transactionReference.ton ? 1 << 0 : 0,
peer: inputPeer,
id: [.inputStarsTransaction(flags: transactionReference.isRefund ? (1 << 0) : 0, id: transactionReference.id)]
)

View file

@ -86,8 +86,8 @@ public extension TelegramEngine {
return StarsContext(account: self.account, ton: true)
}
public func peerStarsRevenueContext(peerId: EnginePeer.Id) -> StarsRevenueStatsContext {
return StarsRevenueStatsContext(account: self.account, peerId: peerId)
public func peerStarsRevenueContext(peerId: EnginePeer.Id, ton: Bool) -> StarsRevenueStatsContext {
return StarsRevenueStatsContext(account: self.account, peerId: peerId, ton: ton)
}
public func peerStarsTransactionsContext(subject: StarsTransactionsContext.Subject, mode: StarsTransactionsContext.Mode) -> StarsTransactionsContext {

View file

@ -889,21 +889,13 @@ public extension TelegramEngine {
public func updatePeerStarGiftStatus(peerId: EnginePeer.Id, starGift: StarGift.UniqueGift, expirationDate: Int32?) -> Signal<Never, UpdatePeerEmojiStatusError> {
return _internal_updatePeerStarGiftStatus(account: self.account, peerId: peerId, starGift: starGift, expirationDate: expirationDate)
}
public func checkChannelRevenueWithdrawalAvailability() -> Signal<Never, RequestRevenueWithdrawalError> {
return _internal_checkChannelRevenueWithdrawalAvailability(account: self.account)
}
public func requestChannelRevenueWithdrawalUrl(peerId: EnginePeer.Id, password: String) -> Signal<String, RequestRevenueWithdrawalError> {
return _internal_requestChannelRevenueWithdrawalUrl(account: self.account, peerId: peerId, password: password)
}
public func checkStarsRevenueWithdrawalAvailability() -> Signal<Never, RequestStarsRevenueWithdrawalError> {
return _internal_checkStarsRevenueWithdrawalAvailability(account: self.account)
}
public func requestStarsRevenueWithdrawalUrl(peerId: EnginePeer.Id, amount: Int64, password: String) -> Signal<String, RequestStarsRevenueWithdrawalError> {
return _internal_requestStarsRevenueWithdrawalUrl(account: self.account, peerId: peerId, amount: amount, password: password)
public func requestStarsRevenueWithdrawalUrl(peerId: EnginePeer.Id, ton: Bool, amount: Int64?, password: String) -> Signal<String, RequestStarsRevenueWithdrawalError> {
return _internal_requestStarsRevenueWithdrawalUrl(account: self.account, ton: ton, peerId: peerId, amount: amount, password: password)
}
public func requestStarsRevenueAdsAccountlUrl(peerId: EnginePeer.Id) -> Signal<String?, NoError> {

View file

@ -173,6 +173,10 @@ public enum PresentationResourceKey: Int32 {
case chatBubbleTodoCheckIncomingIcon
case chatBubbleTodoCheckOutgoingIcon
case chatServiceMessageTodoCompletedIcon
case chatServiceMessageTodoIncompletedIcon
case chatServiceMessageTodoAppendedIcon
case chatBubbleReplyThumbnailPlayImage
case chatBubbleDeliveryFailedIcon

View file

@ -1433,6 +1433,24 @@ public struct PresentationResourcesChat {
})
}
public static func chatServiceMessageTodoCompletedIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatServiceMessageTodoCompletedIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/ServiceTodoCompleted"), color: .white)
})
}
public static func chatServiceMessageTodoIncompletedIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatServiceMessageTodoIncompletedIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/ServiceTodoIncompleted"), color: .white)
})
}
public static func chatServiceMessageTodoAppendedIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.chatServiceMessageTodoAppendedIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/ServiceTodoIncompleted"), color: .white)
})
}
public static func messageButtonsPostReject(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.messageButtonsPostReject.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/SuggestPostDecline"), color: .white)

View file

@ -200,8 +200,10 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
let attributedString = attributedServiceMessageString(theme: item.presentationData.theme, strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, message: item.message, messageCount: messageCount, accountPeerId: item.context.account.peerId, forForumOverview: forForumOverview)
var image: TelegramMediaImage?
var story: TelegramMediaStory?
var suggestedPost: TelegramMediaActionType.SuggestedPostApprovalStatus?
var leadingIcon: UIImage?
var isStory = false
for media in item.message.media {
if let action = media as? TelegramMediaAction {
switch action.action {
@ -209,20 +211,29 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
image = img
case let .suggestedPostApprovalStatus(status):
suggestedPost = status
case let .todoCompletions(completed, _):
if !completed.isEmpty {
leadingIcon = PresentationResourcesChat.chatServiceMessageTodoCompletedIcon(item.presentationData.theme.theme)
} else {
leadingIcon = PresentationResourcesChat.chatServiceMessageTodoIncompletedIcon(item.presentationData.theme.theme)
}
case .todoAppendTasks:
leadingIcon = PresentationResourcesChat.chatServiceMessageTodoAppendedIcon(item.presentationData.theme.theme)
default:
break
}
} else if let media = media as? TelegramMediaStory {
story = media
} else if media is TelegramMediaStory {
leadingIcon = PresentationResourcesChat.chatExpiredStoryIndicatorIcon(item.presentationData.theme.theme, type: .free)
isStory = true
}
}
let imageSize = CGSize(width: 212.0, height: 212.0)
var updatedAttributedString = attributedString
if story != nil, let attributedString {
if leadingIcon != nil, let attributedString {
let mutableString = NSMutableAttributedString(attributedString: attributedString)
mutableString.insert(NSAttributedString(string: " ", font: Font.regular(13.0), textColor: .clear), at: 0)
mutableString.insert(NSAttributedString(string: isStory ? " " : " ", font: Font.regular(13.0), textColor: .clear), at: 0)
updatedAttributedString = mutableString
}
@ -426,8 +437,8 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
}
}
for i in 0 ..< labelRects.count {
labelRects[i] = labelRects[i].insetBy(dx: -6.0, dy: floor((labelRects[i].height - 20.0) / 2.0))
labelRects[i].size.height = 20.0
labelRects[i] = labelRects[i].insetBy(dx: -6.0, dy: floor((labelRects[i].height - 22.0) / 2.0))
labelRects[i].size.height = 22.0
labelRects[i].origin.x = floor((labelLayout.size.width - labelRects[i].width) / 2.0)
}
@ -677,7 +688,7 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
}
}
if story != nil {
if let leadingIcon {
let leadingIconView: UIImageView
if let current = strongSelf.leadingIconView {
leadingIconView = current
@ -687,11 +698,15 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
strongSelf.view.addSubview(leadingIconView)
}
leadingIconView.image = PresentationResourcesChat.chatExpiredStoryIndicatorIcon(item.presentationData.theme.theme, type: .free)
leadingIconView.image = leadingIcon
if let lineRect = labelLayout.linesRects().first, let iconImage = leadingIconView.image {
let iconSize = iconImage.size
leadingIconView.frame = CGRect(origin: CGPoint(x: lineRect.minX + labelFrame.minX - 1.0, y: labelFrame.minY), size: iconSize)
var iconFrame = CGRect(origin: CGPoint(x: lineRect.minX + labelFrame.minX - 1.0, y: labelFrame.minY), size: iconSize)
if !isStory {
iconFrame.origin.x += 3.0
}
leadingIconView.frame = iconFrame
}
} else if let leadingIconView = strongSelf.leadingIconView {
strongSelf.leadingIconView = nil

View file

@ -418,6 +418,8 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
title = item.presentationData.strings.Notification_StarsGift_Title(Int32(count))
text = incoming ? item.presentationData.strings.Notification_StarsGift_Subtitle : item.presentationData.strings.Notification_StarsGift_SubtitleYou(peerName).string
case let .giftTon(currency, amount, cryptoCurrency, cryptoAmount, _):
months = 1000
var peerName = ""
if let peer = item.message.peers[item.message.id.peerId] {
peerName = EnginePeer(peer).compactDisplayTitle
@ -431,6 +433,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
title = "$ \(formatTonAmountText(cryptoAmount, dateTimeFormat: item.presentationData.dateTimeFormat))"
text = incoming ? "Use TON to submit post suggestions to channels." : "With TON, \(peerName) will be able to submit post suggestions to channels."
buttonTitle = ""
case let .prizeStars(count, _, channelId, _, _):
if count <= 1000 {
months = 3
@ -640,6 +643,8 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
}
switch months {
case 1000:
animationName = "GiftDiamond"
case 12:
animationName = "Gift12"
case 6:

View file

@ -375,7 +375,10 @@ private func generatePercentageAnimationImages(presentationData: ChatPresentatio
private final class ChatMessageTodoItemNode: ASDisplayNode {
private var backgroundWallpaperNode: ChatMessageBubbleBackdrop?
private var backgroundNode: ChatMessageBackground?
private var snapshotView: UIView?
private var extractedRadioView: UIView?
private var extractedAvatarView: UIView?
private var extractedTitleNode: TextNodeWithEntities?
private var extractedNameView: UIView?
fileprivate let contextSourceNode: ContextExtractedContentContainingNode
fileprivate let containerNode: ASDisplayNode
@ -385,6 +388,7 @@ private final class ChatMessageTodoItemNode: ASDisplayNode {
private var iconNode: ASImageNode?
fileprivate var titleNode: TextNodeWithEntities?
fileprivate var nameNode: TextNode?
private let buttonNode: HighlightTrackingButtonNode
let separatorNode: ASDisplayNode
@ -545,16 +549,48 @@ private final class ChatMessageTodoItemNode: ASDisplayNode {
// self.backgroundWallpaperNode?.update(rect: mappedRect, within: containerSize)
// }
if let snapshotView = self.containerNode.view.snapshotContentTree() {
self.snapshotView = snapshotView
self.contextSourceNode.contentNode.view.addSubview(snapshotView)
if let extractedRadioView = self.radioNode?.view.snapshotContentTree() {
self.extractedRadioView = extractedRadioView
self.contextSourceNode.contentNode.view.addSubview(extractedRadioView)
}
if let extractedAvatarView = self.avatarNode?.view.snapshotContentTree() {
self.extractedAvatarView = extractedAvatarView
self.contextSourceNode.contentNode.view.addSubview(extractedAvatarView)
}
if let titleNode = self.titleNode, let context = self.context, let presentationData = self.presentationData {
let titleConstrainedWidth = titleNode.textNode.cachedLayout?.size.width ?? 1.0
let makeTitleLayout = TextNodeWithEntities.asyncLayout(self.extractedTitleNode)
let (_, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: self.titleNode?.textNode.cachedLayout?.attributedString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: titleConstrainedWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .left, cutout: nil, insets: UIEdgeInsets(top: 1.0, left: 0.0, bottom: 1.0, right: 0.0)))
let extractedTitleNode = titleApply(TextNodeWithEntities.Arguments(
context: context,
cache: context.animationCache,
renderer: context.animationRenderer,
placeholderColor: incoming ? presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor,
attemptSynchronous: true
))
extractedTitleNode.textNode.frame = titleNode.textNode.frame
self.contextSourceNode.contentNode.addSubnode(extractedTitleNode.textNode)
self.extractedTitleNode = extractedTitleNode
}
if let extractedNameView = self.nameNode?.view.snapshotContentTree() {
self.extractedNameView = extractedNameView
self.contextSourceNode.contentNode.view.addSubview(extractedNameView)
}
} else {
if let backgroundNode = self.backgroundNode {
self.backgroundNode = nil
transition.updateAlpha(node: backgroundNode, alpha: 0.0, completion: { [weak backgroundNode] _ in
self.snapshotView?.removeFromSuperview()
self.snapshotView = nil
self.extractedRadioView?.removeFromSuperview()
self.extractedRadioView = nil
self.extractedAvatarView?.removeFromSuperview()
self.extractedAvatarView = nil
self.extractedTitleNode?.textNode.removeFromSupernode()
self.extractedTitleNode = nil
self.extractedNameView?.removeFromSuperview()
self.extractedNameView = nil
backgroundNode?.removeFromSupernode()
})
@ -596,7 +632,7 @@ private final class ChatMessageTodoItemNode: ASDisplayNode {
return { context, presentationData, presentationContext, message, todo, option, completion, translation, constrainedWidth in
var canMark = false
if (todo.flags.contains(.othersCanComplete) || message.author?.id == context.account.peerId) {
if let forwardInfo = message.forwardInfo, let authorId = forwardInfo.author?.id, authorId != context.account.peerId {
if let _ = message.forwardInfo {
} else {
canMark = true
}
@ -725,9 +761,9 @@ private final class ChatMessageTodoItemNode: ASDisplayNode {
if let (nameLayout, nameApply) = nameLayoutAndApply {
var nameNodeFrame: CGRect
if titleLayout.hasRTL {
nameNodeFrame = CGRect(origin: CGPoint(x: width - rightInset - nameLayout.size.width, y: 26.0), size: nameLayout.size)
nameNodeFrame = CGRect(origin: CGPoint(x: width - rightInset - nameLayout.size.width, y: titleNodeFrame.maxY - 4.0), size: nameLayout.size)
} else {
nameNodeFrame = CGRect(origin: CGPoint(x: leftInset, y: 26.0), size: nameLayout.size)
nameNodeFrame = CGRect(origin: CGPoint(x: leftInset, y: titleNodeFrame.maxY - 4.0), size: nameLayout.size)
}
let nameNode = nameApply()
if node.nameNode !== nameNode {

View file

@ -385,8 +385,8 @@ final class PeerInfoScreenData {
let tonState: StarsContext.State?
let starsRevenueStatsState: StarsRevenueStats?
let starsRevenueStatsContext: StarsRevenueStatsContext?
let revenueStatsState: RevenueStats?
let revenueStatsContext: RevenueStatsContext?
let revenueStatsState: StarsRevenueStats?
let revenueStatsContext: StarsRevenueStatsContext?
let profileGiftsContext: ProfileGiftsContext?
let premiumGiftOptions: [PremiumGiftCodeOption]
let webAppPermissions: WebAppPermissionsState?
@ -437,8 +437,8 @@ final class PeerInfoScreenData {
tonState: StarsContext.State?,
starsRevenueStatsState: StarsRevenueStats?,
starsRevenueStatsContext: StarsRevenueStatsContext?,
revenueStatsState: RevenueStats?,
revenueStatsContext: RevenueStatsContext?,
revenueStatsState: StarsRevenueStats?,
revenueStatsContext: StarsRevenueStatsContext?,
profileGiftsContext: ProfileGiftsContext?,
premiumGiftOptions: [PremiumGiftCodeOption],
webAppPermissions: WebAppPermissionsState?
@ -1300,7 +1300,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
guard canViewStarsRevenue else {
return .single((nil, nil))
}
let starsRevenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId)
let starsRevenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId, ton: false)
return starsRevenueStatsContext.state
|> map { state -> (StarsRevenueStatsContext?, StarsRevenueStats?) in
return (starsRevenueStatsContext, state.stats)
@ -1313,7 +1313,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.CanViewRevenue(id: peerId))
|> distinctUntilChanged
)
|> mapToSignal { peer, canViewRevenue -> Signal<(RevenueStatsContext?, RevenueStats?), NoError> in
|> mapToSignal { peer, canViewRevenue -> Signal<(StarsRevenueStatsContext?, StarsRevenueStats?), NoError> in
var canViewRevenue = canViewRevenue
if let peer, case let .user(user) = peer, let _ = user.botInfo, context.sharedContext.applicationBindings.appBuildType == .internal || context.sharedContext.immediateExperimentalUISettings.devRequests {
canViewRevenue = true
@ -1324,9 +1324,9 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
guard canViewRevenue else {
return .single((nil, nil))
}
let revenueStatsContext = RevenueStatsContext(account: context.account, peerId: peerId)
let revenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId, ton: true)
return revenueStatsContext.state
|> map { state -> (RevenueStatsContext?, RevenueStats?) in
|> map { state -> (StarsRevenueStatsContext?, StarsRevenueStats?) in
return (revenueStatsContext, state.stats)
}
}
@ -1572,7 +1572,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
guard canViewStarsRevenue else {
return .single((nil, nil))
}
let starsRevenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId)
let starsRevenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId, ton: false)
return starsRevenueStatsContext.state
|> map { state -> (StarsRevenueStatsContext?, StarsRevenueStats?) in
return (starsRevenueStatsContext, state.stats)
@ -1583,13 +1583,13 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
TelegramEngine.EngineData.Item.Peer.CanViewRevenue(id: peerId)
)
|> distinctUntilChanged
|> mapToSignal { canViewRevenue -> Signal<(RevenueStatsContext?, RevenueStats?), NoError> in
|> mapToSignal { canViewRevenue -> Signal<(StarsRevenueStatsContext?, StarsRevenueStats?), NoError> in
guard canViewRevenue else {
return .single((nil, nil))
}
let revenueStatsContext = RevenueStatsContext(account: context.account, peerId: peerId)
let revenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId, ton: true)
return revenueStatsContext.state
|> map { state -> (RevenueStatsContext?, RevenueStats?) in
|> map { state -> (StarsRevenueStatsContext?, StarsRevenueStats?) in
return (revenueStatsContext, state.stats)
}
}
@ -1911,7 +1911,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
guard canViewStarsRevenue else {
return .single((nil, nil))
}
let starsRevenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId)
let starsRevenueStatsContext = StarsRevenueStatsContext(account: context.account, peerId: peerId, ton: false)
return starsRevenueStatsContext.state
|> map { state -> (StarsRevenueStatsContext?, StarsRevenueStats?) in
return (starsRevenueStatsContext, state.stats)

View file

@ -1597,11 +1597,11 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
}))
}
let revenueBalance = data.revenueStatsState?.balances.currentBalance ?? 0
let overallRevenueBalance = data.revenueStatsState?.balances.overallRevenue ?? 0
let revenueBalance = data.revenueStatsState?.balances.currentBalance.amount.value ?? 0
let overallRevenueBalance = data.revenueStatsState?.balances.overallRevenue.amount.value ?? 0
let starsBalance = data.starsRevenueStatsState?.balances.currentBalance ?? StarsAmount.zero
let overallStarsBalance = data.starsRevenueStatsState?.balances.overallRevenue ?? StarsAmount.zero
let starsBalance = data.starsRevenueStatsState?.balances.currentBalance.amount ?? StarsAmount.zero
let overallStarsBalance = data.starsRevenueStatsState?.balances.overallRevenue.amount ?? StarsAmount.zero
if overallRevenueBalance > 0 || overallStarsBalance > StarsAmount.zero {
items[.balances]!.append(PeerInfoScreenHeaderItem(id: 20, text: presentationData.strings.PeerInfo_BotBalance_Title))
@ -1907,11 +1907,11 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
section = .peerMembers
}
if cachedData.flags.contains(.canViewRevenue) || cachedData.flags.contains(.canViewStarsRevenue) {
let revenueBalance = data.revenueStatsState?.balances.currentBalance ?? 0
let starsBalance = data.starsRevenueStatsState?.balances.currentBalance ?? StarsAmount.zero
let revenueBalance = data.revenueStatsState?.balances.currentBalance.amount.value ?? 0
let starsBalance = data.starsRevenueStatsState?.balances.currentBalance.amount ?? StarsAmount.zero
let overallRevenueBalance = data.revenueStatsState?.balances.overallRevenue ?? 0
let overallStarsBalance = data.starsRevenueStatsState?.balances.overallRevenue ?? StarsAmount.zero
let overallRevenueBalance = data.revenueStatsState?.balances.overallRevenue.amount.value ?? 0
let overallStarsBalance = data.starsRevenueStatsState?.balances.overallRevenue.amount ?? StarsAmount.zero
if overallRevenueBalance > 0 || overallStarsBalance > StarsAmount.zero {
let smallLabelFont = Font.regular(floor(presentationData.listsFontSize.itemListBaseFontSize / 17.0 * 13.0))

View file

@ -62,6 +62,7 @@ swift_library(
"//submodules/AppBundle",
"//submodules/GZip",
"//submodules/LegacyComponents",
"//submodules/TelegramPresentationData",
"//submodules/Components/MultilineTextComponent:MultilineTextComponent",
"//submodules/TelegramUI/Components/Premium/PremiumStarComponent",
"//submodules/TelegramUI/Components/Utils/AnimatableProperty",

View file

@ -8,6 +8,7 @@ import GZip
import AppBundle
import LegacyComponents
import PremiumStarComponent
import TelegramPresentationData
private let sceneVersion: Int = 5
@ -20,11 +21,14 @@ private func rad2deg(_ number: Float) -> Float {
}
public final class PremiumDiamondComponent: Component {
public init() {
let theme: PresentationTheme
public init(theme: PresentationTheme) {
self.theme = theme
}
public static func ==(lhs: PremiumDiamondComponent, rhs: PremiumDiamondComponent) -> Bool {
return true
return lhs.theme === rhs.theme
}
public final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView {
@ -88,14 +92,47 @@ public final class PremiumDiamondComponent: Component {
}
private func setup() {
guard let scene = loadCompressedScene(name: "diamond", version: sceneVersion) else {
guard let scene = loadCompressedScene(name: "gift2", version: sceneVersion) else {
return
}
self.sceneView.scene = scene
self.sceneView.delegate = self
let _ = self.sceneView.snapshot()
let names: [String] = [
"particles_left",
"particles_right",
"particles_left_bottom",
"particles_right_bottom",
"particles_center"
]
let particleColor = UIColor(rgb: 0x428df4) //0x3b9bff)
for name in names {
if let node = scene.rootNode.childNode(withName: name, recursively: false), let particleSystem = node.particleSystems?.first {
particleSystem.particleIntensity = min(1.0, 2.0 * particleSystem.particleIntensity)
particleSystem.particleIntensityVariation = 0.05
particleSystem.particleColor = particleColor
particleSystem.particleColorVariation = SCNVector4Make(0.0, 0.0, 0.1, 0.0)
if let propertyControllers = particleSystem.propertyControllers, let sizeController = propertyControllers[.size], let colorController = propertyControllers[.color] {
let animation = CAKeyframeAnimation()
if let existing = colorController.animation as? CAKeyframeAnimation {
animation.keyTimes = existing.keyTimes
animation.values = existing.values?.compactMap { ($0 as? UIColor)?.alpha } ?? []
} else {
animation.values = [ 0.0, 1.0, 1.0, 0.0 ]
}
let opacityController = SCNParticlePropertyController(animation: animation)
particleSystem.propertyControllers = [
.size: sizeController,
.opacity: opacityController
]
}
}
}
//let _ = self.sceneView.snapshot()
}
private var didSetReady = false
@ -214,6 +251,8 @@ public final class PremiumDiamondComponent: Component {
func update(component: PremiumDiamondComponent, availableSize: CGSize, transition: ComponentTransition) -> CGSize {
self.component = component
self.sceneView.backgroundColor = component.theme.list.blocksBackgroundColor
self.sceneView.bounds = CGRect(origin: .zero, size: CGSize(width: availableSize.width * 2.0, height: availableSize.height * 2.0))
self.sceneView.center = CGPoint(x: availableSize.width / 2.0, y: availableSize.height / 2.0)

View file

@ -158,22 +158,7 @@ public final class GiftAvatarComponent: Component {
self.sceneView.scene = scene
self.sceneView.delegate = self
if let color = self.component?.color {
// let names: [String] = [
// "particles_left",
// "particles_right",
// "particles_left_bottom",
// "particles_right_bottom",
// "particles_center"
// ]
//
// for name in names {
// if let node = scene.rootNode.childNode(withName: name, recursively: false), let particleSystem = node.particleSystems?.first {
// particleSystem.particleColor = color
// particleSystem.particleColorVariation = SCNVector4Make(0, 0, 0, 0)
// }
// }
if let color = self.component?.color {
let names: [String] = [
"particles_left",
"particles_right",

View file

@ -347,7 +347,7 @@ final class LanguageSelectionScreenNode: ViewControllerTracingNode {
let openSearch: () -> Void = {
requestActivateSearch()
}
let previousState = Atomic<LocalizationListState?>(value: nil)
let previousEntriesHolder = Atomic<([LanguageListEntry], PresentationTheme, PresentationStrings)?>(value: nil)
self.listDisposable = combineLatest(
@ -360,7 +360,7 @@ final class LanguageSelectionScreenNode: ViewControllerTracingNode {
guard let strongSelf = self else {
return
}
var entries: [LanguageListEntry] = []
var existingIds = Set<String>()

View file

@ -103,12 +103,12 @@ public final class StarsBalanceOverlayComponent: Component {
})
}
} else {
let starsRevenueStatsContext = StarsRevenueStatsContext(account: component.context.account, peerId: component.peerId)
let starsRevenueStatsContext = StarsRevenueStatsContext(account: component.context.account, peerId: component.peerId, ton: false)
self.starsRevenueStatsContext = starsRevenueStatsContext
self.balanceDisposable = (starsRevenueStatsContext.state
|> map { state -> Int64 in
return state.stats?.balances.currentBalance.value ?? 0
return state.stats?.balances.currentBalance.amount.value ?? 0
}
|> distinctUntilChanged
|> deliverOnMainQueue).start(next: { [weak self] balance in

View file

@ -851,7 +851,7 @@ public final class StarsImageComponent: Component {
if let current = self.animationNode {
animationNode = current
} else {
let stickerName: String = "Gift\(count)"
let stickerName: String = count == 1000 ? "GiftDiamond" : "Gift\(count)"
animationNode = DefaultAnimatedStickerNodeImpl()
animationNode.autoplay = true
animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: stickerName), width: 384, height: 384, playbackMode: .still(.end), mode: .direct(cachePathPrefix: nil))

View file

@ -416,8 +416,15 @@ private final class StarsTransactionSheetContent: CombinedComponent {
isSubscriptionFee = true
} else if transaction.flags.contains(.isGift) {
titleText = strings.Stars_Gift_Received_Title
descriptionText = strings.Stars_Gift_Received_Text
count = transaction.count
//TODO:localize
if count.currency == .ton {
descriptionText = "Use TON to submit post suggestions to channels on Telegram."
} else {
descriptionText = strings.Stars_Gift_Received_Text
}
countOnTop = true
transactionId = transaction.id
date = transaction.date
@ -552,7 +559,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
toPeer = peer
}
transactionPeer = transaction.peer
media = transaction.media.map { AnyMediaReference.starsTransaction(transaction: StarsTransactionReference(peerId: parentPeer.id, id: transaction.id, isRefund: transaction.flags.contains(.isRefund)), media: $0) }
media = transaction.media.map { AnyMediaReference.starsTransaction(transaction: StarsTransactionReference(peerId: parentPeer.id, ton: false, id: transaction.id, isRefund: transaction.flags.contains(.isRefund)), media: $0) }
photo = transaction.photo
if transaction.flags.contains(.isRefund) {
@ -706,6 +713,10 @@ private final class StarsTransactionSheetContent: CombinedComponent {
transition: .immediate
)
if count.currency == .ton {
premiumGiftMonths = 1000
}
let imageSubject: StarsImageComponent.Subject
var imageIcon: StarsImageComponent.Icon?
if let premiumGiftMonths {
@ -732,9 +743,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
imageSubject = .none
}
if isSubscription || isSubscriber || isSubscriptionFee || giveawayMessageId != nil {
imageIcon = count.currency == .ton ? .ton : .star
imageIcon = count.currency == .ton ? nil : .star
} else {
imageIcon = count.currency == .ton ? .ton : nil
imageIcon = nil
}
if isSubscription && "".isEmpty {

View file

@ -522,21 +522,21 @@ final class StarsStatisticsScreenComponent: Component {
theme: environment.theme,
dateTimeFormat: environment.dateTimeFormat,
title: strings.Stars_BotRevenue_Proceeds_Available,
value: starsState?.balances.availableBalance ?? StarsAmount.zero,
value: starsState?.balances.availableBalance.amount ?? StarsAmount.zero,
rate: starsState?.usdRate ?? 0.0
))),
AnyComponentWithIdentity(id: 1, component: AnyComponent(StarsOverviewItemComponent(
theme: environment.theme,
dateTimeFormat: environment.dateTimeFormat,
title: strings.Stars_BotRevenue_Proceeds_Current,
value: starsState?.balances.currentBalance ?? StarsAmount.zero,
value: starsState?.balances.currentBalance.amount ?? StarsAmount.zero,
rate: starsState?.usdRate ?? 0.0
))),
AnyComponentWithIdentity(id: 2, component: AnyComponent(StarsOverviewItemComponent(
theme: environment.theme,
dateTimeFormat: environment.dateTimeFormat,
title: strings.Stars_BotRevenue_Proceeds_Total,
value: starsState?.balances.overallRevenue ?? StarsAmount.zero,
value: starsState?.balances.overallRevenue.amount ?? StarsAmount.zero,
rate: starsState?.usdRate ?? 0.0
)))
],
@ -579,7 +579,7 @@ final class StarsStatisticsScreenComponent: Component {
theme: environment.theme,
strings: strings,
dateTimeFormat: environment.dateTimeFormat,
count: self.starsState?.balances.availableBalance ?? StarsAmount.zero,
count: self.starsState?.balances.availableBalance.amount ?? StarsAmount.zero,
currency: .stars,
rate: self.starsState?.usdRate ?? 0,
actionTitle: strings.Stars_Intro_BuyShort,
@ -623,7 +623,7 @@ final class StarsStatisticsScreenComponent: Component {
theme: environment.theme,
strings: strings,
dateTimeFormat: environment.dateTimeFormat,
count: self.starsState?.balances.availableBalance ?? StarsAmount.zero,
count: self.starsState?.balances.availableBalance.amount ?? StarsAmount.zero,
currency: .stars,
rate: self.starsState?.usdRate ?? 0,
actionTitle: strings.Stars_BotRevenue_Withdraw_WithdrawShort,

View file

@ -501,7 +501,7 @@ final class StarsTransactionsScreenComponent: Component {
let headerComponent: AnyComponent<Empty>
if component.starsContext.ton {
headerComponent = AnyComponent(PremiumDiamondComponent())
headerComponent = AnyComponent(PremiumDiamondComponent(theme: environment.theme))
} else {
headerComponent = AnyComponent(PremiumStarComponent(
theme: environment.theme,
@ -667,9 +667,8 @@ final class StarsTransactionsScreenComponent: Component {
contentHeight += descriptionSize.height
contentHeight += 29.0
let withdrawAvailable = component.starsContext.ton ? (self.starsState?.balance.value ?? 0) > 0 : (self.revenueState?.balances.overallRevenue.value ?? 0) > 0
let withdrawAvailable = (self.revenueState?.balances.overallRevenue.amount.value ?? 0) > 0
//TODO:localize
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
let balanceSize = self.balanceView.update(
transition: .immediate,
@ -685,8 +684,8 @@ final class StarsTransactionsScreenComponent: Component {
count: self.starsState?.balance ?? StarsAmount.zero,
currency: component.starsContext.ton ? .ton : .stars,
rate: nil,
actionTitle: component.starsContext.ton ? "Withdraw via Fragment" : (withdrawAvailable ? environment.strings.Stars_Intro_BuyShort : environment.strings.Stars_Intro_Buy),
actionAvailable: (component.starsContext.ton && withdrawAvailable) || (!premiumConfiguration.areStarsDisabled && !premiumConfiguration.isPremiumDisabled),
actionTitle: (withdrawAvailable ? environment.strings.Stars_Intro_BuyShort : environment.strings.Stars_Intro_Buy),
actionAvailable: (!component.starsContext.ton && !premiumConfiguration.areStarsDisabled && !premiumConfiguration.isPremiumDisabled),
actionIsEnabled: true,
actionIcon: component.starsContext.ton ? nil : PresentationResourcesItemList.itemListRoundTopupIcon(environment.theme),
action: { [weak self] in
@ -1139,7 +1138,7 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
self.context = context
self.starsContext = starsContext
self.starsRevenueStatsContext = context.engine.payments.peerStarsRevenueContext(peerId: context.account.peerId)
self.starsRevenueStatsContext = context.engine.payments.peerStarsRevenueContext(peerId: context.account.peerId, ton: false)
if !starsContext.ton {
self.subscriptionsContext = context.engine.payments.peerStarsSubscriptionsContext(starsContext: starsContext)
} else {

View file

@ -46,7 +46,7 @@ public func confirmStarsRevenueWithdrawalController(context: AccountContext, upd
}
contentNode.updateIsChecking(true)
let signal = context.engine.peers.requestStarsRevenueWithdrawalUrl(peerId: peerId, amount: amount, password: contentNode.password)
let signal = context.engine.peers.requestStarsRevenueWithdrawalUrl(peerId: peerId, ton: false, amount: amount, password: contentNode.password)
disposable.set((signal |> deliverOnMainQueue).start(next: { url in
dismissImpl?()
completion(url)

View file

@ -162,7 +162,7 @@ private final class SheetContent: CombinedComponent {
amountPlaceholder = environment.strings.Stars_Withdraw_AmountPlaceholder
minAmount = withdrawConfiguration.minWithdrawAmount.flatMap { StarsAmount(value: $0, nanos: 0) }
maxAmount = status.balances.availableBalance
maxAmount = status.balances.availableBalance.amount
case .accountWithdraw:
titleString = environment.strings.Stars_Withdraw_Title
amountTitle = environment.strings.Stars_Withdraw_AmountTitle
@ -241,7 +241,7 @@ private final class SheetContent: CombinedComponent {
} else if case .reaction = component.mode {
balance = state.starsBalance
} else if case let .withdraw(starsState, _) = component.mode {
balance = starsState.balances.availableBalance
balance = starsState.balances.availableBalance.amount
} else {
balance = nil
}
@ -785,7 +785,7 @@ private final class SheetContent: CombinedComponent {
var currency: CurrencyAmount.Currency = .stars
switch mode {
case let .withdraw(stats, _):
amount = StarsAmount(value: stats.balances.availableBalance.value, nanos: 0)
amount = StarsAmount(value: stats.balances.availableBalance.amount.value, nanos: 0)
case .accountWithdraw:
amount = context.starsContext?.currentState.flatMap { StarsAmount(value: $0.balance.value, nanos: 0) }
case let .paidMedia(initialValue, _):

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "sistemplus_16.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "sistemdone_16.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "sistemundone_16.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "checks.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -611,15 +611,9 @@ extension ChatControllerImpl {
}
if #available(iOS 18.0, *) {
if self.context.sharedContext.immediateExperimentalUISettings.enableLocalTranslation {
if engineExperimentalInternalTranslationService == nil, let hostView = self.context.sharedContext.mainWindow?.hostView {
let translationService = ExperimentalInternalTranslationServiceImpl(view: hostView.containerView)
engineExperimentalInternalTranslationService = translationService
}
} else {
if engineExperimentalInternalTranslationService != nil {
engineExperimentalInternalTranslationService = nil
}
if engineExperimentalInternalTranslationService == nil, let hostView = self.context.sharedContext.mainWindow?.hostView {
let translationService = ExperimentalInternalTranslationServiceImpl(view: hostView.containerView)
engineExperimentalInternalTranslationService = translationService
}
}

View file

@ -3582,15 +3582,23 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let _ = ApplicationSpecificNotice.incrementTranslationSuggestion(accountManager: context.sharedContext.accountManager, timestamp: Int32(Date().timeIntervalSince1970)).startStandalone()
let controller = TranslateScreen(context: context, text: text.string, canCopy: canCopy, fromLanguage: language, ignoredLanguages: translationSettings.ignoredLanguages)
controller.pushController = { [weak self] c in
self?.effectiveNavigationController?._keepModalDismissProgress = true
self?.push(c)
}
controller.presentController = { [weak self] c in
self?.present(c, in: .window(.root))
}
strongSelf.present(controller, in: .window(.root))
presentTranslateScreen(
context: context,
text: text.string,
canCopy: canCopy,
fromLanguage: language,
ignoredLanguages: translationSettings.ignoredLanguages,
pushController: { [weak self] c in
self?.effectiveNavigationController?._keepModalDismissProgress = true
self?.push(c)
},
presentController: { [weak self] c in
self?.present(c, in: .window(.root))
},
display: { [weak self] c in
self?.present(c, in: .window(.root))
}
)
})
}
if let currentContextController = strongSelf.currentContextController {

View file

@ -98,6 +98,21 @@ func openResolvedUrlImpl(
case let .botStart(peer, payload):
openPeer(EnginePeer(peer), .withBotStartPayload(ChatControllerInitialBotStart(payload: payload, behavior: .interactive)))
case let .groupBotStart(botPeerId, payload, adminRights, peerType):
let defaultAdminRights = Promise<(group: TelegramChatAdminRights?, channel: TelegramChatAdminRights?)?>(nil)
if adminRights == nil {
defaultAdminRights.set(
context.engine.peers.fetchAndUpdateCachedPeerData(peerId: botPeerId)
|> mapToSignal { _ in
return context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.BotGroupAdminRights(id: botPeerId),
TelegramEngine.EngineData.Item.Peer.BotChannelAdminRights(id: botPeerId)
) |> map { groupRights, channelRights in
return (groupRights, channelRights)
}
}
)
}
var filter: ChatListNodePeersFilter = [.onlyGroupsAndChannels, .onlyManageable, .excludeDisabled, .excludeRecent, .doNotSearchMessages]
var title: String = presentationData.strings.Bot_AddToChat_Title
switch peerType {
@ -179,11 +194,20 @@ func openResolvedUrlImpl(
}
if case let .channel(peer) = peer {
var isGroup = false
if case .group = peer.info {
isGroup = true
}
if peer.flags.contains(.isCreator) || peer.adminRights?.rights.contains(.canAddAdmins) == true {
let controller = channelAdminController(context: context, peerId: peerId, adminId: botPeerId, initialParticipant: nil, invite: true, initialAdminRights: adminRights?.chatAdminRights, updated: { _ in
controller?.dismiss()
}, upgradedToSupergroup: { _, _ in }, transferedOwnership: { _ in })
navigationController?.pushViewController(controller)
let _ = (defaultAdminRights.get()
|> take(1)
|> deliverOnMainQueue).start(next: { defaultAdminRights in
let initialAdminRights = adminRights?.chatAdminRights ?? (isGroup ? defaultAdminRights?.group?.rights : defaultAdminRights?.channel?.rights)
let controller = channelAdminController(context: context, peerId: peerId, adminId: botPeerId, initialParticipant: nil, invite: true, initialAdminRights: initialAdminRights, updated: { _ in
controller?.dismiss()
}, upgradedToSupergroup: { _, _ in }, transferedOwnership: { _ in })
navigationController?.pushViewController(controller)
})
} else {
addMemberImpl()
}
@ -191,10 +215,15 @@ func openResolvedUrlImpl(
if case .member = peer.role {
addMemberImpl()
} else {
let controller = channelAdminController(context: context, peerId: peerId, adminId: botPeerId, initialParticipant: nil, invite: true, initialAdminRights: adminRights?.chatAdminRights, updated: { _ in
controller?.dismiss()
}, upgradedToSupergroup: { _, _ in }, transferedOwnership: { _ in })
navigationController?.pushViewController(controller)
let _ = (defaultAdminRights.get()
|> take(1)
|> deliverOnMainQueue).start(next: { defaultAdminRights in
let initialAdminRights = adminRights?.chatAdminRights ?? defaultAdminRights?.group?.rights
let controller = channelAdminController(context: context, peerId: peerId, adminId: botPeerId, initialParticipant: nil, invite: true, initialAdminRights: initialAdminRights, updated: { _ in
controller?.dismiss()
}, upgradedToSupergroup: { _, _ in }, transferedOwnership: { _ in })
navigationController?.pushViewController(controller)
})
}
}
}

View file

@ -180,7 +180,8 @@ public func translateMessageIds(context: AccountContext, messageIds: [EngineMess
}
}
}
return context.engine.messages.translateMessages(messageIds: messageIdsToTranslate, fromLang: fromLang, toLang: toLang, enableLocalIfPossible: context.sharedContext.immediateExperimentalUISettings.enableLocalTranslation)
return context.engine.messages.translateMessages(messageIds: messageIdsToTranslate, fromLang: fromLang, toLang: toLang, enableLocalIfPossible: true) //context.sharedContext.immediateExperimentalUISettings.enableLocalTranslation)
|> `catch` { _ -> Signal<Never, NoError> in
return .complete()
}

View file

@ -176,6 +176,21 @@ public func canTranslateText(context: AccountContext, text: String, showTranslat
return (false, nil)
}
let translationConfiguration = TranslationConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
var translateButtonAvailable = false
switch translationConfiguration.manual {
case .enabled, .alternative:
translateButtonAvailable = true
case .system:
if #available(iOS 18.0, *) {
translateButtonAvailable = true
}
default:
break
}
let showTranslate = showTranslate && translateButtonAvailable
if #available(iOS 12.0, *) {
if context.sharedContext.immediateExperimentalUISettings.disableLanguageRecognition {
return (true, nil)
@ -403,3 +418,121 @@ public final class ExperimentalInternalTranslationServiceImpl: ExperimentalInter
}
}
}
func alternativeTranslateText(text: String, fromLang: String?, toLang: String) -> Signal<(String, [MessageTextEntity])?, TelegramCore.TranslationError> {
return Signal { subscriber in
var task: URLSessionTask?
Queue.concurrentDefaultQueue().async {
let effectiveFromLang: String
if let fromLang {
effectiveFromLang = fromLang
} else {
languageRecognizer.processString(text)
let hypotheses = languageRecognizer.languageHypotheses(withMaximum: 3)
languageRecognizer.reset()
let filteredLanguages = hypotheses.filter { supportedTranslationLanguages.contains(normalizeTranslationLanguage($0.key.rawValue)) }.sorted(by: { $0.value > $1.value })
if let language = filteredLanguages.first {
let languageCode = normalizeTranslationLanguage(language.key.rawValue)
effectiveFromLang = languageCode
} else {
effectiveFromLang = "en"
}
}
var uri = "https://translate.goo"
uri += "gleapis.com/transl"
uri += "ate_a"
uri += "/singl"
uri += "e?client=gtx&sl=\(effectiveFromLang.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")"
uri += "&tl=\(toLang.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")"
uri += "&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=0&tsel=0&kc=7&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&q="
uri += text.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
guard let url = URL(string: uri) else {
subscriber.putError(.generic)
return
}
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue(getRandomUserAgent(), forHTTPHeaderField: "User-Agent")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Translation failed: \(error.localizedDescription)")
subscriber.putError(.generic)
return
}
guard let httpResponse = response as? HTTPURLResponse else {
subscriber.putError(.generic)
return
}
if httpResponse.statusCode != 200 {
print("Translation failed with status code: \(httpResponse.statusCode)")
let isRateLimit = httpResponse.statusCode == 429
subscriber.putError(isRateLimit ? .limitExceeded : .generic)
return
}
guard let data = data else {
subscriber.putError(.generic)
return
}
do {
guard let jsonArray = try JSONSerialization.jsonObject(with: data) as? [Any] else {
subscriber.putError(.generic)
return
}
guard let translationArray = jsonArray.first as? [Any] else {
subscriber.putError(.generic)
return
}
// var sourceLanguage: String? = nil
// if jsonArray.count > 2, let lang = jsonArray[2] as? String {
// sourceLanguage = lang.contains("-") ? String(lang.prefix(while: { $0 != "-" })) : lang
// }
var result = ""
for element in translationArray {
if let translationBlock = element as? [Any],
translationBlock.count > 0,
let blockText = translationBlock[0] as? String,
blockText != "null" && !blockText.isEmpty {
result += blockText
}
}
if text.hasPrefix("\n") {
result = "\n" + result
}
subscriber.putNext((result, []))
subscriber.putCompletion()
} catch {
print("JSON parsing error: \(error)")
subscriber.putError(.generic)
}
}
task?.resume()
}
return ActionDisposable {
task?.cancel()
}
}
}
func getRandomUserAgent() -> String {
let userAgents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.4 Mobile/15E148 Safari/604.1"
]
return userAgents.randomElement() ?? userAgents[0]
}

View file

@ -14,6 +14,7 @@ import MultilineTextComponent
import MultilineTextWithEntitiesComponent
import BundleIconComponent
import UndoUI
import SwiftUI
private func generateExpandBackground(size: CGSize, color: UIColor) -> UIImage {
return generateImage(size, rotatedContext: { size, context in
@ -94,6 +95,8 @@ private final class TranslateScreenComponent: CombinedComponent {
fileprivate var moreBackgroundImage: (CGSize, UIImage, UIColor)?
private let useAlternativeTranslation: Bool
init(context: AccountContext, fromLanguage: String?, text: String, toLanguage: String, expand: @escaping () -> Void) {
self.context = context
self.text = text
@ -102,9 +105,19 @@ private final class TranslateScreenComponent: CombinedComponent {
self.expand = expand
self.availableSpeakLanguages = supportedSpeakLanguages()
let translationConfiguration = TranslationConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
var useAlternativeTranslation = false
switch translationConfiguration.manual {
case .alternative:
useAlternativeTranslation = true
default:
break
}
self.useAlternativeTranslation = useAlternativeTranslation
super.init()
self.translationDisposable.set((context.engine.messages.translate(text: text, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in
self.translationDisposable.set((self.translate(text: text, fromLang: fromLanguage, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in
guard let strongSelf = self else {
return
}
@ -120,6 +133,14 @@ private final class TranslateScreenComponent: CombinedComponent {
self.translationDisposable.dispose()
}
func translate(text: String, fromLang: String?, toLang: String) -> Signal<(String, [MessageTextEntity])?, TranslationError> {
if self.useAlternativeTranslation {
return alternativeTranslateText(text: text, fromLang: fromLang, toLang: toLang)
} else {
return self.context.engine.messages.translate(text: text, toLang: toLang)
}
}
func changeLanguage(fromLanguage: String, toLanguage: String) {
guard self.fromLanguage != fromLanguage || self.toLanguage != toLanguage else {
return
@ -129,7 +150,7 @@ private final class TranslateScreenComponent: CombinedComponent {
self.translatedText = nil
self.updated(transition: .immediate)
self.translationDisposable.set((self.context.engine.messages.translate(text: text, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in
self.translationDisposable.set((self.translate(text: text, fromLang: fromLanguage, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in
guard let strongSelf = self else {
return
}
@ -1163,3 +1184,85 @@ public class TranslateScreen: ViewController {
self.node.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: ComponentTransition(transition))
}
}
public func presentTranslateScreen(
context: AccountContext,
text: String,
entities: [MessageTextEntity] = [],
canCopy: Bool,
fromLanguage: String?,
toLanguage: String? = nil,
isExpanded: Bool = false,
ignoredLanguages: [String]? = nil,
pushController: @escaping (ViewController) -> Void = { _ in },
presentController: @escaping (ViewController) -> Void = { _ in },
wasDismissed: (() -> Void)? = nil,
display: (ViewController) -> Void
) {
let translationConfiguration = TranslationConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
var useSystemTranslation = false
switch translationConfiguration.manual {
case .system:
if #available(iOS 18.0, *) {
useSystemTranslation = true
}
default:
break
}
if useSystemTranslation {
presentSystemTranslateScreen(context: context, text: text)
} else {
let controller = TranslateScreen(context: context, text: text, canCopy: canCopy, fromLanguage: fromLanguage, toLanguage: toLanguage, isExpanded: isExpanded, ignoredLanguages: ignoredLanguages)
controller.pushController = pushController
controller.presentController = presentController
controller.wasDismissed = wasDismissed
display(controller)
}
}
private func presentSystemTranslateScreen(context: AccountContext, text: String) {
if #available(iOS 18.0, *), let rootViewController = context.sharedContext.mainWindow?.viewController?.view.window?.rootViewController {
var dismissImpl: (() -> Void)?
let pickerView = TranslateScreenHostingView(text: text, completionHandler: { [weak rootViewController] in
DispatchQueue.main.async(execute: {
guard let presentedController = rootViewController?.presentedViewController, presentedController.isBeingDismissed == false else { return }
dismissImpl?()
})
})
let hostingController = UIHostingController(rootView: pickerView)
hostingController.view.isHidden = true
hostingController.modalPresentationStyle = .overCurrentContext
rootViewController.present(hostingController, animated: true)
dismissImpl = { [weak hostingController] in
Queue.mainQueue().after(0.4, {
hostingController?.dismiss(animated: false)
})
}
}
}
@available(iOS 18.0, *)
struct TranslateScreenHostingView: View {
@State var presented = true
var text: String
var handler: () -> Void
init(text: String, completionHandler: @escaping () -> Void) {
self.text = text
self.handler = completionHandler
}
var body: some View {
Spacer()
.translationPresentation(
isPresented: $presented,
text: text
)
.onChange(of: presented) { newValue in
if newValue == false {
handler()
}
}
}
}