diff --git a/db/migrate/20240324053509_add_emoji_to_posts.rb b/db/migrate/20240324053509_add_emoji_to_posts.rb new file mode 100644 index 0000000..2059059 --- /dev/null +++ b/db/migrate/20240324053509_add_emoji_to_posts.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +ROM::SQL.migration do + change do + alter_table :posts do + add_column :emoji, :text + end + end +end diff --git a/slices/main/actions/feeds/statuses_json.rb b/slices/main/actions/feeds/statuses_json.rb new file mode 100644 index 0000000..f0038e6 --- /dev/null +++ b/slices/main/actions/feeds/statuses_json.rb @@ -0,0 +1,18 @@ +module Main + module Actions + module Feeds + class StatusesJSON < Action + include Deps["views.feeds.statuses_json", "repos.post_repo"] + + def handle(req, res) + posts = post_repo.statuses_for_rss.map do |post| + Decorators::Posts::Decorator.new(post).to_h + end + + res.content_type = "application/json; charset=utf-8" + res.body = JSON.generate(posts, quirks_mode: true) + end + end + end + end +end diff --git a/slices/main/config/routes.rb b/slices/main/config/routes.rb index 6103a0e..40df02e 100644 --- a/slices/main/config/routes.rb +++ b/slices/main/config/routes.rb @@ -24,6 +24,8 @@ module Main get "/feeds/rss", to: "feeds.rss" get "/feeds/statuses_rss", to: "feeds.statuses_rss" + get "/feeds/statuses_json", to: "feeds.statuses_json" + get "/more", to: "more.index" get "/hikes", to: "workouts.index" diff --git a/slices/main/decorators/posts/decorator.rb b/slices/main/decorators/posts/decorator.rb index 4d8f3bd..df21b5c 100644 --- a/slices/main/decorators/posts/decorator.rb +++ b/slices/main/decorators/posts/decorator.rb @@ -53,11 +53,23 @@ module Main doc.at("//img") end + def inline_image_sources + inline_images + &.select {|attr, _value| attr == "src"} + &.map {|img| img[1] } || [] + end + + def photo_sources + photos.map{|photo| photo["value"]} + end + def prefix_emoji if name nil elsif photos? && content == "" "📷" + elsif __getobj__.emoji + __getobj__.emoji else @prefix_emoji ||= if (match = content.match(Unicode::Emoji::REGEX)) match @@ -133,6 +145,15 @@ module Main __getobj__.trips end + def to_h + { + id: slug, + emoji: prefix_emoji, + content: raw_content, + images: (inline_image_sources + photo_sources).compact + } + end + private # e.g. geo:-37.75188,144.90417;u=35 diff --git a/slices/main/templates/feeds/statuses_json.json.builder b/slices/main/templates/feeds/statuses_json.json.builder new file mode 100644 index 0000000..e69de29 diff --git a/slices/main/views/feeds/statuses_json.rb b/slices/main/views/feeds/statuses_json.rb new file mode 100644 index 0000000..51a5f96 --- /dev/null +++ b/slices/main/views/feeds/statuses_json.rb @@ -0,0 +1,21 @@ +require "builder" + +module Main + module Views + module Feeds + class StatusesJSON < Main::View + include Deps["repos.post_repo"] + + expose :posts do + post_repo.statuses_for_rss.map do |post| + Decorators::Posts::Decorator.new post + end + end + + expose :json, decorate: false, layout: true do |posts| + posts.to_json + end + end + end + end +end diff --git a/slices/micropub/entities/post_request.rb b/slices/micropub/entities/post_request.rb index 6c84117..1708cea 100644 --- a/slices/micropub/entities/post_request.rb +++ b/slices/micropub/entities/post_request.rb @@ -11,6 +11,7 @@ module Micropub attribute :post_type, Types::Coercible::String attribute :syndicate_to, Types::Array.of(Types::Coercible::String) attribute :in_reply_to, Types::Coercible::String + attribute :emoji, Types::Coercible::String attribute :photos, Types::Array.of(Types::Hash) attribute :location, Types::Coercible::String.optional end diff --git a/slices/micropub/request_parser.rb b/slices/micropub/request_parser.rb index ff27228..ce3be15 100644 --- a/slices/micropub/request_parser.rb +++ b/slices/micropub/request_parser.rb @@ -98,6 +98,7 @@ module Micropub slug: params[:slug] || params[:"mp-slug"], syndicate_to: Array(params[:properties][:"mp-syndicate-to"]) || [], in_reply_to: params[:properties][:"in-reply-to"] || nil, + emoji: params[:properties][:emoji] || nil, photos: photos, location: params[:properties][:location] }) @@ -121,6 +122,7 @@ module Micropub new_params.merge({ syndicate_to: Array(params[:"mp-syndicate-to"]) || [], in_reply_to: params[:"in-reply-to"], + emoji: params[:emoji], name: params[:name], slug: params[:slug] || params[:"mp-slug"], published_at: (params[:"post-status"] == "draft") ? nil : publish_time, diff --git a/slices/micropub/validation/posts/post_contract.rb b/slices/micropub/validation/posts/post_contract.rb index 7cdcb0f..fdb0baa 100644 --- a/slices/micropub/validation/posts/post_contract.rb +++ b/slices/micropub/validation/posts/post_contract.rb @@ -13,6 +13,7 @@ module Micropub required(:photos).array(:hash) required(:location).maybe(:string) required(:in_reply_to).maybe(:string) + required(:emoji).maybe(:string) end end end diff --git a/spec/requests/create_webmention_spec.rb b/spec/requests/create_webmention_spec.rb index af5d6c9..36a87fe 100644 --- a/spec/requests/create_webmention_spec.rb +++ b/spec/requests/create_webmention_spec.rb @@ -7,26 +7,28 @@ RSpec.describe "Webmention creation", :db, :requests do 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 + post: { + 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 + } } } diff --git a/spec/syndication/unit/mastodon_spec.rb b/spec/syndication/unit/mastodon_spec.rb index e882547..245508e 100644 --- a/spec/syndication/unit/mastodon_spec.rb +++ b/spec/syndication/unit/mastodon_spec.rb @@ -21,7 +21,8 @@ RSpec.describe Adamantium::Syndication::Mastodon do syndicate_to: [], photos: [], location: nil, - in_reply_to: nil + in_reply_to: nil, + emoji: nil ) }