story: stories, albums, viewers and stealth on the registry - #12
Merged
Conversation
Three shapes exist because the API makes a distinction the GUI hides: a story item comes back as one of three TL classes for one id, an audience is a base rule plus exceptions rather than a value, and the viewers screen mixes plain views with forwards and reposts. Media areas are flattened into one struct with a type discriminator so that `story get --areas-out` writes JSON `story post --areas` reads back.
Four RPCs behind one `story list` because the GUI shows one grid with tabs; `story read` clears the unread ring and only `--register-view` puts the account in the poster's viewer list, because an agent that silently appears there is a privacy bug. The feed pages on an opaque state rather than an offset, so its cursor carries the state and the next flag instead of an id that would restart the walk.
The v1 command, its IPC route and ClientWrapper.set_stories_hidden() are gone; the path stays invocable because the op declares it as a legacy path, --unhide included. That makes the registry generate the 'user' group, so 'user get' and 'user dialog-status' move into LEGACY_EXTRAS until PR-5 migrates them rather than being a second group of the same name, which build_cli() refuses on purpose.
The whole-domain waiver is gone: 104 of the 120 required ids are covered and the remaining 16 name the group that owns them — close friends are contacts, the live-story call is 'vc', story notifications are 'notify'. Three ids other domains had waived to PR-8 or PR-5 are covered here instead, so their waivers go too.
…o watch Telethon has no event builder for stories, so the six story updates only arrive through a Raw handler. They get their own normaliser rather than a branch in normalise(): the raw feed also carries UpdateNewMessage, whose class name matches that function's substring table and would emit a second, empty message_new beside the real one.
The fake grows real story items per peer, a profile page and an archive that pin/unpin really move ids between, albums, viewer rows and the opaque feed state. The suite asserts the three things only a request can show: reading a story sends readStories and nothing else, the privacy vector is base-then-allow-then-disallow, and a channel story's viewers come from getStoryReactionsList with the source named in a warning. canSendStory has no result union on layer 227 — the server raises — so the refusal is read off the error, keeping the seconds or boosts the message carries.
…ind it AGENT.md gains a Stories section built around the four rules that bite: reading is not being seen, the audience is a base rule plus exceptions in that order, a feed placeholder is not a caption-less story, and the post quota moves under you. The v1 'user hide-stories' paragraph now points at 'story hide' and keeps its promise. CHANGELOG records the group, the one deletion and the paths that survive it.
…lags getPeerStories hands back the peer's whole active set in one call, so guessing has_more from a full page there would hand out a cursor that returns nothing. The condition now has a name and the comment says why.
Three of this branch's decisions were written against a `main` that has since moved. Replaying them verbatim would have produced a tree that does not import, so they are merged rather than repeated. `user hide-stories`. PR-5 landed it as an operation of its own while this branch declared the same path as a legacy path of `story hide`, and the registry refuses one alias claimed by two ops — correctly, because a toggle with two implementations is a toggle that will disagree with itself. `story hide` keeps the implementation and absorbs what the `user` op had that it did not: several peers in one pass, and the whole-bar toggle. AGENT.md's four frozen keys, the idempotence and the bulk `peers` shape are unchanged, and PR-5's contract tests exercise them through `story.hide`. `hidden` and `already` lose their defaults so that `omit_defaults` cannot drop the two false values AGENT.md publishes. Story events. PR-4's taxonomy already names all six story constructors and the daemon already subscribes with one `events.Raw()` handler, so the second normaliser and the second handler are gone: the payload shaping is a branch inside `normalise_update`, keeping the fine-grained `kind` that tells a received story reaction from one this account sent. Waivers. PR-5, PR-7 and PR-11 cover close friends, boost status and the whole live-story call surface outright, so `stories` needs 7 waivers rather than 16 and the floors rise to what the registry now claims. The fake client is one merged file, so nine handler pairs are merged by hand rather than shadowed: `SearchPosts` dispatches on the TL namespace (`messages.` and `stories.` share a class name), `LoadAsyncGraph` on the token, and the blocklist, hidden-peer and read-marker stores collapse onto one field each.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR-8 of the v2 plan: stories on the operation registry — 31 operations under
story(feed all/hidden/peer, get by id or link, read, react, reply, share, post/edit/delete with the full privacy-rule vocabulary and media areas, pin/unpin/reorder on profile, archive, albums, viewers list with reactions/search/export, hide/unhide peers, the story-only blocklist, stealth mode, stats, search, live stories,story watch).user hide-storiesstays invocable as a legacy path ofstory hide.payload@X,Y,W,H[,ROT[,RADIUS]]sugar over an authoritative--areasJSON thatstory get --areas-outround-trips.story readclears your own unread ring and tells the poster nothing; appearing in their viewer list costs an explicit--register-view.story live getcannot reach the stream's viewer count/publisher in layer 227 and says so.What the rebase onto
mainchangedThree of the branch's decisions were written against a
mainthat has since moved, and were merged rather than replayed:user.hide-storiesas an operation of its own while this branch madeuser hide-storiesa legacy path ofstory.hide— and the registry refuses one alias claimed by two ops.story hidekeeps the implementation and absorbs what theuserop had that it did not (several peers in one pass,--allfor the whole bar);user hide-storiesis now purely the §12.4 path onto it. AGENT.md's four frozen keys (user_id,username,hidden,already), the idempotence and the bulkpeersshape are unchanged, and PR-5's contract tests now exercise them throughstory.hide.core/eventtypes.pyand already subscribes with a singleevents.Raw()handler, so the branch's second normaliser and second Raw handler are gone: the story payload shaping is a branch insidenormalise_update, keeping the fine-grainedkindthat tells a received story reaction from one this account sent.storiesneeds only 7 waivers, not 16.The fake Telegram client is one merged file now, so nine handler pairs were merged by hand rather than shadowed:
SearchPostsdispatches on the TL namespace (messages.vsstories.share a class name),LoadAsyncGraphon the token, and the blocklist, hidden-peers and read-marker stores collapsed onto one field each.Numbers
8 commits, 10,449 tests green, ruff + mypy clean,
make docs parityreproduces the checked-in artefacts. Parity:stories113/120 required ids covered and 100 % accounted; P0 floor 148 → 161, covered floor 1285 → 1390; total 1390/1797 covered, 100 % accounted.