Refactor micropub specific things out to a slice
This commit is contained in:
0
app/commands/.keep
Normal file
0
app/commands/.keep
Normal file
0
app/entities/.keep
Normal file
0
app/entities/.keep
Normal file
@@ -3,86 +3,6 @@ module Adamantium
|
|||||||
class PostRepo < Adamantium::Repo[:posts]
|
class PostRepo < Adamantium::Repo[:posts]
|
||||||
Sequel.extension :pg_json
|
Sequel.extension :pg_json
|
||||||
Sequel.extension :pg_json_ops
|
Sequel.extension :pg_json_ops
|
||||||
commands update: :by_pk
|
|
||||||
|
|
||||||
def create(post_attrs)
|
|
||||||
posts.transaction do
|
|
||||||
new_post = posts.changeset(:create, post_attrs).commit
|
|
||||||
|
|
||||||
post_attrs[:category].each do |tag_name|
|
|
||||||
next if tag_name == ""
|
|
||||||
|
|
||||||
tag = posts.tags.where(label: tag_name).one ||
|
|
||||||
posts
|
|
||||||
.tags
|
|
||||||
.changeset(:create, {label: tag_name, slug: tag_name.downcase.strip.tr(" ", "-").gsub(/[^\w-]/, "")})
|
|
||||||
.commit
|
|
||||||
|
|
||||||
posts.post_tags.changeset(:create, {
|
|
||||||
post_id: new_post.id,
|
|
||||||
tag_id: tag[:id]
|
|
||||||
})
|
|
||||||
.commit
|
|
||||||
end
|
|
||||||
|
|
||||||
new_post
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def tag_post(post_id:, tags:)
|
|
||||||
tags.each do |tag_name|
|
|
||||||
next if tag_name == ""
|
|
||||||
|
|
||||||
tag = posts.tags.where(label: tag_name).one ||
|
|
||||||
posts
|
|
||||||
.tags
|
|
||||||
.changeset(:create, {label: tag_name, slug: tag_name.downcase.strip.tr(" ", "-").gsub(/[^\w-]/, "")})
|
|
||||||
.commit
|
|
||||||
|
|
||||||
posts.post_tags.changeset(:create, {
|
|
||||||
post_id: post_id,
|
|
||||||
tag_id: tag[:id]
|
|
||||||
})
|
|
||||||
.commit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def auto_tag_post(post_id:, tag_id:)
|
|
||||||
return if posts
|
|
||||||
.post_tags
|
|
||||||
.where(
|
|
||||||
post_id: post_id,
|
|
||||||
tag_id: tag_id
|
|
||||||
).count > 0
|
|
||||||
|
|
||||||
posts
|
|
||||||
.post_tags
|
|
||||||
.changeset(:create, {
|
|
||||||
post_id: post_id,
|
|
||||||
tag_id: tag_id
|
|
||||||
})
|
|
||||||
.commit
|
|
||||||
end
|
|
||||||
|
|
||||||
def by_title(title_contains:)
|
|
||||||
posts
|
|
||||||
.where(post_type: "post")
|
|
||||||
.published
|
|
||||||
.where(Sequel.ilike(:name, "%#{title_contains}%")).to_a
|
|
||||||
end
|
|
||||||
|
|
||||||
def by_content(body_contains:)
|
|
||||||
posts
|
|
||||||
.where(post_type: "post")
|
|
||||||
.published
|
|
||||||
.where(Sequel.ilike(:content, "%#{body_contains}%")).to_a
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_tag(post_id:, tag:)
|
|
||||||
tag = posts.tags.where(label: tag).one
|
|
||||||
|
|
||||||
posts.post_tags.where(post_id: post_id, tag_id: tag[:id]).changeset(:delete).commit if tag
|
|
||||||
end
|
|
||||||
|
|
||||||
def by_year(year:)
|
def by_year(year:)
|
||||||
posts
|
posts
|
||||||
@@ -250,35 +170,12 @@ module Adamantium
|
|||||||
.one!
|
.one!
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_unpublished!(slug)
|
|
||||||
posts
|
|
||||||
.combine(:tags)
|
|
||||||
.where(slug: slug)
|
|
||||||
.one!
|
|
||||||
end
|
|
||||||
|
|
||||||
def find!(id)
|
def find!(id)
|
||||||
posts
|
posts
|
||||||
.by_pk(id)
|
.by_pk(id)
|
||||||
.one!
|
.one!
|
||||||
end
|
end
|
||||||
|
|
||||||
def slug_exists?(slug)
|
|
||||||
!!posts
|
|
||||||
.where(slug: slug)
|
|
||||||
.one
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete!(slug)
|
|
||||||
delete_post = posts.where(slug: slug).command(:update)
|
|
||||||
delete_post.call(published_at: nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
def restore!(slug)
|
|
||||||
delete_post = posts.where(slug: slug).command(:update)
|
|
||||||
delete_post.call(published_at: Time.now)
|
|
||||||
end
|
|
||||||
|
|
||||||
def post_years
|
def post_years
|
||||||
posts
|
posts
|
||||||
.where(post_type: "post", location: nil)
|
.where(post_type: "post", location: nil)
|
||||||
|
@@ -23,9 +23,16 @@ module Adamantium
|
|||||||
config.logger.stream = "log/hanami.log"
|
config.logger.stream = "log/hanami.log"
|
||||||
|
|
||||||
config.shared_app_component_keys += [
|
config.shared_app_component_keys += [
|
||||||
|
"post_utilities.slugify",
|
||||||
"syndication.dayone",
|
"syndication.dayone",
|
||||||
|
"syndication.mastodon",
|
||||||
|
"syndication.blue_sky",
|
||||||
|
"syndication.raindrop",
|
||||||
"renderers.markdown",
|
"renderers.markdown",
|
||||||
"post_utilities.link_finder"
|
"post_utilities.link_finder",
|
||||||
|
"param_parser.micropub_post",
|
||||||
|
"param_parser.webmention",
|
||||||
|
"post_utilities.page_cacher"
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Hanami.app.register_provider :param_parser, namespace: true do
|
Hanami.app.register_provider :param_parser, namespace: true do
|
||||||
start do
|
start do
|
||||||
register "micropub_post", Adamantium::MicropubRequestParser.new
|
register "micropub_post", Micropub::RequestParser.new
|
||||||
register "webmention", Adamantium::WebmentionRequestParser.new
|
register "webmention", Adamantium::WebmentionRequestParser.new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -9,14 +9,7 @@ module Adamantium
|
|||||||
use Hanami::Middleware::BodyParser, [:form, :json]
|
use Hanami::Middleware::BodyParser, [:form, :json]
|
||||||
# use Adamantium::Middleware::ProcessParams
|
# use Adamantium::Middleware::ProcessParams
|
||||||
|
|
||||||
scope "micropub" do
|
slice :micropub, at: "/micropub"
|
||||||
get "/", to: "site.config"
|
|
||||||
post "/", to: "posts.handle"
|
|
||||||
post "/media", to: "media.create"
|
|
||||||
get "/media", to: "media.show"
|
|
||||||
|
|
||||||
post "/webmentions", to: "webmentions.create"
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/", to: "site.home"
|
get "/", to: "site.home"
|
||||||
get "/post/top_tracks/:slug", to: "posts.top_tracks"
|
get "/post/top_tracks/:slug", to: "posts.top_tracks"
|
||||||
|
7
slices/micropub/action.rb
Normal file
7
slices/micropub/action.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# auto_register: false
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Micropub
|
||||||
|
class Action < Adamantium::Action
|
||||||
|
end
|
||||||
|
end
|
0
slices/micropub/actions/.keep
Normal file
0
slices/micropub/actions/.keep
Normal file
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Actions
|
module Actions
|
||||||
module Media
|
module Media
|
||||||
class Create < Action
|
class Create < Action
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Actions
|
module Actions
|
||||||
module Media
|
module Media
|
||||||
class Show < Action
|
class Show < Action
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Actions
|
module Actions
|
||||||
module Posts
|
module Posts
|
||||||
class Handle < Action
|
class Handle < Action
|
@@ -1,8 +1,8 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Actions
|
module Actions
|
||||||
module Site
|
module Site
|
||||||
class Config < Action
|
class Config < Action
|
||||||
include Deps["settings", "views.site.home", "queries.posts.microformat_post"]
|
include Deps["settings", "queries.posts.microformat_post"]
|
||||||
before :authenticate!
|
before :authenticate!
|
||||||
|
|
||||||
def handle(req, res)
|
def handle(req, res)
|
||||||
@@ -60,7 +60,7 @@ module Adamantium
|
|||||||
res.content_type = "Application/JSON"
|
res.content_type = "Application/JSON"
|
||||||
res.body = microformat_post.call(url: req.params[:url], properties: req.params[:properties]).to_json
|
res.body = microformat_post.call(url: req.params[:url], properties: req.params[:properties]).to_json
|
||||||
else
|
else
|
||||||
res.render home
|
res.redirect_to "/"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@@ -1,6 +1,6 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Actions
|
module Actions
|
||||||
module Webmentions
|
module Webmentions
|
||||||
class Create < Adamantium::Action
|
class Create < Adamantium::Action
|
5
slices/micropub/assets/css/app.css
Normal file
5
slices/micropub/assets/css/app.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
body {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #000;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
1
slices/micropub/assets/js/app.js
Normal file
1
slices/micropub/assets/js/app.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import "../css/app.css";
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module AutoTagging
|
module AutoTagging
|
||||||
class Tag
|
class Tag
|
@@ -6,10 +6,10 @@ require "filemagic"
|
|||||||
require "image_processing/vips"
|
require "image_processing/vips"
|
||||||
require "open3"
|
require "open3"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Media
|
module Media
|
||||||
class Upload < Command
|
class Upload < Adamantium::Command
|
||||||
include Deps["settings"]
|
include Deps["settings"]
|
||||||
include Dry::Monads[:result]
|
include Dry::Monads[:result]
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class AddSyndicationSource
|
class AddSyndicationSource
|
@@ -1,9 +1,9 @@
|
|||||||
require "dry/monads"
|
require "dry/monads"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class CreateBookPost < Command
|
class CreateBookPost < Adamantium::Command
|
||||||
include Deps["repos.post_repo"]
|
include Deps["repos.post_repo"]
|
||||||
|
|
||||||
include Dry::Monads[:result]
|
include Dry::Monads[:result]
|
@@ -1,9 +1,9 @@
|
|||||||
require "dry/monads"
|
require "dry/monads"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class CreateBookmark < Command
|
class CreateBookmark < Adamantium::Command
|
||||||
include Deps["repos.post_repo",
|
include Deps["repos.post_repo",
|
||||||
"post_utilities.page_cacher",
|
"post_utilities.page_cacher",
|
||||||
syndicate: "commands.posts.syndicate",
|
syndicate: "commands.posts.syndicate",
|
@@ -1,9 +1,9 @@
|
|||||||
require "dry/monads"
|
require "dry/monads"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class CreateCheckin < Command
|
class CreateCheckin < Adamantium::Command
|
||||||
include Deps["repos.post_repo",
|
include Deps["repos.post_repo",
|
||||||
"post_utilities.slugify",
|
"post_utilities.slugify",
|
||||||
"logger",
|
"logger",
|
@@ -1,9 +1,9 @@
|
|||||||
require "dry/monads"
|
require "dry/monads"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class CreateEntry < Command
|
class CreateEntry < Adamantium::Command
|
||||||
include Deps["repos.post_repo",
|
include Deps["repos.post_repo",
|
||||||
"post_utilities.slugify",
|
"post_utilities.slugify",
|
||||||
renderer: "renderers.markdown",
|
renderer: "renderers.markdown",
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class CreationResolver
|
class CreationResolver
|
@@ -1,7 +1,7 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class Delete < Command
|
class Delete < Adamantium::Command
|
||||||
include Deps["repos.post_repo"]
|
include Deps["repos.post_repo"]
|
||||||
def call(params:)
|
def call(params:)
|
||||||
slug = URI(params[:url]).path.split("/").last
|
slug = URI(params[:url]).path.split("/").last
|
@@ -1,7 +1,7 @@
|
|||||||
require "httparty"
|
require "httparty"
|
||||||
require "que"
|
require "que"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class SendWebmentions
|
class SendWebmentions
|
@@ -1,7 +1,7 @@
|
|||||||
require "dry/monads"
|
require "dry/monads"
|
||||||
require "dry/monads/do"
|
require "dry/monads/do"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class Syndicate
|
class Syndicate
|
@@ -1,7 +1,7 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class Undelete < Command
|
class Undelete < Adamantium::Command
|
||||||
include Deps["repos.post_repo"]
|
include Deps["repos.post_repo"]
|
||||||
def call(params:)
|
def call(params:)
|
||||||
slug = URI(params[:url]).path.split("/").last
|
slug = URI(params[:url]).path.split("/").last
|
@@ -1,7 +1,7 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Commands
|
module Commands
|
||||||
module Posts
|
module Posts
|
||||||
class Update < Command
|
class Update < Adamantium::Command
|
||||||
include Deps[
|
include Deps[
|
||||||
"repos.post_repo",
|
"repos.post_repo",
|
||||||
"renderers.markdown",
|
"renderers.markdown",
|
16
slices/micropub/config/routes.rb
Normal file
16
slices/micropub/config/routes.rb
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "hanami/middleware/body_parser"
|
||||||
|
|
||||||
|
module Micropub
|
||||||
|
class Routes < Hanami::Routes
|
||||||
|
use Hanami::Middleware::BodyParser, [:form, :json]
|
||||||
|
|
||||||
|
get "/", to: "site.config"
|
||||||
|
post "/", to: "posts.handle"
|
||||||
|
post "/media", to: "media.create"
|
||||||
|
get "/media", to: "media.show"
|
||||||
|
|
||||||
|
post "/webmentions", to: "webmentions.create"
|
||||||
|
end
|
||||||
|
end
|
167
slices/micropub/decorators/posts/decorator.rb
Normal file
167
slices/micropub/decorators/posts/decorator.rb
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# frozen_string_literal: false
|
||||||
|
|
||||||
|
# auto_register: false
|
||||||
|
|
||||||
|
require "rexml/parsers/pullparser"
|
||||||
|
require "sanitize"
|
||||||
|
|
||||||
|
module Micropub
|
||||||
|
module Decorators
|
||||||
|
module Posts
|
||||||
|
class Decorator < SimpleDelegator
|
||||||
|
def syndicated?
|
||||||
|
!syndication_sources.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def syndicated_to
|
||||||
|
syndication_sources.map do |source, url|
|
||||||
|
{
|
||||||
|
location: source,
|
||||||
|
url: url
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def photos?
|
||||||
|
__getobj__.photos.count { |p| !p["value"].end_with?("mp4") } > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def photos
|
||||||
|
__getobj__.photos.select { |p| !p["value"].end_with?("mp4") }
|
||||||
|
end
|
||||||
|
|
||||||
|
def videos?
|
||||||
|
__getobj__.photos.count { |p| p["value"].end_with?("mp4") } > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def videos
|
||||||
|
__getobj__.photos.select { |p| p["value"].end_with?("mp4") }
|
||||||
|
end
|
||||||
|
|
||||||
|
def prefix_emoji
|
||||||
|
if name
|
||||||
|
""
|
||||||
|
elsif photos? && content == ""
|
||||||
|
"📷"
|
||||||
|
else
|
||||||
|
"💬"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def display_title
|
||||||
|
title = name
|
||||||
|
"#{prefix_emoji} #{title}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def display_published_at
|
||||||
|
published_at.strftime("%e %B, %Y")
|
||||||
|
end
|
||||||
|
|
||||||
|
def machine_published_at
|
||||||
|
published_at.rfc2822
|
||||||
|
end
|
||||||
|
|
||||||
|
def feed_content
|
||||||
|
photos? ? "<div>#{photos.map { |p| "<img src='#{p["value"]}'/>" }.join("")} #{content}</div>" : content
|
||||||
|
end
|
||||||
|
|
||||||
|
def raw_content
|
||||||
|
Sanitize.fragment(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def excerpt
|
||||||
|
name ? truncate_html(content, 240, true) : content
|
||||||
|
end
|
||||||
|
|
||||||
|
def permalink
|
||||||
|
"#{Hanami.app.settings.micropub_site_url}/post/#{slug}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def lat
|
||||||
|
geo[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
def lon
|
||||||
|
geo[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
def small_map
|
||||||
|
"https://api.mapbox.com/styles/v1/dnitza/cleb2o734000k01pbifls5620/static/pin-s+555555(#{lon},#{lat})/#{lon},#{lat},14,0/200x100@2x?access_token=pk.eyJ1IjoiZG5pdHphIiwiYSI6ImNsZWIzOHFmazBkODIzdm9kZHgxdDF4ajQifQ.mSneE-1SKeju8AOz5gp4BQ"
|
||||||
|
end
|
||||||
|
|
||||||
|
def large_map
|
||||||
|
"https://api.mapbox.com/styles/v1/dnitza/cleb2o734000k01pbifls5620/static/pin-s+555555(#{lon},#{lat})/#{lon},#{lat},14,0/620x310@2x?access_token=pk.eyJ1IjoiZG5pdHphIiwiYSI6ImNsZWIzOHFmazBkODIzdm9kZHgxdDF4ajQifQ.mSneE-1SKeju8AOz5gp4BQ"
|
||||||
|
end
|
||||||
|
|
||||||
|
def template_type
|
||||||
|
:post
|
||||||
|
end
|
||||||
|
|
||||||
|
def posted_in
|
||||||
|
if name.nil?
|
||||||
|
:statuses
|
||||||
|
elsif post_type.to_sym == :book
|
||||||
|
:bookshelf
|
||||||
|
elsif location.nil?
|
||||||
|
:posts
|
||||||
|
else
|
||||||
|
:places
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def trips
|
||||||
|
__getobj__.trips
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# e.g. geo:-37.75188,144.90417;u=35
|
||||||
|
def geo
|
||||||
|
loc = location.split(":")[1]
|
||||||
|
p = loc.split(";")[0]
|
||||||
|
|
||||||
|
p.split(",")
|
||||||
|
end
|
||||||
|
|
||||||
|
def truncate_html(content, len = 30, at_end = nil)
|
||||||
|
return content if content.to_s.length <= len
|
||||||
|
|
||||||
|
p = REXML::Parsers::PullParser.new(content)
|
||||||
|
tags = []
|
||||||
|
new_len = len
|
||||||
|
results = ""
|
||||||
|
while p.has_next? && new_len > 0
|
||||||
|
p_e = p.pull
|
||||||
|
case p_e.event_type
|
||||||
|
when :start_element
|
||||||
|
tags.push p_e[0]
|
||||||
|
results << "<#{tags.last}#{attrs_to_s(p_e[1])}>"
|
||||||
|
when :end_element
|
||||||
|
results << "</#{tags.pop}>"
|
||||||
|
when :text
|
||||||
|
results << p_e[0][0..new_len]
|
||||||
|
new_len -= p_e[0].length
|
||||||
|
else
|
||||||
|
results << "<!-- #{p_e.inspect} -->"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if at_end
|
||||||
|
results << "..."
|
||||||
|
end
|
||||||
|
tags.reverse_each do |tag|
|
||||||
|
results << "</#{tag}>"
|
||||||
|
end
|
||||||
|
results
|
||||||
|
end
|
||||||
|
|
||||||
|
def attrs_to_s(attrs)
|
||||||
|
if attrs.empty?
|
||||||
|
""
|
||||||
|
else
|
||||||
|
" " + attrs.to_a.map { |attr| %(#{attr[0]}="#{attr[1]}") }.join(" ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@@ -1,6 +1,7 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Entities
|
module Entities
|
||||||
class AutoTagging < Dry::Struct
|
class AutoTagging < Dry::Struct
|
||||||
|
attribute :id, Types::Coercible::Integer
|
||||||
attribute? :title_contains, Types::Optional::String
|
attribute? :title_contains, Types::Optional::String
|
||||||
attribute? :body_contains, Types::Optional::String
|
attribute? :body_contains, Types::Optional::String
|
||||||
attribute :tag_id, Types::Coercible::Integer
|
attribute :tag_id, Types::Coercible::Integer
|
||||||
@@ -8,6 +9,14 @@ module Adamantium
|
|||||||
def title_only?
|
def title_only?
|
||||||
!title_contains.empty?
|
!title_contains.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def term
|
||||||
|
title_only? ? title_contains : body_contains
|
||||||
|
end
|
||||||
|
|
||||||
|
class WithTag < AutoTagging
|
||||||
|
attribute :tag, Types::Tag
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Entities
|
module Entities
|
||||||
class BookRequest < Dry::Struct
|
class BookRequest < Dry::Struct
|
||||||
attribute :h, Types::Coercible::String
|
attribute :h, Types::Coercible::String
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Entities
|
module Entities
|
||||||
class BookmarkRequest < Dry::Struct
|
class BookmarkRequest < Dry::Struct
|
||||||
attribute :h, Types::Coercible::String
|
attribute :h, Types::Coercible::String
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Entities
|
module Entities
|
||||||
class CheckinRequest < Dry::Struct
|
class CheckinRequest < Dry::Struct
|
||||||
attribute :h, Types::Coercible::String
|
attribute :h, Types::Coercible::String
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Entities
|
module Entities
|
||||||
class PostRequest < Dry::Struct
|
class PostRequest < Dry::Struct
|
||||||
attribute :h, Types::Coercible::String
|
attribute :h, Types::Coercible::String
|
@@ -1,6 +1,6 @@
|
|||||||
require "reverse_markdown"
|
require "reverse_markdown"
|
||||||
|
|
||||||
module Adamantium
|
module Micropub
|
||||||
module Queries
|
module Queries
|
||||||
module Posts
|
module Posts
|
||||||
class MicroformatPost
|
class MicroformatPost
|
@@ -1,16 +1,16 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Repos
|
module Repos
|
||||||
class AutoTaggingRepo < Adamantium::Repo[:auto_taggings]
|
class AutoTaggingRepo < Adamantium::Repo[:auto_taggings]
|
||||||
def find(id)
|
def find(id)
|
||||||
auto_taggings
|
auto_taggings
|
||||||
.where(id: id)
|
.where(id: id)
|
||||||
.map_to(Adamantium::Entities::AutoTagging)
|
.map_to(Micropub::Entities::AutoTagging)
|
||||||
.to_a
|
.to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
def all
|
def all
|
||||||
auto_taggings
|
auto_taggings
|
||||||
.map_to(Adamantium::Entities::AutoTagging)
|
.map_to(Micropub::Entities::AutoTagging)
|
||||||
.to_a
|
.to_a
|
||||||
end
|
end
|
||||||
end
|
end
|
7
slices/micropub/repos/movie_repo.rb
Normal file
7
slices/micropub/repos/movie_repo.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module Micropub
|
||||||
|
module Repos
|
||||||
|
class MovieRepo < Adamantium::Repo[:movies]
|
||||||
|
commands :create
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
15
slices/micropub/repos/podcast_repo.rb
Normal file
15
slices/micropub/repos/podcast_repo.rb
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
module Micropub
|
||||||
|
module Repos
|
||||||
|
class PodcastRepo < Adamantium::Repo[:podcasts]
|
||||||
|
commands :create
|
||||||
|
|
||||||
|
def listing
|
||||||
|
podcasts.order(:name).to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_all
|
||||||
|
podcasts.delete
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
112
slices/micropub/repos/post_repo.rb
Normal file
112
slices/micropub/repos/post_repo.rb
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
module Micropub
|
||||||
|
module Repos
|
||||||
|
class PostRepo < Adamantium::Repo[:posts]
|
||||||
|
commands update: :by_pk
|
||||||
|
|
||||||
|
def remove_tag(post_id:, tag:)
|
||||||
|
tag = posts.tags.where(label: tag).one
|
||||||
|
|
||||||
|
posts.post_tags.where(post_id: post_id, tag_id: tag[:id]).changeset(:delete).commit if tag
|
||||||
|
end
|
||||||
|
|
||||||
|
def create(post_attrs)
|
||||||
|
posts.transaction do
|
||||||
|
new_post = posts.changeset(:create, post_attrs).commit
|
||||||
|
|
||||||
|
post_attrs[:category].each do |tag_name|
|
||||||
|
next if tag_name == ""
|
||||||
|
|
||||||
|
tag = posts.tags.where(label: tag_name).one ||
|
||||||
|
posts
|
||||||
|
.tags
|
||||||
|
.changeset(:create, {label: tag_name, slug: tag_name.downcase.strip.tr(" ", "-").gsub(/[^\w-]/, "")})
|
||||||
|
.commit
|
||||||
|
|
||||||
|
posts.post_tags.changeset(:create, {
|
||||||
|
post_id: new_post.id,
|
||||||
|
tag_id: tag[:id]
|
||||||
|
})
|
||||||
|
.commit
|
||||||
|
end
|
||||||
|
|
||||||
|
new_post
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def slug_exists?(slug)
|
||||||
|
!!posts
|
||||||
|
.where(slug: slug)
|
||||||
|
.one
|
||||||
|
end
|
||||||
|
|
||||||
|
def find!(id)
|
||||||
|
posts
|
||||||
|
.by_pk(id)
|
||||||
|
.one!
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch!(slug)
|
||||||
|
posts
|
||||||
|
.published
|
||||||
|
.combine(:tags, :trips, :webmentions)
|
||||||
|
.node(:webmentions) { |webmention|
|
||||||
|
webmention.where(type: "reply")
|
||||||
|
}
|
||||||
|
.where(slug: slug)
|
||||||
|
.one!
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_unpublished!(slug)
|
||||||
|
posts
|
||||||
|
.combine(:tags)
|
||||||
|
.where(slug: slug)
|
||||||
|
.one!
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_post(post_id:, tags:)
|
||||||
|
tags.each do |tag_name|
|
||||||
|
next if tag_name == ""
|
||||||
|
|
||||||
|
tag = posts.tags.where(label: tag_name).one ||
|
||||||
|
posts
|
||||||
|
.tags
|
||||||
|
.changeset(:create, {label: tag_name, slug: tag_name.downcase.strip.tr(" ", "-").gsub(/[^\w-]/, "")})
|
||||||
|
.commit
|
||||||
|
|
||||||
|
posts.post_tags.changeset(:create, {
|
||||||
|
post_id: post_id,
|
||||||
|
tag_id: tag[:id]
|
||||||
|
})
|
||||||
|
.commit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def auto_tag_post(post_id:, tag_id:)
|
||||||
|
return if posts
|
||||||
|
.post_tags
|
||||||
|
.where(
|
||||||
|
post_id: post_id,
|
||||||
|
tag_id: tag_id
|
||||||
|
).count > 0
|
||||||
|
|
||||||
|
posts
|
||||||
|
.post_tags
|
||||||
|
.changeset(:create, {
|
||||||
|
post_id: post_id,
|
||||||
|
tag_id: tag_id
|
||||||
|
})
|
||||||
|
.commit
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete!(slug)
|
||||||
|
delete_post = posts.where(slug: slug).command(:update)
|
||||||
|
delete_post.call(published_at: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
def restore!(slug)
|
||||||
|
delete_post = posts.where(slug: slug).command(:update)
|
||||||
|
delete_post.call(published_at: Time.now)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
7
slices/micropub/repos/webmentions_repo.rb
Normal file
7
slices/micropub/repos/webmentions_repo.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module Micropub
|
||||||
|
module Repos
|
||||||
|
class WebmentionsRepo < Adamantium::Repo[:webmentions]
|
||||||
|
commands :create
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
7
slices/micropub/repos/workout_repo.rb
Normal file
7
slices/micropub/repos/workout_repo.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module Micropub
|
||||||
|
module Repos
|
||||||
|
class WorkoutRepo < Adamantium::Repo[:workouts]
|
||||||
|
commands :create, update: :by_pk
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@@ -1,5 +1,5 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
class MicropubRequestParser
|
class RequestParser
|
||||||
def call(params:)
|
def call(params:)
|
||||||
return nil if params.key?(:action)
|
return nil if params.key?(:action)
|
||||||
|
|
0
slices/micropub/templates/.keep
Normal file
0
slices/micropub/templates/.keep
Normal file
0
slices/micropub/templates/layouts/.keep
Normal file
0
slices/micropub/templates/layouts/.keep
Normal file
14
slices/micropub/templates/layouts/app.html.erb
Normal file
14
slices/micropub/templates/layouts/app.html.erb
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Adamantium - Micropub</title>
|
||||||
|
<%= favicon_tag %>
|
||||||
|
<%= stylesheet_tag "micropub/app" %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%= yield %>
|
||||||
|
<%= javascript_tag "micropub/app" %>
|
||||||
|
</body>
|
||||||
|
</html>
|
13
slices/micropub/types.rb
Normal file
13
slices/micropub/types.rb
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "dry/types"
|
||||||
|
|
||||||
|
module Micropub
|
||||||
|
Types = Dry.Types
|
||||||
|
|
||||||
|
module Types
|
||||||
|
class Tag < Dry::Struct
|
||||||
|
attribute :label, Types::Coercible::String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Validation
|
module Validation
|
||||||
module Posts
|
module Posts
|
||||||
class BookContract < Dry::Validation::Contract
|
class BookContract < Dry::Validation::Contract
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Validation
|
module Validation
|
||||||
module Posts
|
module Posts
|
||||||
class BookmarkContract < Dry::Validation::Contract
|
class BookmarkContract < Dry::Validation::Contract
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Validation
|
module Validation
|
||||||
module Posts
|
module Posts
|
||||||
class CheckinContract < Dry::Validation::Contract
|
class CheckinContract < Dry::Validation::Contract
|
@@ -1,4 +1,4 @@
|
|||||||
module Adamantium
|
module Micropub
|
||||||
module Validation
|
module Validation
|
||||||
module Posts
|
module Posts
|
||||||
class PostContract < Dry::Validation::Contract
|
class PostContract < Dry::Validation::Contract
|
7
slices/micropub/view.rb
Normal file
7
slices/micropub/view.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# auto_register: false
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Micropub
|
||||||
|
class View < Adamantium::View
|
||||||
|
end
|
||||||
|
end
|
0
slices/micropub/views/.keep
Normal file
0
slices/micropub/views/.keep
Normal file
10
slices/micropub/views/helpers.rb
Normal file
10
slices/micropub/views/helpers.rb
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# auto_register: false
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Micropub
|
||||||
|
module Views
|
||||||
|
module Helpers
|
||||||
|
# Add your view helpers here
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@@ -1,4 +1,4 @@
|
|||||||
RSpec.describe Adamantium::MicropubRequestParser do
|
RSpec.describe Micropub::RequestParser do
|
||||||
subject { described_class.new }
|
subject { described_class.new }
|
||||||
|
|
||||||
context "json request" do
|
context "json request" do
|
||||||
@@ -19,7 +19,7 @@ RSpec.describe Adamantium::MicropubRequestParser do
|
|||||||
it "parses the params in to the expected shape" do
|
it "parses the params in to the expected shape" do
|
||||||
Timecop.freeze do
|
Timecop.freeze do
|
||||||
result = subject.call(params: params)
|
result = subject.call(params: params)
|
||||||
expect(result).to be_a Adamantium::Entities::PostRequest
|
expect(result).to be_a Micropub::Entities::PostRequest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -38,7 +38,7 @@ RSpec.describe Adamantium::MicropubRequestParser do
|
|||||||
it "parses the params in to the expected shape" do
|
it "parses the params in to the expected shape" do
|
||||||
Timecop.freeze do
|
Timecop.freeze do
|
||||||
result = subject.call(params: params)
|
result = subject.call(params: params)
|
||||||
expect(result).to be_a Adamantium::Entities::PostRequest
|
expect(result).to be_a Micropub::Entities::PostRequest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -140,7 +140,7 @@ RSpec.describe Adamantium::MicropubRequestParser do
|
|||||||
it "parses the request" do
|
it "parses the request" do
|
||||||
Timecop.freeze do
|
Timecop.freeze do
|
||||||
result = subject.call(params: params)
|
result = subject.call(params: params)
|
||||||
expect(result).to be_a Adamantium::Entities::CheckinRequest
|
expect(result).to be_a Micropub::Entities::CheckinRequest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
require "dry/monads"
|
require "dry/monads"
|
||||||
require "base64"
|
require "base64"
|
||||||
|
|
||||||
RSpec.describe Adamantium::Commands::Media::Upload do
|
RSpec.describe Micropub::Commands::Media::Upload do
|
||||||
subject { described_class.new }
|
subject { described_class.new }
|
||||||
|
|
||||||
it "saves a file and returns its URL" do
|
it "saves a file and returns its URL" do
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
require "spec_helper"
|
require "spec_helper"
|
||||||
|
|
||||||
RSpec.describe Adamantium::Commands::Posts::AddSyndicationSource, :db do
|
RSpec.describe Micropub::Commands::Posts::AddSyndicationSource, :db do
|
||||||
subject { described_class.new }
|
subject { described_class.new }
|
||||||
|
|
||||||
describe "setting a syndication source" do
|
describe "setting a syndication source" do
|
||||||
let(:post) { Test::Factory[:post] }
|
let(:post) { Test::Factory[:post] }
|
||||||
let(:repo) { Adamantium::Container["repos.post_repo"] }
|
let(:repo) { Micropub::Container["repos.post_repo"] }
|
||||||
|
|
||||||
context "when no sources exist" do
|
context "when no sources exist" do
|
||||||
it "sets a new source" do
|
it "sets a new source" do
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
require "spec_helper"
|
require "spec_helper"
|
||||||
|
|
||||||
RSpec.describe Adamantium::Commands::Posts::Delete, :db do
|
RSpec.describe Micropub::Commands::Posts::Delete, :db do
|
||||||
let(:post_repo) { spy(Adamantium::Repos::PostRepo) }
|
let(:post_repo) { spy(Micropub::Repos::PostRepo) }
|
||||||
let(:subject) { described_class.new(post_repo: post_repo) }
|
let(:subject) { described_class.new(post_repo: post_repo) }
|
||||||
|
|
||||||
it "deletes a post" do
|
it "deletes a post" do
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
require "spec_helper"
|
require "spec_helper"
|
||||||
require "dry/monads"
|
require "dry/monads"
|
||||||
|
|
||||||
RSpec.describe Adamantium::Commands::Posts::Syndicate do
|
RSpec.describe Micropub::Commands::Posts::Syndicate do
|
||||||
include Dry::Monads[:result]
|
include Dry::Monads[:result]
|
||||||
|
|
||||||
let(:settings) { double("settings", mastodon_server: "https://mastodon.example/@tester", blue_sky_url: "https://bluesky.app") }
|
let(:settings) { double("settings", mastodon_server: "https://mastodon.example/@tester", blue_sky_url: "https://bluesky.app") }
|
||||||
let(:mastodon_client) { double("Adamantium::Client::Mastodon") }
|
let(:mastodon_client) { double("Adamantium::Client::Mastodon") }
|
||||||
let(:mastodon_syndicator) { Adamantium::Syndication::Mastodon.new(mastodon_client: mastodon_client) }
|
let(:mastodon_syndicator) { Adamantium::Syndication::Mastodon.new(mastodon_client: mastodon_client) }
|
||||||
let(:post) { {url: "example.com", syndicate_to: ["https://mastodon.example", "https://pinboard.in"], category: []} }
|
let(:post) { {url: "example.com", syndicate_to: ["https://mastodon.example", "https://pinboard.in"], category: []} }
|
||||||
let(:add_post_syndication_source) { spy(Adamantium::Commands::Posts::AddSyndicationSource) }
|
let(:add_post_syndication_source) { spy(Micropub::Commands::Posts::AddSyndicationSource) }
|
||||||
|
|
||||||
subject {
|
subject {
|
||||||
described_class.new(mastodon: mastodon_syndicator,
|
described_class.new(mastodon: mastodon_syndicator,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
require "spec_helper"
|
require "spec_helper"
|
||||||
|
|
||||||
RSpec.describe Adamantium::Commands::Posts::Undelete, :db do
|
RSpec.describe Micropub::Commands::Posts::Undelete, :db do
|
||||||
let(:post_repo) { spy(Adamantium::Repos::PostRepo) }
|
let(:post_repo) { spy(Micropub::Repos::PostRepo) }
|
||||||
let(:subject) { described_class.new(post_repo: post_repo) }
|
let(:subject) { described_class.new(post_repo: post_repo) }
|
||||||
|
|
||||||
it "deletes a post" do
|
it "deletes a post" do
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
require "spec_helper"
|
require "spec_helper"
|
||||||
|
|
||||||
RSpec.describe Adamantium::Commands::Posts::Update, :db do
|
RSpec.describe Micropub::Commands::Posts::Update, :db do
|
||||||
# Adding: add a property that didn't previously exist
|
# Adding: add a property that didn't previously exist
|
||||||
# If there are any existing values for this property, they are not changed, the new values are added.
|
# If there are any existing values for this property, they are not changed, the new values are added.
|
||||||
# If the property does not exist already, it is created.
|
# If the property does not exist already, it is created.
|
||||||
@@ -10,7 +10,7 @@ RSpec.describe Adamantium::Commands::Posts::Update, :db do
|
|||||||
|
|
||||||
describe "add" do
|
describe "add" do
|
||||||
let(:post) { Test::Factory[:post] }
|
let(:post) { Test::Factory[:post] }
|
||||||
let(:repo) { Adamantium::Container["repos.post_repo"] }
|
let(:repo) { Micropub::Container["repos.post_repo"] }
|
||||||
|
|
||||||
let(:params) {
|
let(:params) {
|
||||||
{
|
{
|
||||||
@@ -37,7 +37,7 @@ RSpec.describe Adamantium::Commands::Posts::Update, :db do
|
|||||||
# Replacing: Replace all values of the property. If the property does not exist already, it is created.
|
# Replacing: Replace all values of the property. If the property does not exist already, it is created.
|
||||||
describe "replace" do
|
describe "replace" do
|
||||||
let(:post) { Test::Factory[:post] }
|
let(:post) { Test::Factory[:post] }
|
||||||
let(:repo) { Adamantium::Container["repos.post_repo"] }
|
let(:repo) { Micropub::Container["repos.post_repo"] }
|
||||||
|
|
||||||
let(:params) {
|
let(:params) {
|
||||||
{
|
{
|
||||||
@@ -62,7 +62,7 @@ RSpec.describe Adamantium::Commands::Posts::Update, :db do
|
|||||||
describe "remove" do
|
describe "remove" do
|
||||||
let(:post1) { Test::Factory[:post] }
|
let(:post1) { Test::Factory[:post] }
|
||||||
let(:post2) { Test::Factory[:post] }
|
let(:post2) { Test::Factory[:post] }
|
||||||
let(:repo) { Adamantium::Container["repos.post_repo"] }
|
let(:repo) { Micropub::Container["repos.post_repo"] }
|
||||||
|
|
||||||
let(:complete_params) {
|
let(:complete_params) {
|
||||||
{
|
{
|
||||||
|
@@ -9,7 +9,7 @@ RSpec.describe Adamantium::Syndication::Mastodon do
|
|||||||
|
|
||||||
describe "syndication to mastodon" do
|
describe "syndication to mastodon" do
|
||||||
let(:post) {
|
let(:post) {
|
||||||
Adamantium::Entities::PostRequest.new(
|
Micropub::Entities::PostRequest.new(
|
||||||
h: "h-type",
|
h: "h-type",
|
||||||
action: nil,
|
action: nil,
|
||||||
name: "My Post",
|
name: "My Post",
|
||||||
|
Reference in New Issue
Block a user