minisky 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +43 -7
- data/example/fetch_profile.rb +53 -0
- data/example/post_skeet.rb +4 -2
- data/example/science_feed.rb +1 -0
- data/lib/minisky/requests.rb +27 -1
- data/lib/minisky/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a753ae5a6f7d2dd3089ee9b6a637e578051261c615fedd28a44f63ac1774b4d
|
4
|
+
data.tar.gz: 479240c065cb3ba705aa4a9d07efa8c4904ec2aca2e6ed0e847d391ab8cd62fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f87814325757d1b19cee4e403d6e13afbf84b1353b932eedbce23faa6cb1abfe772d0cf2c459b21bb45ea08fa34173457dea3fdb266f32f1f4334e2e90d22692
|
7
|
+
data.tar.gz: c4bea17a09982db0462e15e092fdf43c454fd94163d04099b119104fde555387621c5c1b8d51e1a1247ad2cece0b5fd9258b1c98555b0ffb7eca4b96107dd83a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -18,6 +18,32 @@ Or alternatively, add it to the `Gemfile` file for Bundler:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
+
All calls to the XRPC API are made through an instance of the `Minisky` class. There are two ways to use the library: with or without authentication.
|
22
|
+
|
23
|
+
|
24
|
+
### Unauthenticated access
|
25
|
+
|
26
|
+
You can access parts of the API anonymously without any authentication. This currently includes: read-only `com.atproto.*` routes on the PDS (user's data server) and most read-only `app.bsky.*` routes on the AppView server.
|
27
|
+
|
28
|
+
This allows you to do things like:
|
29
|
+
|
30
|
+
- look up specific records or lists of all records of a given type in any account (in their raw form)
|
31
|
+
- look up profile information about any account
|
32
|
+
- load complete threads or users' profile feeds from the AppView
|
33
|
+
|
34
|
+
To use Minisky this way, create a `Minisky` instance passing the API hostname string (at the moment there is only one server at `bsky.social`, but there will be more once federation support goes live) and `nil` as the configuration in the arguments:
|
35
|
+
|
36
|
+
```rb
|
37
|
+
require 'minisky'
|
38
|
+
|
39
|
+
bsky = Minisky.new('bsky.social', nil)
|
40
|
+
```
|
41
|
+
|
42
|
+
|
43
|
+
### Authenticated access
|
44
|
+
|
45
|
+
To use the complete API including posting or reading your home feed, you need to log in using your account info and get an access token which will be added as an authentication header to all requests.
|
46
|
+
|
21
47
|
First, you need to create a `.yml` config file with the authentication data, e.g. `bluesky.yml`. It should look like this:
|
22
48
|
|
23
49
|
```yaml
|
@@ -29,18 +55,20 @@ The `id` can be either your handle, or your DID, or the email you've used to sig
|
|
29
55
|
|
30
56
|
After you log in, this file will also be used to store your access & request tokens and DID. The data in the config file can be accessed through a `user` wrapper property that exposes them as methods, e.g. the password is available as `user.pass` and the DID as `user.did`.
|
31
57
|
|
32
|
-
Next, create the Minisky client instance, passing the server name and the config file name
|
58
|
+
Next, create the Minisky client instance, passing the server name and the config file name:
|
33
59
|
|
34
60
|
```rb
|
35
61
|
require 'minisky'
|
36
62
|
|
37
63
|
bsky = Minisky.new('bsky.social', 'bluesky.yml')
|
38
|
-
bsky.check_access
|
39
64
|
```
|
40
65
|
|
41
|
-
|
66
|
+
Minisky automatically manages your access and refresh tokens - it will first log you in using the login & password, and then use the refresh token to update the access token before the request when it expires.
|
67
|
+
|
42
68
|
|
43
|
-
|
69
|
+
### Making requests
|
70
|
+
|
71
|
+
With a `Minisky` client instance, you can make requests to the Bluesky API using `get_request` and `post_request`:
|
44
72
|
|
45
73
|
```rb
|
46
74
|
json = bsky.get_request('com.atproto.repo.listRecords', {
|
@@ -63,7 +91,7 @@ bsky.post_request('com.atproto.repo.createRecord', {
|
|
63
91
|
})
|
64
92
|
```
|
65
93
|
|
66
|
-
|
94
|
+
In authenticated mode, the requests use the saved access token for auth headers automatically. You can also pass `auth: false` or `auth: nil` to not send any authentication headers for a given request, or `auth: sometoken` to use a specific other token. In unauthenticated mode, sending of auth headers is disabled.
|
67
95
|
|
68
96
|
The third useful method you can use is `#fetch_all`, which loads multiple paginated responses and collects all returned items on a single list (you need to pass the name of the field that contains the items in the response). Optionally, you can also specify a limit of pages to load as `max_pages: n`, or a break condition `break_when` to stop fetching when any item matches it. You can use it to e.g. to fetch all of your posts from the last 30 days, but not earlier:
|
69
97
|
|
@@ -97,9 +125,18 @@ You can find more examples in the [example](https://github.com/mackuba/minisky/t
|
|
97
125
|
|
98
126
|
## Customization
|
99
127
|
|
100
|
-
The `Minisky` client currently supports
|
128
|
+
The `Minisky` client currently supports such configuration options:
|
101
129
|
|
102
130
|
- `default_progress` - a progress character to automatically use for `#fetch_all` calls (default: `nil`)
|
131
|
+
- `send_auth_headers` - whether auth headers should be added by default (default: `true` in authenticated mode)
|
132
|
+
- `auto_manage_tokens` - whether access tokens should be generated and refreshed automatically when needed (default: `true` in authenticated mode)
|
133
|
+
|
134
|
+
In authenticated mode, you can disable the `send_auth_headers` option and then explicitly add `auth: true` to specific requests to include a header there.
|
135
|
+
|
136
|
+
You can also disable the `auto_manage_tokens` option - in this case you will need to call the `#check_access` method before a request to refresh a token if needed, or alternatively, call either `#login` or `#perform_token_refresh`.
|
137
|
+
|
138
|
+
|
139
|
+
### Using your own class
|
103
140
|
|
104
141
|
Instead of using the `Minisky` class, you can also make your own class that includes the `Minisky::Requests` module and provides a different way to load & save the config, e.g. from a JSON file:
|
105
142
|
|
@@ -128,7 +165,6 @@ It can then be used just like the `Minisky` class:
|
|
128
165
|
|
129
166
|
```rb
|
130
167
|
bsky = BlueskyClient.new('config/access.json')
|
131
|
-
bsky.check_access
|
132
168
|
bsky.get_request(...)
|
133
169
|
```
|
134
170
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Example: fetch the profile info of a given user and their last 10 posts (excluding reposts).
|
4
|
+
#
|
5
|
+
# This script connects to the AppView server at api.bsky.app, which allows calling such endpoints as getProfile or
|
6
|
+
# getAuthorFeed without authentication.
|
7
|
+
|
8
|
+
# load minisky from a local folder - you normally won't need this
|
9
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
10
|
+
|
11
|
+
require 'minisky'
|
12
|
+
require 'time'
|
13
|
+
|
14
|
+
if ARGV[0].to_s !~ /^@?[\w\-]+(\.[\w\-]+)+$/
|
15
|
+
puts "Usage: #{$PROGRAM_NAME} <handle>"
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
|
19
|
+
handle = ARGV[0].gsub(/^@/, '')
|
20
|
+
|
21
|
+
# passing nil as config file to use an unauthenticated client
|
22
|
+
bsky = Minisky.new('api.bsky.app', nil)
|
23
|
+
|
24
|
+
# fetch profile info
|
25
|
+
profile = bsky.get_request('app.bsky.actor.getProfile', { actor: handle })
|
26
|
+
|
27
|
+
# fetch posts, without replies - we fetch a bit more than we need because we'll also filter out reposts
|
28
|
+
posts = bsky.get_request('app.bsky.feed.getAuthorFeed', { actor: handle, filter: 'posts_no_replies', limit: 40 })
|
29
|
+
|
30
|
+
# print the profile
|
31
|
+
|
32
|
+
puts
|
33
|
+
puts "====[ @#{handle} • #{profile['displayName']} • #{profile['did']} ]===="
|
34
|
+
puts
|
35
|
+
puts profile['description']
|
36
|
+
puts
|
37
|
+
puts '=' * 80
|
38
|
+
puts
|
39
|
+
|
40
|
+
# print the posts
|
41
|
+
|
42
|
+
posts['feed'].map { |r|
|
43
|
+
r['post']
|
44
|
+
}.select { |p|
|
45
|
+
# select only posts from this account
|
46
|
+
p['author']['handle'] == handle
|
47
|
+
}.slice(0, 10).each { |p|
|
48
|
+
time = Time.parse(p['record']['createdAt'])
|
49
|
+
timestamp = time.getlocal.strftime('%a %d.%m %H:%M')
|
50
|
+
|
51
|
+
puts "#{timestamp}: #{p['record']['text']}"
|
52
|
+
puts
|
53
|
+
}
|
data/example/post_skeet.rb
CHANGED
@@ -21,13 +21,15 @@ text = ARGV[0]
|
|
21
21
|
# create a client instance
|
22
22
|
bsky = Minisky.new('bsky.social', File.join(__dir__, 'bluesky.yml'))
|
23
23
|
|
24
|
+
# to make a post, we upload a post record to the posts collection (app.bsky.feed.post) in the user's repo
|
25
|
+
|
24
26
|
bsky.post_request('com.atproto.repo.createRecord', {
|
25
27
|
repo: bsky.user.did,
|
26
28
|
collection: 'app.bsky.feed.post',
|
27
29
|
record: {
|
28
30
|
text: text,
|
29
|
-
|
30
|
-
|
31
|
+
createdAt: Time.now.iso8601, # we need to set the date to current time manually
|
32
|
+
langs: ["en"] # if a post does not have a language set, it may be autodetected as an incorrect language
|
31
33
|
}
|
32
34
|
})
|
33
35
|
|
data/example/science_feed.rb
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
# terminal. Does not require any authentication.
|
5
5
|
#
|
6
6
|
# It's definitely not the most efficient way to do this, but it demonstrates how to load single records from the API.
|
7
|
+
# (A more efficient way would be e.g. to connect to the AppView at api.bsky.app and make one call to getPosts.)
|
7
8
|
|
8
9
|
# load minisky from a local folder - you normally won't need this
|
9
10
|
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
data/lib/minisky/requests.rb
CHANGED
@@ -57,7 +57,9 @@ class Minisky
|
|
57
57
|
url.query = URI.encode_www_form(params)
|
58
58
|
end
|
59
59
|
|
60
|
-
|
60
|
+
request = Net::HTTP::Get.new(url, headers)
|
61
|
+
|
62
|
+
response = make_request(request)
|
61
63
|
handle_response(response)
|
62
64
|
end
|
63
65
|
|
@@ -145,8 +147,32 @@ class Minisky
|
|
145
147
|
nil
|
146
148
|
end
|
147
149
|
|
150
|
+
if RUBY_VERSION.to_i == 2
|
151
|
+
alias_method :do_get_request, :get_request
|
152
|
+
alias_method :do_post_request, :post_request
|
153
|
+
private :do_get_request, :do_post_request
|
154
|
+
|
155
|
+
def get_request(method, params = nil, auth: default_auth_mode, **kwargs)
|
156
|
+
params ||= kwargs unless kwargs.empty?
|
157
|
+
do_get_request(method, params, auth: auth)
|
158
|
+
end
|
159
|
+
|
160
|
+
def post_request(method, params = nil, auth: default_auth_mode, **kwargs)
|
161
|
+
params ||= kwargs unless kwargs.empty?
|
162
|
+
do_post_request(method, params, auth: auth)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
|
148
167
|
private
|
149
168
|
|
169
|
+
def make_request(request)
|
170
|
+
# this long form is needed because #get_response only supports a headers param in Ruby 3.x
|
171
|
+
response = Net::HTTP.start(request.uri.hostname, request.uri.port, use_ssl: true) do |http|
|
172
|
+
http.request(request)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
150
176
|
def default_auth_mode
|
151
177
|
!!send_auth_headers
|
152
178
|
end
|
data/lib/minisky/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minisky
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kuba Suder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A very simple client class that lets you log in to the Bluesky API and
|
14
14
|
make any requests there.
|
@@ -22,6 +22,7 @@ files:
|
|
22
22
|
- LICENSE.txt
|
23
23
|
- README.md
|
24
24
|
- example/fetch_my_posts.rb
|
25
|
+
- example/fetch_profile.rb
|
25
26
|
- example/post_skeet.rb
|
26
27
|
- example/science_feed.rb
|
27
28
|
- lib/minisky.rb
|