rpc: add android startup and messaging compat

(cherry picked from commit d718593156cc7310105007f37645948c17637e0a)
This commit is contained in:
A 2026-06-08 22:30:23 +08:00
parent fc01346160
commit b4e47c894f
11 changed files with 184 additions and 2 deletions

View file

@ -88,6 +88,13 @@ status 取值done(真实实现) / stub(兼容响应) / todo(已发现未实
| help.getPromoData | stub | empty | 无 PSA/MTProxy 推广,返回空并设置短期 expires |
| help.getTermsOfServiceUpdate | stub | empty | 第一阶段无 TOS 更新 |
| help.getPremiumPromo | stub | empty | 第一阶段不做 Premium 展示数据 |
| help.getInviteText | stub | default-text | DrKLO Android 主界面预取邀请文案;当前不接配置中心 invite text返回默认短文避免启动后 NOT_IMPLEMENTED |
## Payments / Stars
| method | status | behavior | note |
|---|---|---|---|
| payments.getStarsStatus | stub | zero-balance | DrKLO Android 消息页会后台预取 stars/TON 余额;当前不实现 Stars 商业模型,按请求类型返回零余额 `payments.starsStatus`history/chats/users 为空,避免发送后 NOT_IMPLEMENTED |
## Auth
@ -117,7 +124,7 @@ status 取值done(真实实现) / stub(兼容响应) / todo(已发现未实
| account.setPrivacy | done | real-privacy/online-update | 校验 `InputPrivacyKey/InputPrivacyRule` 与 input user access_hash 后持久化;返回 `account.privacyRules` 并向当前账号在线 session 推 `updatePrivacy`Stars/Premium/Bot 等高级产品只保存规则,不扩展商业模型。离线 `updates.getDifference` 恢复 `updatePrivacy` 仍需扩展 `user_update_events` privacy payload |
| account.getAuthorizations / account.resetAuthorization | done | real-devices | 从 `authorizations` 返回当前账号设备列表,带 current/hash/device/app/ip/dateresetAuthorization 按 hash 删除同账号授权并清理 session/auth cache |
| account.getWebAuthorizations / account.resetWebAuthorization / account.resetWebAuthorizations | stub | empty/ack | 当前无 Telegram Login Widget/Web 授权模型,返回空列表并接受清理请求 |
| account.registerDevice / account.unregisterDevice | stub | ack | 当前未接真实 APNS/FCM 推送网关,接受 TDesktop 设备 token 注册/注销避免后台噪声 |
| account.registerDevice / account.unregisterDevice | stub | ack+legacy-adapter | 当前未接真实 APNS/FCM 推送网关,接受 TDesktop/DrKLO 设备 token 注册/注销避免后台噪声DrKLO Android 仍会发 legacy `account.registerDevice#637ea878 token_type:int token:string`RPC edge 解码后返回 true |
| account.getDefaultEmojiStatuses / account.getRecentEmojiStatuses / account.clearRecentEmojiStatuses / account.updateEmojiStatus | stub | empty/notModified | 当前不提供云 emoji status读取返回空或 notModified写入/清理返回成功 |
| account.getCollectibleEmojiStatuses | stub | empty | TDesktop 启动/emoji status 面板会刷新 collectible gift emoji statuses当前无 gift/status 模型,返回空 `account.emojiStatuses` |
| account.getDefaultProfilePhotoEmojis / account.getDefaultGroupPhotoEmojis / account.getDefaultBackgroundEmojis / account.getChannelDefaultEmojiStatuses / account.getChannelRestrictedStatusEmojis | stub | empty | TDesktop 头像/背景/频道状态编辑页默认 emoji 入口;当前无 custom-emoji 候选,返回空 `emojiList` 或空 statuses |
@ -131,6 +138,7 @@ status 取值done(真实实现) / stub(兼容响应) / todo(已发现未实
| account.getAutoDownloadSettings / account.saveAutoDownloadSettings | stub | defaults/ack | TDesktop 自动下载设置预取;返回保守默认下载阈值,写入接受但不持久化 |
| account.setAuthorizationTTL / account.changeAuthorizationSettings | stub | ack | Settings 设备管理长尾写入入口;当前只维护 active authorization 删除,不持久化授权 TTL/设备名设置 |
| account.getSavedMusicIds | stub | empty | TDesktop saved/profile music 预取;当前没有 profile music media store返回空 id vector |
| account.getSavedRingtones | stub | empty | DrKLO Android 主界面通知音预取;当前无 saved ringtone store返回空 `account.savedRingtones` |
| account.updateStatus | done | persisted-presence | 记录 `auth_key/session/user` 维度运行时在线状态并持久化 `users.last_seen_at``offline=false` 与重连后 session 身份恢复都会写入 last_seen 并推送 `updateUserStatus(userStatusOnline expires=now+5m)``offline=true` 写入精确 `userStatusOffline.was_online`;最后一个 MTProto session 断开/destroy_session 也会写 last_seen 并推送 offline。状态推送给当前用户其它在线 session、在线联系人、以及已有私聊 dialog 的在线对端session 恢复时还会向当前 session 补发在线联系人/私聊对端状态。users/dialog/history projection 已按 StatusTimestamp privacy 裁剪返回值presence fanout 的精细 privacy 过滤仍为后续项 |
## Updates
@ -138,7 +146,7 @@ status 取值done(真实实现) / stub(兼容响应) / todo(已发现未实
| method | status | behavior | note |
|---|---|---|---|
| updates.getState | done | real | auth_key+user 维度持久化 update_states账号级当前 pts 报告**最大连续已提交 pts**MaxContiguousPts非 allocator 最大已分配值),避免同设备换号/多账号串差分,也避免越过在途空洞 |
| updates.getDifference | done | real | 按 user_id 从 user_update_events 拉取 pts 后增量;只返回从客户端 pts 起**连续**的事件(遇在途空洞即截断),超 100 条置 differenceSlice支持 new_message、read_history_inbox/read_history_outbox私聊与 channel peerchannel read 映射 updateReadChannelInbox、edit_message、message_reactions输出带最新 `message.reactions` 的 affected message + `updateMessageReactions`,并按 viewer 重取最新聚合,避免 TDesktop 离线恢复时本地 message cache 不刷新、read_message_contents、delete_messages、contacts_reset、dialog pinned/order/manual unread、peer_settings、dialog filters/folder peers 与 noop gap消息事件携带 fwd/reply 所需 users/chatspayload 来自 durable log。若请求 date 后存在当前账号 active channel 的 channel durable events会追加计算型 `updateChannelTooLong(channel_id,pts)` nudge提示 TDesktop 再走 `updates.getChannelDifference`;该 nudge 不写 `user_update_events`,不消耗账号 pts。**账号级绝不返回 `differenceTooLong`**:已核对 TDesktop 基线 `api_updates.cpp:516`——对账号级 differenceTooLong 只打一行日志、不读 pts 且漏 `setRequesting(false)`,会永久锁死 update 引擎(`:689` 早退,重连/新 session 不可恢复);落后客户端改用 `differenceSlice` 续传。因此 `user_update_events` **永久保留、不做 retention 裁剪**(对齐 参考实现),详见 docs/performance-audit.md 附录 C |
| updates.getDifference | done | real+legacy-adapter | 按 user_id 从 user_update_events 拉取 pts 后增量;只返回从客户端 pts 起**连续**的事件(遇在途空洞即截断),超 100 条置 differenceSlice支持 new_message、read_history_inbox/read_history_outbox私聊与 channel peerchannel read 映射 updateReadChannelInbox、edit_message、message_reactions输出带最新 `message.reactions` 的 affected message + `updateMessageReactions`,并按 viewer 重取最新聚合,避免 TDesktop 离线恢复时本地 message cache 不刷新、read_message_contents、delete_messages、contacts_reset、dialog pinned/order/manual unread、peer_settings、dialog filters/folder peers 与 noop gap消息事件携带 fwd/reply 所需 users/chatspayload 来自 durable log。若请求 date 后存在当前账号 active channel 的 channel durable events会追加计算型 `updateChannelTooLong(channel_id,pts)` nudge提示 TDesktop 再走 `updates.getChannelDifference`;该 nudge 不写 `user_update_events`,不消耗账号 pts。DrKLO Android 仍会发 legacy `#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int`RPC edge 映射到当前 Layer225 request 后复用本实现。**账号级绝不返回 `differenceTooLong`**:已核对 TDesktop 基线 `api_updates.cpp:516`——对账号级 differenceTooLong 只打一行日志、不读 pts 且漏 `setRequesting(false)`,会永久锁死 update 引擎(`:689` 早退,重连/新 session 不可恢复);落后客户端改用 `differenceSlice` 续传。因此 `user_update_events` **永久保留、不做 retention 裁剪**(对齐 参考实现),详见 docs/performance-audit.md 附录 C |
| updates.getChannelDifference | done | real-channel | 超级群/频道使用 channel 维度 durable log`channel_update_events(channel_id, pts, pts_count, ...)`;按 channel pts 返回 `channelDifferenceEmpty/channelDifference/channelDifferenceTooLong`limit cap=100`pts < 0``pts > current_channel_pts` 返回 `PERSISTENT_TIMESTAMP_INVALID`;当前 member 的 `available_min_pts` 会抬高请求 pts避免新加入/重新加入成员拉到入群前消息类 durable 事件;公共 username 频道允许非成员以只读预览身份拉可见差分并返回 synthetic read dialog私有频道和禁看用户仍返回权限错误`current_channel_pts-pts > cap` 时返回带当前 dialog pts 和最新有界消息快照的 `channelDifferenceTooLong`,避免大频道旧 pts 客户端循环拉大量页;普通 difference 优先使用事件 payload 中的 message 快照,连续编辑/删除后不会被当前消息状态污染;`updateChannelParticipant` 不进入 channel pts log成员权限/封禁状态靠在线 `updateChannelParticipant/updateChannel``channels.getFullChannel/getParticipants/getParticipant` 刷新;本页消息的 sender/send_as/fwd_from/reply_to/action peers 会随 users/chats 返回,禁止复用 user_update_events |
### 兼容硬约束pts / pts_count跨所有产生 update 的 RPC
@ -234,6 +242,7 @@ outbox 多 worker 并发 + 发送事务乱序提交 → **主动推送可能乱
| messages.getRecentStickers | stub | empty/notModified | TDesktop 输入框/emoji 面板预取最近贴纸;第一阶段返回空列表或 hash notModified |
| messages.getFavedStickers | stub | empty/notModified | TDesktop 输入框/emoji 面板预取收藏贴纸;第一阶段返回空列表或 hash notModified |
| messages.getStickers | stub | notModified | 第一阶段不提供贴纸搜索结果 |
| messages.getArchivedStickers | stub | empty | DrKLO Android 聊天页/贴纸设置后台预取归档贴纸;当前无 archived sticker store返回空 `messages.archivedStickers`,避免后台 NOT_IMPLEMENTED 重试 |
| messages.getStickerSet | done | real-sets | `stickerSetRefFromInput``inputStickerSetID/ShortName/AnimatedEmoji/Dice/EmojiGenericAnimations` 解析为 `domain.StickerSetRef`,从 `sticker_sets` 加载集元数据 + 按 `document_ids` 顺序加载真实文档(含 packsdocument id / pack document id / thumb_document_id 均为 seed 阶段归一后的服务端 id返回完整 `messages.stickerSet`hash 命中返回 notModified未 seed 的系统集/未知短名回退空集 stub 避免破坏客户端 |
| messages.getFeaturedStickers | stub | empty/notModified | TDesktop 输入框/emoji 面板预取推荐贴纸;第一阶段返回空列表或 hash notModified |
| messages.getEmojiGroups | stub | notModified | 第一阶段不提供 emoji 分组目录 |
@ -375,6 +384,7 @@ outbox 多 worker 并发 + 发送事务乱序提交 → **主动推送可能乱
| contacts.block | done | real-blocklist | 写入当前 owner blocklist幂等同步刷新 peer settingsstory-only block flag 当前按主 blocklist 处理,完整 stories privacy 留后续 |
| contacts.unblock | done | real-blocklist | 从当前 owner blocklist 删除 peer幂等同步刷新 peer settings |
| contacts.getBlocked | done | real-blocklist | Settings 隐私/安全预取;`contacts.block/unblock/getBlocked` 维护 `owner_user_id + blocked_user_id` 唯一 blocklistlimit cap=100按 date/user_id 返回 `peerBlocked` + users`contacts.getPeerSettings` 按当前 owner block 状态返回 block/unblock action并按 PhoneNumber privacy 决定 `ShareContact`。blocklist 仍是私聊 send/edit/delete 的拒绝 gate完整 privacy key 用于资料投影/手机号分享 |
| contacts.getBirthdays | stub | empty | DrKLO Android 主界面周期性预取联系人生日;当前无 birthday reminder store返回空 contacts/users |
| contacts.getTopPeers | stub | disabled | 第一阶段不维护 top peers 统计 |
| contacts.getSponsoredPeers | stub | empty | 第一阶段不做 sponsored peersTDesktop 搜索框分支返回 sponsoredPeersEmpty |
| users.getUsers | done | real | InputUserSelf 与已知 InputUser 返回用户(含 777000 官方账号);未登录则跳过(空列表) |
@ -390,6 +400,8 @@ outbox 多 worker 并发 + 发送事务乱序提交 → **主动推送可能乱
| stories.getStoriesArchive | stub | empty | TDesktop 主界面后台拉 archived stories第一阶段返回空 archive |
| stories.getPinnedStories | stub | empty | TDesktop 资料页 stories 区域后台查询;当前返回空 `stories.stories` |
| stories.getAlbums | stub | empty | TDesktop 资料页 story albums 后台查询;当前无 story album 模型,返回空 `stories.albums` |
| stories.getAllReadPeerStories | stub | empty-updates | DrKLO Android 登录后拉已读 story 状态;当前无 story read store返回空 updates |
| stories.getPeerMaxIDs | stub | empty-recent | DrKLO Android 登录后按 peer 拉已读 story max id当前无 story read store按输入 peer 数返回空 `recentStory` |
| stories.sendReaction | stub | validated-noop | 当前无 story store校验 peer/story_id/reaction`add_to_recent` 会更新账号 top/recent emoji reaction返回空 updates避免 story 反应入口落 unknown |
| payments.getStarGiftActiveAuctions | stub | notModified | 第一阶段不做 stars/gifts |
| payments.getSavedStarGifts | stub | empty | TDesktop 资料页 gifts 区域后台查询;当前返回空 `payments.savedStarGifts` |