Add VK (VKontakte) as a platform - #311
Open
gynsus wants to merge 7 commits into
Open
Conversation
VK publishes to a community or profile wall via wall.post with a user access token (scope: wall, photos, groups, video, offline) — VK no longer grants the wall scope to new OAuth apps, so the connect flow accepts a token directly, modeled on the Bluesky credential form: validate the token, list manageable walls (own profile + administered communities), store the chosen wall as the account. Publisher uploads photos via getWallUploadServer/saveWallPhoto and videos via video.save, then attaches them to wall.post. VK reports failures as HTTP 200 with an error object; error 5 maps to TokenExpiredException, rate-limit and permission codes to their categories.
VK joins the analytics page: account level shows the community member count (profile wall: follower count) via groups.getById/users.get; post level pulls views, likes, reposts and comments from wall.getById. Deeper community stats need the stats scope the connect flow doesn't request, so they are deliberately out.
wall.post with a user token is limited to standalone apps; community access tokens publish to their community regardless of the issuing app type. users.get error 27 tells the two apart on the shared token field; verification for community-token accounts goes through groups.getById.
VK has no API to resolve which community a token belongs to (groups.getById without group_ids returns nothing for community tokens), so the form asks for the community link/screen name and groups.getOnlineStatus — callable only with the community's own token — proves the key matches it.
…or 27 users.get is callable with a community access token — without user_ids it returns an empty response instead of a group-auth error, so a successful-but-empty users.get is the community-token signal.
groups.getOnlineStatus fails with 'group messages is disabled' for communities that turned messages off; getCallbackConfirmationCode works with the community's own token regardless and still rejects foreign tokens.
Contributor
|
@gynsus I'm looking into this; do I need a Russian VPN to install this app? |
Author
|
Should work worldwide, no VPN needed — vk.com and api.vk.com are not geo-restricted. For the easiest test path you don't even need to register a VK app: any VK account (a non-Russian phone number should work for signup) → create a community → Manage → API usage → Access tokens → create a token with photos/wall/manage → paste it into TryPost's Connect VK form. That exercises the recommended community-token flow end to end. The user-token path needs a standalone app of your own, but it's optional — happy to walk you through it if you want to test video upload too. |
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.
Why
VK (VKontakte) is the dominant social network for Russian-speaking audiences, and self-hosted TryPost users publishing there currently have to do it by hand. This PR adds VK as a full platform: connect, publish (text, photos, video), and analytics.
The connect flow is deliberately token-based, not OAuth. VK stopped granting the
wallscope to newly registered OAuth apps years ago, so a stock "log in with VK" integration cannot post to walls at all. What still works, verified against the live API:wall.postwithowner_id=-<group>+from_group=1is allowed for these regardless of the app type that issued them; this is the recommended path and the one the form suggests first;wall, photos, groups, video, offlinescopes) — needed for profile walls and for video upload, which VK only allows with user tokens.What changed
Platform::Vk+ContentType::VkPost(16,000-char limit, VK's actual cap), lang strings for all 16 locales, platform tile/logo/theme.VkController): one token field for both token kinds. A community token is detected by a successful-but-emptyusers.get(the method accepts community tokens and just returns an empty list withoutuser_ids— it does not error). Three live-API quirks shaped the flow:vk.com/club…, screen name, or bare id — all normalized) and resolves it viagroups.getById.groups.getCallbackConfirmationCode, which only answers for the token's own community. (groups.getOnlineStatuslooked right for this but fails with "group messages is disabled" for communities that turned messages off.)users.get+groups.get(filter=admin,editor)builds a picker of publishable walls (own profile + administered communities).VkPublisher):wall.postwith attachments; photos via the three-stepgetWallUploadServer → upload → saveWallPhotoflow (images optimized first), video viavideo.savewithwallpost=0so the video attaches to our post instead of auto-publishing. A failed single attachment is skipped with a log, not a sunk post. VK reports errors as HTTP 200 +errorobject;VkPublishExceptionmaps codes to the shared error categories (rate limit / permission / media format).VkAnalytics): community member count on the account level; views/likes/reposts/comments per post viawall.getById. Handles both the v5.199 response shape (response.groups[]/response.items[]) and the older flat one.ConnectionVerifier):users.getfor user tokens,groups.getByIdfor community tokens (whichusers.getcan't verify); VK error 5 is the confirmed-dead-token signal.Testing
VkControllerTest(9 tests: both token kinds, community mismatch/unknown address, VK-side errors),VkPublisherTest,VkAnalyticsTest,VkPublishExceptionTest, plusConnectionVerifierTestadditions for both verify paths.What only you can decide
Token-based connect is unusual for this codebase — every other platform is OAuth. We kept the UI to the same two-step popup pattern as LinkedIn's identity picker, but if you'd rather gate VK behind a
SELF_HOSTED-style env flag until it settles, that's a small change on top.