+37
-5
app/bluesky_account.rb
+37
-5
app/bluesky_account.rb
···
2
2
require_relative 'bluesky_client'
3
3
4
4
class BlueskyAccount
5
+
def initialize
6
+
@sky = BlueskyClient.new
7
+
end
8
+
9
+
def did
10
+
@sky.user.did
11
+
end
12
+
5
13
def login_with_password(handle, password)
6
14
did = DID.resolve_handle(handle)
7
15
if did.nil?
···
11
19
12
20
pds = did.get_document.pds_endpoint.gsub('https://', '')
13
21
14
-
sky = BlueskyClient.new
15
-
sky.host = pds
16
-
sky.user.id = handle
17
-
sky.user.pass = password
18
-
sky.log_in
22
+
@sky.host = pds
23
+
@sky.user.id = handle
24
+
@sky.user.pass = password
25
+
26
+
@sky.log_in
27
+
end
28
+
29
+
def fetch_likes
30
+
json = @sky.get_request('com.atproto.repo.listRecords', {
31
+
repo: @sky.user.did,
32
+
collection: 'app.bsky.feed.like',
33
+
limit: 100
34
+
})
35
+
36
+
json['records']
37
+
end
38
+
39
+
def fetch_record(repo, collection, rkey)
40
+
@sky.get_request('com.atproto.repo.getRecord', { repo: repo, collection: collection, rkey: rkey })
41
+
end
42
+
43
+
def delete_record_at(uri)
44
+
repo, collection, rkey = uri.split('/')[2..4]
45
+
46
+
begin
47
+
@sky.post_request('com.atproto.repo.deleteRecord', { repo: repo, collection: collection, rkey: rkey })
48
+
rescue JSON::ParserError
49
+
# todo
50
+
end
19
51
end
20
52
end
+6
app/mastodon_account.rb
+6
app/mastodon_account.rb
···
41
41
client = Mastodon::REST::Client.new(base_url: "https://#{instance}")
42
42
client.create_app(APP_NAME, 'urn:ietf:wg:oauth:2.0:oob', scopes)
43
43
end
44
+
45
+
def post_status(text)
46
+
instance = @config['handle'].split('@').last
47
+
api = MastodonAPI.new(instance, @config['access_token'])
48
+
api.post_status(text)
49
+
end
44
50
end
+28
app/mastodon_api.rb
+28
app/mastodon_api.rb
···
67
67
get_json("/accounts/#{user_id}/statuses", params)
68
68
end
69
69
70
+
def post_status(text)
71
+
post_json("/statuses", {
72
+
status: text
73
+
})
74
+
end
75
+
70
76
def get_json(path, params = {})
71
77
url = URI(path.start_with?('https://') ? path : @root + path)
72
78
url.query = URI.encode_www_form(params) if params
···
81
87
JSON.parse(response.body)
82
88
elsif status / 100 == 3
83
89
get_json(response['Location'])
90
+
else
91
+
raise APIError.new(response)
92
+
end
93
+
end
94
+
95
+
def post_json(path, params = {})
96
+
url = URI(path.start_with?('https://') ? path : @root + path)
97
+
98
+
headers = {}
99
+
headers['Authorization'] = "Bearer #{@access_token}" if @access_token
100
+
101
+
request = Net::HTTP::Post.new(url, headers)
102
+
request.form_data = params
103
+
104
+
response = Net::HTTP.start(url.hostname, url.port, :use_ssl => true) do |http|
105
+
http.request(request)
106
+
end
107
+
108
+
status = response.code.to_i
109
+
110
+
if status / 100 == 2
111
+
JSON.parse(response.body)
84
112
else
85
113
raise APIError.new(response)
86
114
end
+29
app/tootify.rb
+29
app/tootify.rb
···
29
29
30
30
@mastodon.oauth_login(handle, email, password)
31
31
end
32
+
33
+
def sync
34
+
likes = @bluesky.fetch_likes
35
+
36
+
likes.each do |r|
37
+
like_uri = r['uri']
38
+
post_uri = r['value']['subject']['uri']
39
+
repo, collection, rkey = post_uri.split('/')[2..4]
40
+
41
+
next unless repo == @bluesky.did && collection == 'app.bsky.feed.post'
42
+
43
+
begin
44
+
record = @bluesky.fetch_record(repo, collection, rkey)
45
+
rescue Minisky::ClientErrorResponse => e
46
+
puts "Record not found: #{post_uri}"
47
+
@bluesky.delete_record_at(like_uri)
48
+
next
49
+
end
50
+
51
+
post_to_mastodon(record['value'])
52
+
53
+
@bluesky.delete_record_at(like_uri)
54
+
end
55
+
end
56
+
57
+
def post_to_mastodon(record)
58
+
p record
59
+
p @mastodon.post_status(record['text'])
60
+
end
32
61
end