Skip to content

Instantly share code, notes, and snippets.

@heyajulia
Last active November 18, 2024 16:57
Show Gist options
  • Save heyajulia/40d455c1df71833994bbac0a0a0643ca to your computer and use it in GitHub Desktop.
Save heyajulia/40d455c1df71833994bbac0a0a0643ca to your computer and use it in GitHub Desktop.
http \
  POST \
  https://bsky.social/xrpc/com.atproto.server.createSession \
  identifier=USERNAME.bsky.social \
  password=APP_SPECIFIC_PASSWORD

http \
  POST \
  https://bsky.social/xrpc/com.atproto.repo.createRecord \
  Authorization:"Bearer ACCESS_JWT" \
  repo=DID \
  collection=app.bsky.feed.post \
  record\[\$type\]=app.bsky.feed.post \
  record\[text\]="Test post please ignore" \
  record\[createdAt\]="$(date -Iseconds)"

Copy the ACCESS_JWT and DID from the response of the createSession call (in real code, you'd store the response in a variable).

These resources helped me put this together:

@heyajulia
Copy link
Author

heyajulia commented Nov 1, 2024

@heyajulia
Copy link
Author

@heyajulia
Copy link
Author

@heyajulia
Copy link
Author

@heyajulia
Copy link
Author

Threadgate (restrict replies to) a post:

http \
  POST \
  https://bsky.social/xrpc/com.atproto.repo.createRecord \
  Authorization:"Bearer $ACCESS_JWT" \
  rkey=3l7xx22ztwz2k \
  repo="did:plc:o55pshlohxgjgvsg7nusfqdf" \
  collection="app.bsky.feed.threadgate" \
  record\[\$type\]="app.bsky.feed.threadgate" \
  record\[post\]="at://did:plc:o55pshlohxgjgvsg7nusfqdf/app.bsky.feed.post/3l7xx22ztwz2k" \
  record\[allow\]:=\[\] \
  record\[createdAt\]="$(date -Iseconds)"

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 282
Content-Type: application/json; charset=utf-8
Date: Sat, 02 Nov 2024 14:56:51 GMT
RateLimit-Limit: 3000
RateLimit-Policy: 3000;w=300
RateLimit-Remaining: 2996
RateLimit-Reset: 1730559657
Vary: Accept-Encoding
X-Powered-By: Express

{
    "cid": "bafyreiay5zlzjnpf7kuhjp7lkks7kkujhaeqrgjadsm4busclxnmwsg3ke",
    "commit": {
        "cid": "bafyreih4klondc6vkwl6awp6wuwbu56kdwt4aewxbgh5y7wpl6be4c4nvu",
        "rev": "3l7xx3jro2b2y"
    },
    "uri": "at://did:plc:o55pshlohxgjgvsg7nusfqdf/app.bsky.feed.threadgate/3l7xx22ztwz2k",
    "validationStatus": "valid"
}

@heyajulia
Copy link
Author

using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text.Json.Serialization;

var client = new HttpClient { BaseAddress = new Uri("https://bsky.social/xrpc/") };
var resp = await client.PostAsJsonAsync("com.atproto.server.createSession", new CreateSessionRequest("julia.cool", "5u2w-awce-e4z6-tknq"));
resp.EnsureSuccessStatusCode();

var creds = await resp.Content.ReadFromJsonAsync<CreateSessionResponse>();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", creds.AccessJwt);

resp = await client.PostAsJsonAsync("com.atproto.repo.createRecord", new CreateRecordRequest(
    creds.Did,
    new Post("👋")));
resp.EnsureSuccessStatusCode();

Console.WriteLine(await resp.Content.ReadAsStringAsync());

internal record CreateSessionRequest(
    [property: JsonPropertyName("identifier")] string Identifier,
    [property: JsonPropertyName("password")] string Password);

internal record CreateSessionResponse(
    [property: JsonPropertyName("did")] string Did,
    [property: JsonPropertyName("accessJwt")] string AccessJwt);

internal record CreateRecordRequest(
    [property: JsonPropertyName("repo")] string Repo,
    [property: JsonPropertyName("record")] Post Record)
{
    [JsonPropertyName("collection")]
    internal static string Collection => "app.bsky.feed.post";
}

internal record Post
{
    [JsonPropertyName("$type")]
    internal static string Type => "app.bsky.feed.post";

    [JsonPropertyName("text")]
    internal string Text { get; }

    [JsonPropertyName("createdAt")]
    internal static DateTime CreatedAt => DateTime.UtcNow;

    internal Post(string text)
    {
        Text = text ?? throw new ArgumentNullException(nameof(text));
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment