Toot toooooooot (Bluesky-Mastodon cross-poster)
1require 'json'
2require 'net/http'
3require 'uri'
4
5class MastodonAPI
6 class UnauthenticatedError < StandardError
7 end
8
9 class UnexpectedResponseError < StandardError
10 end
11
12 class APIError < StandardError
13 attr_reader :response
14
15 def initialize(response)
16 @response = response
17 super("APIError #{response.code}: #{response.body}")
18 end
19
20 def status
21 response.code.to_i
22 end
23 end
24
25 attr_accessor :access_token
26
27 def initialize(host, access_token = nil)
28 @host = host
29 @root = "https://#{@host}/api/v1"
30 @access_token = access_token
31 end
32
33 def oauth_login_with_password(client_id, client_secret, email, password, scopes)
34 url = URI("https://#{@host}/oauth/token")
35
36 params = {
37 client_id: client_id,
38 client_secret: client_secret,
39 grant_type: 'password',
40 scope: scopes,
41 username: email,
42 password: password
43 }
44
45 response = Net::HTTP.post_form(url, params)
46 status = response.code.to_i
47
48 if status / 100 == 2
49 JSON.parse(response.body)
50 else
51 raise APIError.new(response)
52 end
53 end
54
55 def account_info
56 raise UnauthenticatedError.new unless @access_token
57 get_json("/accounts/verify_credentials")
58 end
59
60 def lookup_account(username)
61 json = get_json("/accounts/lookup", { acct: username })
62 raise UnexpectedResponseError.new unless json.is_a?(Hash) && json['id'].is_a?(String)
63 json
64 end
65
66 def account_statuses(user_id, params = {})
67 get_json("/accounts/#{user_id}/statuses", params)
68 end
69
70 def get_json(path, params = {})
71 url = URI(path.start_with?('https://') ? path : @root + path)
72 url.query = URI.encode_www_form(params) if params
73
74 headers = {}
75 headers['Authorization'] = "Bearer #{@access_token}" if @access_token
76
77 response = Net::HTTP.get_response(url, headers)
78 status = response.code.to_i
79
80 if status / 100 == 2
81 JSON.parse(response.body)
82 elsif status / 100 == 3
83 get_json(response['Location'])
84 else
85 raise APIError.new(response)
86 end
87 end
88end