Class: Jekyll::StandardSite::Publisher

Inherits:
Object
  • Object
show all
Defined in:
lib/jekyll-standard-site/publisher.rb

Constant Summary collapse

DEFAULT_PDS =
"https://bsky.social".freeze

Instance Method Summary collapse

Constructor Details

#initialize(site:, handle:, password:, pds: DEFAULT_PDS, http: HttpClient.new, logger: Jekyll.logger) ⇒ Publisher

Returns a new instance of Publisher.



30
31
32
33
34
35
36
37
# File 'lib/jekyll-standard-site/publisher.rb', line 30

def initialize(site:, handle:, password:, pds: DEFAULT_PDS, http: HttpClient.new, logger: Jekyll.logger)
  @site = site
  @handle = handle
  @password = password
  @pds = pds.sub(%r{/\z}, "")
  @http = http
  @logger = logger
end

Instance Method Details

#build_record(publication, post) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/jekyll-standard-site/publisher.rb', line 85

def build_record(publication, post)
  data = post.data
  record = {
    "$type" => "site.standard.document",
    "site" => publication,
    "title" => data["title"].to_s,
    "publishedAt" => normalize_time(post.date)
  }
  record["path"] = post.url if post.url
  record["description"] = data["description"] if data["description"]
  record["tags"] = Array(data["tags"]) if data["tags"] && !Array(data["tags"]).empty?
  record["updatedAt"] = normalize_time(data["updated"]) if data["updated"]
  record
end

#create_document_record(session, publication, post) ⇒ Object

Raises:



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/jekyll-standard-site/publisher.rb', line 70

def create_document_record(session, publication, post)
  record = build_record(publication, post)
  code, body = @http.post_json(
    "#{@pds}/xrpc/com.atproto.repo.createRecord",
    {
      "repo" => session["did"],
      "collection" => "site.standard.document",
      "record" => record
    },
    "Authorization" => "Bearer #{session["accessJwt"]}"
  )
  raise PublisherError, "createRecord failed for #{post.relative_path} (#{code}): #{body["message"] || body}" unless code == 200
  body["uri"]
end

#loginObject

Raises:



61
62
63
64
65
66
67
68
# File 'lib/jekyll-standard-site/publisher.rb', line 61

def 
  code, body = @http.post_json(
    "#{@pds}/xrpc/com.atproto.server.createSession",
    { "identifier" => @handle, "password" => @password }
  )
  raise PublisherError, "login failed (#{code}): #{body["message"] || body}" unless code == 200
  body
end

#normalize_time(value) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/jekyll-standard-site/publisher.rb', line 100

def normalize_time(value)
  case value
  when Time then value.utc.strftime("%Y-%m-%dT%H:%M:%S.000Z")
  when String then value
  else raise PublisherError, "unrecognised time value: #{value.inspect}"
  end
end

#patch_front_matter(path, at_uri) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/jekyll-standard-site/publisher.rb', line 108

def patch_front_matter(path, at_uri)
  content = File.read(path)
  unless content.start_with?("---\n") || content.start_with?("---\r\n")
    raise PublisherError, "no front matter in #{path}"
  end

  patched = content.sub(/\n---\r?\n/, %(\nat_uri: "#{at_uri}"\n---\n))
  if patched == content
    raise PublisherError, "could not locate closing front-matter delimiter in #{path}"
  end

  File.write(path, patched)
end

#publish_allObject

Raises:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/jekyll-standard-site/publisher.rb', line 39

def publish_all
  publication = StandardSite.publication_uri(@site)
  raise PublisherError, "standard_site.publication is not set in _config.yml" unless publication

  session = 
  published = []

  unpublished_posts.each do |post|
    uri = create_document_record(session, publication, post)
    patch_front_matter(post.path, uri)
    @logger.info "Standard.site:", "published #{post.relative_path} -> #{uri}"
    published << [post.relative_path, uri]
  end

  published
end

#unpublished_postsObject



56
57
58
59
# File 'lib/jekyll-standard-site/publisher.rb', line 56

def unpublished_posts
  @site.read if @site.posts.docs.empty?
  @site.posts.docs.reject { |p| p.data["at_uri"] }
end