处理文件引用

文件引用是字节字符串,可以在文档和照片file_reference对象的字段中遇到。

客户端必须缓存这些文件及其来源,以便在文件引用过期时重新获取。

参考数据库示例实现:MadelineProto、android、telegram desktop、tdlib。

自动生成

通过使用文件引用数据库模式生成器工具»及其生成的文件引用数据库映射文件,可以完全自动化文件引用数据库的实施和维护。

当前图层的最新文件参考数据库地图文件 »

字典:

数据库映射文件包含所有可能的来源,对应所有可能的文件引用路径。

它由文件引用数据库模式生成器工具自动生成和验证 »;该工具可在较新的或实验性的层上手动运行,以生成给定 API 模式的文件引用数据库映射文件:请参阅此处 »了解更多信息。

执行

以下是如何使用文件引用数据库映射文件在 MTProto 客户端中生成文件引用数据库所需的所有逻辑。

文件引用数据库可以用以下类型表示:

HashMap<FileId, Vector<FileSource>>

它将 a 映射FileId到一个或多个类型为 的对象FileSource: 和 的确切结构和可能的类型FileId在映射文件FileSource中指定。

当反序列化从 API 接收的特定类型的对象时,会添加新条目,将接收到的文件 ID 映射到一个或多个s;确切的过程和受影响的对象在映射文件FileSource中完全指定。

之后,当使用文件时(例如发送或下载媒体文件时),并且FILE_REFERENCE_EXPIRED收到特定 RPC 错误时FileId,客户端必须获取List<FileSource>与所用 RPC 关联的RPCFileId,并为每个 RPC 执行特定的方法调用,直到获取到FileSource新的RPC 为止。file_referenceFileId

请注意,数据库不必存储实际的文件file_reference,只需存储文件 ID => 文件源映射:文件引用本身可以存储在例如消息数据库或文档数据库中,或者以任何其他方式存储,以便FileId在提取或存储时与文件关联,如映射文件中所指定。

映射文件本身遵循自定义的 TL 模式,并以 JSON 或序列化的 TL 格式提供。

地图文件的序列化 TL 版本 »

JSON 映射文件 »- 构造函数谓词按键序列化_,bytes字段按以下方式序列化:{"_": "bytes", "bytes": "<base64 encoded value>"}

地图文件的TL架构»

映射文件的 TL 模式的 JSON 版本 »

这是地图文件的TL架构:

boolFalse#bc799737 = Bool; boolTrue#997275b5 = Bool; true#3fedd339 = True;vector#1cb5c415 {t:Type} # [ t ] = Vector t;// RootfileReferenceOrigins#ed01a4f1 db_schema:string db_schema_json:string locations:Vector<Location> origins:Vector<Origin> skipped:Vector<SkippedOrigin> actions:Vector<Action> = FileReferenceOrigins;locationIncoming#e18770f4 predicate:string stored_constructor:string = Location;locationOutgoing#e7740ae0 predicate:string stored_constructor:string = Location;origin#b62177bf flags:# predicate:string is_constructor:flags.0?true stored_constructor:string stored_params:Vector<FieldExtractor> skipped_flags:Vector<string> needs_parent:flags.3?string parent_is_constructor:flags.4?true = origin;skippedOrigin#7c62809e flags:# predicate:string is_constructor:flags.0?true why:string = SkippedOrigin;action#9539f410 stored_constructor:string action:ActionOp = Action;// Field extraction pathparamNotFlag#acd9d5cf = ParamFlag;paramIsFlagAbortIfEmpty#f8fe9fee = ParamFlag;paramIsFlagFallback#202b77a1 fallback:TypedOp = ParamFlag;paramIsFlagPassthrough#1dc6e17d = ParamFlag;pathPart#8dc6ff46 constructor:string param:string flag:ParamFlag = PathPart;path#0c3586a2 parts:Vector<PathPart> = Path;pathParent#58f13684 parts:Vector<PathPart> = Path;// ExtractorextractAndStore#72069549 from:Path to:string = FieldExtractor;extractInputStickerSetFromDocumentAttributesAndStore#369d8d14 from:Path to:string = FieldExtractor;extractInputStickerSetFromStickerSetAndStore#c167d470 from:Path to:string = FieldExtractor;extractPeerIdFromPeerAndStore#7d33019c from:Path to:string = FieldExtractor;extractPeerIdFromInputPeerAndStore#a51acfb4 from:Path to:string = FieldExtractor;extractChannelIdFromChannelAndStore#5675bc97 from:Path to:string = FieldExtractor;extractChannelIdFromInputChannelAndStore#b662660e from:Path to:string = FieldExtractor;extractUserIdFromUserAndStore#4778ec63 from:Path to:string = FieldExtractor;extractUserIdFromInputUserAndStore#7720aa2e from:Path to:string = FieldExtractor;// ActionscallOp#c2ff3383 method:string args:Vector<TypedOpArg> = ActionOp;getMessageOp#237849e8 peer:TypedOp id:TypedOp from_scheduled:TypedOp quick_reply_shortcut_id:TypedOp = ActionOp;// For string => TypedOp dictionariestypedOpArg#3a2930c2 key:string value:TypedOp = TypedOpArg;// Typed constructors, the type is specified to simplify codegen,// but isn't strictly necessary as it can be inferred from the TypedOpOp.// It is fully pre-validated during the generation of the definition file.typedOp#705b10ec type:string op:TypedOpOp = TypedOp;// The actual opscopyOp#f48f418f from:string = TypedOpOp;getInputChannelByIdOp#3cb47531 from:string = TypedOpOp;getInputUserByIdOp#c0ee4326 from:string = TypedOpOp;getInputPeerByIdOp#19813750 from:string = TypedOpOp;// Literals & constructors (methods not allowed or needed here)constructorOp#107f8d8a constructor:string args:Vector<TypedOpArg> = TypedOpOp;vectorOp#f8fb8f72 values:Vector<TypedOp> = TypedOpOp;intLiteralOp#cbfabe7c value:int = TypedOpOp;longLiteralOp#d08b8d3a value:long = TypedOpOp;stringLiteralOp#2b56ea8e value:string = TypedOpOp;bytesLiteralOp#fdb395a4 value:bytes = TypedOpOp;boolLiteralOp#37e07911 value:Bool = TypedOpOp;doubleLiteralOp#3651e3bf value:double = TypedOpOp;themeFormatLiteralOp#8e4f9208 = TypedOpOp;

当前图层的当前值:

数据库模式:

boolFalse#bc799737 = Bool; boolTrue#997275b5 = Bool; true#3fedd339 = True;vector#1cb5c415 {t:Type} # [ t ] = Vector t;fileIdPhoto#47a0bd49 id:long = FileId;fileIdDocument#461b1d89 id:long = FileId;fileSourceMessage#7e015bb0 flags:# from_scheduled:flags.0?true quick_reply_shortcut_id:flags.1?int peer:long id:int = FileSource;fileSourceStarsTransaction#c1bac8c7 flags:# peer:long id:string refund:flags.0?true ton:flags.1?true = FileSource;fileSourceStory#c820e3eb id:int peer:long = FileSource;fileSourceWebPage#9e5b749c url:string = FileSource;fileSourceBotApp#01cf8b7a id:long access_hash:long = FileSource;fileSourceUserFull#70fdb7b0 id:long = FileSource;fileSourceAdminLog#4797f959 channel:long max_id:long = FileSource;fileSourceStoryAlbum#5e01f223 peer:long = FileSource;fileSourceBotPreviewMedia#0aa91441 bot:long = FileSource;fileSourceBotPreviewInfo#f9d2d6fc bot:long lang_code:string = FileSource;fileSourcePaidMedia#b18d9042 id:int peer:long = FileSource;fileSourceSavedMusic#dd1a7664 user_id:long id:long access_hash:long = FileSource;fileSourceChatFull#9de75fde chat_id:long = FileSource;fileSourceChannelFull#6fe19339 channel:long = FileSource;fileSourcePremiumPromo#c907a44f = FileSource;fileSourceAttachMenuBot#c3002694 bot:long = FileSource;fileSourceTheme#92d05e0c id:long access_hash:long = FileSource;fileSourceWallPaper#50dbf2f7 id:long access_hash:long = FileSource;fileSourceStickerSet#34c73709 stickerset:InputStickerSet = FileSource;fileSourceSavedGifs#13e78e07 = FileSource;fileSourceSavedRingtones#2b25ef1b = FileSource;fileSourceAvailableEffects#eb8578f0 = FileSource;fileSourceAvailableReactions#0e432388 = FileSource;fileSourceUserProfilePhoto#e39ee274 user_id:long max_id:long = FileSource;fileSourceDocumentByHash#0f151e0f sha256:bytes size:long mime_type:string = FileSource;地点:


  • inputPhoto-fileIdPhoto(发送)
  • 输入文档-fileIdDocument(传出)
  • inputDocumentFileLocation-fileIdDocument(输出)
  • inputPhotoFileLocation-fileIdPhoto(传出)
  • 文件-fileIdDocument(接收)
  • 照片-fileIdPhoto(即将发布)

操作:

  • 文件源消息 -getMessageOp(peer: getInputPeerByIdOp(peer), id: copyOp(id), from_scheduled: copyOp(from_scheduled)quick_reply_shortcut_id: copyOp(quick_reply_shortcut_id))
  • fileSourceStory -stories.getStoriesByID(id: [copyOp(id)], peer: getInputPeerByIdOp(peer))
  • 文件源网页 -messages.getWebPage(url: copyOp(url), hash: 0)
  • fileSourceBotApp -messages.getBotApp(app: inputBotAppID{id: copyOp(id), access_hash: copyOp(access_hash)}, hash: 0)
  • fileSourceUserFull -users.getFullUser(id: getInputUserByIdOp(id))
  • 文件源管理日志 -channels.getAdminLog(channel: getInputChannelByIdOp(channel), max_id: copyOp(max_id), min_id: copyOp(max_id), limit: 1, q: "")
  • 文件源故事专辑 -stories.getAlbums(peer: getInputPeerByIdOp(peer), hash: 0)
  • fileSourceBotPreviewMedia -bots.getPreviewMedias(bot: getInputUserByIdOp(bot))
  • fileSourceBotPreviewInfo -bots.getPreviewInfo(bot: getInputUserByIdOp(bot), lang_code: copyOp(lang_code))
  • fileSourcePaidMedia -messages.getExtendedMedia(id: [copyOp(id)], peer: getInputPeerByIdOp(peer))
  • fileSourceSavedMusic -users.getSavedMusicByID(id: getInputUserByIdOp(user_id), documents: [inputDocument{id: copyOp(id), access_hash: copyOp(access_hash), file_reference: base64_decode("")}])
  • fileSourceChatFull -messages.getFullChat(chat_id: copyOp(chat_id))
  • fileSourceChannelFull -channels.getFullChannel(channel: getInputChannelByIdOp(channel))
  • fileSourcePremiumPromo -help.getPremiumPromo()
  • fileSourceStarsTransaction -payments.getStarsTransactionsByID(peer: getInputPeerByIdOp(peer), ton: copyOp(ton), id: [inputStarsTransaction{id: copyOp(id), refund: copyOp(refund)}])
  • fileSourceAttachMenuBot -messages.getAttachMenuBot(bot: getInputUserByIdOp(bot))
  • 文件源主题 -account.getTheme(theme: inputTheme{id: copyOp(id), access_hash: copyOp(access_hash)}, format: $themeFormat)
  • 文件源壁纸 -account.getWallPaper(wallpaper: inputWallPaper{id: copyOp(id), access_hash: copyOp(access_hash)})
  • fileSourceStickerSet -messages.getStickerSet(stickerset: copyOp(stickerset), hash: 0)
  • fileSourceSavedGifs -messages.getSavedGifs(hash: 0)
  • 文件源已保存的铃声 -account.getSavedRingtones(hash: 0)
  • fileSourceAvailableEffects -messages.getAvailableEffects(hash: 0)
  • fileSourceAvailableReactions -messages.getAvailableReactions(hash: 0)
  • fileSourceUserProfilePhoto -photos.getUserPhotos(user_id: getInputUserByIdOp(user_id), offset: -1, max_id: copyOp(max_id), limit: 1)
  • fileSourceDocumentByHash -messages.getDocumentByHash(sha256: copyOp(sha256), size: copyOp(size), mime_type: copyOp(mime_type))

起源:

  • 信息-fileSourceMessage{from_scheduled: message.from_scheduled?passthrough, quick_reply_shortcut_id: message.quick_reply_shortcut_id?passthrough, peer: extractPeerIdFromPeerAndStore(message.peer_id), id: message.id}
  • 消息服务-fileSourceMessage{peer: extractPeerIdFromPeerAndStore(messageService.peer_id), id: messageService.id, from_scheduled: false, quick_reply_shortcut_id: false}
  • (1)故事项-(needs stories.getPinnedStories) fileSourceStory{id: storyItem.id, peer: extractPeerIdFromInputPeerAndStore(stories.getPinnedStories.peer)}
  • (2)故事项-(needs stories.getStoriesArchive) fileSourceStory{id: storyItem.id, peer: extractPeerIdFromInputPeerAndStore(stories.getStoriesArchive.peer)}
  • (3)故事项-(needs stories.getStoriesByID) fileSourceStory{id: storyItem.id, peer: extractPeerIdFromInputPeerAndStore(stories.getStoriesByID.peer)}
  • (4)故事项-(needs stories.getAlbumStories) fileSourceStory{id: storyItem.id, peer: extractPeerIdFromInputPeerAndStore(stories.getAlbumStories.peer)}
  • (5)故事项-(needs peerStories) fileSourceStory{id: storyItem.id, peer: extractPeerIdFromPeerAndStore(peerStories.peer)}
  • (6)故事项-fileSourceStory{id: storyItem.id, peer: extractPeerIdFromPeerAndStore(storyItem.from_id?abort_if_empty)}
  • storyViewPublicRepost-fileSourceStory{id: storyViewPublicRepost.story.storyItem.id, peer: extractPeerIdFromPeerAndStore(storyViewPublicRepost.peer_id)}
  • storyReactionPublicRepost-fileSourceStory{id: storyReactionPublicRepost.story.storyItem.id, peer: extractPeerIdFromPeerAndStore(storyReactionPublicRepost.peer_id)}
  • foundStory-fileSourceStory{id: foundStory.story.storyItem.id, peer: extractPeerIdFromPeerAndStore(foundStory.peer)}
  • 公开前瞻故事-fileSourceStory{id: publicForwardStory.story.storyItem.id, peer: extractPeerIdFromPeerAndStore(publicForwardStory.peer)}
  • webPageAttributeStory-fileSourceStory{id: webPageAttributeStory.story?abort_if_empty.storyItem.id, peer: extractPeerIdFromPeerAndStore(webPageAttributeStory.peer)}
  • messageMediaStory-fileSourceStory{id: messageMediaStory.story?abort_if_empty.storyItem.id, peer: extractPeerIdFromPeerAndStore(messageMediaStory.peer)}
  • 网页-fileSourceWebPage{url: webPage.url}
  • 机器人应用-fileSourceBotApp{id: botApp.id, access_hash: botApp.access_hash}
  • botInfo-fileSourceUserFull{id: botInfo.user_id?abort_if_empty}
  • channelAdminLogEvent-(needs channels.getAdminLog) fileSourceAdminLog{channel: extractChannelIdFromInputChannelAndStore(channels.getAdminLog.channel), max_id: channelAdminLogEvent.id}
  • stories.createAlbum-fileSourceStoryAlbum{peer: extractPeerIdFromInputPeerAndStore(stories.createAlbum.peer)}
  • stories.getAlbums-fileSourceStoryAlbum{peer: extractPeerIdFromInputPeerAndStore(stories.getAlbums.peer)}
  • stories.updateAlbum-fileSourceStoryAlbum{peer: extractPeerIdFromInputPeerAndStore(stories.updateAlbum.peer)}
  • bots.getPreviewMedias-fileSourceBotPreviewMedia{bot: extractUserIdFromInputUserAndStore(bots.getPreviewMedias.bot)}
  • bots.getPreviewInfo-fileSourceBotPreviewInfo{bot: extractUserIdFromInputUserAndStore(bots.getPreviewInfo.bot), lang_code: bots.getPreviewInfo.lang_code}
  • bots.addPreviewMedia-fileSourceBotPreviewInfo{bot: extractUserIdFromInputUserAndStore(bots.addPreviewMedia.bot), lang_code: bots.addPreviewMedia.lang_code}
  • bots.editPreviewMedia-fileSourceBotPreviewInfo{bot: extractUserIdFromInputUserAndStore(bots.editPreviewMedia.bot), lang_code: bots.editPreviewMedia.lang_code}
  • updateMessageExtendedMedia-fileSourcePaidMedia{id: updateMessageExtendedMedia.msg_id, peer: extractPeerIdFromPeerAndStore(updateMessageExtendedMedia.peer)}
  • (1)userFull-fileSourceUserFull{id: userFull.id}
  • (2)userFull-fileSourceSavedMusic{user_id: userFull.id, id: userFull.saved_music?abort_if_empty.document.id, access_hash: userFull.saved_music?abort_if_empty.document.access_hash}
  • chatFull-fileSourceChatFull{chat_id: chatFull.id}
  • 频道完整-fileSourceChannelFull{channel: channelFull.id}
  • help.getPremiumPromo-fileSourcePremiumPromo{}
  • (1)starsTransaction-(needs payments.getStarsStatus) fileSourceStarsTransaction{peer: extractPeerIdFromInputPeerAndStore(payments.getStarsStatus.peer), ton: payments.getStarsStatus.ton?passthrough, id: starsTransaction.id, refund: starsTransaction.refund?passthrough}
  • (2)starsTransaction-(needs payments.getStarsTransactions) fileSourceStarsTransaction{peer: extractPeerIdFromInputPeerAndStore(payments.getStarsTransactions.peer), ton: payments.getStarsTransactions.ton?passthrough, id: starsTransaction.id, refund: starsTransaction.refund?passthrough}
  • (3)starsTransaction-(needs payments.getStarsTransactionsByID) fileSourceStarsTransaction{peer: extractPeerIdFromInputPeerAndStore(payments.getStarsTransactionsByID.peer), ton: payments.getStarsTransactionsByID.ton?passthrough, id: starsTransaction.id, refund: starsTransaction.refund?passthrough}
  • (4)starsTransaction-(needs payments.getStarsSubscriptions) fileSourceStarsTransaction{peer: extractPeerIdFromInputPeerAndStore(payments.getStarsSubscriptions.peer), id: starsTransaction.id, refund: starsTransaction.refund?passthrough, ton: false}
  • attachMenuBot-fileSourceAttachMenuBot{bot: attachMenuBot.bot_id}
  • 主题-fileSourceTheme{id: theme.id, access_hash: theme.access_hash}
  • 墙纸-fileSourceWallPaper{id: wallPaper.id, access_hash: wallPaper.access_hash}
  • 贴纸套装多覆盖-fileSourceStickerSet{stickerset: extractInputStickerSetFromStickerSetAndStore(stickerSetMultiCovered.set)}
  • 贴纸套装全覆盖-fileSourceStickerSet{stickerset: extractInputStickerSetFromStickerSetAndStore(stickerSetFullCovered.set)}
  • messages.stickerSet-fileSourceStickerSet{stickerset: extractInputStickerSetFromStickerSetAndStore(messages.stickerSet.set)}
  • messages.savedGifs-fileSourceSavedGifs{}
  • account.savedRingtones-fileSourceSavedRingtones{}
  • account.savedRingtoneConverted-fileSourceSavedRingtones{}
  • account.uploadRingtone-fileSourceSavedRingtones{}
  • messages.availableEffects-fileSourceAvailableEffects{}
  • messages.availableReactions-fileSourceAvailableReactions{}
  • 照片-(needs photos.getUserPhotos) fileSourceUserProfilePhoto{user_id: extractUserIdFromInputUserAndStore(photos.getUserPhotos.user_id), max_id: photo.id}
  • photos.updateProfilePhoto-fileSourceUserProfilePhoto{user_id: extractUserIdFromInputUserAndStore(photos.updateProfilePhoto.bot?fallback(inputUserSelf{})), max_id: photos.updateProfilePhoto.(return value).photos.photo.photo.photo.id}
  • photos.uploadProfilePhoto-fileSourceUserProfilePhoto{user_id: extractUserIdFromInputUserAndStore(photos.uploadProfilePhoto.bot?fallback(inputUserSelf{})), max_id: photos.uploadProfilePhoto.(return value).photos.photo.photo.photo.id}
  • photos.uploadContactProfilePhoto-fileSourceUserProfilePhoto{user_id: extractUserIdFromInputUserAndStore(photos.uploadContactProfilePhoto.user_id), max_id: photos.uploadContactProfilePhoto.(return value).photos.photo.photo.photo.id}
  • (1)文件-fileSourceStickerSet{stickerset: extractInputStickerSetFromDocumentAttributesAndStore(document.attributes)}
  • (2)文件-(needs users.getSavedMusic) fileSourceSavedMusic{user_id: extractUserIdFromInputUserAndStore(users.getSavedMusic.id), id: document.id, access_hash: document.access_hash}
  • (3)文件-(needs users.getSavedMusicByID) fileSourceSavedMusic{user_id: extractUserIdFromInputUserAndStore(users.getSavedMusicByID.id), id: document.id, access_hash: document.access_hash}
  • messages.getDocumentByHash-fileSourceDocumentByHash{sha256: messages.getDocumentByHash.sha256, size: messages.getDocumentByHash.size, mime_type: messages.getDocumentByHash.mime_type}

已跳过:

  • messages.getSponsoredMessages- 不存储赞助消息中的文件引用
  • help.getAppUpdate- 不处理来自临时应用更新信息的文件引用
  • help.getRecentMeUrls- 不处理来自最近 t.me URL 的文件引用
  • recentMeUrlChatInvite- 请勿存储基于聊天邀请链接的引用
  • messages.checkChatInvite- 不存储基于聊天邀请链接的引用
  • messages.getInlineBotResults- 内联机器人结果是临时的
  • messages.getPreparedInlineMessage- 内联机器人结果是临时的
  • messages.uploadMedia- 新上传的媒体文件只有在发送到聊天窗口后才会获得上下文。
  • messages.uploadImportedMedia- 新上传的媒体文件只有在发送到聊天窗口后才会获得上下文。
  • updateServiceNotification- 无法重新获取服务通知
  • messages.getWebPagePreview- 由于该方法调用不使用持久 ID 作为输入,因此不会添加任何位置信息;位置信息是从返回的 WebPage 对象中的持久 ID 中提取的。
  • payments.resaleStarGifts- 星形礼品的相关功能尚未实现
  • payments.starGiftUpgradePreview- 星形礼品的上下文尚未实现
  • starGift- 星形礼物的相关功能尚未实现
  • starGiftUnique- 星形礼物的上下文尚未实现
  • starGiftCollection- 星形礼物的上下文尚未实现
  • payments.starGiftCollections- 星形礼品的上下文尚未实现
  • messages.getCustomEmojiDocuments- 请勿在此上下文中存储文件引用
  • account.uploadTheme- 新上传的主题文件只有在通过 account.createTheme 创建后才能获得上下文。

以下是构造函数的详细描述。

fileReferenceOrigins#ed01a4f1 db_schema:string db_schema_json:string locations:Vector<Location> origins:Vector<Origin> skipped:Vector<SkippedOrigin> actions:Vector<Action> = FileReferenceOrigins;locationIncoming#e18770f4 predicate:string stored_constructor:string = Location;locationOutgoing#e7740ae0 predicate:string stored_constructor:string = Location;origin#b62177bf flags:# predicate:string is_constructor:flags.0?true stored_constructor:string stored_params:Vector<FieldExtractor> skipped_flags:Vector<string> needs_parent:flags.3?string parent_is_constructor:flags.4?true = origin;skippedOrigin#7c62809e flags:# predicate:string is_constructor:flags.0?true why:string = SkippedOrigin;action#9539f410 stored_constructor:string action:ActionOp = Action;

映射文件由一个构造函数组成fileReferenceOrigins,该构造函数包含:

  • 和字段具有 TL数据库模式s 和s。是文本 TL 模式,是 JSON 格式中相同的 TL 模式,db_schema也用于 API 模式 »。db_schema_jsonFileIdFileSource
    db_schemadb_schema_json

  • 构造函数列表Location,包含具有字段的构造函数的完整列表file_reference,以及如何FileId从中生成的信息。

  • 构造函数列表,其中包含有关如何从接收到的构造函数或方法响应origin生成 s 的说明。FileSource

  • 构造函数列表,其中包含使用先前存储的和action刷新文件引用时要调用的方法调用。FileIdFileSource

  • 构造函数列表skippedOrigin。这些构造函数表明应该完全忽略 origin(包括在代码生成期间):skippedOriginorigins 在内部用于确保在验证期间所有文件引用路径仍然以某种方式被覆盖,包括临时媒体(如内联结果)的路径,或没有任何关联 origin 的媒体的路径(例如,使用messages.uploadMedia上传但尚未发送到任何地方的媒体显然没有任何关联的 origin)。

    • skippedOrigin.predicate- 指示被忽略的构造函数或方法的名称。
    • skippedOrigin.is_constructor- 如果设置了参数,predicate则指向构造函数;否则,指向方法。
    • skippedOrigin.why- 一个通俗易懂的理由,说明为什么应该忽略这个来源。

    每个被跳过的谓词都可以有一个关联的原因。

地点

locationIncoming#e18770f4 predicate:string stored_constructor:string = Location;locationOutgoing#e7740ae0 predicate:string stored_constructor:string = Location;

Locations 包含具有 afile_reference和 anid字段的构造函数(而非方法)的完整列表。

必须使用该id字段生成类型为的对象。predicateFileIdstored_constructor

locationIncoming引用只能从 API 接收的构造函数。
locationOutgoing引用只能发送到 API 的构造函数。

参数:

  • predicate- API 构造函数的名称。
  • stored_constructorFileId-用于数据库读/写操作的对象的名称。

每个唯一谓词只能有一个stored_constructor。

例如,当前 API 层位于以下位置:

  • 照片=>fileIdPhoto(即将到来)
  • 文档=>fileIdDocument(传入)
  • inputPhoto=>fileIdPhoto(发送)
  • inputPhotoFileLocation=>fileIdPhoto(outgoation)
  • 输入文档=>fileIdDocument(输出)
  • inputDocumentFileLocation=>fileIdDocument(outgoing)

当遇到左侧的对象之一时,使用该id字段生成FileId右侧类型的对象。

刷新引用时,替换file_reference左侧对象的字段。

(inputFileLocation当前映射文件会忽略旧版构造函数)。

起源

origin#b62177bf flags:# predicate:string is_constructor:flags.0?true stored_constructor:string stored_params:Vector<FieldExtractor> skipped_flags:Vector<string> needs_parent:flags.3?string parent_is_constructor:flags.4?true = origin;

包含有关origin如何从传入的方法响应或更新中提取和存储文件引用来源的说明。

注意:以下各节假设所有Update构造函数都已转换为Update构造函数向量,包括像updateShortMessage、updateShortSentMessage和updateShortChatMessage这样的短版本。这些短版本必须由客户端使用从方法调用中提取的信息预先转换为Update
构造函数。 虽然此操作可以在映射文件中完成,但这会不必要地增加路径数量:鉴于大多数客户端已经将短版本构造函数转换为 Update 构造函数,映射文件仅考虑以 Update 构造函数开头的路径。

参数:

  • predicate- 指示构造函数或提取原始字段必须开始的方法的名称。
  • is_constructor- 如果设置了参数,predicate则指向构造函数;否则,指向方法。
  • needs_parent- 如果设置,则包含一个构造函数的名称,该构造函数需要作为父级出现在反序列化对象中,或者包含一个方法的名称,我们正在反序列化该方法的响应,因为它将被操作中的一个或多个路径使用。
  • parent_is_constructor- 如果设置了参数,needs_parent则指向构造函数;否则,指向方法。
  • stored_constructorFileSource- 包含中指定的 TL 模式中的构造函数的名称,该构造函数在按如下方式fileReferenceOrigins.db_schema填充后应存储到数据库中。stored_params
  • stored_params- 包含有关如何填充FileSource构造函数的信息stored_constructor
  • skipped_flags- 在某些情况下,某些标志字段stored_constructor未被引用action:此字段包含当前源永远不会引用的标志的完整列表,必须取消设置。

每个唯一谓词可以有一个或多个stored_constructor具有不同参数的谓词。

如果is_constructor设置了该标志,则在反序列化包含谓词等于的构造函数时predicate,无论该构造函数位于传入的Update还是方法调用响应的任何深度,都执行以下操作:

  • 在开始反序列化构造函数之前FileSource,将类型为 `new` 的实例压stored_constructor入文件源栈。如果设置了该实例,但父类中没有该类型的构造函数或方法,
    则跳过压入操作。FileSourceneeds_parentneeds_parent
  • 在反序列化过程中,将所有遇到的FileIds(根据位置模式生成)与栈上当前所有类型的所有源关联起来。
  • 构造函数反序列化后FileSource,弹出已推送的类型stored_constructor,确保它能够按照要求进行处理stored_params(所有必需的标志字段均已设置,所有路径均可正确提取),如果可以,则相应地填充FileSource类型stored_constructor,并将源提交到数据库(使用FileId步骤 2 中关联的作为键,stored_constructor作为值)。如果已设置,但父级中没有类型为的构造函数或方法,
    则跳过此步骤。needs_parentneeds_parent

如果未is_constructor设置该标志,则在反序列化名称等于 的方法的响应时,执行以下操作:predicate

  • 在开始反序列化方法响应之前,将一个新的FileSource类型推stored_constructor送到文件源堆栈。
  • 在反序列化过程中,将所有遇到的FileIds(根据位置模式生成)与栈上当前所有类型的所有源关联起来。
  • 在反序列化方法响应后,弹出推送FileSource的类型stored_constructor,确保可以根据进行处理stored_params(所有必需的标志字段都已设置,所有路径都可以正确提取),如果是,则相应地填充FileSource类型stored_constructor,并将源提交到数据库(使用FileId步骤 2 中关联的作为键,stored_constructor作为值)。

请注意,方法 origins 不能使用needs_parent。

场提取

// ExtractorextractAndStore#72069549 from:Path to:string = FieldExtractor;extractInputStickerSetFromDocumentAttributesAndStore#369d8d14 from:Path to:string = FieldExtractor;extractInputStickerSetFromStickerSetAndStore#c167d470 from:Path to:string = FieldExtractor;extractPeerIdFromPeerAndStore#7d33019c from:Path to:string = FieldExtractor;extractPeerIdFromInputPeerAndStore#a51acfb4 from:Path to:string = FieldExtractor;extractChannelIdFromChannelAndStore#5675bc97 from:Path to:string = FieldExtractor;extractChannelIdFromInputChannelAndStore#b662660e from:Path to:string = FieldExtractor;extractUserIdFromUserAndStore#4778ec63 from:Path to:string = FieldExtractor;extractUserIdFromInputUserAndStore#7720aa2e from:Path to:string = FieldExtractor;// PathsparamNotFlag#acd9d5cf = ParamFlag;paramIsFlagAbortIfEmpty#f8fe9fee = ParamFlag;paramIsFlagFallback#202b77a1 fallback:TypedOp = ParamFlag;paramIsFlagPassthrough#1dc6e17d = ParamFlag;pathPart#8dc6ff46 constructor:string param:string flag:ParamFlag = PathPart;path#c3586a2 parts:Vector<PathPart> = Path;pathParent#58f13684 parts:Vector<PathPart> = Path;

字段提取器用于从一个或多个构造函数中提取参数,updateStory.story -> storyItem.media -> messageMediaDocument.document -> document.file_reference并将其存储到指定的字段中FileSource。

萃取器
extractAndStore#72069549 from:Path to:string = FieldExtractor;extractInputStickerSetFromDocumentAttributesAndStore#369d8d14 from:Path to:string = FieldExtractor;extractInputStickerSetFromStickerSetAndStore#c167d470 from:Path to:string = FieldExtractor;extractPeerIdFromPeerAndStore#7d33019c from:Path to:string = FieldExtractor;extractPeerIdFromInputPeerAndStore#a51acfb4 from:Path to:string = FieldExtractor;extractChannelIdFromChannelAndStore#5675bc97 from:Path to:string = FieldExtractor;extractChannelIdFromInputChannelAndStore#b662660e from:Path to:string = FieldExtractor;extractUserIdFromUserAndStore#4778ec63 from:Path to:string = FieldExtractor;extractUserIdFromInputUserAndStore#7720aa2e from:Path to:string = FieldExtractor;
extractAndStore

提取指定路径中的值并将其存储到$FileSource.$to.

extractInputStickerSetFromDocumentAttributesAndStore

接受Vector<DocumentAttribute>atfrom,查找documentAttributeSticker,并将documentAttributeSticker中包含的InputStickerSet存储到.中。stickerset$FileSource.$to

如果传递的向量中没有documentAttributeSticker类型的属性,则中止操作。

extractInputStickerSetFromStickerSetAndStore

从获取stickerSetfrom,将其转换为InputStickerSet,并将其存储到 中$FileSource.$to。

extractPeerIdFromPeerAndStore

获取对等节点,from将其转换为机器人 API 对等节点 ID(类型为long)»,并将其存储到$FileSource.$to。

extractPeerIdFromPeerAndStore

从获取InputPeerfrom,将其转换为bot API peer ID(类型为long),并将其存储到$FileSource.$to。

extractChannelIdFromChannelAndStore

获取通道,from获取id字段并将其存储到$FileSource.$to。

extractChannelIdFromInputChannelAndStore

从输入通道获取输入from通道,获取该channel_id字段并将其存储到输入通道中$FileSource.$to。

如果from指向inputChannelEmpty,则中止。

extractUserIdFromUserAndStore

获取用户,from获取id字段并将其存储到$FileSource.$to。

extractUserIdFromInputUserAndStore

从输入用户处获取from该user_id字段并将其存储到 中$FileSource.$to。

如果from指向inputUserSelf,则改为存储当前用户的 ID。

如果from指向inputUserEmpty,则中止。

路径

路径的第一部分始终指向:

  • 构造函数/方法origin(origin.predicate),对于path
  • 包含在父级中的构造函数/方法origin.needs_parent,对于pathParent

pathPart一条路径由多个s组成。

每个字段都pathPart包含以下字段,用于描述如何提取该字段。

  • constructor- 指示所需的构造函数/方法谓词。如果遇到不同的构造函数类型(例如documentEmpty而不是document),则中止提取。
    根据定义,如果传递了方法名,则它始终等于关联源的方法。
  • param- 表示必需参数;如果为空字符串,则表示方法的返回值。
  • flag- 包含以下构造函数之一:
    • paramNotFlag- 当前参数不是标志
    • paramIsFlagAbortIfEmpty- 当前参数是一个标志,如果未设置,则中止提取。
    • paramIsFlagFallback- 当前参数是一个标志,如果未设置,则使用指定的TypedOp备用值。请注意,在此上下文中不允许使用类型为 `<op>`、 `<op>` 和`
      <op>` 的 OP 。copyOpgetInputChannelByIdOpgetInputUserByIdOpgetInputPeerByIdOp
    • paramIsFlagPassthrough- 当前参数是一个标志,其值应原样复制/返回;只能用于路径的最后一个元素,并且仅当使用此路径的参数是相同类型的标志时,才能在 constructorOp/callOp/getMessageOp 的参数中使用。

行动

action#9539f410 stored_constructor:string action:ActionOp = Action;// ActionscallOp#c2ff3383 method:string args:Vector<TypedOpArg> = ActionOp;getMessageOp#237849e8 peer:TypedOp id:TypedOp from_scheduled:TypedOp quick_reply_shortcut_id:TypedOp = ActionOp;// For string => TypedOp dictionariestypedOpArg#3a2930c2 key:string value:TypedOp = TypedOpArg;// Typed constructors, the type is specified to simplify codegen,// but isn't strictly necessary as it can be inferred from the TypedOpOp.// It is fully pre-validated during the generation of the definition file.typedOp#705b10ec type:string op:TypedOpOp = TypedOp;

操作用于根据FileSource与文件引用关联的规则刷新过期的文件引用FileId(即,FILE_REFERENCE_EXPIRED使用文件引用时返回 RPC 错误)。

参数:

  • stored_constructor- 类型为的对象的名称FileSource,在db_schema.
  • actionstored_constructor- 刷新类型为.的文件源时要执行的操作

每个构造函数只能包含一个操作。

该动作的参数由一组typedOp构造函数组成。

typedOp»是一个构造函数的包装器,其中还包含关联的TypedOpOpTL;这对于评估来说并非绝对必要,但在从定义文件自动生成代码期间可能很有用。typeTypedOpOp

callOp

callOp是一个通用操作,它调用指定的方法,method并传入指定参数args。

callOp.args将始终包含至少所有必需参数,并且可能还包含一些标记参数。

getMessageOp

getMessageOp这是一个特殊操作,它会根据对象的类型(始终是InputPeer的子类型)调用messages.getMessages或channels.getMessages,并将对象作为向量参数的唯一元素传递。如果设置了点的标志,则应改为执行messages.getScheduledMessages。如果设置了点的标志,则应改为执行 messages.getQuickReplyMessages,并将标志的值传递给messages.getQuickReplyMessages,并将对象作为向量的唯一元素传递给messages.getQuickReplyMessages。peeridid
from_scheduled
quick_reply_shortcut_idquick_reply_shortcut_idshortcut_ididid

动作参数

copyOp#f48f418f from:string = TypedOpOp;getInputChannelByIdOp#3cb47531 from:string = TypedOpOp;getInputUserByIdOp#c0ee4326 from:string = TypedOpOp;getInputPeerByIdOp#19813750 from:string = TypedOpOp;// Literals & constructors (methods not allowed or needed here)constructorOp#107f8d8a constructor:string args:Vector<TypedOpArg> = TypedOpOp;vectorOp#f8fb8f72 values:Vector<TypedOp> = TypedOpOp;intLiteralOp#cbfabe7c value:int = TypedOpOp;longLiteralOp#d08b8d3a value:long = TypedOpOp;stringLiteralOp#2b56ea8e value:string = TypedOpOp;bytesLiteralOp#fdb395a4 value:bytes = TypedOpOp;boolLiteralOp#37e07911 value:Bool = TypedOpOp;doubleLiteralOp#3651e3bf value:double = TypedOpOp;themeFormatLiteralOp#8e4f9208 = TypedOpOp;

动作参数由构造函数表示TypedOpOp。

copyOp

最常用的类型,从存储的值复制值$FileSource.$from。

getInputChannelByIdOp

根据存储的long类型通道 ID,从客户端的对等数据库中返回InputChannel构造函数。$FileSource.$from

getInputUserByIdOp

根据存储的long类型通道 ID,从客户端的对等数据库中返回InputUser构造函数。$FileSource.$from

getInputPeerByIdOp

根据存储的long类型指定的机器人 API 对等 ID,从客户端的对等数据库中返回InputPeer构造函数。$FileSource.$from

constructorOp

constructor使用指定的参数构造类型为(谓词)的构造函数args。

vectorOp

构造一个包含传入构造函数的向量values。

intLiteralOp

使用传入的值构造一个字面整数value。

longLiteralOp

使用传入的值构造一个字面量longvalue。

stringLiteralOp

使用传入的值构造一个字面字符串value。

bytesLiteralOp

使用传入的值构造一个字面字节value。

boolLiteralOp

使用传入的值构造一个字面布尔value值。

doubleLiteralOp

使用传入的值构造一个字面双精度浮点数value。

themeFormatLiteralOp

构造一个字符串,指示客户端支持的主题引擎(用于处理与主题相关的媒体,如果客户端不支持主题,则可以为空字符串)。