Skip to content

Instantly share code, notes, and snippets.

@lucianghinda
Created March 30, 2024 18:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucianghinda/3e70725ed2a2f8d2f183985efd3788a8 to your computer and use it in GitHub Desktop.
Save lucianghinda/3e70725ed2a2f8d2f183985efd3788a8 to your computer and use it in GitHub Desktop.
Mastodon Client
module Mastodon
ApiResponse = Data.define(:body, :headers, :code, :links)
end
# frozen_string_literal: true
module Mastodon
class Client
class UnauthenticatedError < StandardError; end
class InvalidPostError < StandardError; end
class InvalidResponseBodyError < StandardError; end
LINK_HEADER_KEY = "Link"
def initialize(access_token = ENV.fetch("MASTODON_ACCESS_TOKEN"))
@api_url = Instance.new(ENV.fetch("MASTODON_INSTANCE")).api_url
@access_token = access_token
end
def bookmarks(id_type: nil, id: nil)
query_params = if id_type.nil?
{}
else
{ id_type => id }
end
get("/bookmarks", query_params:)
end
def post(id:) = get("/statuses/#{id}")
def embed(url:) = get("/api/oembed", query_params: { url: })
private
attr_reader :api_url, :access_token
def get(path, query_params: {}) = request(:get, path:, query_params:)
def request(method, path:, query_params: {})
url = api_url.dup
url.path += path
url.query = query_params.to_query unless query_params.empty?
request = Typhoeus::Request.new(url.to_s, method:, headers:)
begin
response = request.run
if response.code == 401
Rails.logger.error("Unauthenticated: #{response.body}")
raise UnauthenticatedError
end
if response.code == 400
Rails.logger.error("Invalid post: #{response.body}")
raise InvalidPostError
end
api_response(code: response.code, response_body: response.body, headers: response.headers)
rescue StandardError => e
Rails.logger.error("An error has occurred: #{e.message}")
Rails.logger.error(e.backtrace.join("\n"))
::ImportErrorLogger.error("Mastodon::Error importing #{path}", e)
end
end
def headers
{
"Authorization": "Bearer #{access_token}",
"User-Agent": "ShortRubyClient"
}
end
def api_response(code:, response_body:, headers:)
body = JSON.parse(response_body, symbolize_names: true)
links = parse_links(headers)
Mastodon::ApiResponse.new(
body:,
code:,
headers:,
links:
)
rescue JSON::ParserError => e
Rails.logger.error("Invalid response body: #{response_body}, with headers: #{headers}. Error #{e.message}")
raise InvalidResponseBodyError
end
def parse_links(headers)
links = headers[LINK_HEADER_KEY]
return [] if links.nil?
links.split(",").map do |link|
Mastodon::PaginationLink.parse(link)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment