diff --git a/app/actions/webmentions/create.rb b/app/actions/webmentions/create.rb index 978e792..4a68b2d 100644 --- a/app/actions/webmentions/create.rb +++ b/app/actions/webmentions/create.rb @@ -4,29 +4,24 @@ module Adamantium module Actions module Webmentions class Create < Adamantium::Action - - include Deps["repos.webmentions_repo", "repos.post_repo"] + include Deps["repos.webmentions_repo", + "repos.post_repo", + webmention_parser: "param_parser.webmention" + ] def handle(req, res) - if req.params[:"wm-property"] == "in-reply-to" - + webmention = webmention_parser.call(params: req.params) + case webmention + in Success[:reply, reply] slug = req.params[:"in-reply-to"].split("/").last post = post_repo.fetch!(slug) - attrs = { - type: "reply", - author_name: req.params[:author][:name], - author_photo: req.params[:author][:photo], - author_url: req.params[:author][:url], - published_at: req.params[:published], - content_html: req.params[:content][:html], - content_text: req.params[:content][:text], - source_url: req.params[:url], - target_url: req.params[:"in-reply-to"], - post_id: post.id - } + reply[:post_id] = post.id - webmentions_repo.create(attrs) + webmentions_repo.create(reply) + res.status = 201 + in Failure(:invalid_request) + res.status = 429 end end end diff --git a/app/repos/webmentions_repo.rb b/app/repos/webmentions_repo.rb index 2efc0e8..7f6c9ce 100644 --- a/app/repos/webmentions_repo.rb +++ b/app/repos/webmentions_repo.rb @@ -4,4 +4,4 @@ module Adamantium commands :create end end -end \ No newline at end of file +end diff --git a/config/providers/param_parser.rb b/config/providers/param_parser.rb index 271bd7a..4e88582 100644 --- a/config/providers/param_parser.rb +++ b/config/providers/param_parser.rb @@ -3,5 +3,6 @@ Hanami.app.register_provider :param_parser, namespace: true do start do register "micropub_post", Adamantium::MicropubRequestParser.new + register "webmention", Adamantium::WebmentionRequestParser.new end end diff --git a/lib/adamantium/webmention_request_parser.rb b/lib/adamantium/webmention_request_parser.rb new file mode 100644 index 0000000..9f93dfe --- /dev/null +++ b/lib/adamantium/webmention_request_parser.rb @@ -0,0 +1,26 @@ +require "dry/monads" + +module Adamantium + class WebmentionRequestParser + + include Dry::Monads[:result] + + def call(params:) + if params[:"wm-property"] == "in-reply-to" + Success[:reply, { + type: "reply", + author_name: params[:author][:name], + author_photo: params[:author][:photo], + author_url: params[:author][:url], + published_at: params[:published], + content_html: params[:content][:html], + content_text: params[:content][:text], + source_url: params[:url], + target_url: params[:"in-reply-to"] + }] + else + Failure(:invalid_request) + end + end + end +end diff --git a/spec/adamantium/webmention_request_parser_spec.rb b/spec/adamantium/webmention_request_parser_spec.rb new file mode 100644 index 0000000..93f1b0e --- /dev/null +++ b/spec/adamantium/webmention_request_parser_spec.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true +# +RSpec.describe Adamantium::WebmentionRequestParser do + include Dry::Monads[:result] + subject { described_class.new } + + let(:reply_json) { + '{ + "type": "entry", + "author": { + "type": "card", + "name": "nitza", + "photo": "", + "url": "https://micro.blog/nitza" + }, + "url": "https://micro.blog/nitza/20554783", + "published": "2023-07-05T09:44:41+00:00", + "wm-received": "2023-07-05T09:44:48Z", + "wm-id": 1692950, + "wm-source": "https://micro.blog/nitza/20554783", + "wm-target": "https://dnitza.com/post/e413397a-9912-4914-a0d1-3d1c324e014b", + "content": { + "html": "
@example hah! I thought the same thing — but this is the most affordable thing that Teenage Engineering makes 😅
", + "text": "@example hah! I thought the same thing — but this is the most affordable thing that Teenage Engineering makes 😅" + }, + "in-reply-to": "https://dnitza.com/post/e413397a-9912-4914-a0d1-3d1c324e014b", + "wm-property": "in-reply-to", + "wm-private": false + }' + } + + context "reply" do + it "parses a reply" do + expect(subject.call(params: JSON.parse(reply_json, symbolize_names: true))).to be_success + end + + it "fails to parses a reply" do + expect(subject.call(params: JSON.parse("{ }", symbolize_names: true))).to be_failure + end + end +end + diff --git a/spec/requests/create_webmention_spec.rb b/spec/requests/create_webmention_spec.rb new file mode 100644 index 0000000..e730d8f --- /dev/null +++ b/spec/requests/create_webmention_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +RSpec.describe "Webmention creation", :db, :requests do + let(:post_repo) { Adamantium::Repos::PostRepo.new } + let(:post_record) { Test::Factory[:post] } + + context "reply" do + let(:reply_json) { + { + "type": "entry", + "author": { + "type": "card", + "name": "nitza", + "photo": "", + "url": "https://micro.blog/nitza" + }, + "url": "https://micro.blog/nitza/20554783", + "published": "2023-07-05T09:44:41+00:00", + "wm-received": "2023-07-05T09:44:48Z", + "wm-id": 1692950, + "wm-source": "https://micro.blog/nitza/20554783", + "wm-target": "https://dnitza.com/post/#{post_record.slug}", + "content": { + "html": "@example hah! I thought the same thing — but this is the most affordable thing that Teenage Engineering makes 😅
", + "text": "@example hah! I thought the same thing — but this is the most affordable thing that Teenage Engineering makes 😅" + }, + "in-reply-to": "https://dnitza.com/post/#{post_record.slug}", + "wm-property": "in-reply-to", + "wm-private": false + } + } + + it "is successful" do + # params = JSON.parse(reply_json, symbolize_names: true) + + post "/micropub/webmentions", reply_json + + expect(last_response).to be_successful + end + end +end \ No newline at end of file