Toot toooooooot (Bluesky-Mastodon cross-poster)

switched to oauth flow by authorizing on a website

+15 -7
app/mastodon_account.rb
··· 20 File.write(CONFIG_FILE, YAML.dump(@config)) 21 end 22 23 - def oauth_login(handle, email, password) 24 instance = handle.split('@').last 25 app_response = register_oauth_app(instance, OAUTH_SCOPES) 26 27 api = MastodonAPI.new(instance) 28 29 - json = api.oauth_login_with_password( 30 - app_response.client_id, 31 - app_response.client_secret, 32 - email, password, OAUTH_SCOPES 33 - ) 34 35 api.access_token = json['access_token'] 36 info = api.account_info ··· 43 44 def register_oauth_app(instance, scopes) 45 client = Mastodon::REST::Client.new(base_url: "https://#{instance}") 46 - client.create_app(APP_NAME, 'urn:ietf:wg:oauth:2.0:oob', scopes) 47 end 48 49 def post_status(text, media_ids = nil, parent_id = nil)
··· 20 File.write(CONFIG_FILE, YAML.dump(@config)) 21 end 22 23 + def oauth_login(handle) 24 instance = handle.split('@').last 25 app_response = register_oauth_app(instance, OAUTH_SCOPES) 26 27 api = MastodonAPI.new(instance) 28 29 + login_url = api.generate_oauth_login_url(app_response.client_id, OAUTH_SCOPES) 30 + 31 + puts "Open this URL in your web browser and authorize the app:" 32 + puts 33 + puts login_url 34 + puts 35 + puts "Then, enter the received code here:" 36 + puts 37 + 38 + print ">> " 39 + code = STDIN.gets.chomp 40 + 41 + json = api.complete_oauth_login(app_response.client_id, app_response.client_secret, code) 42 43 api.access_token = json['access_token'] 44 info = api.account_info ··· 51 52 def register_oauth_app(instance, scopes) 53 client = Mastodon::REST::Client.new(base_url: "https://#{instance}") 54 + client.create_app(APP_NAME, MastodonAPI::CODE_REDIRECT_URI, scopes) 55 end 56 57 def post_status(text, media_ids = nil, parent_id = nil)
+19 -5
app/mastodon_api.rb
··· 3 require 'uri' 4 5 class MastodonAPI 6 class UnauthenticatedError < StandardError 7 end 8 ··· 32 @access_token = access_token 33 end 34 35 - def oauth_login_with_password(client_id, client_secret, email, password, scopes) 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 post_json("https://#{@host}/oauth/token", params)
··· 3 require 'uri' 4 5 class MastodonAPI 6 + CODE_REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob' 7 + 8 class UnauthenticatedError < StandardError 9 end 10 ··· 34 @access_token = access_token 35 end 36 37 + def generate_oauth_login_url(client_id, scopes) 38 + login_url = URI("https://#{@host}/oauth/authorize") 39 + 40 + login_url.query = URI.encode_www_form( 41 + client_id: client_id, 42 + redirect_uri: CODE_REDIRECT_URI, 43 + response_type: 'code', 44 + scope: scopes 45 + ) 46 + 47 + login_url 48 + end 49 + 50 + def complete_oauth_login(client_id, client_secret, code) 51 params = { 52 client_id: client_id, 53 client_secret: client_secret, 54 + redirect_uri: CODE_REDIRECT_URI, 55 + grant_type: 'authorization_code', 56 + code: code 57 } 58 59 post_json("https://#{@host}/oauth/token", params)
+3 -10
app/tootify.rb
··· 26 end 27 end 28 29 - def login_bluesky(handle) 30 handle = handle.gsub(/^@/, '') 31 32 print "App password: " ··· 36 @bluesky.login_with_password(handle, password) 37 end 38 39 - def login_mastodon(handle) 40 - print "Email: " 41 - email = STDIN.gets.chomp 42 - 43 - print "Password: " 44 - password = STDIN.noecho(&:gets).chomp 45 - puts 46 - 47 - @mastodon.oauth_login(handle, email, password) 48 end 49 50 def sync
··· 26 end 27 end 28 29 + def login_to_bluesky(handle) 30 handle = handle.gsub(/^@/, '') 31 32 print "App password: " ··· 36 @bluesky.login_with_password(handle, password) 37 end 38 39 + def login_to_mastodon(handle) 40 + @mastodon.oauth_login(handle) 41 end 42 43 def sync
+2 -2
tootify
··· 36 app = Tootify.new 37 38 if name =~ /\A[^@]+@[^@]+\z/ 39 - app.login_mastodon(name) 40 elsif name =~ /\A@[^@]+\z/ 41 - app.login_bluesky(name) 42 elsif name.nil? 43 print_help 44 else
··· 36 app = Tootify.new 37 38 if name =~ /\A[^@]+@[^@]+\z/ 39 + app.login_to_mastodon(name) 40 elsif name =~ /\A@[^@]+\z/ 41 + app.login_to_bluesky(name) 42 elsif name.nil? 43 print_help 44 else