Merge commit '8ad27b9ef21990ebc224f9110b8e3ad6e83b2fd0'

This commit is contained in:
Isaac 2024-06-14 11:49:57 +04:00
commit 032ded0817
24 changed files with 1036 additions and 364 deletions

View File

@ -72,6 +72,18 @@ enum BaseConstants {
return numberFormatter return numberFormatter
}() }()
static let starNumberFormatter: NumberFormatter = {
let numberFormatter = NumberFormatter()
numberFormatter.allowsFloats = true
numberFormatter.numberStyle = .decimal
numberFormatter.usesGroupingSeparator = true
numberFormatter.groupingSeparator = " "
numberFormatter.minimumIntegerDigits = 1
numberFormatter.minimumFractionDigits = 0
numberFormatter.maximumFractionDigits = 2
return numberFormatter
}()
static let detailsNumberFormatter: NumberFormatter = { static let detailsNumberFormatter: NumberFormatter = {
let detailsNumberFormatter = NumberFormatter() let detailsNumberFormatter = NumberFormatter()
detailsNumberFormatter.allowsFloats = false detailsNumberFormatter.allowsFloats = false

View File

@ -13,7 +13,23 @@ import Cocoa
import UIKit import UIKit
#endif #endif
public enum GraphCurrency : String {
case xtr = "XTR"
case ton = "TON"
var formatter: NumberFormatter {
switch self {
case .xtr:
return BaseConstants.starNumberFormatter
case .ton:
return BaseConstants.tonNumberFormatter
}
}
}
public class StackedBarsChartController: BaseChartController { public class StackedBarsChartController: BaseChartController {
let barsController: BarsComponentController let barsController: BarsComponentController
let zoomedBarsController: BarsComponentController let zoomedBarsController: BarsComponentController
@ -23,12 +39,12 @@ public class StackedBarsChartController: BaseChartController {
} }
} }
public init(chartsCollection: ChartsCollection, isCrypto: Bool = false, rate: Double = 1.0) { public init(chartsCollection: ChartsCollection, currency: GraphCurrency? = nil, drawCurrency:((CGContext, UIColor, CGPoint)->Void)? = nil, rate: Double = 1.0) {
let horizontalScalesRenderer = HorizontalScalesRenderer() let horizontalScalesRenderer = HorizontalScalesRenderer()
let verticalScalesRenderer = VerticalScalesRenderer() let verticalScalesRenderer = VerticalScalesRenderer()
var secondaryScalesRenderer: VerticalScalesRenderer? var secondaryScalesRenderer: VerticalScalesRenderer?
if isCrypto { if let _ = currency {
verticalScalesRenderer.isCrypto = true verticalScalesRenderer.drawCurrency = drawCurrency
secondaryScalesRenderer = VerticalScalesRenderer() secondaryScalesRenderer = VerticalScalesRenderer()
secondaryScalesRenderer?.isRightAligned = true secondaryScalesRenderer?.isRightAligned = true
} }
@ -38,10 +54,10 @@ public class StackedBarsChartController: BaseChartController {
verticalScalesRenderer: verticalScalesRenderer, verticalScalesRenderer: verticalScalesRenderer,
secondaryScalesRenderer: secondaryScalesRenderer, secondaryScalesRenderer: secondaryScalesRenderer,
previewBarsChartRenderer: BarChartRenderer()) previewBarsChartRenderer: BarChartRenderer())
if isCrypto { if let currency {
barsController.conversionRate = rate barsController.conversionRate = rate
barsController.verticalLimitsNumberFormatter = BaseConstants.tonNumberFormatter barsController.verticalLimitsNumberFormatter = currency.formatter
barsController.detailsNumberFormatter = BaseConstants.tonNumberFormatter barsController.detailsNumberFormatter = currency.formatter
} }
zoomedBarsController = BarsComponentController(isZoomed: true, zoomedBarsController = BarsComponentController(isZoomed: true,
mainBarsRenderer: BarChartRenderer(), mainBarsRenderer: BarChartRenderer(),

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
#if os(macOS) #if os(macOS)
import Cocoa import Cocoa
typealias UIColor = NSColor public typealias UIColor = NSColor
#else #else
import UIKit import UIKit
#endif #endif
@ -26,7 +26,7 @@ class VerticalScalesRenderer: BaseChartRenderer {
var axisXWidth: CGFloat = GView.oneDevicePixel var axisXWidth: CGFloat = GView.oneDevicePixel
var isRightAligned: Bool = false var isRightAligned: Bool = false
var isCrypto: Bool = false var drawCurrency:((CGContext, UIColor, CGPoint)->Void)?
var horizontalLinesColor: GColor = .black { var horizontalLinesColor: GColor = .black {
didSet { didSet {
@ -122,45 +122,6 @@ class VerticalScalesRenderer: BaseChartRenderer {
context.strokeLineSegments(between: lineSegments) context.strokeLineSegments(between: lineSegments)
} }
func drawTonSymbol(context: CGContext, color: UIColor, at point: CGPoint) {
let width: CGFloat = 8.0
let height: CGFloat = 7.5
let cornerRadius: CGFloat = 0.5
let topPoint = CGPoint(x: point.x + width / 2, y: point.y)
let bottomPoint = CGPoint(x: point.x + width / 2, y: point.y + height)
let leftTopPoint = CGPoint(x: point.x, y: point.y)
let rightTopPoint = CGPoint(x: point.x + width, y: point.y)
context.saveGState()
context.beginPath()
context.move(to: CGPoint(x: leftTopPoint.x + cornerRadius, y: leftTopPoint.y))
context.addArc(tangent1End: leftTopPoint, tangent2End: bottomPoint, radius: cornerRadius)
context.addLine(to: CGPoint(x: bottomPoint.x, y: bottomPoint.y - cornerRadius + GView.oneDevicePixel))
context.move(to: CGPoint(x: rightTopPoint.x - cornerRadius, y: rightTopPoint.y))
context.addArc(tangent1End: rightTopPoint, tangent2End: bottomPoint, radius: cornerRadius)
context.addLine(to: CGPoint(x: bottomPoint.x, y: bottomPoint.y - cornerRadius + GView.oneDevicePixel))
context.move(to: CGPoint(x: leftTopPoint.x + cornerRadius, y: leftTopPoint.y))
context.addLine(to: CGPoint(x: rightTopPoint.x - cornerRadius, y: rightTopPoint.y))
context.move(to: topPoint)
context.addLine(to: CGPoint(x: bottomPoint.x, y: bottomPoint.y - 1.0))
context.setLineWidth(1.0)
context.setLineCap(.round)
context.setFillColor(UIColor.clear.cgColor)
context.setStrokeColor(color.withAlphaComponent(1.0).cgColor)
context.setAlpha(color.alphaValue)
context.strokePath()
context.restoreGState()
}
func drawVerticalLabels(_ labels: [LinesChartLabel], attributes: [NSAttributedString.Key: Any]) { func drawVerticalLabels(_ labels: [LinesChartLabel], attributes: [NSAttributedString.Key: Any]) {
if isRightAligned { if isRightAligned {
for label in labels { for label in labels {
@ -176,9 +137,9 @@ class VerticalScalesRenderer: BaseChartRenderer {
let textNode = LabelNode.layoutText(attributedString, bounds.size) let textNode = LabelNode.layoutText(attributedString, bounds.size)
var xOffset = 0.0 var xOffset = 0.0
if self.isCrypto { if let drawCurrency {
xOffset += 11.0 xOffset += 11.0
drawTonSymbol(context: context, color: attributes[.foregroundColor] as? UIColor ?? .black, at: CGPoint(x: chartFrame.minX, y: y + 4.0)) drawCurrency(context, attributes[.foregroundColor] as? UIColor ?? .black, CGPoint(x: chartFrame.minX, y: y + 4.0))
} }
textNode.1.draw(CGRect(origin: CGPoint(x: chartFrame.minX + xOffset, y: y), size: textNode.0.size), in: context, backingScaleFactor: deviceScale) textNode.1.draw(CGRect(origin: CGPoint(x: chartFrame.minX + xOffset, y: y), size: textNode.0.size), in: context, backingScaleFactor: deviceScale)

View File

@ -60,3 +60,5 @@ class TonNumberFormatter: NumberFormatter, @unchecked Sendable {
return balanceText return balanceText
} }
} }

View File

@ -21,7 +21,7 @@ func makeCIColor(color: GColor) -> CIColor {
#endif #endif
} }
extension GColor { public extension GColor {
var redValue: CGFloat{ return makeCIColor(color: self).red } var redValue: CGFloat{ return makeCIColor(color: self).red }
var greenValue: CGFloat{ return makeCIColor(color: self).green } var greenValue: CGFloat{ return makeCIColor(color: self).green }
var blueValue: CGFloat{ return makeCIColor(color: self).blue } var blueValue: CGFloat{ return makeCIColor(color: self).blue }

View File

@ -20,6 +20,6 @@ public typealias GView = UIView
#endif #endif
extension GView { public extension GView {
static let oneDevicePixel: CGFloat = (1.0 / max(2, min(1, deviceScale))) static let oneDevicePixel: CGFloat = (1.0 / max(2, min(1, deviceScale)))
} }

View File

@ -872,8 +872,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-425595208] = { return Api.SmsJob.parse_smsJob($0) } dict[-425595208] = { return Api.SmsJob.parse_smsJob($0) }
dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) } dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) } dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
dict[-407138204] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) }
dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) } dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) }
dict[-865044046] = { return Api.StarsTransaction.parse_starsTransaction($0) } dict[-1442789224] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) } dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) }
dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) } dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) }
dict[-382740222] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerFragment($0) } dict[-382740222] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerFragment($0) }
@ -944,6 +945,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-2095595325] = { return Api.Update.parse_updateBotWebhookJSON($0) } dict[-2095595325] = { return Api.Update.parse_updateBotWebhookJSON($0) }
dict[-1684914010] = { return Api.Update.parse_updateBotWebhookJSONQuery($0) } dict[-1684914010] = { return Api.Update.parse_updateBotWebhookJSONQuery($0) }
dict[-539401739] = { return Api.Update.parse_updateBroadcastRevenueTransactions($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[1666927625] = { return Api.Update.parse_updateChannel($0) }
dict[-1304443240] = { return Api.Update.parse_updateChannelAvailableMessages($0) } dict[-1304443240] = { return Api.Update.parse_updateChannelAvailableMessages($0) }
dict[-761649164] = { return Api.Update.parse_updateChannelMessageForwards($0) } dict[-761649164] = { return Api.Update.parse_updateChannelMessageForwards($0) }
@ -1045,6 +1047,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) } dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) }
dict[-245208620] = { return Api.Update.parse_updateSmsJob($0) } dict[-245208620] = { return Api.Update.parse_updateSmsJob($0) }
dict[263737752] = { return Api.Update.parse_updateStarsBalance($0) } dict[263737752] = { return Api.Update.parse_updateStarsBalance($0) }
dict[-1518030823] = { return Api.Update.parse_updateStarsRevenueStatus($0) }
dict[834816008] = { return Api.Update.parse_updateStickerSets($0) } dict[834816008] = { return Api.Update.parse_updateStickerSets($0) }
dict[196268545] = { return Api.Update.parse_updateStickerSetsOrder($0) } dict[196268545] = { return Api.Update.parse_updateStickerSetsOrder($0) }
dict[738741697] = { return Api.Update.parse_updateStoriesStealthMode($0) } dict[738741697] = { return Api.Update.parse_updateStoriesStealthMode($0) }
@ -1309,6 +1312,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) } dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) } dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) } dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
dict[-919881925] = { return Api.payments.StarsRevenueStats.parse_starsRevenueStats($0) }
dict[497778871] = { return Api.payments.StarsRevenueWithdrawalUrl.parse_starsRevenueWithdrawalUrl($0) }
dict[-1930105248] = { return Api.payments.StarsStatus.parse_starsStatus($0) } dict[-1930105248] = { return Api.payments.StarsStatus.parse_starsStatus($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) } dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[541839704] = { return Api.phone.ExportedGroupCallInvite.parse_exportedGroupCallInvite($0) } dict[541839704] = { return Api.phone.ExportedGroupCallInvite.parse_exportedGroupCallInvite($0) }
@ -1978,6 +1983,8 @@ public extension Api {
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.SponsoredMessageReportOption: case let _1 as Api.SponsoredMessageReportOption:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsRevenueStatus:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsTopupOption: case let _1 as Api.StarsTopupOption:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.StarsTransaction: case let _1 as Api.StarsTransaction:
@ -2334,6 +2341,10 @@ public extension Api {
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.payments.SavedInfo: case let _1 as Api.payments.SavedInfo:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.payments.StarsRevenueStats:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarsRevenueWithdrawalUrl:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarsStatus: case let _1 as Api.payments.StarsStatus:
_1.serialize(buffer, boxed) _1.serialize(buffer, boxed)
case let _1 as Api.payments.ValidatedRequestedInfo: case let _1 as Api.payments.ValidatedRequestedInfo:

View File

@ -602,6 +602,54 @@ public extension Api {
} }
} }
public extension Api {
enum StarsRevenueStatus: TypeConstructorDescription {
case starsRevenueStatus(flags: Int32, currentBalance: Int64, availableBalance: Int64, overallRevenue: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsRevenueStatus(let flags, let currentBalance, let availableBalance, let overallRevenue):
if boxed {
buffer.appendInt32(-407138204)
}
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 .starsRevenueStatus(let flags, let currentBalance, let availableBalance, let overallRevenue):
return ("starsRevenueStatus", [("flags", flags as Any), ("currentBalance", currentBalance as Any), ("availableBalance", availableBalance as Any), ("overallRevenue", overallRevenue as Any)])
}
}
public static func parse_starsRevenueStatus(_ reader: BufferReader) -> StarsRevenueStatus? {
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.StarsRevenueStatus.starsRevenueStatus(flags: _1!, currentBalance: _2!, availableBalance: _3!, overallRevenue: _4!)
}
else {
return nil
}
}
}
}
public extension Api { public extension Api {
enum StarsTopupOption: TypeConstructorDescription { enum StarsTopupOption: TypeConstructorDescription {
case starsTopupOption(flags: Int32, stars: Int64, storeProduct: String?, currency: String, amount: Int64) case starsTopupOption(flags: Int32, stars: Int64, storeProduct: String?, currency: String, amount: Int64)
@ -656,13 +704,13 @@ public extension Api {
} }
public extension Api { public extension Api {
enum StarsTransaction: TypeConstructorDescription { enum StarsTransaction: TypeConstructorDescription {
case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?) case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?, transactionDate: Int32?, transactionUrl: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self { switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo): case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl):
if boxed { if boxed {
buffer.appendInt32(-865044046) buffer.appendInt32(-1442789224)
} }
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false) serializeString(id, buffer: buffer, boxed: false)
@ -672,14 +720,16 @@ public extension Api {
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(description!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {photo!.serialize(buffer, true)} if Int(flags) & Int(1 << 2) != 0 {photo!.serialize(buffer, true)}
if Int(flags) & Int(1 << 5) != 0 {serializeInt32(transactionDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 5) != 0 {serializeString(transactionUrl!, buffer: buffer, boxed: false)}
break break
} }
} }
public func descriptionFields() -> (String, [(String, Any)]) { public func descriptionFields() -> (String, [(String, Any)]) {
switch self { switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo): case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl):
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)]) 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)])
} }
} }
@ -704,6 +754,10 @@ public extension Api {
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.WebDocument _8 = Api.parse(reader, signature: signature) as? Api.WebDocument
} } } }
var _9: Int32?
if Int(_1!) & Int(1 << 5) != 0 {_9 = reader.readInt32() }
var _10: String?
if Int(_1!) & Int(1 << 5) != 0 {_10 = parseString(reader) }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
@ -712,8 +766,10 @@ public extension Api {
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { let _c9 = (Int(_1!) & Int(1 << 5) == 0) || _9 != nil
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8) let _c10 = (Int(_1!) & Int(1 << 5) == 0) || _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10)
} }
else { else {
return nil return nil

View File

@ -271,6 +271,7 @@ public extension Api {
case updateBotWebhookJSON(data: Api.DataJSON) case updateBotWebhookJSON(data: Api.DataJSON)
case updateBotWebhookJSONQuery(queryId: Int64, data: Api.DataJSON, timeout: Int32) case updateBotWebhookJSONQuery(queryId: Int64, data: Api.DataJSON, timeout: Int32)
case updateBroadcastRevenueTransactions(peer: Api.Peer, balances: Api.BroadcastRevenueBalances) 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 updateChannel(channelId: Int64)
case updateChannelAvailableMessages(channelId: Int64, availableMinId: Int32) case updateChannelAvailableMessages(channelId: Int64, availableMinId: Int32)
case updateChannelMessageForwards(channelId: Int64, id: Int32, forwards: Int32) case updateChannelMessageForwards(channelId: Int64, id: Int32, forwards: Int32)
@ -372,6 +373,7 @@ public extension Api {
case updateServiceNotification(flags: Int32, inboxDate: Int32?, type: String, message: String, media: Api.MessageMedia, entities: [Api.MessageEntity]) case updateServiceNotification(flags: Int32, inboxDate: Int32?, type: String, message: String, media: Api.MessageMedia, entities: [Api.MessageEntity])
case updateSmsJob(jobId: String) case updateSmsJob(jobId: String)
case updateStarsBalance(balance: Int64) case updateStarsBalance(balance: Int64)
case updateStarsRevenueStatus(peer: Api.Peer, status: Api.StarsRevenueStatus)
case updateStickerSets(flags: Int32) case updateStickerSets(flags: Int32)
case updateStickerSetsOrder(flags: Int32, order: [Int64]) case updateStickerSetsOrder(flags: Int32, order: [Int64])
case updateStoriesStealthMode(stealthMode: Api.StoriesStealthMode) case updateStoriesStealthMode(stealthMode: Api.StoriesStealthMode)
@ -602,6 +604,19 @@ public extension Api {
peer.serialize(buffer, true) peer.serialize(buffer, true)
balances.serialize(buffer, true) balances.serialize(buffer, true)
break break
case .updateBusinessBotCallbackQuery(let flags, let queryId, let userId, let connectionId, let message, let replyToMessage, let chatInstance, let data):
if boxed {
buffer.appendInt32(513998247)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(queryId, buffer: buffer, boxed: false)
serializeInt64(userId, buffer: buffer, boxed: false)
serializeString(connectionId, buffer: buffer, boxed: false)
message.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {replyToMessage!.serialize(buffer, true)}
serializeInt64(chatInstance, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeBytes(data!, buffer: buffer, boxed: false)}
break
case .updateChannel(let channelId): case .updateChannel(let channelId):
if boxed { if boxed {
buffer.appendInt32(1666927625) buffer.appendInt32(1666927625)
@ -1460,6 +1475,13 @@ public extension Api {
} }
serializeInt64(balance, buffer: buffer, boxed: false) serializeInt64(balance, buffer: buffer, boxed: false)
break break
case .updateStarsRevenueStatus(let peer, let status):
if boxed {
buffer.appendInt32(-1518030823)
}
peer.serialize(buffer, true)
status.serialize(buffer, true)
break
case .updateStickerSets(let flags): case .updateStickerSets(let flags):
if boxed { if boxed {
buffer.appendInt32(834816008) buffer.appendInt32(834816008)
@ -1621,6 +1643,8 @@ public extension Api {
return ("updateBotWebhookJSONQuery", [("queryId", queryId as Any), ("data", data as Any), ("timeout", timeout as Any)]) return ("updateBotWebhookJSONQuery", [("queryId", queryId as Any), ("data", data as Any), ("timeout", timeout as Any)])
case .updateBroadcastRevenueTransactions(let peer, let balances): case .updateBroadcastRevenueTransactions(let peer, let balances):
return ("updateBroadcastRevenueTransactions", [("peer", peer as Any), ("balances", balances as Any)]) 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): case .updateChannel(let channelId):
return ("updateChannel", [("channelId", channelId as Any)]) return ("updateChannel", [("channelId", channelId as Any)])
case .updateChannelAvailableMessages(let channelId, let availableMinId): case .updateChannelAvailableMessages(let channelId, let availableMinId):
@ -1823,6 +1847,8 @@ public extension Api {
return ("updateSmsJob", [("jobId", jobId as Any)]) return ("updateSmsJob", [("jobId", jobId as Any)])
case .updateStarsBalance(let balance): case .updateStarsBalance(let balance):
return ("updateStarsBalance", [("balance", balance as Any)]) return ("updateStarsBalance", [("balance", balance as Any)])
case .updateStarsRevenueStatus(let peer, let status):
return ("updateStarsRevenueStatus", [("peer", peer as Any), ("status", status as Any)])
case .updateStickerSets(let flags): case .updateStickerSets(let flags):
return ("updateStickerSets", [("flags", flags as Any)]) return ("updateStickerSets", [("flags", flags as Any)])
case .updateStickerSetsOrder(let flags, let order): case .updateStickerSetsOrder(let flags, let order):
@ -2333,6 +2359,42 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_updateBusinessBotCallbackQuery(_ reader: BufferReader) -> Update? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int64?
_3 = reader.readInt64()
var _4: String?
_4 = parseString(reader)
var _5: Api.Message?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Message
}
var _6: Api.Message?
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.Message
} }
var _7: Int64?
_7 = reader.readInt64()
var _8: Buffer?
if Int(_1!) & Int(1 << 0) != 0 {_8 = parseBytes(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
let _c7 = _7 != nil
let _c8 = (Int(_1!) & Int(1 << 0) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.Update.updateBusinessBotCallbackQuery(flags: _1!, queryId: _2!, userId: _3!, connectionId: _4!, message: _5!, replyToMessage: _6, chatInstance: _7!, data: _8)
}
else {
return nil
}
}
public static func parse_updateChannel(_ reader: BufferReader) -> Update? { public static func parse_updateChannel(_ reader: BufferReader) -> Update? {
var _1: Int64? var _1: Int64?
_1 = reader.readInt64() _1 = reader.readInt64()
@ -4010,6 +4072,24 @@ public extension Api {
return nil return nil
} }
} }
public static func parse_updateStarsRevenueStatus(_ reader: BufferReader) -> Update? {
var _1: Api.Peer?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _2: Api.StarsRevenueStatus?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarsRevenueStatus
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.Update.updateStarsRevenueStatus(peer: _1!, status: _2!)
}
else {
return nil
}
}
public static func parse_updateStickerSets(_ reader: BufferReader) -> Update? { public static func parse_updateStickerSets(_ reader: BufferReader) -> Update? {
var _1: Int32? var _1: Int32?
_1 = reader.readInt32() _1 = reader.readInt32()

View File

@ -1044,6 +1044,90 @@ public extension Api.payments {
} }
} }
public extension Api.payments {
enum StarsRevenueStats: TypeConstructorDescription {
case starsRevenueStats(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):
if boxed {
buffer.appendInt32(-919881925)
}
revenueGraph.serialize(buffer, true)
status.serialize(buffer, true)
serializeDouble(usdRate, buffer: buffer, boxed: false)
break
}
}
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)])
}
}
public static func parse_starsRevenueStats(_ reader: BufferReader) -> StarsRevenueStats? {
var _1: Api.StatsGraph?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _2: Api.StarsRevenueStatus?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarsRevenueStatus
}
var _3: Double?
_3 = reader.readDouble()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.payments.StarsRevenueStats.starsRevenueStats(revenueGraph: _1!, status: _2!, usdRate: _3!)
}
else {
return nil
}
}
}
}
public extension Api.payments {
enum StarsRevenueWithdrawalUrl: TypeConstructorDescription {
case starsRevenueWithdrawalUrl(url: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsRevenueWithdrawalUrl(let url):
if boxed {
buffer.appendInt32(497778871)
}
serializeString(url, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsRevenueWithdrawalUrl(let url):
return ("starsRevenueWithdrawalUrl", [("url", url as Any)])
}
}
public static func parse_starsRevenueWithdrawalUrl(_ reader: BufferReader) -> StarsRevenueWithdrawalUrl? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.payments.StarsRevenueWithdrawalUrl.starsRevenueWithdrawalUrl(url: _1!)
}
else {
return nil
}
}
}
}
public extension Api.payments { public extension Api.payments {
enum StarsStatus: TypeConstructorDescription { enum StarsStatus: TypeConstructorDescription {
case starsStatus(flags: Int32, balance: Int64, history: [Api.StarsTransaction], nextOffset: String?, chats: [Api.Chat], users: [Api.User]) case starsStatus(flags: Int32, balance: Int64, history: [Api.StarsTransaction], nextOffset: String?, chats: [Api.Chat], users: [Api.User])
@ -1590,95 +1674,3 @@ public extension Api.photos {
} }
} }
public extension Api.photos {
enum Photos: TypeConstructorDescription {
case photos(photos: [Api.Photo], users: [Api.User])
case photosSlice(count: Int32, photos: [Api.Photo], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .photos(let photos, let users):
if boxed {
buffer.appendInt32(-1916114267)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(photos.count))
for item in photos {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
case .photosSlice(let count, let photos, let users):
if boxed {
buffer.appendInt32(352657236)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(photos.count))
for item in photos {
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 .photos(let photos, let users):
return ("photos", [("photos", photos as Any), ("users", users as Any)])
case .photosSlice(let count, let photos, let users):
return ("photosSlice", [("count", count as Any), ("photos", photos as Any), ("users", users as Any)])
}
}
public static func parse_photos(_ reader: BufferReader) -> Photos? {
var _1: [Api.Photo]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self)
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.photos.Photos.photos(photos: _1!, users: _2!)
}
else {
return nil
}
}
public static func parse_photosSlice(_ reader: BufferReader) -> Photos? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.Photo]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self)
}
var _3: [Api.User]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.photos.Photos.photosSlice(count: _1!, photos: _2!, users: _3!)
}
else {
return nil
}
}
}
}

View File

@ -1,3 +1,95 @@
public extension Api.photos {
enum Photos: TypeConstructorDescription {
case photos(photos: [Api.Photo], users: [Api.User])
case photosSlice(count: Int32, photos: [Api.Photo], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .photos(let photos, let users):
if boxed {
buffer.appendInt32(-1916114267)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(photos.count))
for item in photos {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
case .photosSlice(let count, let photos, let users):
if boxed {
buffer.appendInt32(352657236)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(photos.count))
for item in photos {
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 .photos(let photos, let users):
return ("photos", [("photos", photos as Any), ("users", users as Any)])
case .photosSlice(let count, let photos, let users):
return ("photosSlice", [("count", count as Any), ("photos", photos as Any), ("users", users as Any)])
}
}
public static func parse_photos(_ reader: BufferReader) -> Photos? {
var _1: [Api.Photo]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self)
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.photos.Photos.photos(photos: _1!, users: _2!)
}
else {
return nil
}
}
public static func parse_photosSlice(_ reader: BufferReader) -> Photos? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.Photo]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self)
}
var _3: [Api.User]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.photos.Photos.photosSlice(count: _1!, photos: _2!, users: _3!)
}
else {
return nil
}
}
}
}
public extension Api.premium { public extension Api.premium {
enum BoostsList: TypeConstructorDescription { enum BoostsList: TypeConstructorDescription {
case boostsList(flags: Int32, count: Int32, boosts: [Api.Boost], nextOffset: String?, users: [Api.User]) case boostsList(flags: Int32, count: Int32, boosts: [Api.Boost], nextOffset: String?, users: [Api.User])
@ -1498,141 +1590,3 @@ public extension Api.stories {
} }
} }
public extension Api.stories {
enum StoryViews: TypeConstructorDescription {
case storyViews(views: [Api.StoryViews], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyViews(let views, let users):
if boxed {
buffer.appendInt32(-560009955)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(views.count))
for item in views {
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 .storyViews(let views, let users):
return ("storyViews", [("views", views as Any), ("users", users as Any)])
}
}
public static func parse_storyViews(_ reader: BufferReader) -> StoryViews? {
var _1: [Api.StoryViews]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryViews.self)
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.stories.StoryViews.storyViews(views: _1!, users: _2!)
}
else {
return nil
}
}
}
}
public extension Api.stories {
enum StoryViewsList: TypeConstructorDescription {
case storyViewsList(flags: Int32, count: Int32, viewsCount: Int32, forwardsCount: Int32, reactionsCount: Int32, views: [Api.StoryView], chats: [Api.Chat], users: [Api.User], nextOffset: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
if boxed {
buffer.appendInt32(1507299269)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
serializeInt32(viewsCount, buffer: buffer, boxed: false)
serializeInt32(forwardsCount, buffer: buffer, boxed: false)
serializeInt32(reactionsCount, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(views.count))
for item in views {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
return ("storyViewsList", [("flags", flags as Any), ("count", count as Any), ("viewsCount", viewsCount as Any), ("forwardsCount", forwardsCount as Any), ("reactionsCount", reactionsCount as Any), ("views", views as Any), ("chats", chats as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)])
}
}
public static func parse_storyViewsList(_ reader: BufferReader) -> StoryViewsList? {
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()
var _6: [Api.StoryView]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryView.self)
}
var _7: [Api.Chat]?
if let _ = reader.readInt32() {
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _8: [Api.User]?
if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
var _9: String?
if Int(_1!) & Int(1 << 0) != 0 {_9 = parseString(reader) }
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 = (Int(_1!) & Int(1 << 0) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.stories.StoryViewsList.storyViewsList(flags: _1!, count: _2!, viewsCount: _3!, forwardsCount: _4!, reactionsCount: _5!, views: _6!, chats: _7!, users: _8!, nextOffset: _9)
}
else {
return nil
}
}
}
}

View File

@ -1,3 +1,141 @@
public extension Api.stories {
enum StoryViews: TypeConstructorDescription {
case storyViews(views: [Api.StoryViews], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyViews(let views, let users):
if boxed {
buffer.appendInt32(-560009955)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(views.count))
for item in views {
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 .storyViews(let views, let users):
return ("storyViews", [("views", views as Any), ("users", users as Any)])
}
}
public static func parse_storyViews(_ reader: BufferReader) -> StoryViews? {
var _1: [Api.StoryViews]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryViews.self)
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.stories.StoryViews.storyViews(views: _1!, users: _2!)
}
else {
return nil
}
}
}
}
public extension Api.stories {
enum StoryViewsList: TypeConstructorDescription {
case storyViewsList(flags: Int32, count: Int32, viewsCount: Int32, forwardsCount: Int32, reactionsCount: Int32, views: [Api.StoryView], chats: [Api.Chat], users: [Api.User], nextOffset: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
if boxed {
buffer.appendInt32(1507299269)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
serializeInt32(viewsCount, buffer: buffer, boxed: false)
serializeInt32(forwardsCount, buffer: buffer, boxed: false)
serializeInt32(reactionsCount, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(views.count))
for item in views {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
return ("storyViewsList", [("flags", flags as Any), ("count", count as Any), ("viewsCount", viewsCount as Any), ("forwardsCount", forwardsCount as Any), ("reactionsCount", reactionsCount as Any), ("views", views as Any), ("chats", chats as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)])
}
}
public static func parse_storyViewsList(_ reader: BufferReader) -> StoryViewsList? {
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()
var _6: [Api.StoryView]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryView.self)
}
var _7: [Api.Chat]?
if let _ = reader.readInt32() {
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _8: [Api.User]?
if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
var _9: String?
if Int(_1!) & Int(1 << 0) != 0 {_9 = parseString(reader) }
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 = (Int(_1!) & Int(1 << 0) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.stories.StoryViewsList.storyViewsList(flags: _1!, count: _2!, viewsCount: _3!, forwardsCount: _4!, reactionsCount: _5!, views: _6!, chats: _7!, users: _8!, nextOffset: _9)
}
else {
return nil
}
}
}
}
public extension Api.updates { public extension Api.updates {
indirect enum ChannelDifference: TypeConstructorDescription { indirect enum ChannelDifference: TypeConstructorDescription {
case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User]) case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User])

View File

@ -8731,6 +8731,39 @@ public extension Api.functions.payments {
}) })
} }
} }
public extension Api.functions.payments {
static func getStarsRevenueStats(flags: Int32, peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsRevenueStats>) {
let buffer = Buffer()
buffer.appendInt32(-652215594)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
return (FunctionDescription(name: "payments.getStarsRevenueStats", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsRevenueStats? in
let reader = BufferReader(buffer)
var result: Api.payments.StarsRevenueStats?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.StarsRevenueStats
}
return result
})
}
}
public extension Api.functions.payments {
static func getStarsRevenueWithdrawalUrl(peer: Api.InputPeer, stars: Int64, password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsRevenueWithdrawalUrl>) {
let buffer = Buffer()
buffer.appendInt32(331081907)
peer.serialize(buffer, true)
serializeInt64(stars, 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
let reader = BufferReader(buffer)
var result: Api.payments.StarsRevenueWithdrawalUrl?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.StarsRevenueWithdrawalUrl
}
return result
})
}
}
public extension Api.functions.payments { public extension Api.functions.payments {
static func getStarsStatus(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) { static func getStarsStatus(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
let buffer = Buffer() let buffer = Buffer()
@ -8762,13 +8795,14 @@ public extension Api.functions.payments {
} }
} }
public extension Api.functions.payments { public extension Api.functions.payments {
static func getStarsTransactions(flags: Int32, peer: Api.InputPeer, offset: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) { static func getStarsTransactions(flags: Int32, peer: Api.InputPeer, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(1731904249) buffer.appendInt32(-1751937702)
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
serializeString(offset, buffer: buffer, boxed: false) serializeString(offset, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getStarsTransactions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getStarsTransactions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
let reader = BufferReader(buffer) let reader = BufferReader(buffer)
var result: Api.payments.StarsStatus? var result: Api.payments.StarsStatus?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {

View File

@ -130,6 +130,7 @@ enum AccountStateMutationOperation {
case UpdateWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?) case UpdateWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?)
case UpdateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances) case UpdateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances)
case UpdateStarsBalance(peerId: PeerId, balance: Int64) case UpdateStarsBalance(peerId: PeerId, balance: Int64)
case UpdateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances)
} }
struct HoleFromPreviousState { struct HoleFromPreviousState {
@ -683,9 +684,13 @@ struct AccountMutableState {
self.addOperation(.UpdateStarsBalance(peerId: peerId, balance: balance)) self.addOperation(.UpdateStarsBalance(peerId: peerId, balance: balance))
} }
mutating func updateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances) {
self.addOperation(.UpdateStarsRevenueStatus(peerId: peerId, status: status))
}
mutating func addOperation(_ operation: AccountStateMutationOperation) { mutating func addOperation(_ operation: AccountStateMutationOperation) {
switch operation { 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, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateRevenueBalances, .UpdateStarsBalance: 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, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus:
break break
case let .AddMessages(messages, location): case let .AddMessages(messages, location):
for message in messages { for message in messages {
@ -831,6 +836,7 @@ struct AccountReplayedFinalState {
let isPremiumUpdated: Bool let isPremiumUpdated: Bool
let updatedRevenueBalances: [PeerId: RevenueStats.Balances] let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
let updatedStarsBalance: [PeerId: Int64] let updatedStarsBalance: [PeerId: Int64]
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
} }
struct AccountFinalStateEvents { struct AccountFinalStateEvents {
@ -859,12 +865,13 @@ struct AccountFinalStateEvents {
let isPremiumUpdated: Bool let isPremiumUpdated: Bool
let updatedRevenueBalances: [PeerId: RevenueStats.Balances] let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
let updatedStarsBalance: [PeerId: Int64] let updatedStarsBalance: [PeerId: Int64]
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
var isEmpty: Bool { var isEmpty: Bool {
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.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 return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.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.updatedStarsRevenueStatus.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: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:], updatedStarsBalance: [PeerId: Int64] = [:]) { 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: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:], updatedStarsBalance: [PeerId: Int64] = [:], updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:]) {
self.addedIncomingMessageIds = addedIncomingMessageIds self.addedIncomingMessageIds = addedIncomingMessageIds
self.addedReactionEvents = addedReactionEvents self.addedReactionEvents = addedReactionEvents
self.wasScheduledMessageIds = wasScheduledMessageIds self.wasScheduledMessageIds = wasScheduledMessageIds
@ -890,6 +897,7 @@ struct AccountFinalStateEvents {
self.isPremiumUpdated = isPremiumUpdated self.isPremiumUpdated = isPremiumUpdated
self.updatedRevenueBalances = updatedRevenueBalances self.updatedRevenueBalances = updatedRevenueBalances
self.updatedStarsBalance = updatedStarsBalance self.updatedStarsBalance = updatedStarsBalance
self.updatedStarsRevenueStatus = updatedStarsRevenueStatus
} }
init(state: AccountReplayedFinalState) { init(state: AccountReplayedFinalState) {
@ -918,6 +926,7 @@ struct AccountFinalStateEvents {
self.isPremiumUpdated = state.isPremiumUpdated self.isPremiumUpdated = state.isPremiumUpdated
self.updatedRevenueBalances = state.updatedRevenueBalances self.updatedRevenueBalances = state.updatedRevenueBalances
self.updatedStarsBalance = state.updatedStarsBalance self.updatedStarsBalance = state.updatedStarsBalance
self.updatedStarsRevenueStatus = state.updatedStarsRevenueStatus
} }
func union(with other: AccountFinalStateEvents) -> AccountFinalStateEvents { func union(with other: AccountFinalStateEvents) -> AccountFinalStateEvents {
@ -947,6 +956,6 @@ struct AccountFinalStateEvents {
let isPremiumUpdated = self.isPremiumUpdated || other.isPremiumUpdated let isPremiumUpdated = self.isPremiumUpdated || other.isPremiumUpdated
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, addedReactionEvents: self.addedReactionEvents + other.addedReactionEvents, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, deletedMessageIds: self.deletedMessageIds + other.deletedMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, updatedGroupCallParticipants: self.updatedGroupCallParticipants + other.updatedGroupCallParticipants, storyUpdates: self.storyUpdates + other.storyUpdates, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, dismissBotWebViews: self.dismissBotWebViews + other.dismissBotWebViews, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, 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 })) return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, addedReactionEvents: self.addedReactionEvents + other.addedReactionEvents, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, deletedMessageIds: self.deletedMessageIds + other.deletedMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, updatedGroupCallParticipants: self.updatedGroupCallParticipants + other.updatedGroupCallParticipants, storyUpdates: self.storyUpdates + other.storyUpdates, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, dismissBotWebViews: self.dismissBotWebViews + other.dismissBotWebViews, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, 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 }), updatedStarsRevenueStatus: self.updatedStarsRevenueStatus.merging(other.updatedStarsRevenueStatus, uniquingKeysWith: { lhs, _ in lhs }))
} }
} }

View File

@ -1780,6 +1780,8 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
updatedState.updateRevenueBalances(peerId: peer.peerId, balances: RevenueStats.Balances(apiRevenueBalances: balances)) updatedState.updateRevenueBalances(peerId: peer.peerId, balances: RevenueStats.Balances(apiRevenueBalances: balances))
case let .updateStarsBalance(balance): case let .updateStarsBalance(balance):
updatedState.updateStarsBalance(peerId: accountPeerId, balance: balance) updatedState.updateStarsBalance(peerId: accountPeerId, balance: balance)
case let .updateStarsRevenueStatus(peer, status):
updatedState.updateStarsRevenueStatus(peerId: peer.peerId, status: StarsRevenueStats.Balances(apiStarsRevenueStatus: status))
default: default:
break break
} }
@ -3271,7 +3273,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
var currentAddQuickReplyMessages: OptimizeAddMessagesState? var currentAddQuickReplyMessages: OptimizeAddMessagesState?
for operation in operations { for operation in operations {
switch operation { 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, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateRevenueBalances, .UpdateStarsBalance: 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, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus:
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty { if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location)) result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
} }
@ -3406,6 +3408,7 @@ func replayFinalState(
var updateConfig = false var updateConfig = false
var updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:] var updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:]
var updatedStarsBalance: [PeerId: Int64] = [:] var updatedStarsBalance: [PeerId: Int64] = [:]
var updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:]
var holesFromPreviousStateMessageIds: [MessageId] = [] var holesFromPreviousStateMessageIds: [MessageId] = []
var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:] var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:]
@ -4842,6 +4845,9 @@ func replayFinalState(
updatedRevenueBalances[peerId] = balances updatedRevenueBalances[peerId] = balances
case let .UpdateStarsBalance(peerId, balance): case let .UpdateStarsBalance(peerId, balance):
updatedStarsBalance[peerId] = balance updatedStarsBalance[peerId] = balance
case let .UpdateStarsRevenueStatus(peerId, status):
updatedStarsRevenueStatus[peerId] = status
} }
} }
@ -5336,5 +5342,5 @@ func replayFinalState(
} }
} }
return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, addedReactionEvents: addedReactionEvents, wasScheduledMessageIds: wasScheduledMessageIds, addedSecretMessageIds: addedSecretMessageIds, deletedMessageIds: deletedMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, addedCallSignalingData: addedCallSignalingData, updatedGroupCallParticipants: updatedGroupCallParticipants, storyUpdates: storyUpdates, updatedPeersNearby: updatedPeersNearby, isContactUpdates: isContactUpdates, delayNotificatonsUntil: delayNotificatonsUntil, updatedIncomingThreadReadStates: updatedIncomingThreadReadStates, updatedOutgoingThreadReadStates: updatedOutgoingThreadReadStates, updateConfig: updateConfig, isPremiumUpdated: isPremiumUpdated, updatedRevenueBalances: updatedRevenueBalances, updatedStarsBalance: updatedStarsBalance) return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, addedReactionEvents: addedReactionEvents, wasScheduledMessageIds: wasScheduledMessageIds, addedSecretMessageIds: addedSecretMessageIds, deletedMessageIds: deletedMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, addedCallSignalingData: addedCallSignalingData, updatedGroupCallParticipants: updatedGroupCallParticipants, storyUpdates: storyUpdates, updatedPeersNearby: updatedPeersNearby, isContactUpdates: isContactUpdates, delayNotificatonsUntil: delayNotificatonsUntil, updatedIncomingThreadReadStates: updatedIncomingThreadReadStates, updatedOutgoingThreadReadStates: updatedOutgoingThreadReadStates, updateConfig: updateConfig, isPremiumUpdated: isPremiumUpdated, updatedRevenueBalances: updatedRevenueBalances, updatedStarsBalance: updatedStarsBalance, updatedStarsRevenueStatus: updatedStarsRevenueStatus)
} }

View File

@ -52,6 +52,10 @@ private final class UpdatedStarsBalanceSubscriberContext {
let subscribers = Bag<([PeerId: Int64]) -> Void>() let subscribers = Bag<([PeerId: Int64]) -> Void>()
} }
private final class UpdatedStarsRevenueStatusSubscriberContext {
let subscribers = Bag<([PeerId: StarsRevenueStats.Balances]) -> Void>()
}
public enum DeletedMessageId: Hashable { public enum DeletedMessageId: Hashable {
case global(Int32) case global(Int32)
case messageId(MessageId) case messageId(MessageId)
@ -287,6 +291,7 @@ public final class AccountStateManager {
private var updatedPeersNearbyContext = UpdatedPeersNearbySubscriberContext() private var updatedPeersNearbyContext = UpdatedPeersNearbySubscriberContext()
private var updatedRevenueBalancesContext = UpdatedRevenueBalancesSubscriberContext() private var updatedRevenueBalancesContext = UpdatedRevenueBalancesSubscriberContext()
private var updatedStarsBalanceContext = UpdatedStarsBalanceSubscriberContext() private var updatedStarsBalanceContext = UpdatedStarsBalanceSubscriberContext()
private var updatedStarsRevenueStatusContext = UpdatedStarsRevenueStatusSubscriberContext()
private let delayNotificatonsUntil = Atomic<Int32?>(value: nil) private let delayNotificatonsUntil = Atomic<Int32?>(value: nil)
private let appliedMaxMessageIdPromise = Promise<Int32?>(nil) private let appliedMaxMessageIdPromise = Promise<Int32?>(nil)
@ -1038,6 +1043,9 @@ public final class AccountStateManager {
if !events.updatedStarsBalance.isEmpty { if !events.updatedStarsBalance.isEmpty {
strongSelf.notifyUpdatedStarsBalance(events.updatedStarsBalance) strongSelf.notifyUpdatedStarsBalance(events.updatedStarsBalance)
} }
if !events.updatedStarsRevenueStatus.isEmpty {
strongSelf.notifyUpdatedStarsRevenueStatus(events.updatedStarsRevenueStatus)
}
if !events.updatedCalls.isEmpty { if !events.updatedCalls.isEmpty {
for call in events.updatedCalls { for call in events.updatedCalls {
strongSelf.callSessionManager?.updateSession(call, completion: { _ in }) strongSelf.callSessionManager?.updateSession(call, completion: { _ in })
@ -1664,6 +1672,33 @@ public final class AccountStateManager {
} }
} }
public func updatedStarsRevenueStatus() -> Signal<[PeerId: StarsRevenueStats.Balances], NoError> {
let queue = self.queue
return Signal { [weak self] subscriber in
let disposable = MetaDisposable()
queue.async {
if let strongSelf = self {
let index = strongSelf.updatedStarsRevenueStatusContext.subscribers.add({ revenueBalances in
subscriber.putNext(revenueBalances)
})
disposable.set(ActionDisposable {
if let strongSelf = self {
strongSelf.updatedStarsRevenueStatusContext.subscribers.remove(index)
}
})
}
}
return disposable
}
}
private func notifyUpdatedStarsRevenueStatus(_ updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]) {
for subscriber in self.updatedStarsRevenueStatusContext.subscribers.copyItems() {
subscriber(updatedStarsRevenueStatus)
}
}
func notifyDeletedMessages(messageIds: [MessageId]) { func notifyDeletedMessages(messageIds: [MessageId]) {
self.deletedMessagesPipe.putNext(messageIds.map { .messageId($0) }) self.deletedMessagesPipe.putNext(messageIds.map { .messageId($0) })
} }
@ -1963,6 +1998,12 @@ public final class AccountStateManager {
} }
} }
public func updatedStarsRevenueStatus() -> Signal<[PeerId: StarsRevenueStats.Balances], NoError> {
return self.impl.signalWith { impl, subscriber in
return impl.updatedStarsRevenueStatus().start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
}
}
func addCustomOperation<T, E>(_ f: Signal<T, E>) -> Signal<T, E> { func addCustomOperation<T, E>(_ f: Signal<T, E>) -> Signal<T, E> {
return self.impl.signalWith { impl, subscriber in return self.impl.signalWith { impl, subscriber in
return impl.addCustomOperation(f).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion) return impl.addCustomOperation(f).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)

View File

@ -0,0 +1,304 @@
import Foundation
import SwiftSignalKit
import Postbox
import TelegramApi
import MtProtoKit
public struct StarsRevenueStats: Equatable {
public struct Balances: Equatable {
public let currentBalance: Int64
public let availableBalance: Int64
public let overallRevenue: Int64
public let withdrawEnabled: Bool
}
public let revenueGraph: StatsGraph
public let balances: Balances
public let usdRate: Double
init(revenueGraph: StatsGraph, balances: Balances, usdRate: Double) {
self.revenueGraph = revenueGraph
self.balances = balances
self.usdRate = usdRate
}
public static func == (lhs: StarsRevenueStats, rhs: StarsRevenueStats) -> Bool {
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 StarsRevenueStats {
func withUpdated(balances: StarsRevenueStats.Balances) -> StarsRevenueStats {
return StarsRevenueStats(
revenueGraph: self.revenueGraph,
balances: balances,
usdRate: self.usdRate
)
}
}
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)
}
}
}
extension StarsRevenueStats.Balances {
init(apiStarsRevenueStatus: Api.StarsRevenueStatus) {
switch apiStarsRevenueStatus {
case let .starsRevenueStatus(flags, currentBalance, availableBalance, overallRevenue):
self.init(currentBalance: currentBalance, availableBalance: availableBalance, overallRevenue: overallRevenue, withdrawEnabled: ((flags & (1 << 0)) != 0))
}
}
}
public struct StarsRevenueStatsContextState: Equatable {
public var stats: StarsRevenueStats?
}
private func requestStarsRevenueStats(postbox: Postbox, network: Network, peerId: PeerId, dark: Bool = false) -> Signal<StarsRevenueStats?, NoError> {
return postbox.transaction { transaction -> Peer? in
if let peer = transaction.getPeer(peerId) {
return peer
}
return nil
} |> mapToSignal { peer -> Signal<StarsRevenueStats?, NoError> in
guard let peer, let inputPeer = apiInputPeer(peer) else {
return .never()
}
var flags: Int32 = 0
if dark {
flags |= (1 << 1)
}
return network.request(Api.functions.payments.getStarsRevenueStats(flags: flags, peer: inputPeer))
|> map { result -> StarsRevenueStats? in
return StarsRevenueStats(apiStarsRevenueStats: result, peerId: peerId)
}
|> retryRequest
}
}
private final class StarsRevenueStatsContextImpl {
private let account: Account
private let peerId: PeerId
private var _state: StarsRevenueStatsContextState {
didSet {
if self._state != oldValue {
self._statePromise.set(.single(self._state))
}
}
}
private let _statePromise = Promise<StarsRevenueStatsContextState>()
var state: Signal<StarsRevenueStatsContextState, 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 = StarsRevenueStatsContextState(stats: nil)
self._statePromise.set(.single(self._state))
self.load()
}
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 = requestStarsRevenueStats(postbox: self.account.postbox, network: self.account.network, peerId: self.peerId)
|> mapToSignal { initial -> Signal<StarsRevenueStats?, NoError> in
guard let initial else {
return .single(nil)
}
return .single(initial)
|> then(
account.stateManager.updatedStarsRevenueStatus()
|> 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 strongSelf = self {
strongSelf._state = StarsRevenueStatsContextState(stats: stats)
strongSelf._statePromise.set(.single(strongSelf._state))
}
}))
}
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 StarsRevenueStatsContext {
private let impl: QueueLocalObject<StarsRevenueStatsContextImpl>
public var state: Signal<StarsRevenueStatsContextState, 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 StarsRevenueStatsContextImpl(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
}
}
}
public enum RequestStarsRevenueWithdrawalError : Equatable {
case generic
case twoStepAuthMissing
case twoStepAuthTooFresh(Int32)
case authSessionTooFresh(Int32)
case limitExceeded
case requestPassword
case invalidPassword
}
func _internal_checkStarsRevenueWithdrawalAvailability(account: Account) -> Signal<Never, RequestStarsRevenueWithdrawalError> {
return account.network.request(Api.functions.payments.getStarsRevenueWithdrawalUrl(peer: .inputPeerEmpty, stars: 0, password: .inputCheckPasswordEmpty))
|> mapError { error -> RequestStarsRevenueWithdrawalError 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_requestStarsRevenueWithdrawalUrl(account: Account, peerId: PeerId, amount: Int64, password: String) -> Signal<String, RequestStarsRevenueWithdrawalError> {
guard !password.isEmpty else {
return .fail(.invalidPassword)
}
return account.postbox.transaction { transaction -> Signal<String, RequestStarsRevenueWithdrawalError> in
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
let checkPassword = _internal_twoStepAuthData(account.network)
|> mapError { error -> RequestStarsRevenueWithdrawalError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic
}
}
|> mapToSignal { authData -> Signal<Api.InputCheckPasswordSRP, RequestStarsRevenueWithdrawalError> 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, RequestStarsRevenueWithdrawalError> in
return account.network.request(Api.functions.payments.getStarsRevenueWithdrawalUrl(peer: inputPeer, stars: amount, password: password), automaticFloodWait: false)
|> mapError { error -> RequestStarsRevenueWithdrawalError 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 .starsRevenueWithdrawalUrl(url):
return url
}
}
}
}
|> mapError { _ -> RequestStarsRevenueWithdrawalError in }
|> switchToLatest
}

View File

@ -565,7 +565,7 @@ public struct StoryListContextState: Equatable {
public var isCached: Bool public var isCached: Bool
public var hasCache: Bool public var hasCache: Bool
public var allEntityFiles: [MediaId: TelegramMediaFile] public var allEntityFiles: [MediaId: TelegramMediaFile]
public var isLoading: Bool
public init( public init(
peerReference: PeerReference?, peerReference: PeerReference?,
items: [Item], items: [Item],
@ -574,7 +574,8 @@ public struct StoryListContextState: Equatable {
loadMoreToken: AnyHashable?, loadMoreToken: AnyHashable?,
isCached: Bool, isCached: Bool,
hasCache: Bool, hasCache: Bool,
allEntityFiles: [MediaId: TelegramMediaFile] allEntityFiles: [MediaId: TelegramMediaFile],
isLoading: Bool
) { ) {
self.peerReference = peerReference self.peerReference = peerReference
self.items = items self.items = items
@ -584,6 +585,7 @@ public struct StoryListContextState: Equatable {
self.isCached = isCached self.isCached = isCached
self.hasCache = hasCache self.hasCache = hasCache
self.allEntityFiles = allEntityFiles self.allEntityFiles = allEntityFiles
self.isLoading = isLoading
} }
} }
@ -625,7 +627,7 @@ public final class PeerStoryListContext: StoryListContext {
self.peerId = peerId self.peerId = peerId
self.isArchived = isArchived self.isArchived = isArchived
self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: AnyHashable(0 as Int), isCached: true, hasCache: false, allEntityFiles: [:]) self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: AnyHashable(0 as Int), isCached: true, hasCache: false, allEntityFiles: [:], isLoading: false)
let _ = (account.postbox.transaction { transaction -> (PeerReference?, [State.Item], [Int32], Int, [MediaId: TelegramMediaFile], Bool) in let _ = (account.postbox.transaction { transaction -> (PeerReference?, [State.Item], [Int32], Int, [MediaId: TelegramMediaFile], Bool) in
let key = ValueBoxKey(length: 8 + 1) let key = ValueBoxKey(length: 8 + 1)
@ -714,7 +716,7 @@ public final class PeerStoryListContext: StoryListContext {
return return
} }
var updatedState = State(peerReference: peerReference, items: items, pinnedIds: Set(pinnedIds), totalCount: totalCount, loadMoreToken: AnyHashable(0 as Int), isCached: true, hasCache: hasCache, allEntityFiles: allEntityFiles) var updatedState = State(peerReference: peerReference, items: items, pinnedIds: Set(pinnedIds), totalCount: totalCount, loadMoreToken: AnyHashable(0 as Int), isCached: true, hasCache: hasCache, allEntityFiles: allEntityFiles, isLoading: false)
updatedState.items.sort(by: { lhs, rhs in updatedState.items.sort(by: { lhs, rhs in
let lhsPinned = updatedState.pinnedIds.contains(lhs.storyItem.id) let lhsPinned = updatedState.pinnedIds.contains(lhs.storyItem.id)
let rhsPinned = updatedState.pinnedIds.contains(rhs.storyItem.id) let rhsPinned = updatedState.pinnedIds.contains(rhs.storyItem.id)
@ -1280,7 +1282,11 @@ public final class SearchStoryListContext: StoryListContext {
return self.statePromise.get() return self.statePromise.get()
} }
private var isLoadingMore: Bool = false private var isLoadingMore: Bool = false {
didSet {
self.stateValue.isLoading = isLoadingMore
}
}
private var requestDisposable: Disposable? private var requestDisposable: Disposable?
private var updatesDisposable: Disposable? private var updatesDisposable: Disposable?
@ -1292,7 +1298,7 @@ public final class SearchStoryListContext: StoryListContext {
self.account = account self.account = account
self.source = source self.source = source
self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: AnyHashable(""), isCached: false, hasCache: false, allEntityFiles: [:]) self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: AnyHashable(""), isCached: false, hasCache: false, allEntityFiles: [:], isLoading: false)
self.statePromise.set(.single(self.stateValue)) self.statePromise.set(.single(self.stateValue))
self.loadMore(completion: nil) self.loadMore(completion: nil)

View File

@ -59,6 +59,15 @@ public struct BotPaymentInvoice : Equatable {
public let prices: [BotPaymentPrice] public let prices: [BotPaymentPrice]
public let tip: Tip? public let tip: Tip?
public let termsInfo: RecurrentInfo? public let termsInfo: RecurrentInfo?
public init(isTest: Bool, requestedFields: BotPaymentInvoiceFields, currency: String, prices: [BotPaymentPrice], tip: Tip?, termsInfo: RecurrentInfo?) {
self.isTest = isTest
self.requestedFields = requestedFields
self.currency = currency
self.prices = prices
self.tip = tip
self.termsInfo = termsInfo
}
} }
public struct BotPaymentNativeProvider : Equatable { public struct BotPaymentNativeProvider : Equatable {
@ -125,6 +134,20 @@ public struct BotPaymentForm : Equatable {
public let savedInfo: BotPaymentRequestedInfo? public let savedInfo: BotPaymentRequestedInfo?
public let savedCredentials: [BotPaymentSavedCredentials] public let savedCredentials: [BotPaymentSavedCredentials]
public let additionalPaymentMethods: [BotPaymentMethod] public let additionalPaymentMethods: [BotPaymentMethod]
public init(id: Int64, canSaveCredentials: Bool, passwordMissing: Bool, invoice: BotPaymentInvoice, paymentBotId: PeerId, providerId: PeerId?, url: String?, nativeProvider: BotPaymentNativeProvider?, savedInfo: BotPaymentRequestedInfo?, savedCredentials: [BotPaymentSavedCredentials], additionalPaymentMethods: [BotPaymentMethod]) {
self.id = id
self.canSaveCredentials = canSaveCredentials
self.passwordMissing = passwordMissing
self.invoice = invoice
self.paymentBotId = paymentBotId
self.providerId = providerId
self.url = url
self.nativeProvider = nativeProvider
self.savedInfo = savedInfo
self.savedCredentials = savedCredentials
self.additionalPaymentMethods = additionalPaymentMethods
}
} }
public struct BotPaymentMethod: Equatable { public struct BotPaymentMethod: Equatable {

View File

@ -76,7 +76,7 @@ private enum RequestStarsStateError {
case generic case generic
} }
private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id, subject: StarsTransactionsContext.Subject, offset: String?) -> Signal<InternalStarsStatus, RequestStarsStateError> { private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id, mode: StarsTransactionsContext.Mode, offset: String?, limit: Int32) -> Signal<InternalStarsStatus, RequestStarsStateError> {
return account.postbox.transaction { transaction -> Peer? in return account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId) return transaction.getPeer(peerId)
} }
@ -89,7 +89,7 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
let signal: Signal<Api.payments.StarsStatus, MTRpcError> let signal: Signal<Api.payments.StarsStatus, MTRpcError>
if let offset { if let offset {
var flags: Int32 = 0 var flags: Int32 = 0
switch subject { switch mode {
case .incoming: case .incoming:
flags = 1 << 0 flags = 1 << 0
case .outgoing: case .outgoing:
@ -97,7 +97,7 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
default: default:
break break
} }
signal = account.network.request(Api.functions.payments.getStarsTransactions(flags: flags, peer: inputPeer, offset: offset)) signal = account.network.request(Api.functions.payments.getStarsTransactions(flags: flags, peer: inputPeer, offset: offset, limit: limit))
} else { } else {
signal = account.network.request(Api.functions.payments.getStarsStatus(peer: inputPeer)) signal = account.network.request(Api.functions.payments.getStarsStatus(peer: inputPeer))
} }
@ -177,7 +177,7 @@ private final class StarsContextImpl {
} }
self.previousLoadTimestamp = currentTimestamp self.previousLoadTimestamp = currentTimestamp
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, subject: .all, offset: nil) self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, mode: .all, offset: nil, limit: 5)
|> deliverOnMainQueue).start(next: { [weak self] status in |> deliverOnMainQueue).start(next: { [weak self] status in
guard let self else { guard let self else {
return return
@ -199,7 +199,7 @@ private final class StarsContextImpl {
return return
} }
var transactions = state.transactions var transactions = state.transactions
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil), at: 0) transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil), at: 0)
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: state.balance + balance, transactions: transactions, canLoadMore: state.canLoadMore, isLoading: state.isLoading)) self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: state.balance + balance, transactions: transactions, canLoadMore: state.canLoadMore, isLoading: state.isLoading))
} }
@ -220,7 +220,7 @@ private final class StarsContextImpl {
self._state?.isLoading = true self._state?.isLoading = true
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, subject: .all, offset: nextOffset) self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, mode: .all, offset: nextOffset, limit: 10)
|> deliverOnMainQueue).start(next: { [weak self] status in |> deliverOnMainQueue).start(next: { [weak self] status in
if let self { if let self {
self.updateState(StarsContext.State(flags: [], balance: status.balance, transactions: currentState.transactions + status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false)) self.updateState(StarsContext.State(flags: [], balance: status.balance, transactions: currentState.transactions + status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false))
@ -238,7 +238,7 @@ private final class StarsContextImpl {
private extension StarsContext.State.Transaction { private extension StarsContext.State.Transaction {
init?(apiTransaction: Api.StarsTransaction, transaction: Transaction) { init?(apiTransaction: Api.StarsTransaction, transaction: Transaction) {
switch apiTransaction { switch apiTransaction {
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo): case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl):
let parsedPeer: StarsContext.State.Transaction.Peer let parsedPeer: StarsContext.State.Transaction.Peer
switch transactionPeer { switch transactionPeer {
case .starsTransactionPeerAppStore: case .starsTransactionPeerAppStore:
@ -262,7 +262,7 @@ private extension StarsContext.State.Transaction {
if (apiFlags & (1 << 3)) != 0 { if (apiFlags & (1 << 3)) != 0 {
flags.insert(.isRefund) flags.insert(.isRefund)
} }
self.init(flags: flags, id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init)) self.init(flags: flags, id: id, count: stars, date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl)
} }
} }
} }
@ -279,6 +279,7 @@ public final class StarsContext {
public static let isRefund = Flags(rawValue: 1 << 0) public static let isRefund = Flags(rawValue: 1 << 0)
public static let isLocal = Flags(rawValue: 1 << 1) public static let isLocal = Flags(rawValue: 1 << 1)
public static let isPending = Flags(rawValue: 1 << 2)
} }
public enum Peer: Equatable { public enum Peer: Equatable {
@ -298,6 +299,8 @@ public final class StarsContext {
public let title: String? public let title: String?
public let description: String? public let description: String?
public let photo: TelegramMediaWebFile? public let photo: TelegramMediaWebFile?
public let transactionDate: Int32?
public let transactionUrl: String?
public init( public init(
flags: Flags, flags: Flags,
@ -307,7 +310,9 @@ public final class StarsContext {
peer: Peer, peer: Peer,
title: String?, title: String?,
description: String?, description: String?,
photo: TelegramMediaWebFile? photo: TelegramMediaWebFile?,
transactionDate: Int32?,
transactionUrl: String?
) { ) {
self.flags = flags self.flags = flags
self.id = id self.id = id
@ -317,6 +322,8 @@ public final class StarsContext {
self.title = title self.title = title
self.description = description self.description = description
self.photo = photo self.photo = photo
self.transactionDate = transactionDate
self.transactionUrl = transactionUrl
} }
} }
@ -430,7 +437,7 @@ private final class StarsTransactionsContextImpl {
private let account: Account private let account: Account
private weak var starsContext: StarsContext? private weak var starsContext: StarsContext?
private let peerId: EnginePeer.Id private let peerId: EnginePeer.Id
private let subject: StarsTransactionsContext.Subject private let mode: StarsTransactionsContext.Mode
private var _state: StarsTransactionsContext.State private var _state: StarsTransactionsContext.State
private let _statePromise = Promise<StarsTransactionsContext.State>() private let _statePromise = Promise<StarsTransactionsContext.State>()
@ -442,17 +449,22 @@ private final class StarsTransactionsContextImpl {
private let disposable = MetaDisposable() private let disposable = MetaDisposable()
private var stateDisposable: Disposable? private var stateDisposable: Disposable?
init(account: Account, starsContext: StarsContext, subject: StarsTransactionsContext.Subject) { init(account: Account, subject: StarsTransactionsContext.Subject, mode: StarsTransactionsContext.Mode) {
assert(Queue.mainQueue().isCurrent()) assert(Queue.mainQueue().isCurrent())
self.account = account self.account = account
self.starsContext = starsContext
self.peerId = starsContext.peerId
self.subject = subject
let currentTransactions = starsContext.currentState?.transactions ?? []
let initialTransactions: [StarsContext.State.Transaction]
switch subject { switch subject {
case let .starsContext(starsContext):
self.starsContext = starsContext
self.peerId = starsContext.peerId
case let .peer(peerId):
self.peerId = peerId
}
self.mode = mode
let currentTransactions = self.starsContext?.currentState?.transactions ?? []
let initialTransactions: [StarsContext.State.Transaction]
switch mode {
case .all: case .all:
initialTransactions = currentTransactions initialTransactions = currentTransactions
case .incoming: case .incoming:
@ -464,41 +476,43 @@ private final class StarsTransactionsContextImpl {
self._state = StarsTransactionsContext.State(transactions: initialTransactions, canLoadMore: true, isLoading: false) self._state = StarsTransactionsContext.State(transactions: initialTransactions, canLoadMore: true, isLoading: false)
self._statePromise.set(.single(self._state)) self._statePromise.set(.single(self._state))
self.stateDisposable = (starsContext.state if let starsContext = self.starsContext {
|> deliverOnMainQueue).start(next: { [weak self] state in self.stateDisposable = (starsContext.state
guard let self, let state else { |> deliverOnMainQueue).start(next: { [weak self] state in
return guard let self, let state else {
} return
let currentTransactions = state.transactions
let filteredTransactions: [StarsContext.State.Transaction]
switch subject {
case .all:
filteredTransactions = currentTransactions
case .incoming:
filteredTransactions = currentTransactions.filter { $0.count > 0 }
case .outgoing:
filteredTransactions = currentTransactions.filter { $0.count < 0 }
}
if filteredTransactions != initialTransactions {
var existingIds = Set<String>()
for transaction in self._state.transactions {
if !transaction.flags.contains(.isLocal) {
existingIds.insert(transaction.id)
}
} }
var updatedState = self._state let currentTransactions = state.transactions
updatedState.transactions.removeAll(where: { $0.flags.contains(.isLocal) }) let filteredTransactions: [StarsContext.State.Transaction]
for transaction in filteredTransactions.reversed() { switch mode {
if !existingIds.contains(transaction.id) { case .all:
updatedState.transactions.insert(transaction, at: 0) filteredTransactions = currentTransactions
} case .incoming:
filteredTransactions = currentTransactions.filter { $0.count > 0 }
case .outgoing:
filteredTransactions = currentTransactions.filter { $0.count < 0 }
} }
self.updateState(updatedState)
} if filteredTransactions != initialTransactions {
}) var existingIds = Set<String>()
for transaction in self._state.transactions {
if !transaction.flags.contains(.isLocal) {
existingIds.insert(transaction.id)
}
}
var updatedState = self._state
updatedState.transactions.removeAll(where: { $0.flags.contains(.isLocal) })
for transaction in filteredTransactions.reversed() {
if !existingIds.contains(transaction.id) {
updatedState.transactions.insert(transaction, at: 0)
}
}
self.updateState(updatedState)
}
})
}
} }
deinit { deinit {
@ -522,7 +536,7 @@ private final class StarsTransactionsContextImpl {
updatedState.isLoading = true updatedState.isLoading = true
self.updateState(updatedState) self.updateState(updatedState)
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, subject: self.subject, offset: nextOffset) self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, mode: self.mode, offset: nextOffset, limit: 10)
|> deliverOnMainQueue).start(next: { [weak self] status in |> deliverOnMainQueue).start(next: { [weak self] status in
guard let self else { guard let self else {
return return
@ -535,7 +549,7 @@ private final class StarsTransactionsContextImpl {
updatedState.canLoadMore = self.nextOffset != nil updatedState.canLoadMore = self.nextOffset != nil
self.updateState(updatedState) self.updateState(updatedState)
if case .all = self.subject, nextOffset.isEmpty { if case .all = self.mode, nextOffset.isEmpty {
self.starsContext?.updateBalance(status.balance, transactions: status.transactions) self.starsContext?.updateBalance(status.balance, transactions: status.transactions)
} else { } else {
self.starsContext?.updateBalance(status.balance, transactions: nil) self.starsContext?.updateBalance(status.balance, transactions: nil)
@ -565,6 +579,11 @@ public final class StarsTransactionsContext {
fileprivate let impl: QueueLocalObject<StarsTransactionsContextImpl> fileprivate let impl: QueueLocalObject<StarsTransactionsContextImpl>
public enum Subject { public enum Subject {
case starsContext(StarsContext)
case peer(EnginePeer.Id)
}
public enum Mode {
case all case all
case incoming case incoming
case outgoing case outgoing
@ -594,9 +613,9 @@ public final class StarsTransactionsContext {
} }
} }
init(account: Account, starsContext: StarsContext, subject: Subject) { init(account: Account, subject: Subject, mode: Mode) {
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: { self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
return StarsTransactionsContextImpl(account: account, starsContext: starsContext, subject: subject) return StarsTransactionsContextImpl(account: account, subject: subject, mode: mode)
}) })
} }
} }

View File

@ -75,8 +75,8 @@ public extension TelegramEngine {
} }
public func peerStarsTransactionsContext(starsContext: StarsContext, subject: StarsTransactionsContext.Subject) -> StarsTransactionsContext { public func peerStarsTransactionsContext(subject: StarsTransactionsContext.Subject, mode: StarsTransactionsContext.Mode) -> StarsTransactionsContext {
return StarsTransactionsContext(account: self.account, starsContext: starsContext, subject: subject) return StarsTransactionsContext(account: self.account, subject: subject, mode: mode)
} }
public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> { public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {

View File

@ -823,6 +823,14 @@ public extension TelegramEngine {
return _internal_requestChannelRevenueWithdrawalUrl(account: self.account, peerId: peerId, password: password) 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 getChatListPeers(filterPredicate: ChatListFilterPredicate) -> Signal<[EnginePeer], NoError> { public func getChatListPeers(filterPredicate: ChatListFilterPredicate) -> Signal<[EnginePeer], NoError> {
return self.account.postbox.transaction { transaction -> [EnginePeer] in return self.account.postbox.transaction { transaction -> [EnginePeer] in
return transaction.getChatListPeers(groupId: .root, filterPredicate: filterPredicate, additionalFilter: nil).map(EnginePeer.init) return transaction.getChatListPeers(groupId: .root, filterPredicate: filterPredicate, additionalFilter: nil).map(EnginePeer.init)

View File

@ -433,7 +433,7 @@ final class StarsStatisticsScreenComponent: Component {
if let current = self.allTransactionsContext { if let current = self.allTransactionsContext {
allTransactionsContext = current allTransactionsContext = current
} else { } else {
allTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .all) allTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(subject: .starsContext(component.starsContext), mode: .all)
} }
panelItems.append(StarsTransactionsPanelContainerComponent.Item( panelItems.append(StarsTransactionsPanelContainerComponent.Item(

View File

@ -554,21 +554,21 @@ final class StarsTransactionsScreenComponent: Component {
if let current = self.allTransactionsContext { if let current = self.allTransactionsContext {
allTransactionsContext = current allTransactionsContext = current
} else { } else {
allTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .all) allTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(subject: .starsContext(component.starsContext), mode: .all)
} }
let incomingTransactionsContext: StarsTransactionsContext let incomingTransactionsContext: StarsTransactionsContext
if let current = self.incomingTransactionsContext { if let current = self.incomingTransactionsContext {
incomingTransactionsContext = current incomingTransactionsContext = current
} else { } else {
incomingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .incoming) incomingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(subject: .starsContext(component.starsContext), mode: .incoming)
} }
let outgoingTransactionsContext: StarsTransactionsContext let outgoingTransactionsContext: StarsTransactionsContext
if let current = self.outgoingTransactionsContext { if let current = self.outgoingTransactionsContext {
outgoingTransactionsContext = current outgoingTransactionsContext = current
} else { } else {
outgoingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .outgoing) outgoingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(subject: .starsContext(component.starsContext), mode: .outgoing)
} }
panelItems.append(StarsTransactionsPanelContainerComponent.Item( panelItems.append(StarsTransactionsPanelContainerComponent.Item(