Idealisan

Telegram macOS 复制/保存内容限制机制分析

数据来源:服务端标记

限制信息通过 MTProto 协议同步到客户端,分为两个层面:

1. 消息级标记 CopyProtected

  • 定义MessageFlags.CopyProtected = MessageFlags(rawValue: 512) (bit 512)
    • submodules/Postbox/Sources/Message.swift:495
    • submodules/Postbox/Sources/Message.swift:866 (StoreMessageFlags)
  • 解析来源: MTProto 消息 flag 第 26 位
    • submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift:1044-1046,1201-1203

2. 对话级标记 copyProtectionEnabled

  • 频道TelegramChannelFlags.copyProtectionEnabled (bit 8)
    • submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift:181
    • 从 MTProto 第 27 位解析: submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift:125-126
  • 群组TelegramGroupFlags.copyProtectionEnabled (bit 4)
    • submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramGroup.swift:122
    • 从 MTProto 第 25 位解析: submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift:56-57

3. 服务端切换 API

  • submodules/TelegramCore/Sources/TelegramEngine/Peers/CopyProtection.swift:7-17
  • 调用 messages.toggleNoForwards 接口

核心判断逻辑

通用判断 Message.isCopyProtected()

submodules/TelegramCore/Sources/Utils/MessageUtils.swift:382-392

func isCopyProtected() -> Bool {
if self.flags.contains(.CopyProtected) { return true } // 消息级标记
if group.flags.contains(.copyProtectionEnabled) { return true } // 群组级标记
if channel.flags.contains(.copyProtectionEnabled) { return true } // 频道级标记
return false
}

Peer 级判断 Peer.isCopyProtectionEnabled

submodules/TelegramCore/Sources/Utils/PeerUtils.swift:236-245

var isCopyProtectionEnabled: Bool {
switch self {
case let group as TelegramGroup: return group.flags.contains(.copyProtectionEnabled)
case let channel as TelegramChannel: return channel.flags.contains(.copyProtectionEnabled)
default: return false
}
}

macOS 特有判断 Peer.isCopyProtected(对群主/管理员豁免)

Telegram-Mac/CoreExtension.swift:3810-3818

var isCopyProtected: Bool {
if let peer = self as? TelegramGroup {
return peer.flags.contains(.copyProtectionEnabled) && !peer.groupAccess.isCreator
} else if let peer = self as? TelegramChannel {
return peer.flags.contains(.copyProtectionEnabled) && !(peer.adminRights != nil || peer.groupAccess.isCreator)
} else {
return false
}
}

macOS 层执行点

功能文件位置行为
Cmd+C 复制文本ChatSelectText.swiftL110-115拦截复制、弹 alert
右键菜单-复制文本ChatMessageMenuItems.swiftL690不添加菜单项
右键菜单-复制链接ChatMessageMenuItems.swiftL701不添加菜单项
转发到其他聊天ChatInputAccessory.swiftL297, L328不添加菜单项
转发能力ChatRowItem.swiftL1076-1078canForward 返回 false
Gallery 保存按钮GalleryModernControls.swiftL190-220fastSaveControl.isHidden = true
Gallery 右键-另存为GalleryViewer.swiftL1362-1369不添加菜单项
Gallery 分享GalleryViewer.swiftL377-384canShare 返回 false
MGalleryItem 分享MGalleryItem.swiftL156canShare 返回 false
MGalleryItem 保存MGalleryItem.swiftL326canSave 返回 false
Gallery 文本识别GalleryRecognition.swiftL27跳过 OCR 识别
列表缩略图防截屏ChatListRowView.swiftL702preventsCapture = true
管理员开关 UIChannelVisibilityController.swiftL719-730Restrict Copying 开关

iOS 层关键执行点(供参考)

功能文件位置行为
文本选择复制ChatMessageTextBubbleContentNode.swiftL1408-1409textSelectionNode.enableCopy = false
上下文菜单复制ChatInterfaceStateContextMenus.swiftL1259-1263Copy 菜单项不添加
上下文菜单保存到文件ChatInterfaceStateContextMenus.swiftL1369不添加菜单项
选中面板-转发/分享ChatMessageSelectionInputPanelNode.swiftL218-233弹 copyProtectionTip
另一聊天回复ChatMessageActionOptions.swiftL424-425canReplyInAnotherChat = false
Gallery 分享/编辑ChatItemGalleryFooterContentNode.swiftL943-946canShare=falsecanEdit=false
Gallery 防截屏ChatImageGalleryItem.swiftL456setLayerDisableScreenshots
Sticker 分享ChatMessageStickerItemNode.swiftL566needsShareButton = false
动画 Sticker 分享ChatMessageAnimatedStickerItemNode.swiftL945needsShareButton = false
视频消息分享ChatMessageInstantVideoItemNode.swiftL384needsShareButton = false
Bubble 分享ChatMessageBubbleItemNode.swiftL1783needsShareButton = false
Video captureProtectNativeVideoContent.swiftL431-432captureProtected = true
PeerInfo 防截屏PeerInfoScreen.swiftL5378-5382setLayerDisableScreenshots
Story 防截屏StoryItemImageView.swiftL48-56UITextField.secureTextEntry 方式
防截屏底层实现UIKitRuntimeUtils/UIKitUtils.mL247-269setLayerDisableScreenshots()

架构流程图

服务端 (MTProto)


Parsing Layer
├── StoreMessage_Telegram.swift → MessageFlags.CopyProtected (bit 512)
└── ApiGroupOrChannel.swift → TelegramChannelFlags / TelegramGroupFlags .copyProtectionEnabled


Data Model Layer
├── Message.swift → flags.contains(.CopyProtected)
├── SyncCore_TelegramChannel.swift → channel.flags.contains(.copyProtectionEnabled)
└── SyncCore_TelegramGroup.swift → group.flags.contains(.copyProtectionEnabled)


Business Logic Layer
├── MessageUtils.swift (isCopyProtected) → 三者 OR 判断
├── PeerUtils.swift (isCopyProtectionEnabled) → peer 级判断
└── CoreExtension.swift (macOS Peer.isCopyProtected) → 对管理员豁免


UI Enforcement Layer
├── ChatSelectText.swift → Cmd+C 拦截
├── ChatMessageMenuItems.swift → 右键菜单项控制
├── GalleryModernControls.swift → 保存按钮隐藏
├── GalleryViewer.swift → 分享/另存为控制
├── ChatInputAccessory.swift → 转发菜单控制
├── ChatRowItem.swift → 转发能力控制
├── ChatListRowView.swift → 防截屏
└── GalleryRecognition.swift → 文本识别
分类

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注