mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-06-20 18:24:43 +00:00
120 lines
5.4 KiB
Swift
120 lines
5.4 KiB
Swift
import Foundation
|
|
import Postbox
|
|
import TelegramApi
|
|
import SwiftSignalKit
|
|
import MtProtoKit
|
|
|
|
|
|
public enum JoinChannelError {
|
|
case generic
|
|
case tooMuchJoined
|
|
case tooMuchUsers
|
|
case inviteRequestSent
|
|
}
|
|
|
|
public enum JoinChannelResult {
|
|
case joined(RenderedChannelParticipant?)
|
|
case webView(JoinChatWebView)
|
|
}
|
|
|
|
func _internal_joinChannel(account: Account, peerId: PeerId, hash: String?) -> Signal<JoinChannelResult, JoinChannelError> {
|
|
return account.postbox.loadedPeerWithId(peerId)
|
|
|> take(1)
|
|
|> castError(JoinChannelError.self)
|
|
|> mapToSignal { peer -> Signal<JoinChannelResult, JoinChannelError> in
|
|
let request: Signal<Api.messages.ChatInviteJoinResult, MTRpcError>
|
|
if let hash = hash {
|
|
request = account.network.request(Api.functions.messages.importChatInvite(hash: hash))
|
|
} else if let inputChannel = apiInputChannel(peer) {
|
|
request = account.network.request(Api.functions.channels.joinChannel(channel: inputChannel))
|
|
} else {
|
|
request = .fail(.init())
|
|
}
|
|
|
|
return request
|
|
|> mapError { error -> JoinChannelError in
|
|
switch error.errorDescription {
|
|
case "CHANNELS_TOO_MUCH":
|
|
return .tooMuchJoined
|
|
case "USERS_TOO_MUCH":
|
|
return .tooMuchUsers
|
|
case "INVITE_REQUEST_SENT":
|
|
return .inviteRequestSent
|
|
default:
|
|
return .generic
|
|
}
|
|
}
|
|
|> mapToSignal { result -> Signal<JoinChannelResult, JoinChannelError> in
|
|
let updates: Api.Updates
|
|
switch result {
|
|
case let .chatInviteJoinResultOk(data):
|
|
updates = data.updates
|
|
case let .chatInviteJoinResultWebView(data):
|
|
switch data.webview {
|
|
case let .webViewResultUrl(urlData):
|
|
let botPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(data.botId))
|
|
return account.postbox.transaction { transaction -> Signal<JoinChannelResult, JoinChannelError> in
|
|
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: AccumulatedPeers(users: data.users))
|
|
guard let botPeer = transaction.getPeer(botPeerId) else {
|
|
return .fail(.generic)
|
|
}
|
|
return .single(.webView(JoinChatWebView(botPeer: EnginePeer(botPeer), url: urlData.url, queryId: urlData.queryId ?? 0, peerId: peerId)))
|
|
}
|
|
|> castError(JoinChannelError.self)
|
|
|> switchToLatest
|
|
}
|
|
}
|
|
|
|
account.stateManager.addUpdates(updates)
|
|
if hash == nil {
|
|
let _ = _internal_requestRecommendedChannels(account: account, peerId: peerId, forceUpdate: true).startStandalone()
|
|
}
|
|
|
|
let channels = updates.chats.compactMap { parseTelegramGroupOrChannel(chat: $0) }.compactMap(apiInputChannel)
|
|
|
|
if let inputChannel = channels.first {
|
|
return account.network.request(Api.functions.channels.getParticipant(channel: inputChannel, participant: .inputPeerSelf))
|
|
|> map(Optional.init)
|
|
|> `catch` { _ -> Signal<Api.channels.ChannelParticipant?, JoinChannelError> in
|
|
return .single(nil)
|
|
}
|
|
|> mapToSignal { result -> Signal<JoinChannelResult, JoinChannelError> in
|
|
guard let result = result else {
|
|
return .fail(.generic)
|
|
}
|
|
return account.postbox.transaction { transaction -> JoinChannelResult in
|
|
var peers: [EnginePeer.Id: EnginePeer] = [:]
|
|
var presences: [PeerId: PeerPresence] = [:]
|
|
guard let peer = transaction.getPeer(account.peerId) else {
|
|
return .joined(nil)
|
|
}
|
|
peers[account.peerId] = EnginePeer(peer)
|
|
if let presence = transaction.getPeerPresence(peerId: account.peerId) {
|
|
presences[account.peerId] = presence
|
|
}
|
|
let updatedParticipant: ChannelParticipant
|
|
switch result {
|
|
case let .channelParticipant(channelParticipantData):
|
|
let participant = channelParticipantData.participant
|
|
updatedParticipant = ChannelParticipant(apiParticipant: participant)
|
|
}
|
|
if case let .member(_, _, maybeAdminInfo, _, _, _) = updatedParticipant {
|
|
if let adminInfo = maybeAdminInfo {
|
|
if let peer = transaction.getPeer(adminInfo.promotedBy) {
|
|
peers[peer.id] = EnginePeer(peer)
|
|
}
|
|
}
|
|
}
|
|
|
|
return .joined(RenderedChannelParticipant(participant: updatedParticipant, peer: EnginePeer(peer), peers: peers, presences: presences))
|
|
}
|
|
|> castError(JoinChannelError.self)
|
|
}
|
|
} else {
|
|
return .fail(.generic)
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|