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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f4836f5b8d8de9c5f9af0368144fe60f274e1b61176d1c919b70d3fd645a3f3
4
- data.tar.gz: 8c87cdbb362b19651e848804aa6c551c88abc759bbdd3df6e609b62b94a7da4b
3
+ metadata.gz: 7a753ae5a6f7d2dd3089ee9b6a637e578051261c615fedd28a44f63ac1774b4d
4
+ data.tar.gz: 479240c065cb3ba705aa4a9d07efa8c4904ec2aca2e6ed0e847d391ab8cd62fe
5
5
  SHA512:
6
- metadata.gz: 84052665f10f23db1513a5135dcb9032f0fbc4c5ae55fc7bbeb15e26d85904acda3ac55170e58d8901e5549ceaaafa34aa038ec8987da9dfdded5349080f12d2
7
- data.tar.gz: 5557b97bb51b8feb757a2d16dccfefd7dfd31655a833b379681d89cc924717e234baa19523cda89368f6610481cf11c0dd9494355539d4c7364c9913a05c2ca1
6
+ metadata.gz: f87814325757d1b19cee4e403d6e13afbf84b1353b932eedbce23faa6cb1abfe772d0cf2c459b21bb45ea08fa34173457dea3fdb266f32f1f4334e2e90d22692
7
+ data.tar.gz: c4bea17a09982db0462e15e092fdf43c454fd94163d04099b119104fde555387621c5c1b8d51e1a1247ad2cece0b5fd9258b1c98555b0ffb7eca4b96107dd83a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [0.3.1] - 2023-10-10
2
+
3
+ * fixed Minisky not working on Ruby 2.x
4
+
1
5
  ## [0.3.0] - 2023-10-05
2
6
 
3
7
  * authentication improvements & changes:
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 (at the moment there is only one server at `bsky.social`, but there will be more once federation support goes live):
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
- `check_access` will check if an access token is saved, if not - it will log you in using the login & password, otherwise it will check if the token is still valid and refresh it if needed.
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
- Now, you can make requests to the Bluesky API using `get_request` and `post_request`:
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
- The requests use the saved access token for authentication automatically. You can also pass `auth: false` or `auth: nil` to not send any authentication headers, or `auth: sometoken` to use a specific other token.
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 one configuration option:
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
+ }
@@ -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
- langs: ["en"],
30
- createdAt: Time.now.iso8601
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
 
@@ -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__))
@@ -57,7 +57,9 @@ class Minisky
57
57
  url.query = URI.encode_www_form(params)
58
58
  end
59
59
 
60
- response = Net::HTTP.get_response(url, headers)
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
@@ -1,5 +1,5 @@
1
1
  require_relative 'minisky'
2
2
 
3
3
  class Minisky
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.1"
5
5
  end
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.0
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-05 00:00:00.000000000 Z
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