chore: migrate to new version + fixed several critical bugs

- Migrated project to latest Telegram iOS base (v12.3.2+)
- Fixed circular dependency between GhostModeManager and MiscSettingsManager
- Fixed multiple Bazel build configuration errors (select() default conditions)
- Fixed duplicate type definitions in PeerInfoScreen
- Fixed swiftmodule directory resolution in build scripts
- Added Ghostgram Settings tab in main Settings menu with all 5 features
- Cleared sensitive credentials from config.json (template-only now)
- Excluded bazel-cache from version control
This commit is contained in:
ichmagmaus 812
2026-02-23 23:04:32 +01:00
parent 703e291bcb
commit db53826061
1017 changed files with 62337 additions and 40559 deletions
@@ -571,5 +571,26 @@ public extension TelegramEngine.EngineData.Item {
return value
}
}
public struct EmojiGame: TelegramEngineDataItem, PostboxViewDataItem {
public typealias Result = EmojiGameInfo
public init() {
}
var key: PostboxViewKey {
return .preferences(keys: Set([PreferencesKeys.emojiGameInfo()]))
}
func extract(view: PostboxView) -> Result {
guard let view = view as? PreferencesView else {
preconditionFailure()
}
guard let emojiGameInfo = view.values[PreferencesKeys.emojiGameInfo()]?.get(EmojiGameInfo.self) else {
return .unavailable
}
return emojiGameInfo
}
}
}
}
@@ -482,6 +482,12 @@ private class AdMessagesHistoryContextImpl {
}
self.isActivated = true
// MISC: Block ads if setting enabled
if MiscSettingsManager.shared.shouldBlockAds {
self.stateValue = State(interPostInterval: nil, startDelay: nil, betweenDelay: nil, messages: [])
return
}
let peerId = self.peerId
let accountPeerId = self.account.peerId
let account = self.account
@@ -64,7 +64,10 @@ func _internal_applyMaxReadIndexInteractively(transaction: Transaction, stateMan
}
}
} else if index.id.peerId.namespace == Namespaces.Peer.CloudUser || index.id.peerId.namespace == Namespaces.Peer.CloudGroup || index.id.peerId.namespace == Namespaces.Peer.CloudChannel {
stateManager.notifyAppliedIncomingReadMessages([index.id])
// GHOST MODE: Don't send read receipts (blue checkmarks)
if !GhostModeManager.shared.shouldHideReadReceipts {
stateManager.notifyAppliedIncomingReadMessages([index.id])
}
}
}
@@ -51,6 +51,11 @@ func _internal_markMessageContentAsConsumedInteractively(postbox: Postbox, messa
for i in 0 ..< updatedAttributes.count {
if let attribute = updatedAttributes[i] as? AutoremoveTimeoutMessageAttribute {
if attribute.countdownBeginTime == nil || attribute.countdownBeginTime == 0 {
// MISC: Don't start countdown for view-once if bypass enabled
if attribute.timeout == viewOnceTimeout && MiscSettingsManager.shared.shouldDisableViewOnceAutoDelete {
continue
}
var timeout = attribute.timeout
if let duration = message.secretMediaDuration {
timeout = max(timeout, Int32(duration))
@@ -194,7 +199,9 @@ func markMessageContentAsConsumedRemotely(transaction: Transaction, messageId: M
if message.id.peerId.namespace == Namespaces.Peer.SecretChat {
} else {
if attribute.timeout == viewOnceTimeout || timestamp >= countdownBeginTime + attribute.timeout {
// MISC: Don't expire view-once media if bypass enabled
let shouldExpire = !(attribute.timeout == viewOnceTimeout && MiscSettingsManager.shared.shouldDisableViewOnceAutoDelete)
if shouldExpire && (attribute.timeout == viewOnceTimeout || timestamp >= countdownBeginTime + attribute.timeout) {
for i in 0 ..< updatedMedia.count {
if let _ = updatedMedia[i] as? TelegramMediaImage {
updatedMedia[i] = TelegramMediaExpiredContent(data: .image)
@@ -0,0 +1,83 @@
import Foundation
import Postbox
import SwiftSignalKit
import TelegramApi
import MtProtoKit
public enum SummarizeError {
case generic
case invalidMessageId
case limitExceeded
case invalidLanguage
case limitExceededPremium
}
func _internal_summarizeMessage(account: Account, messageId: EngineMessage.Id, translateToLang: String?) -> Signal<Never, SummarizeError> {
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer)
}
|> castError(SummarizeError.self)
|> mapToSignal { inputPeer -> Signal<Never, SummarizeError> in
guard let inputPeer else {
return .never()
}
var flags: Int32 = 0
if let _ = translateToLang {
flags |= (1 << 0)
}
return account.network.request(Api.functions.messages.summarizeText(flags: flags, peer: inputPeer, id: messageId.id, toLang: translateToLang))
|> map(Optional.init)
|> mapError { error -> SummarizeError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else if error.errorDescription == "MSG_ID_INVALID" {
return .invalidMessageId
} else if error.errorDescription == "TO_LANG_INVALID" {
return .invalidLanguage
} else if error.errorDescription == "SUMMARY_FLOOD_PREMIUM" {
return .limitExceededPremium
} else {
return .generic
}
}
|> mapToSignal { result -> Signal<Void, SummarizeError> in
return account.postbox.transaction { transaction in
switch result {
case let .textWithEntities(text, entities):
transaction.updateMessage(messageId, update: { currentMessage in
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
var attributes = currentMessage.attributes
let currentAttribute = attributes.first(where: { $0 is SummarizationMessageAttribute }) as? SummarizationMessageAttribute
let updatedAttribute: SummarizationMessageAttribute
if let translateToLang {
var translated = currentAttribute?.translated ?? [:]
translated[translateToLang] = SummarizationMessageAttribute.Summary(text: text, entities: messageTextEntitiesFromApiEntities(entities))
updatedAttribute = SummarizationMessageAttribute(
fromLang: currentAttribute?.fromLang ?? "",
summary: currentAttribute?.summary,
translated: translated
)
} else {
updatedAttribute = SummarizationMessageAttribute(
fromLang: currentAttribute?.fromLang ?? "",
summary: .init(text: text, entities: messageTextEntitiesFromApiEntities(entities)),
translated: currentAttribute?.translated ?? [:]
)
}
attributes = attributes.filter { !($0 is SummarizationMessageAttribute) }
attributes.append(updatedAttribute)
return .update(StoreMessage(id: currentMessage.id, customStableId: nil, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
})
default:
break
}
}
|> castError(SummarizeError.self)
}
|> ignoreValues
}
}
@@ -604,6 +604,10 @@ public extension TelegramEngine {
return _internal_togglePeerMessagesTranslationHidden(account: self.account, peerId: peerId, hidden: hidden)
}
public func summarizeMessage(messageId: EngineMessage.Id, translateToLang: String?) -> Signal<Never, SummarizeError> {
return _internal_summarizeMessage(account: self.account, messageId: messageId, translateToLang: translateToLang)
}
public func transcribeAudio(messageId: MessageId) -> Signal<EngineAudioTranscriptionResult, NoError> {
return _internal_transcribeAudio(postbox: self.account.postbox, network: self.account.network, messageId: messageId)
}
@@ -1578,7 +1578,8 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: Star
prepaidUpgradeHash: nil,
upgradeSeparate: false,
dropOriginalDetailsStars: dropOriginalDetailsStars,
number: nil
number: nil,
isRefunded: false
))
}
}
@@ -2533,6 +2534,7 @@ public final class ProfileGiftsContext {
case upgradeSeparate
case dropOriginalDetailsStars
case number
case isRefunded
}
public let gift: TelegramCore.StarGift
@@ -2556,7 +2558,8 @@ public final class ProfileGiftsContext {
public let upgradeSeparate: Bool
public let dropOriginalDetailsStars: Int64?
public let number: Int32?
public let isRefunded: Bool
fileprivate let _fromPeerId: EnginePeer.Id?
public enum DecodingError: Error {
@@ -2584,7 +2587,8 @@ public final class ProfileGiftsContext {
prepaidUpgradeHash: String?,
upgradeSeparate: Bool,
dropOriginalDetailsStars: Int64?,
number: Int32?
number: Int32?,
isRefunded: Bool
) {
self.gift = gift
self.reference = reference
@@ -2608,6 +2612,7 @@ public final class ProfileGiftsContext {
self.upgradeSeparate = upgradeSeparate
self.dropOriginalDetailsStars = dropOriginalDetailsStars
self.number = number
self.isRefunded = isRefunded
}
public init(from decoder: Decoder) throws {
@@ -2641,6 +2646,7 @@ public final class ProfileGiftsContext {
self.upgradeSeparate = try container.decodeIfPresent(Bool.self, forKey: .upgradeSeparate) ?? false
self.dropOriginalDetailsStars = try container.decodeIfPresent(Int64.self, forKey: .dropOriginalDetailsStars)
self.number = try container.decodeIfPresent(Int32.self, forKey: .number)
self.isRefunded = try container.decodeIfPresent(Bool.self, forKey: .isRefunded) ?? false
}
public func encode(to encoder: Encoder) throws {
@@ -2667,6 +2673,8 @@ public final class ProfileGiftsContext {
try container.encode(self.upgradeSeparate, forKey: .upgradeSeparate)
try container.encodeIfPresent(self.dropOriginalDetailsStars, forKey: .dropOriginalDetailsStars)
try container.encodeIfPresent(self.number, forKey: .number)
try container.encode(self.isRefunded, forKey: .isRefunded)
}
public func withGift(_ gift: TelegramCore.StarGift) -> StarGift {
@@ -2691,7 +2699,8 @@ public final class ProfileGiftsContext {
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
number: self.number,
isRefunded: self.isRefunded
)
}
@@ -2717,7 +2726,8 @@ public final class ProfileGiftsContext {
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
number: self.number,
isRefunded: self.isRefunded
)
}
@@ -2743,7 +2753,8 @@ public final class ProfileGiftsContext {
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
number: self.number,
isRefunded: self.isRefunded
)
}
fileprivate func withFromPeer(_ fromPeer: EnginePeer?) -> StarGift {
@@ -2768,7 +2779,8 @@ public final class ProfileGiftsContext {
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
number: self.number,
isRefunded: self.isRefunded
)
}
@@ -2794,7 +2806,8 @@ public final class ProfileGiftsContext {
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
number: self.number,
isRefunded: self.isRefunded
)
}
}
@@ -3063,6 +3076,7 @@ extension ProfileGiftsContext.State.StarGift {
self.upgradeSeparate = (flags & (1 << 17)) != 0
self.dropOriginalDetailsStars = dropOriginalDetailsStars
self.number = number
self.isRefunded = (flags & (1 << 9)) != 0
}
}
}
@@ -580,7 +580,7 @@ public class GiftAuctionsManager {
}
public extension GiftAuctionContext.State {
func getPlace(myBid: Int64?, myBidDate: Int32?) -> Int32? {
func getPlace(myBid: Int64?, myBidDate: Int32?) -> (place: Int32, isApproximate: Bool)? {
guard case let .ongoing(_, _, _, _, bidLevels, _, _, _, _, _, _, _) = self.auctionState else {
return nil
}
@@ -592,7 +592,7 @@ public extension GiftAuctionContext.State {
let levels = bidLevels
guard !levels.isEmpty else {
return 1
return (1, false)
}
func isWorse(than level: GiftAuctionContext.State.BidLevel) -> Bool {
@@ -614,7 +614,7 @@ public extension GiftAuctionContext.State {
}
}
if lowerIndex == -1 {
return 1
return (1, false)
}
let lowerPosition = levels[lowerIndex].position
@@ -626,14 +626,14 @@ public extension GiftAuctionContext.State {
nextPosition = lowerPosition
}
if nextPosition == lowerPosition + 1 {
return lowerPosition + 1
return (lowerPosition + 1, false)
} else {
return nextPosition
return (lowerPosition, true)
}
}
var place: Int32? {
return self.getPlace(myBid: nil, myBidDate: nil)
return self.getPlace(myBid: nil, myBidDate: nil)?.place
}
var startDate: Int32 {
@@ -1644,7 +1644,7 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer, .premiumGift, .starGiftResale, .starGiftPrepaidUpgrade, .starGiftDropOriginalDetails, .starGiftAuctionBid:
receiptMessageId = nil
}
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _, _) = action.action, case let .Id(messageId) = message.id {
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, isRefunded, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _, _) = action.action, case let .Id(messageId) = message.id {
let reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)
@@ -1672,7 +1672,8 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
prepaidUpgradeHash: nil,
upgradeSeparate: false,
dropOriginalDetailsStars: dropOriginalDetailsStars,
number: nil
number: nil,
isRefunded: isRefunded
)
}
}