diff --git a/app/actions/posts/handle.rb b/app/actions/posts/handle.rb index 499df30..d523c5b 100644 --- a/app/actions/posts/handle.rb +++ b/app/actions/posts/handle.rb @@ -12,13 +12,15 @@ module Adamantium create_resolver: "commands.posts.creation_resolver", delete_post: "commands.posts.delete", undelete_post: "commands.posts.undelete", - update_post: "commands.posts.update" + update_post: "commands.posts.update", + syndicate: "commands.posts.syndicate" ] def handle(req, res) req_entity = post_param_parser.call(params: req.params.to_h) action = req.params[:action] + # delete, undelete, update if action operation, permission_check = resolve_operation(action) @@ -28,13 +30,16 @@ module Adamantium else res.status = 401 end - elsif req_entity + elsif req_entity # create halt 401 unless verify_scope(req: req, scope: :create) command, contract = create_resolver.call(entry_type: req_entity).values_at(:command, :validation) validation = contract.call(req_entity.to_h) if validation.success? + + url = syndicate(validation.to_h) # TODO: set URL on post + post = command.call(validation.to_h) res.status = 201 diff --git a/app/commands/posts/syndicate.rb b/app/commands/posts/syndicate.rb new file mode 100644 index 0000000..259edd0 --- /dev/null +++ b/app/commands/posts/syndicate.rb @@ -0,0 +1,15 @@ +module Adamantium + module Commands + module Posts + class Syndicate + include Deps["settings", "syndication.mastodon"] + + def call(post) + if post.syndicate_to.include settings.mastodon_server + mastodon.call(post: post) + end + end + end + end + end +end diff --git a/config/providers/syndication.rb b/config/providers/syndication.rb new file mode 100644 index 0000000..f8fc60e --- /dev/null +++ b/config/providers/syndication.rb @@ -0,0 +1,5 @@ +Hanami.app.register_provider :syndication, namespace: true do + start do + register "mastodon", Adamantium::Syndication::Mastodon.new + end +end diff --git a/lib/adamantium/syndication/mastodon.rb b/lib/adamantium/syndication/mastodon.rb new file mode 100644 index 0000000..818c38e --- /dev/null +++ b/lib/adamantium/syndication/mastodon.rb @@ -0,0 +1,42 @@ +require "digest" +require "dry/monads" +require "httparty" + +module Adamantium + module Syndication + class Mastodon + include Dry::Monads[:result] + include Deps["settings"] + + def call(post:) + return Failure(:no_mastodon_credentials) unless settings.mastodon_token && settings.mastodon_server + + text = post.name + text_with_link = "#{text} — #{settings.micropub_site_url}" + tags = post.category.map { |tag| "##{tag}" }.join(" ") + text_with_tags = "#{text_with_link} #{tags}" + + key = Digest::MD5.hexdigest text_with_tags + mastodon_token = settings.mastodon_token + mastodon_server = settings.mastodon_server.split("@").first + + response = HTTParty.post(mastodon_server, { + headers: { + "Idempotency-Key": key, + Authorization: "Bearer #{mastodon_token}" + }, + body: { + status: text_with_tags + } + }) + + if response.code > 200 + status = response.message + Success("#{mastodon_server}/#{status[:id]}") + else + Failure(response.message) + end + end + end + end +end