同行数据库

API 中的许多构造函数需要在接收时存储在本地数据库中,并且只有在通过更新或其他方式(如文档中所述)接收到时才应被动地进行更新,以避免因不断请求相同未更改的信息而使服务器过载。

用户、聊天、频道构造函数及其完整对应物userFull、chatFull、channelFull尤为重要,因为它们包含有关用户、机器人、聊天和频道(从现在起称为对等节点)的重要信息,最重要的是,它们包含与 API 中的对等节点交互所需的access_hash值。

本页详细介绍了如何以及何时刷新上面列出的构造函数的本地数据库,并包含有关基本对等概念的更详细说明。

为了简单起见,文档在提及对等数据库时通常使用术语“缓存”而不是“数据库”,但请注意,建议将接收到的信息(或至少是 id+访问哈希)持久化到数据库中,以便在启动后调用需要访问哈希的方法并查看其他对等信息,而无需重新获取聊天记录和对等信息。

同行信息数据库

userEmpty#d3bc4b7a id:long = User; user#20b1422 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?int color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;chatEmpty#29562865 id:long = Chat; chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat; chatForbidden#6592a1a7 id:long title:string = Chat;channel#fe685355 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true autotranslation:flags2.15?true broadcast_messages_allowed:flags2.16?true monoforum:flags2.17?true forum_tabs:flags2.19?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long linked_monoforum_id:flags2.18?long = Chat; channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;inputUserEmpty#b98886cf = InputUser; inputUserSelf#f7c1b13f = InputUser; inputUser#f21158c6 user_id:long access_hash:long = InputUser; inputUserFromMessage#1da448e2 peer:InputPeer msg_id:int user_id:long = InputUser;// No inputChat, just a long is used (because basic chats don't have access hashes)inputChannelEmpty#ee8c1e86 = InputChannel; inputChannel#f35aec28 channel_id:long access_hash:long = InputChannel; inputChannelFromMessage#5b934f9d peer:InputPeer msg_id:int channel_id:long = InputChannel;inputPeerEmpty#7f3b18ea = InputPeer; inputPeerSelf#7da07ec9 = InputPeer; inputPeerChat#35a95cb9 chat_id:long = InputPeer; inputPeerUser#dde8a54c user_id:long access_hash:long = InputPeer; inputPeerChannel#27bcbbfc channel_id:long access_hash:long = InputPeer; inputPeerUserFromMessage#a87b0a1c peer:InputPeer msg_id:int user_id:long = InputPeer; inputPeerChannelFromMessage#bd2a0840 peer:InputPeer msg_id:int channel_id:long = InputPeer;---functions---users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>; messages.getChats#49e9528f id:Vector<long> = messages.Chats; channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;

对等体信息数据库包含以下信息:

它必须按如下方式填写:

示例实现:tdlib。

保存构造函数

每当收到类型为user、chat和channel的新构造函数(以及它们的forbidden对应项,用于用户无法访问但可以查看其基本信息的对等节点)时,都需要更新对等信息数据库。

这些构造函数是在与 API 交互时收到的(例如在普通聊天中、通过搜索功能、用户名解析、临时个人资料链接等等……)。

除非另有规定(有关特殊情况,请参阅构造函数页面),否则在更新本地对等数据库时,新接收的构造函数中的所有字段优先于本地缓存的旧构造函数(包括删除新构造函数中未设置的字段)。

处理某些更新

以下更新应触发对等数据库中包含的一小部分信息的更新(包括非完整版本和完整版本):

手动刷新

出于性能原因,服务器不会总是发送包含所有对等节点更新信息的更新:因此,在某些情况下,可以使用批量用户.getUsers、messages.getChats、channels.getChannels方法手动刷新已缓存对等节点的信息,所有这些方法都需要先前缓存的信息。access_hash

以下列表并不详尽,客户也可以在其他一些情况下选择刷新同伴信息(例如,打开个人资料页面时等)。

对等ID

对等体id是一个唯一的 64 位 ID,用于识别特定的用户、聊天或频道。

该字段应用作频道、聊天和用户数据库的主键。

请注意,用户、聊天和频道的 ID 序列存在重叠,因此您必须执行以下操作之一:

点击以下链接查看各种聊天类型的可用 MTProto ID 范围,以及如何将它们转换为单个机器人 API 范围的信息:

即使您决定使用单独的数据库,将对等 ID 转换为机器人 API ID也是一个好主意,因为这将使 ID 对您和您的用户来说更具视觉识别性,并保证与机器人 API 的兼容性。

访问哈希

这是存储在对等数据库access_hash中的第二重要字段,用于生成InputPeer、inputUser和inputChannel构造函数,以便通过 API 与对等节点交互。请注意,聊天(基本群组)没有也不需要访问哈希。用户和频道(超级群组和频道)都有访问哈希,并且它可以有多种形式:

上面列出的访问哈希版本按优先级降序排列,如果当前缓存了优先级较高的版本,则不能用优先级较低的版本覆盖它。

当您与 API 交互时(例如在公共聊天、搜索功能、用户名解析、临时个人资料链接等),系统会获取访问哈希值:如果您只有用户/频道/超级群组 ID 而没有访问哈希值,则无法与该用户/频道/超级群组进行交互。
访问哈希值不能在不同的帐户或同一帐户的不同会话之间重复使用。
这是 Telegram 的一项核心反垃圾邮件功能。

客户端和客户端 API 应该避免向用户暴露访问哈希值,因为这些哈希值无法在当前会话之外重用,而且当客户端可以完美地自行完成这项工作时,用户不应该承担存储这些哈希值的负担。

注意:其他一些与对等节点无关的构造函数(即非用户、聊天或频道)也可能包含访问哈希值,这些哈希值应该存储在不同的数据库中。

其他信息

客户端常用的其他各种字段,如构造函数页面(用户、聊天和频道)中所述。如构造函数文档中所述,如果收到最小构造函数
, 则某些字段不得被覆盖,而其他一些字段的更改必须触发整个信息数据库的失效。

完整信息数据库

users.userFull#3b6d152e full_user:UserFull chats:Vector<Chat> users:Vector<User> = users.UserFull; messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector<Chat> users:Vector<User> = messages.ChatFull;userFull#c577b5ad flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme:flags.15?ChatTheme private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings stars_rating:flags2.17?StarsRating stars_my_pending_rating:flags2.18?StarsRating stars_my_pending_rating_date:flags2.18?int main_tab:flags2.20?ProfileTab saved_music:flags2.21?Document = UserFull; chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull; channelFull#e4e0b29d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true paid_messages_available:flags2.20?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int send_paid_messages_stars:flags2.21?long main_tab:flags2.22?ProfileTab = ChatFull;---functions---users.getFullUser#b60f5918 id:InputUser = users.UserFull; messages.getFullChat#aeb00b34 chat_id:long = messages.ChatFull; channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;

示例实现:tdlib。

完整的数据库包含来自userFull、chatFull和channelFull构造函数的信息。

要填充对等节点的完整信息数据库,请调用users.getFullUser、messages.getFullChat、channels.getFullChannel,所有这些都需要先前缓存的access_hash »。

仅使userFull和channelFull条目在存储 60 秒后失效。

当客户端需要从完整构造函数中获取某些数据,但数据库中尚无相应条目,或者所需条目已因 TTL 过期而失效,或者出现以下情况时,刷新完整信息数据库:

以上列表并不详尽,客户也可以在其他一些情况下选择刷新同伴信息(例如,打开个人资料页面时等)。

生活质量检查

请注意以下事项:对等信息也用于改善生活质量,即直接阻止用户执行对等信息不允许的操作,而不是允许该操作然后显示错误。

所有客户端都应该实施这些改进,但是,服务器也会始终通过发出适当的RPC 错误来阻止用户执行非法操作,因为即使实施了本地检查,有时仍然有可能执行非法操作(见下文)。

客户端不应(或同时)阻止用户在客户端执行非法操作,而应始终提供服务器返回的错误的本地化版本(如从RPC 错误页面下载的 JSON 文件中所列),以告知用户尝试操作失败的原因。

换句话说,如果客户端没有在本地阻止失败的方法调用,因为:

……它仍然应该根据 RPC 错误的描述(如果JSON 错误数据库中有该描述,否则就显示 RPC 错误本身)让用户知道查询失败的原因。