Game link support

This commit is contained in:
Ilya Laktyushin 2026-04-27 16:57:23 +02:00
parent e97422e333
commit 7fdc1ea1d2
3 changed files with 52 additions and 5 deletions

View file

@ -3,6 +3,38 @@ import Postbox
import TelegramApi
import SwiftSignalKit
public enum SendBotGameError {
case generic
}
func _internal_sendBotGame(account: Account, botPeerId: PeerId, game: String, to peerId: PeerId, threadId: Int64?) -> Signal<Void, SendBotGameError> {
return account.postbox.transaction { transaction -> Signal<Void, SendBotGameError> in
guard !game.isEmpty, let botPeer = transaction.getPeer(botPeerId), let inputBot = apiInputUser(botPeer), let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
var flags: Int32 = 1 << 7
var replyTo: Api.InputReplyTo?
if let threadId {
flags |= 1 << 0
let threadMessageId = Int32(clamping: threadId)
let replyFlags: Int32 = 1 << 0
replyTo = .inputReplyToMessage(.init(flags: replyFlags, replyToMsgId: threadMessageId, topMsgId: threadMessageId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil, pollOption: nil))
}
return account.network.request(Api.functions.messages.sendMedia(flags: flags, peer: inputPeer, replyTo: replyTo, media: .inputMediaGame(.init(id: .inputGameShortName(.init(botId: inputBot, shortName: game)))), message: "", randomId: Int64.random(in: Int64.min ... Int64.max), replyMarkup: nil, entities: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, sendAs: nil, quickReplyShortcut: nil, effect: nil, allowPaidStars: nil, suggestedPost: nil))
|> mapError { _ -> SendBotGameError in
return .generic
}
|> mapToSignal { updates -> Signal<Void, SendBotGameError> in
account.stateManager.addUpdates(updates)
return .complete()
}
}
|> castError(SendBotGameError.self)
|> switchToLatest
}
func _internal_forwardGameWithScore(account: Account, messageId: MessageId, to peerId: PeerId, threadId: Int64?, as sendAsPeerId: PeerId?) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let _ = transaction.getMessage(messageId), let fromPeer = transaction.getPeer(messageId.peerId), let fromInputPeer = apiInputPeer(fromPeer), let toPeer = transaction.getPeer(peerId), let toInputPeer = apiInputPeer(toPeer) {

View file

@ -219,6 +219,10 @@ public extension TelegramEngine {
return _internal_forwardGameWithScore(account: self.account, messageId: messageId, to: peerId, threadId: threadId, as: senderPeerId)
}
public func sendBotGame(botPeerId: PeerId, game: String, to peerId: PeerId, threadId: Int64?) -> Signal<Void, SendBotGameError> {
return _internal_sendBotGame(account: self.account, botPeerId: botPeerId, game: game, to: peerId, threadId: threadId)
}
public func requestUpdatePinnedMessage(peerId: PeerId, update: PinnedMessageUpdate) -> Signal<Void, UpdatePinnedMessageError> {
return _internal_requestUpdatePinnedMessage(account: self.account, peerId: peerId, update: update)
}

View file

@ -307,11 +307,8 @@ func openResolvedUrlImpl(
dismissInput()
navigationController?.pushViewController(controller)
case let .gameStart(botPeerId, game):
let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyManageable, .excludeDisabled, .excludeRecent, .doNotSearchMessages], hasContactSelector: false, title: presentationData.strings.Bot_AddToChat_Title, selectForumThreads: true))
controller.peerSelected = { [weak controller] peer, _ in
let _ = peer.id
let _ = botPeerId
let _ = game
let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyWriteable, .excludeDisabled, .doNotSearchMessages], hasContactSelector: false, title: presentationData.strings.ShareMenu_SelectChats, selectForumThreads: true))
controller.peerSelected = { [weak controller] peer, threadId in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let text: String
if case .user = peer {
@ -321,6 +318,20 @@ func openResolvedUrlImpl(
}
let alertController = textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.RequestPeer_SelectionConfirmationSend, action: {
controller?.inProgress = true
let _ = (context.engine.messages.sendBotGame(botPeerId: botPeerId, game: game, to: peer.id, threadId: threadId)
|> deliverOnMainQueue).startStandalone(error: { _ in
controller?.inProgress = false
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
present(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
})
if let navigationController {
if let threadId {
let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: true, keepStack: .always, animated: true).startStandalone()
} else {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always, useExisting: true, scrollToEndIfExists: true))
}
}
controller?.dismiss()
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
})])