Skip to content

Instantly share code, notes, and snippets.

@en30
Created May 6, 2023 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save en30/b85c127126ee523663c04950598c8cda to your computer and use it in GitHub Desktop.
Save en30/b85c127126ee523663c04950598c8cda to your computer and use it in GitHub Desktop.
A Livebook notebook to make a post on Bluesky.

Make a post on Bluesky

Mix.install([
  {:req, "~> 0.3"},
  {:jason, "~> 1.4.0"},
  {:kino, "~> 0.9.1"}
])

Create a session

inputs = [
  identifier: Kino.Input.text("identifier"),
  password: Kino.Input.password("password")
]

form = Kino.Control.form(inputs, submit: "Create a session", reset_on_submit: [:message])
Kino.Control.subscribe(form, :new_session)
form
session =
  receive do
    {:new_session, %{data: data}} ->
      body = Jason.encode!(data)

      Req.post!("https://bsky.social/xrpc/com.atproto.server.createSession",
        body: body,
        headers: [content_type: "application/json", accept: "application/json"]
      )
      |> Map.fetch!(:body)
  end

List posts

query =
  %{
    repo: session["handle"],
    collection: "app.bsky.feed.post"
  }
  |> URI.encode_query()

Req.get!("https://bsky.social/xrpc/app.bsky.feed.getTimeline?#{query}",
  headers: [accept: "application/json", authorization: "Bearer #{session["accessJwt"]}"]
)
|> then(& &1.body["feed"])
|> Enum.map(fn e ->
  [
    created_at: get_in(e, ["post", "record", "createdAt"]),
    author: get_in(e, ["post", "author", "displayName"]),
    text: get_in(e, ["post", "record", "text"])
  ]
end)
|> Kino.DataTable.new()

Create a post

form =
  [
    text: Kino.Input.textarea("text")
  ]
  |> Kino.Control.form(submit: "submit", reset_on_submit: [:text])

Kino.listen(form, fn %{data: data} ->
  body =
    %{
      repo: session["handle"],
      collection: "app.bsky.feed.post",
      record: %{
        text: data.text,
        createdAt: DateTime.utc_now() |> DateTime.to_iso8601()
      }
    }
    |> Jason.encode!()

  Req.post!("https://bsky.social/xrpc/com.atproto.repo.createRecord",
    body: body,
    headers: [
      authorization: "Bearer #{session["accessJwt"]}",
      content_type: "application/json",
      accept: "application/json"
    ]
  )
end)

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