sferik 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +72 -0
- data/LICENSE.md +16 -0
- data/README.md +517 -0
- data/exe/sferik +6 -0
- data/lib/sferik/api/code_endpoints.rb +37 -0
- data/lib/sferik/api/profile_endpoints.rb +113 -0
- data/lib/sferik/api/resume_endpoints.rb +41 -0
- data/lib/sferik/api/site_endpoints.rb +247 -0
- data/lib/sferik/api/talk_endpoints.rb +45 -0
- data/lib/sferik/api.rb +23 -0
- data/lib/sferik/block.rb +25 -0
- data/lib/sferik/body.rb +54 -0
- data/lib/sferik/cache.rb +361 -0
- data/lib/sferik/cli.rb +369 -0
- data/lib/sferik/client.rb +453 -0
- data/lib/sferik/collection.rb +82 -0
- data/lib/sferik/configuration.rb +129 -0
- data/lib/sferik/connections.rb +151 -0
- data/lib/sferik/contributions.rb +86 -0
- data/lib/sferik/day.rb +35 -0
- data/lib/sferik/dependency.rb +26 -0
- data/lib/sferik/deployment.rb +36 -0
- data/lib/sferik/errors.rb +234 -0
- data/lib/sferik/figure.rb +83 -0
- data/lib/sferik/finger.rb +74 -0
- data/lib/sferik/freshness.rb +54 -0
- data/lib/sferik/home/pages.rb +27 -0
- data/lib/sferik/home/profile.rb +51 -0
- data/lib/sferik/home/section.rb +27 -0
- data/lib/sferik/home.rb +38 -0
- data/lib/sferik/json_parsing.rb +28 -0
- data/lib/sferik/name_change.rb +49 -0
- data/lib/sferik/place.rb +33 -0
- data/lib/sferik/podcast.rb +41 -0
- data/lib/sferik/project.rb +49 -0
- data/lib/sferik/projects.rb +138 -0
- data/lib/sferik/push.rb +33 -0
- data/lib/sferik/resource.rb +373 -0
- data/lib/sferik/resume/award.rb +43 -0
- data/lib/sferik/resume/basics.rb +77 -0
- data/lib/sferik/resume/education.rb +59 -0
- data/lib/sferik/resume/location.rb +35 -0
- data/lib/sferik/resume/meta.rb +35 -0
- data/lib/sferik/resume/patent.rb +43 -0
- data/lib/sferik/resume/profile.rb +35 -0
- data/lib/sferik/resume/project.rb +27 -0
- data/lib/sferik/resume/skill.rb +27 -0
- data/lib/sferik/resume/speaking.rb +19 -0
- data/lib/sferik/resume/volunteer.rb +59 -0
- data/lib/sferik/resume/work.rb +51 -0
- data/lib/sferik/resume.rb +125 -0
- data/lib/sferik/session.rb +41 -0
- data/lib/sferik/social_profile.rb +49 -0
- data/lib/sferik/status/github.rb +38 -0
- data/lib/sferik/status/loaded.rb +48 -0
- data/lib/sferik/status.rb +33 -0
- data/lib/sferik/talk.rb +73 -0
- data/lib/sferik/talks.rb +79 -0
- data/lib/sferik/validation.rb +119 -0
- data/lib/sferik/version.rb +7 -0
- data/lib/sferik/web_finger/link.rb +46 -0
- data/lib/sferik/web_finger.rb +43 -0
- data/lib/sferik/who.rb +53 -0
- data/lib/sferik/whoami.rb +36 -0
- data/lib/sferik/wrapping.rb +114 -0
- data/lib/sferik.rb +246 -0
- data/sig/manifest.yaml +13 -0
- data/sig/sferik.rbs +825 -0
- metadata +118 -0
data/lib/sferik.rb
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "forwardable"
|
|
4
|
+
require_relative "sferik/client"
|
|
5
|
+
require_relative "sferik/configuration"
|
|
6
|
+
require_relative "sferik/version"
|
|
7
|
+
|
|
8
|
+
# A Ruby wrapper for the sferik.net API
|
|
9
|
+
#
|
|
10
|
+
# Every public method of {API} is a method of this module too, delegated to {.client}: {API::ProfileEndpoints#whoami}
|
|
11
|
+
# is `Sferik.whoami`, {API::ResumeEndpoints#resume} is `Sferik.resume`, and so on for every endpoint. {API} groups them
|
|
12
|
+
# into one mixin per topic, and each is documented there.
|
|
13
|
+
#
|
|
14
|
+
# @api public
|
|
15
|
+
# @see API The endpoints, grouped into one mixin per topic
|
|
16
|
+
module Sferik
|
|
17
|
+
# The sferik command, loaded when it's first used: a program that only calls the API doesn't load it, or optparse
|
|
18
|
+
autoload :CLI, "#{__dir__}/sferik/cli"
|
|
19
|
+
|
|
20
|
+
extend Configuration
|
|
21
|
+
extend SingleForwardable
|
|
22
|
+
|
|
23
|
+
# The mutex that guards the client the API methods of the module delegate to
|
|
24
|
+
CLIENT_MUTEX = Mutex.new
|
|
25
|
+
private_constant :CLIENT_MUTEX
|
|
26
|
+
|
|
27
|
+
# @!method self.new(**options)
|
|
28
|
+
# Alias for Sferik::Client.new
|
|
29
|
+
# @api public
|
|
30
|
+
# @param options [Hash] options passed to {Sferik::Client#initialize}
|
|
31
|
+
# @return [Sferik::Client] a new client
|
|
32
|
+
# @example Create a client for a local copy of the site
|
|
33
|
+
# Sferik.new(host: "http://localhost:3745")
|
|
34
|
+
def_delegator "Sferik::Client", :new
|
|
35
|
+
|
|
36
|
+
# The endpoints of {API}, each delegated to the client the module has, and documented here so that each is found
|
|
37
|
+
# under the name it's called by
|
|
38
|
+
#
|
|
39
|
+
# @!method self.home
|
|
40
|
+
# Returns the profile and the home page's modules
|
|
41
|
+
# @api public
|
|
42
|
+
# @return [Home]
|
|
43
|
+
# @example
|
|
44
|
+
# Sferik.home.profile.tagline
|
|
45
|
+
# @see API::ProfileEndpoints#home What it raises, and more about it
|
|
46
|
+
# @!method self.whoami
|
|
47
|
+
# Returns the bio: paragraphs of HTML
|
|
48
|
+
# @api public
|
|
49
|
+
# @return [Whoami]
|
|
50
|
+
# @example
|
|
51
|
+
# Sferik.whoami.blocks.map(&:html)
|
|
52
|
+
# @see API::ProfileEndpoints#whoami What it raises, and more about it
|
|
53
|
+
# @!method self.dependency
|
|
54
|
+
# Returns the xkcd comic on the home page: xkcd 2347, adapted
|
|
55
|
+
# @api public
|
|
56
|
+
# @return [Dependency]
|
|
57
|
+
# @example
|
|
58
|
+
# Sferik.dependency.figure.alt
|
|
59
|
+
# @see API::ProfileEndpoints#dependency What it raises, and more about it
|
|
60
|
+
# @!method self.finger
|
|
61
|
+
# Returns contact details and profiles elsewhere
|
|
62
|
+
# @api public
|
|
63
|
+
# @return [Finger]
|
|
64
|
+
# @example
|
|
65
|
+
# Sferik.finger.profiles.map(&:url)
|
|
66
|
+
# @see API::ProfileEndpoints#finger What it raises, and more about it
|
|
67
|
+
# @!method self.finger_vcard
|
|
68
|
+
# Returns contact details and profiles as a contact card (a vCard)
|
|
69
|
+
# @api public
|
|
70
|
+
# @return [String] the vCard
|
|
71
|
+
# @example
|
|
72
|
+
# File.write("erik-berlin.vcf", Sferik.finger_vcard)
|
|
73
|
+
# @see API::ProfileEndpoints#finger_vcard What it raises, and more about it
|
|
74
|
+
# @!method self.name_change
|
|
75
|
+
# Returns the name change, from Erik Michaels-Ober to Erik Berlin, as a git commit
|
|
76
|
+
# @api public
|
|
77
|
+
# @return [NameChange]
|
|
78
|
+
# @example
|
|
79
|
+
# Sferik.name_change.year # => 2017
|
|
80
|
+
# @see API::ProfileEndpoints#name_change What it raises, and more about it
|
|
81
|
+
# @!method self.signature
|
|
82
|
+
# Returns the motto: ~/.signature, which the home page shows as cat .signature
|
|
83
|
+
# @api public
|
|
84
|
+
# @return [String] the motto, without the newline the site ends it with
|
|
85
|
+
# @example
|
|
86
|
+
# Sferik.signature # => "I build libraries and tools software engineers depend on."
|
|
87
|
+
# @see API::ProfileEndpoints#signature What it raises, and more about it
|
|
88
|
+
# @!method self.webfinger(resource = "acct:sferik@sferik.net")
|
|
89
|
+
# Returns where an account at sferik.net points to, as WebFinger answers
|
|
90
|
+
# @api public
|
|
91
|
+
# @param resource [String] the account, as an acct: URI
|
|
92
|
+
# @return [WebFinger]
|
|
93
|
+
# @example
|
|
94
|
+
# Sferik.webfinger.subject # => "acct:sferik@mastodon.social"
|
|
95
|
+
# @see API::ProfileEndpoints#webfinger What it raises, and more about it
|
|
96
|
+
# @!method self.contributions
|
|
97
|
+
# Returns a year of GitHub contributions, the longest streak, and the latest push
|
|
98
|
+
# @api public
|
|
99
|
+
# @return [Contributions]
|
|
100
|
+
# @example
|
|
101
|
+
# Sferik.contributions.days.max_by(&:count).date
|
|
102
|
+
# @see API::CodeEndpoints#contributions What it raises, and more about it
|
|
103
|
+
# @!method self.projects
|
|
104
|
+
# Returns projects with their RubyGems downloads and GitHub stars
|
|
105
|
+
# @api public
|
|
106
|
+
# @return [Projects]
|
|
107
|
+
# @example
|
|
108
|
+
# Sferik.projects.total_downloads # => 5_460_234_129
|
|
109
|
+
# @see API::CodeEndpoints#projects What it raises, and more about it
|
|
110
|
+
# @!method self.talks
|
|
111
|
+
# Returns conference talks, newest first, and podcast appearances
|
|
112
|
+
# @api public
|
|
113
|
+
# @return [Talks]
|
|
114
|
+
# @example
|
|
115
|
+
# Sferik.talks.select(&:video).map(&:title)
|
|
116
|
+
# @see API::TalkEndpoints#talks What it raises, and more about it
|
|
117
|
+
# @!method self.talks_feed
|
|
118
|
+
# Returns the talks as an Atom feed, newest first
|
|
119
|
+
# @api public
|
|
120
|
+
# @return [String] the feed, as XML
|
|
121
|
+
# @example
|
|
122
|
+
# File.write("talks.atom", Sferik.talks_feed)
|
|
123
|
+
# @see API::TalkEndpoints#talks_feed What it raises, and more about it
|
|
124
|
+
# @!method self.podcasts
|
|
125
|
+
# Returns podcast appearances
|
|
126
|
+
# @api public
|
|
127
|
+
# @return [Array<Podcast>]
|
|
128
|
+
# @example
|
|
129
|
+
# Sferik.podcasts.first.show # => "Ruby Rogues, episode 248"
|
|
130
|
+
# @see API::TalkEndpoints#podcasts What it raises, and more about it
|
|
131
|
+
# @!method self.resume
|
|
132
|
+
# Returns the resume as a JSON Resume document
|
|
133
|
+
# @api public
|
|
134
|
+
# @return [Resume]
|
|
135
|
+
# @example
|
|
136
|
+
# Sferik.resume.work.first.position
|
|
137
|
+
# @see API::ResumeEndpoints#resume What it raises, and more about it
|
|
138
|
+
# @!method self.resume_latex
|
|
139
|
+
# Returns the resume as a LaTeX document, ready for pdflatex or tectonic
|
|
140
|
+
# @api public
|
|
141
|
+
# @return [String] the LaTeX source
|
|
142
|
+
# @example
|
|
143
|
+
# File.write("resume.tex", Sferik.resume_latex)
|
|
144
|
+
# @see API::ResumeEndpoints#resume_latex What it raises, and more about it
|
|
145
|
+
# @!method self.resume_pdf
|
|
146
|
+
# Returns the resume as a two-page PDF
|
|
147
|
+
# @api public
|
|
148
|
+
# @return [String] the PDF, as binary
|
|
149
|
+
# @example
|
|
150
|
+
# File.binwrite("resume.pdf", Sferik.resume_pdf)
|
|
151
|
+
# @see API::ResumeEndpoints#resume_pdf What it raises, and more about it
|
|
152
|
+
# @!method self.who
|
|
153
|
+
# Returns everyone reading the site right now
|
|
154
|
+
# @api public
|
|
155
|
+
# @return [Who]
|
|
156
|
+
# @example
|
|
157
|
+
# Sferik.who.map(&:page) # => ["/", "/talks"]
|
|
158
|
+
# @see API::SiteEndpoints#who What it raises, and more about it
|
|
159
|
+
# @!method self.check_in(token, page: "/", &block)
|
|
160
|
+
# Checks in a terminal, or keeps one logged in while a block runs
|
|
161
|
+
# @api public
|
|
162
|
+
# @param token [String] a random token, one per terminal, of 16 to 64 letters, digits, underscores, and hyphens
|
|
163
|
+
# @param page [String] the page the terminal is on: "/", "/talks", or "/resume"
|
|
164
|
+
# @yield [who] what to do while the terminal is logged in: it's checked in again every minute until the block ends
|
|
165
|
+
# @yieldparam who [Who] everyone reading the site when the terminal checked in, with the terminal as {Who#you}
|
|
166
|
+
# @return [Who, Object] everyone reading the site, with the terminal that checked in as {Who#you}, or what the
|
|
167
|
+
# block returns, if there is one
|
|
168
|
+
# @example
|
|
169
|
+
# Sferik.check_in(SecureRandom.uuid).you # => "ttys001"
|
|
170
|
+
# @example Stay logged in for as long as it takes to write a message
|
|
171
|
+
# Sferik.check_in(SecureRandom.uuid) { |who| Sferik.write(gets, tty: who.you) }
|
|
172
|
+
# @see API::SiteEndpoints#check_in What it raises, and more about it
|
|
173
|
+
# @!method self.write(message, tty: nil, key: SecureRandom.uuid)
|
|
174
|
+
# Sends Erik a message, as the shell's write sferik does
|
|
175
|
+
# @api public
|
|
176
|
+
# @param message [String] the message, as plain text: 5,000 bytes at most, sent as UTF-8
|
|
177
|
+
# @param tty [String, nil] the sender's terminal, for the subject line: {Who#you}, from {.check_in}
|
|
178
|
+
# @param key [String] a random key, one per message: the server doesn't email a message twice whose key it has taken
|
|
179
|
+
# @return [String] what the server says: "message sent to sferik"
|
|
180
|
+
# @example
|
|
181
|
+
# Sferik.write("Hello from Ruby. Reply to me@example.com")
|
|
182
|
+
# @see API::SiteEndpoints#write What it raises, and more about it
|
|
183
|
+
# @!method self.text(path = "")
|
|
184
|
+
# Returns a resource as terminal output, wrapped to 80 columns
|
|
185
|
+
# @api public
|
|
186
|
+
# @param path [String] the resource's path: "/whoami", "/resume" (as a man page), etc. (defaults to the home page)
|
|
187
|
+
# @return [String] the text
|
|
188
|
+
# @example
|
|
189
|
+
# puts Sferik.text("/resume")
|
|
190
|
+
# @see API::SiteEndpoints#text What it raises, and more about it
|
|
191
|
+
# @!method self.openapi
|
|
192
|
+
# Returns the API's OpenAPI 3.1 description
|
|
193
|
+
# @api public
|
|
194
|
+
# @return [Hash{String => Object}] the parsed document, deep-frozen
|
|
195
|
+
# @example
|
|
196
|
+
# Sferik.openapi["paths"].keys
|
|
197
|
+
# @see API::SiteEndpoints#openapi What it raises, and more about it
|
|
198
|
+
# @!method self.deployment
|
|
199
|
+
# Returns which commit of the site is deployed, and when it was
|
|
200
|
+
# @api public
|
|
201
|
+
# @return [Deployment]
|
|
202
|
+
# @example
|
|
203
|
+
# Sferik.deployment.commit # => "6a34226a3f351a78339b75430055a018ac30c964"
|
|
204
|
+
# @see API::SiteEndpoints#deployment What it raises, and more about it
|
|
205
|
+
# @!method self.status
|
|
206
|
+
# Returns whether the site's live numbers come as they should
|
|
207
|
+
# @api public
|
|
208
|
+
# @return [Status]
|
|
209
|
+
# @example
|
|
210
|
+
# Sferik.status.github.error # => nil
|
|
211
|
+
# @see API::SiteEndpoints#status What it raises, and more about it
|
|
212
|
+
def_delegators :client, *API.public_instance_methods
|
|
213
|
+
|
|
214
|
+
# The methods of SingleForwardable, which the module delegates with rather than offers (one at a time: YARD can't
|
|
215
|
+
# read the names of a splat)
|
|
216
|
+
SingleForwardable.instance_methods.each { |name| private_class_method name }
|
|
217
|
+
|
|
218
|
+
# The client the API methods of the module delegate to
|
|
219
|
+
#
|
|
220
|
+
# The client is built from the global configuration, and built again whenever that configuration changes.
|
|
221
|
+
#
|
|
222
|
+
# @api public
|
|
223
|
+
# @return [Client] the client
|
|
224
|
+
# @example Perform a raw request with the module's client
|
|
225
|
+
# Sferik.client.get("/whoami", accept: "text/plain")
|
|
226
|
+
def self.client
|
|
227
|
+
CLIENT_MUTEX.synchronize do
|
|
228
|
+
@client = nil unless options.eql?(@client_options)
|
|
229
|
+
@client_options = options
|
|
230
|
+
@client ||= new
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Reset the global configuration and forget the client
|
|
235
|
+
#
|
|
236
|
+
# @api public
|
|
237
|
+
# @return [self]
|
|
238
|
+
# @example Reset the configuration
|
|
239
|
+
# Sferik.reset
|
|
240
|
+
def self.reset
|
|
241
|
+
CLIENT_MUTEX.synchronize do
|
|
242
|
+
@client = @client_options = nil
|
|
243
|
+
super
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|
data/sig/manifest.yaml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# The standard libraries the signatures of sferik refer to, which rbs collection loads for code that depends on it
|
|
2
|
+
dependencies:
|
|
3
|
+
- name: date
|
|
4
|
+
- name: forwardable
|
|
5
|
+
- name: json
|
|
6
|
+
- name: net-http
|
|
7
|
+
- name: openssl
|
|
8
|
+
- name: optparse
|
|
9
|
+
- name: securerandom
|
|
10
|
+
- name: time
|
|
11
|
+
- name: timeout
|
|
12
|
+
- name: uri
|
|
13
|
+
- name: zlib
|