SocialPoster.Posting
0.6.5
See the version list below for details.
dotnet add package SocialPoster.Posting --version 0.6.5
NuGet\Install-Package SocialPoster.Posting -Version 0.6.5
<PackageReference Include="SocialPoster.Posting" Version="0.6.5" />
<PackageVersion Include="SocialPoster.Posting" Version="0.6.5" />
<PackageReference Include="SocialPoster.Posting" />
paket add SocialPoster.Posting --version 0.6.5
#r "nuget: SocialPoster.Posting, 0.6.5"
#:package SocialPoster.Posting@0.6.5
#addin nuget:?package=SocialPoster.Posting&version=0.6.5
#tool nuget:?package=SocialPoster.Posting&version=0.6.5
SocialPoster.Posting
Post text and media to X, Bluesky, LinkedIn, Mastodon and Threads from any .NET app. No database,
UI or ASP.NET required: it needs only HttpClient and a place to read your tokens from.
This is the posting engine behind SocialPoster, the desktop/Blazor app.
Install
Requires .NET 10. Add the package with the .NET CLI:
dotnet add package SocialPoster.Posting
Or with the Package Manager Console in Visual Studio:
Install-Package SocialPoster.Posting
Or add it to your .csproj directly:
<PackageReference Include="SocialPoster.Posting" Version="0.6.1" />
To build from source instead, clone the repository and add a project reference:
dotnet add reference path/to/SocialPoster/src/SocialPoster.Posting/SocialPoster.Posting.csproj
Quick start
using Microsoft.Extensions.DependencyInjection;
using SocialPoster.Posting;
using SocialPoster.Posting.Services;
var services = new ServiceCollection();
services.AddSocialPosting();
services.AddSingleton<ICredentialStore>(new InMemoryCredentialStore(new Dictionary<string, string?>
{
[SettingKeys.BlueskyHandle] = "you.bsky.social",
[SettingKeys.BlueskyAppPassword] = "xxxx-xxxx-xxxx-xxxx",
[SettingKeys.MastodonInstance] = "https://mastodon.social/",
[SettingKeys.MastodonAccessToken] = "...",
}));
await using var provider = services.BuildServiceProvider();
var publisher = provider.GetRequiredService<SocialPublisher>();
var results = await publisher.PublishTextAsync("Hello from .NET!", [Platform.Bluesky, Platform.Mastodon]);
foreach (var r in results)
Console.WriteLine(r.Success ? $"{r.Platform}: {r.Url}" : $"{r.Platform} failed: {r.Error}");
Each platform is rendered, validated and published independently. A failure on one platform (bad token, post too long,
unsupported media) is returned as a PublishResult with Success = false; it never throws or stops the others.
Credentials
Clients read tokens through ICredentialStore, using the keys in SettingKeys:
| Platform | Keys |
|---|---|
| Bluesky | BlueskyHandle, BlueskyAppPassword, optional BlueskyService |
| X | XConsumerKey, XConsumerSecret, XAccessToken, XAccessTokenSecret (or XPostMethod = "intent" for a browser link, no API) |
LinkedInAccessToken, LinkedInPersonUrn, optional LinkedInApiVersion |
|
| Mastodon | MastodonInstance, MastodonAccessToken |
| Threads | ThreadsAccessToken, ThreadsUserId (or call ThreadsClient.ConfigureAsync(token) to verify and fill both) |
InMemoryCredentialStore is the default. To use your own vault, key store or config, implement ICredentialStore
and register it before or after AddSocialPosting() (yours wins).
Posting with media, mentions and previews
publisher.PublishAsync(templates, resolve, media)renders a template per platform.{@key}mentions are resolved by yourContactResolverto each platform's handle format (@user@serveron Mastodon, a real facet on Bluesky, a LinkedIn URN, and so on) and fall back to a plain name when a contact has no account there.PostRenderer.Render(platform, template, resolve)gives you the exact text, character count and warnings without posting, which is handy for live previews.MediaAttachment/MediaRulescheck per-platform limits (counts, sizes, formats). Threads is text only: its API accepts media only by public URL, not uploads.- Counting follows each platform's rules (X weighted characters and 23-character URLs, Bluesky graphemes with shortened links, Mastodon/Threads graphemes).
Individual clients (BlueskyClient, XClient, LinkedInClient, MastodonClient, ThreadsClient) are public if you
want to call one directly.
Notes
- Everything lives in the
SocialPoster.PostingandSocialPoster.Posting.Servicesnamespaces. The SocialPoster app (SocialPoster.Core) is built on these same types. - Tokens are sent only to the platform's own host; Mastodon and Threads clients never follow redirects.
HttpClienttimeout defaults to 30 minutes for large uploads:AddSocialPosting(o => o.PostingTimeout = ...).
MIT licensed.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Http (>= 10.0.13)
- Microsoft.Extensions.Options (>= 10.0.13)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on SocialPoster.Posting:
| Package | Downloads |
|---|---|
|
SocialPoster.Core
Reusable SocialPoster app services: SQLite storage, contacts, scheduling and the Copilot account finder. Posting itself lives in SocialPoster.Posting. |
GitHub repositories
This package is not used by any popular GitHub repositories.