Member invite and capability bits come from a different group-detail
field than the history-visibility switch. Reading the wrong one made
later writes carry leftover bits the server rejects.
The group-detail reply reports whether new members can see history as
a simple yes/no value. The write still flips that setting; the read
no longer expects a multi-bit field.
Bots can now read the current join option, robot-add option, member
invite policy, member permissions, history visibility, and search
settings that previously only had setters.
Fixes#385
Group detail and ext-info can now return the join option, search flags,
invite/permission/history bits, and robot-add switch so setters have a
matching read path.
Replace the shallow refreshMemberCache adapter with fetchGroupList
and fetchGroupMemberList ports. Skip, swallow, and coalesce stay
next to the join/leave/admin trigger.
Move retCode checks and URL assembly into GetGroupFileUrl,
GetPrivateFileUrl, and ListGroupFilesPage so GroupFileApi only
loops pages and resolves display names.
The receive path already collapsed resolvers into ConverterContext,
but elementsToOneBotSegments still took an 8-arg splat. Callers
could drop message-id or media sinks without a type error.
The public function now takes ConverterContext. Self-sent events
pass explicit null resolvers. get_forward_msg uses the instance ctx.
The registry already froze names, kinds, and raw reservations, but
handlers were a second mutable map filled through registerAction.
bind(ctx, api, rawFactories) now returns the complete name-to-handler
table. Stream actions expose toHandler. ApiHandler only installs and
dispatches. The public register ports are gone.
MockBridge.identity gained resolveUin for the like-list Identity
cascade. The uploadPrivate fixture listed every identity field and
failed core typecheck in CI.
FetchFriendListPage and FetchGroupMemberListPage deserialized as
identity functions and leaked Oidb property codes into ContactsApi.
Each page now returns a domain page. Contacts keeps pagination,
category assembly, member cache, and robot classification.
GetLike already filled cached UINs in deserialize. ProfileApi then
opened a second Contacts hop and threw on fetch failure.
Misses now go through Identity.resolveUin after invokeOidb, coalesced
by uid. ProfileApi.getLike is invoke-only. Unresolved rows stay
uin=0 and no longer fail the action.
Decoder used to write Identity: decodeGroupAdmin patched member roles
and decodeFriendMessage stashed invite-card msgseq. That split
observation with IncomingPacketPipeline.rememberEventIdentity and put
pending-application state on Identity.
Decoder now only returns events. Invite-card groupUin/msgseq ride on
FriendMessage; the live pipeline writes them to ContactsApi through
an optional port. Role self-heal for #93 stays in
rememberEventIdentity. History and forward decode do not write.
Identity no longer stores invite-card sequences.
Live #93 and #125 behavior is unchanged.
upload_file_stream now returns file_name with the original name.
create_flash_task accepts { file, name } so a streamed path can
keep the real filename on the fileset.
Fixes#361
create_flash_task already accepted `name`, but the flash card still
showed the first filename. Use a non-empty name as the fileset title
and keep the real filenames on the files themselves.
Fixes#363
Empty inbound tokens were gated on the WebUI page hostname / client IP,
so a remote panel visit blocked clearing the token even when the
listener was 127.0.0.1. Trust the bind host as well: loopback listeners
are not reachable from outside, while 0.0.0.0 still requires a local
WebUI session.
create_flash_task loaded every fileset file through loadBinarySource
and kept the bytes through hash, commit, and sliceupload, so a single
file over 1 GiB could not be sent. Stage to disk like group files,
stream MD5/SHA1/Sha1StateV, then POST 1 MiB chunks from FileChunkSource.
Do not reuse video sha1Blocks as Sha1StateV: an exact N-MiB file would
ship an extra un-finalized last-slice state. Local/HTTP sources use the
4 GiB group-file ceiling; inline base64 stays at 1 GiB because stage
still decodes it in RAM. Protocol order, seconds-pass, and multi-file
commit are unchanged.
Fixes#359
Current clients put fileset identity on markdown extInfo and the
open_fileset scheme, not data.fileSetId. Empty message arrays were
the old scraper missing those fields.
Fixes#358