mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
API
This commit is contained in:
@@ -2264,5 +2264,30 @@ public extension TelegramEngine.EngineData.Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct StarRefProgram: TelegramEngineDataItem, PostboxViewDataItem {
|
||||
public typealias Result = TelegramStarRefProgram?
|
||||
|
||||
public let id: EnginePeer.Id
|
||||
|
||||
public init(id: EnginePeer.Id) {
|
||||
self.id = id
|
||||
}
|
||||
|
||||
var key: PostboxViewKey {
|
||||
return .cachedPeerData(peerId: self.id)
|
||||
}
|
||||
|
||||
func extract(view: PostboxView) -> Result {
|
||||
guard let view = view as? CachedPeerDataView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
if let cachedData = view.cachedPeerData as? CachedUserData {
|
||||
return cachedData.starRefProgram
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,3 +588,324 @@ func _internal_removeChatManagingBot(account: Account, chatId: EnginePeer.Id) ->
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_updateStarRefProgram(account: Account, id: EnginePeer.Id, program: (commissionPermille: Int32, durationMonths: Int32?)?) -> Signal<Never, NoError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
return transaction.getPeer(id).flatMap(apiInputUser)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<Never, NoError> in
|
||||
guard let inputPeer else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
//bots.updateStarRefProgram#549e034e flags:# bot:InputUser commission_permille:int duration_months:flags.0?int = Bool;
|
||||
var flags: Int32 = 0
|
||||
if let program, program.durationMonths != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.bots.updateStarRefProgram(
|
||||
flags: flags,
|
||||
bot: inputPeer,
|
||||
commissionPermille: program?.commissionPermille ?? 0,
|
||||
durationMonths: program?.durationMonths
|
||||
))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(.boolFalse)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||
if result != .boolTrue {
|
||||
return .complete()
|
||||
}
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
transaction.updatePeerCachedData(peerIds: Set([id]), update: { _, current in
|
||||
guard var current = current as? CachedUserData else {
|
||||
return current ?? CachedUserData()
|
||||
}
|
||||
if let program {
|
||||
current = current.withUpdatedStarRefProgram(TelegramStarRefProgram(
|
||||
commissionPermille: program.commissionPermille,
|
||||
durationMonths: program.durationMonths,
|
||||
endDate: nil
|
||||
))
|
||||
} else {
|
||||
if let currentProgram = current.starRefProgram {
|
||||
//TODO:localize
|
||||
let endDate = Int32(Date().timeIntervalSince1970) + (account.testingEnvironment ? 300 : 86400)
|
||||
current = current.withUpdatedStarRefProgram(TelegramStarRefProgram(
|
||||
commissionPermille: currentProgram.commissionPermille,
|
||||
durationMonths: currentProgram.durationMonths,
|
||||
endDate: endDate
|
||||
))
|
||||
}
|
||||
}
|
||||
return current
|
||||
})
|
||||
}
|
||||
|> ignoreValues
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class TelegramConnectedStarRefBotList {
|
||||
public final class Item: Equatable {
|
||||
public let peer: EnginePeer
|
||||
public let url: String
|
||||
public let timestamp: Int32
|
||||
public let commissionPermille: Int32
|
||||
public let durationMonths: Int32?
|
||||
public let participants: Int64
|
||||
public let revenue: Int64
|
||||
|
||||
public init(peer: EnginePeer, url: String, timestamp: Int32, commissionPermille: Int32, durationMonths: Int32?, participants: Int64, revenue: Int64) {
|
||||
self.peer = peer
|
||||
self.url = url
|
||||
self.timestamp = timestamp
|
||||
self.commissionPermille = commissionPermille
|
||||
self.durationMonths = durationMonths
|
||||
self.participants = participants
|
||||
self.revenue = revenue
|
||||
}
|
||||
|
||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
if lhs.peer != rhs.peer {
|
||||
return false
|
||||
}
|
||||
if lhs.url != rhs.url {
|
||||
return false
|
||||
}
|
||||
if lhs.timestamp != rhs.timestamp {
|
||||
return false
|
||||
}
|
||||
if lhs.commissionPermille != rhs.commissionPermille {
|
||||
return false
|
||||
}
|
||||
if lhs.durationMonths != rhs.durationMonths {
|
||||
return false
|
||||
}
|
||||
if lhs.participants != rhs.participants {
|
||||
return false
|
||||
}
|
||||
if lhs.revenue != rhs.revenue {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public let items: [Item]
|
||||
public let totalCount: Int
|
||||
|
||||
public init(items: [Item], totalCount: Int) {
|
||||
self.items = items
|
||||
self.totalCount = totalCount
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_requestConnectedStarRefBots(account: Account, id: EnginePeer.Id, offset: (timestamp: Int32, link: String)?, limit: Int) -> Signal<TelegramConnectedStarRefBotList?, NoError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(id).flatMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<TelegramConnectedStarRefBotList?, NoError> in
|
||||
guard let inputPeer else {
|
||||
return .single(nil)
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
if offset != nil {
|
||||
flags |= 1 << 2
|
||||
}
|
||||
return account.network.request(Api.functions.payments.getConnectedStarRefBots(
|
||||
flags: flags,
|
||||
peer: inputPeer,
|
||||
offsetDate: offset?.timestamp,
|
||||
offsetLink: offset?.link,
|
||||
limit: Int32(limit)
|
||||
))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.payments.ConnectedStarRefBots?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<TelegramConnectedStarRefBotList?, NoError> in
|
||||
guard let result else {
|
||||
return .single(nil)
|
||||
}
|
||||
return account.postbox.transaction { transaction -> TelegramConnectedStarRefBotList? in
|
||||
switch result {
|
||||
case let .connectedStarRefBots(count, connectedBots, users):
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
var items: [TelegramConnectedStarRefBotList.Item] = []
|
||||
for connectedBot in connectedBots {
|
||||
switch connectedBot {
|
||||
case let .connectedBotStarRef(_, url, date, botId, commissionPermille, durationMonths, participants, revenue):
|
||||
guard let botPeer = transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId))) else {
|
||||
continue
|
||||
}
|
||||
items.append(TelegramConnectedStarRefBotList.Item(
|
||||
peer: EnginePeer(botPeer),
|
||||
url: url,
|
||||
timestamp: date,
|
||||
commissionPermille: commissionPermille,
|
||||
durationMonths: durationMonths,
|
||||
participants: participants,
|
||||
revenue: revenue
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return TelegramConnectedStarRefBotList(items: items, totalCount: Int(count))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class TelegramSuggestedStarRefBotList {
|
||||
public final class Item: Equatable {
|
||||
public let peer: EnginePeer
|
||||
public let commissionPermille: Int32
|
||||
public let durationMonths: Int32?
|
||||
|
||||
public init(peer: EnginePeer, commissionPermille: Int32, durationMonths: Int32?) {
|
||||
self.peer = peer
|
||||
self.commissionPermille = commissionPermille
|
||||
self.durationMonths = durationMonths
|
||||
}
|
||||
|
||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
if lhs.peer != rhs.peer {
|
||||
return false
|
||||
}
|
||||
if lhs.commissionPermille != rhs.commissionPermille {
|
||||
return false
|
||||
}
|
||||
if lhs.durationMonths != rhs.durationMonths {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public let items: [Item]
|
||||
public let totalCount: Int
|
||||
public let nextOffset: String?
|
||||
|
||||
public init(items: [Item], totalCount: Int, nextOffset: String?) {
|
||||
self.items = items
|
||||
self.totalCount = totalCount
|
||||
self.nextOffset = nextOffset
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_requestSuggestedStarRefBots(account: Account, id: EnginePeer.Id, orderByCommission: Bool, offset: String?, limit: Int) -> Signal<TelegramSuggestedStarRefBotList?, NoError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(id).flatMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<TelegramSuggestedStarRefBotList?, NoError> in
|
||||
guard let inputPeer else {
|
||||
return .single(nil)
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
if orderByCommission {
|
||||
flags |= 1 << 2
|
||||
}
|
||||
return account.network.request(Api.functions.payments.getSuggestedStarRefBots(
|
||||
flags: flags,
|
||||
peer: inputPeer,
|
||||
offset: offset ?? "",
|
||||
limit: Int32(limit)
|
||||
))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.payments.SuggestedStarRefBots?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<TelegramSuggestedStarRefBotList?, NoError> in
|
||||
guard let result else {
|
||||
return .single(nil)
|
||||
}
|
||||
return account.postbox.transaction { transaction -> TelegramSuggestedStarRefBotList? in
|
||||
switch result {
|
||||
case let .suggestedStarRefBots(_, count, suggestedBots, users, nextOffset):
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
var items: [TelegramSuggestedStarRefBotList.Item] = []
|
||||
for suggestedBot in suggestedBots {
|
||||
switch suggestedBot {
|
||||
case let .suggestedBotStarRef(_, botId, commissionPermille, durationMonths):
|
||||
guard let botPeer = transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId))) else {
|
||||
continue
|
||||
}
|
||||
items.append(TelegramSuggestedStarRefBotList.Item(
|
||||
peer: EnginePeer(botPeer),
|
||||
commissionPermille: commissionPermille,
|
||||
durationMonths: durationMonths
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return TelegramSuggestedStarRefBotList(items: items, totalCount: Int(count), nextOffset: nextOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ConnectStarRefBotError {
|
||||
case generic
|
||||
}
|
||||
|
||||
func _internal_connectStarRefBot(account: Account, id: EnginePeer.Id, botId: EnginePeer.Id) -> Signal<TelegramConnectedStarRefBotList.Item, ConnectStarRefBotError> {
|
||||
return account.postbox.transaction { transaction -> (Api.InputPeer?, Api.InputUser?) in
|
||||
return (
|
||||
transaction.getPeer(id).flatMap(apiInputPeer),
|
||||
transaction.getPeer(botId).flatMap(apiInputUser)
|
||||
)
|
||||
}
|
||||
|> castError(ConnectStarRefBotError.self)
|
||||
|> mapToSignal { inputPeer, inputBotUser -> Signal<TelegramConnectedStarRefBotList.Item, ConnectStarRefBotError> in
|
||||
guard let inputPeer, let inputBotUser else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
return account.network.request(Api.functions.payments.connectStarRefBot(peer: inputPeer, bot: inputBotUser))
|
||||
|> mapError { _ -> ConnectStarRefBotError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<TelegramConnectedStarRefBotList.Item, ConnectStarRefBotError> in
|
||||
return account.postbox.transaction { transaction -> TelegramConnectedStarRefBotList.Item? in
|
||||
switch result {
|
||||
case let .connectedStarRefBots(_, connectedBots, users):
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: AccumulatedPeers(users: users))
|
||||
|
||||
if let bot = connectedBots.first {
|
||||
switch bot {
|
||||
case let .connectedBotStarRef(_, url, date, botId, commissionPermille, durationMonths, participants, revenue):
|
||||
guard let botPeer = transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId))) else {
|
||||
return nil
|
||||
}
|
||||
return TelegramConnectedStarRefBotList.Item(
|
||||
peer: EnginePeer(botPeer),
|
||||
url: url,
|
||||
timestamp: date,
|
||||
commissionPermille: commissionPermille,
|
||||
durationMonths: durationMonths,
|
||||
participants: participants,
|
||||
revenue: revenue
|
||||
)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|> castError(ConnectStarRefBotError.self)
|
||||
|> mapToSignal { item -> Signal<TelegramConnectedStarRefBotList.Item, ConnectStarRefBotError> in
|
||||
if let item {
|
||||
return .single(item)
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +317,8 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
|
||||
|> mapToSignal { result -> Signal<InternalStarsStatus, RequestStarsStateError> in
|
||||
return account.postbox.transaction { transaction -> InternalStarsStatus in
|
||||
switch result {
|
||||
case let .starsStatus(_, balance, _, _, subscriptionsMissingBalance, transactions, nextTransactionsOffset, chats, users):
|
||||
case let .starsStatus(flags: _, balance, balanceNanos, _, _, subscriptionsMissingBalance, transactions, nextTransactionsOffset, chats, users):
|
||||
let _ = balanceNanos
|
||||
let peers = AccumulatedPeers(chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers)
|
||||
|
||||
@@ -367,7 +368,8 @@ private func _internal_requestStarsSubscriptions(account: Account, peerId: Engin
|
||||
|> mapToSignal { result -> Signal<InternalStarsStatus, RequestStarsSubscriptionsError> in
|
||||
return account.postbox.transaction { transaction -> InternalStarsStatus in
|
||||
switch result {
|
||||
case let .starsStatus(_, balance, subscriptions, subscriptionsNextOffset, subscriptionsMissingBalance, _, _, chats, users):
|
||||
case let .starsStatus(_, balance, balanceNanos, subscriptions, subscriptionsNextOffset, subscriptionsMissingBalance, _, _, chats, users):
|
||||
let _ = balanceNanos
|
||||
let peers = AccumulatedPeers(chats: chats, users: users)
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers)
|
||||
|
||||
@@ -490,7 +492,8 @@ private final class StarsContextImpl {
|
||||
private extension StarsContext.State.Transaction {
|
||||
init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) {
|
||||
switch apiTransaction {
|
||||
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod, giveawayPostId, starGift, floodskipNumber):
|
||||
case let .starsTransaction(apiFlags, id, stars, starNanos, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod, giveawayPostId, starGift, floodskipNumber):
|
||||
let _ = starNanos
|
||||
let parsedPeer: StarsContext.State.Transaction.Peer
|
||||
var paidMessageId: MessageId?
|
||||
var giveawayMessageId: MessageId?
|
||||
@@ -1446,7 +1449,7 @@ func _internal_getStarsTransaction(accountPeerId: PeerId, postbox: Postbox, netw
|
||||
}
|
||||
|> mapToSignal { result -> Signal<StarsContext.State.Transaction?, NoError> in
|
||||
return postbox.transaction { transaction -> StarsContext.State.Transaction? in
|
||||
guard let result, case let .starsStatus(_, _, _, _, _, transactions, _, chats, users) = result, let matchingTransaction = transactions?.first else {
|
||||
guard let result, case let .starsStatus(_, _, _, _, _, _, transactions, _, chats, users) = result, let matchingTransaction = transactions?.first else {
|
||||
return nil
|
||||
}
|
||||
let peers = AccumulatedPeers(chats: chats, users: users)
|
||||
|
||||
@@ -41,7 +41,7 @@ func _internal_resolvePeerByName(account: Account, name: String, ageLimit: Int32
|
||||
return .single(.result(cachedEntry.peerId))
|
||||
} else {
|
||||
return .single(.progress)
|
||||
|> then(account.network.request(Api.functions.contacts.resolveUsername(username: normalizedName))
|
||||
|> then(account.network.request(Api.functions.contacts.resolveUsername(flags: 0, username: normalizedName, referer: nil))
|
||||
|> mapError { _ -> Void in
|
||||
return Void()
|
||||
}
|
||||
|
||||
@@ -1632,6 +1632,22 @@ public extension TelegramEngine {
|
||||
_internal_setStarsReactionDefaultToPrivate(isPrivate: isPrivate, transaction: transaction)
|
||||
}).startStandalone()
|
||||
}
|
||||
|
||||
public func updateStarRefProgram(id: EnginePeer.Id, program: (commissionPermille: Int32, durationMonths: Int32?)?) -> Signal<Never, NoError> {
|
||||
return _internal_updateStarRefProgram(account: self.account, id: id, program: program)
|
||||
}
|
||||
|
||||
public func requestConnectedStarRefBots(id: EnginePeer.Id, offset: (timestamp: Int32, link: String)?, limit: Int) -> Signal<TelegramConnectedStarRefBotList?, NoError> {
|
||||
return _internal_requestConnectedStarRefBots(account: self.account, id: id, offset: offset, limit: limit)
|
||||
}
|
||||
|
||||
public func requestSuggestedStarRefBots(id: EnginePeer.Id, orderByCommission: Bool, offset: String?, limit: Int) -> Signal<TelegramSuggestedStarRefBotList?, NoError> {
|
||||
return _internal_requestSuggestedStarRefBots(account: self.account, id: id, orderByCommission: orderByCommission, offset: offset, limit: limit)
|
||||
}
|
||||
|
||||
public func connectStarRefBot(id: EnginePeer.Id, botId: EnginePeer.Id) -> Signal<TelegramConnectedStarRefBotList.Item, ConnectStarRefBotError> {
|
||||
return _internal_connectStarRefBot(account: self.account, id: id, botId: botId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
}
|
||||
|
||||
switch fullUser {
|
||||
case let .userFull(_, _, _, _, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .userFull(_, _, _, _, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
|
||||
transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: userFullNotifySettings)])
|
||||
}
|
||||
@@ -270,7 +270,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
previous = CachedUserData()
|
||||
}
|
||||
switch fullUser {
|
||||
case let .userFull(userFullFlags, userFullFlags2, _, userFullAbout, userFullSettings, personalPhoto, profilePhoto, fallbackPhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, userPremiumGiftOptions, userWallpaper, stories, businessWorkHours, businessLocation, greetingMessage, awayMessage, businessIntro, birthday, personalChannelId, personalChannelMessage, starGiftsCount):
|
||||
case let .userFull(userFullFlags, userFullFlags2, _, userFullAbout, userFullSettings, personalPhoto, profilePhoto, fallbackPhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, userPremiumGiftOptions, userWallpaper, stories, businessWorkHours, businessLocation, greetingMessage, awayMessage, businessIntro, birthday, personalChannelId, personalChannelMessage, starGiftsCount, starRefProgram):
|
||||
let _ = stories
|
||||
let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:))
|
||||
let isBlocked = (userFullFlags & (1 << 0)) != 0
|
||||
@@ -396,6 +396,11 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
)
|
||||
}
|
||||
|
||||
var mappedStarRefProgram: TelegramStarRefProgram?
|
||||
if let starRefProgram {
|
||||
mappedStarRefProgram = TelegramStarRefProgram(apiStarRefProgram: starRefProgram)
|
||||
}
|
||||
|
||||
return previous.withUpdatedAbout(userFullAbout)
|
||||
.withUpdatedBotInfo(botInfo)
|
||||
.withUpdatedEditableBotInfo(editableBotInfo)
|
||||
@@ -427,6 +432,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
.withUpdatedPersonalChannel(personalChannel)
|
||||
.withUpdatedBotPreview(botPreview)
|
||||
.withUpdatedStarGiftsCount(starGiftsCount)
|
||||
.withUpdatedStarRefProgram(mappedStarRefProgram)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user