Skip to content

release: v0.7.0-alpha — align library with MAX Bot API and fix reported issues - #39

Merged
CrazyAngelm merged 2 commits into
mainfrom
claude/laughing-ritchie-wvz9j9
Oct 11, 2026
Merged

CrazyAngelm merged 2 commits into
mainfrom
claude/laughing-ritchie-wvz9j9

Conversation

@CrazyAngelm

@CrazyAngelm CrazyAngelm commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Review of the whole library against the MAX Bot API (schemas of the official Go SDK max-bot-api-client-go) and fixes for all open issues. Version bumped to 0.7.0-alpha (contains breaking changes, see CHANGELOG).

Issues

Other API mismatches found during review

  • Long polling used update_id (absent in MAX API, always 0) as marker → now uses marker from the response
  • Default webhook secret header X-Max-Signature → X-Max-Bot-Api-Secret (real webhooks were rejected when a secret was set)
  • GetPinnedMessageAsync parses {"message": ...}; AddChatAdminRequest sends {"admins":[...]}
  • Incoming attachments merge payload + root fields (filename, size, thumbnail, duration, …); StickerAttachment, ShareAttachment
  • New update fields: message_id, user_id, admin_id, title, is_channel, muted_until, start_payload
  • Lenient enums for chat status / admin permissions; real package version in User-Agent
  • Microsoft.SourceLink.GitHub 8.0.0 → 10.0.401 (vulnerable Microsoft.Build.Tasks.Git made dotnet restore fail with NU1902)

Second commit — fixes from a multi-agent adversarial review of the first commit

  • Culture-invariant ids/query values (U+2212 minus broke negative group chat ids on sv-SE/nb-NO/fi-FI)
  • Webhook hardening: size + secret checked before the body is read/parsed (controller and MapMaxWebhook share one pipeline), no fallback to unconfigured IOptions<MaxBotOptions>, Webhook.HandlerTimeout applied, secret format validated, options updated only on success: true
  • Polling: poison updates are skipped instead of looping forever, marker advances only after a full batch, StopAsync waits for parallel handlers, AllowedUsernames checks the callback presser
  • Tolerant attachment parsing; attachment.not.ready retried by SendMessageAsync(SendMessageRequest) too; non-seekable upload streams buffered for retries; derived photo token not serialized next to photos; no trailing GET after resumable video/audio upload; Retry-After in the past handled
  • GetChatMembersPageAsync with marker, open_app / clipboard buttons, message_chat_created chat id

Test plan

  • dotnet format --verify-no-changes, dotnet format analyzers --verify-no-changes
  • dotnet build -c Release -warnaserror
  • dotnet test — 722 tests pass on net10.0 / net9.0 / net8.0, line coverage 81.25%
  • dotnet pack produces MaxMessenger.Bot.0.7.0-alpha nupkg/snupkg
  • CI (Ubuntu + Windows) on the latest head

🤖 Generated with Claude Code

https://claude.ai/code/session_01JWng6Vbuo8rweWS5x8PX56

…ed issues

Review of the whole library against the MAX Bot API schemas (official Go SDK)
plus fixes for all open issues.

Fixes:
- #34 AnswerCallbackQueryAsync sends callback_id; NewMessageBody uses AttachmentRequest[]/NewMessageLink
- #38 FileUploadResult exposes Photos/FileId again, Token is filled from photos,
  XML CDN responses are not treated as tokens; new IFilesApi.UploadAsync helper
- #22 flat {"code","message"} errors are parsed; MaxAttachmentNotReadyException;
  only attachment.not.ready is retried (send + edit)
- #23 GetChatsAsync parses {"chats","marker"}; GetChatListAsync for pagination
- #35 WebhookController is abstract (no implicit endpoint); app.MapMaxWebhook()
- #36 ConfigureWebhookAsync/DeleteWebhookAsync fall back to Webhook.Endpoint/SecretToken
- #37 Update.ChatId/Chat/ChatType filled from message.recipient
- #15 AttachmentRequest factories (ImageFromUrl, Image, Video, File, Location, ...)
- #18 #20 #21 #25 #16 regression tests and richer attachment/update models
- Polling marker comes from the response (MAX updates have no update_id)
- Default webhook secret header is X-Max-Bot-Api-Secret
- GetPinnedMessageAsync parses {"message"}; AddChatAdminRequest sends {"admins":[...]}
- Lenient enums for chat status / admin permissions, real User-Agent version
- Upload retries rewind the stream
- Bump Microsoft.SourceLink.GitHub to 10.0.401 (NU1902 broke restore)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JWng6Vbuo8rweWS5x8PX56
- Format ids and numeric query values with InvariantCulture (U+2212 minus broke
  negative group chat ids on sv-SE/nb-NO/fi-FI hosts)
- Webhook: controller and MapMaxWebhook share one pipeline that checks size and
  secret before reading/parsing the body; no fallback to unconfigured
  IOptions<MaxBotOptions> (it disabled the secret check); Webhook.HandlerTimeout
  is applied; secret format validated; ConfigureWebhookAsync only updates options
  on success and always stores an explicit secret
- Polling: tolerant batch parsing skips poison updates instead of looping
  forever; marker advances only after the whole batch; StopAsync waits for
  parallel handlers; AllowedUsernames uses the callback presser
- Attachments with unexpected field types no longer break deserialization
- attachment.not.ready is retried by SendMessageAsync(SendMessageRequest) too
- Uploads: non-seekable streams are buffered for retries; derived photo token is
  not serialized next to photos; resumable video/audio upload skips trailing GET
- Retry-After in the past no longer throws; Update.Chat/ChatId setters clear
  inference flags; message_chat_created exposes ChatId
- GetChatMembersPageAsync returns the marker; open_app/clipboard buttons;
  ChatType from is_channel; AddChatAdminRequest.UserId marked obsolete
- CHANGELOG/README accuracy fixes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JWng6Vbuo8rweWS5x8PX56
@CrazyAngelm
CrazyAngelm merged commit 6814d3a into main Oct 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment