Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit b4b9b0d

Browse files
committed
refactor(cited-article): wip
1 parent e5c7665 commit b4b9b0d

File tree

13 files changed

+344
-11
lines changed

13 files changed

+344
-11
lines changed

config/config.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ config :pre_commit, commands: ["format"], verbose: false
3131
# of this file so it overrides the configuration defined above.
3232

3333
config :groupher_server, :general,
34+
site_host: "https://coderplanets.com",
3435
page_size: 30,
3536
inner_page_size: 5,
3637
# today is not include

lib/groupher_server/cms/delegates/article_curd.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
149149
|> Multi.run(:create_article, fn _, _ ->
150150
do_create_article(info.model, attrs, author, community)
151151
end)
152+
|> Multi.run(:block_tasks, fn _, %{create_article: article} ->
153+
# ArticleCommunity.mirror_article(thread, article.id, community.id)
154+
# Later
155+
# BlockTasks.handle(article)
156+
{:ok, :pass}
157+
end)
152158
|> Multi.run(:mirror_article, fn _, %{create_article: article} ->
153159
ArticleCommunity.mirror_article(thread, article.id, community.id)
154160
end)
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
defmodule GroupherServer.CMS.Delegate.BlockTasks do
2+
@moduledoc """
3+
run tasks in every article blocks if need
4+
"""
5+
import Helper.Utils, only: [get_config: 2]
6+
import GroupherServer.CMS.Helper.Matcher
7+
8+
alias GroupherServer.Repo
9+
10+
alias GroupherServer.CMS.Model.CitedContent
11+
alias Helper.ORM
12+
13+
@site_host get_config(:general, :site_host)
14+
@article_threads get_config(:article, :threads)
15+
@valid_article_prefix Enum.map(@article_threads, &"#{@site_host}/#{&1}/")
16+
17+
"""
18+
我被谁引用了 是最重要的信息
19+
我引用了谁不重要,自己扫帖子就行了
20+
cited_thread, cited_article_id, [xxx_article]_id, [block_id, cited_block_id],
21+
22+
POST post_333 -> cited_article_333, [[block_3, cited_block_23]]
23+
24+
cited_type, cited_content_id, [contents]_id, [block_id, cited_block_id],
25+
26+
cited_type: thread or comment
27+
content: article or comment
28+
# cited_article_comment_id, [xxx_article]_id, [block_id, cited_block_id],
29+
"""
30+
31+
# reference
32+
# mention
33+
34+
def handle(%{body: body} = article) do
35+
with {:ok, body_map} <- Jason.decode(body) do
36+
run_tasks(:cite, article, body_map["blocks"])
37+
end
38+
end
39+
40+
defp run_tasks(:cite, article, blocks) do
41+
article = article |> Repo.preload(author: :user)
42+
43+
# NOTE:
44+
cited_contents =
45+
blocks
46+
|> Enum.reduce([], &(&2 ++ get_cited_contents_per_block(article, &1)))
47+
|> merge_same_cited_article_block
48+
49+
IO.inspect(cited_contents, label: "fuck all")
50+
51+
# CitedContent |> ORM.create
52+
end
53+
54+
@doc """
55+
e.g:
56+
[
57+
%{
58+
block_linker: ["block-zByQI"],
59+
cited_by_id: 190058,
60+
cited_by_type: "POST",
61+
post_id: 190059,
62+
user_id: 1413053
63+
},
64+
%{
65+
block_linker: ["block-zByQI"],
66+
cited_by_id: 190057,
67+
cited_by_type: "POST",
68+
post_id: 190059,
69+
user_id: 1413053
70+
},
71+
%{
72+
block_linker: ["block-ZgKJs"],
73+
cited_by_id: 190057,
74+
cited_by_type: "POST",
75+
post_id: 190059,
76+
user_id: 1413053
77+
}
78+
]
79+
into:
80+
[
81+
%{
82+
block_linker: ["block-zByQI"],
83+
cited_by_id: 190058,
84+
cited_by_type: "POST",
85+
post_id: 190059,
86+
user_id: 1413053
87+
},
88+
%{
89+
block_linker: ["block-zByQI", "block-ZgKJs"],
90+
cited_by_id: 190057,
91+
cited_by_type: "POST",
92+
post_id: 190059,
93+
user_id: 1413053
94+
},
95+
]
96+
"""
97+
defp merge_same_cited_article_block(cited_contents) do
98+
cited_contents
99+
|> Enum.chunk_by(& &1.cited_by_id)
100+
|> Enum.map(fn content_by_group ->
101+
Enum.reduce(content_by_group, fn content, acc ->
102+
Map.merge(content, %{block_linker: content.block_linker ++ acc.block_linker})
103+
end)
104+
end)
105+
end
106+
107+
defp get_cited_contents_per_block(article, %{
108+
"id" => block_id,
109+
"data" => %{"text" => text}
110+
}) do
111+
#
112+
links_in_block = Floki.find(text, "a[href]")
113+
114+
Enum.reduce(links_in_block, [], fn link, acc ->
115+
with {:ok, cited_article} <- parse_cited_article(link) do
116+
List.insert_at(acc, 0, shape_cited_content(article, cited_article, block_id))
117+
else
118+
{:error, _} -> acc
119+
end
120+
end)
121+
|> Enum.uniq()
122+
end
123+
124+
defp shape_cited_content(article, cited_article, block_id) do
125+
thread = article.meta.thread |> String.downcase() |> String.to_atom()
126+
{:ok, info} = match(thread)
127+
128+
%{
129+
cited_by_id: cited_article.id,
130+
cited_by_type: cited_article.meta.thread,
131+
block_linker: [block_id],
132+
user_id: article.author.user.id
133+
}
134+
|> Map.put(info.foreign_key, article.id)
135+
end
136+
137+
defp parse_cited_article({"a", attrs, _}) do
138+
with {:ok, link} <- get_link(Enum.find(attrs, fn {a, v} -> a == "href" end)),
139+
true <- is_valid_article_link?(link) do
140+
get_cited_article(link)
141+
end
142+
end
143+
144+
defp get_link({"href", link}), do: {:ok, link}
145+
defp get_link(_), do: {:error, "invalid fmt"}
146+
147+
defp is_valid_article_link?(url) do
148+
Enum.any?(@valid_article_prefix, &String.starts_with?(url, &1))
149+
end
150+
151+
# get cited article from url
152+
# e.g: https://coderplanets.com/post/189993 -> ORM.find(Post, 189993)
153+
defp get_cited_article(url) do
154+
%{path: path} = URI.parse(url)
155+
path_list = path |> String.split("/")
156+
thread = path_list |> Enum.at(1) |> String.downcase() |> String.to_atom()
157+
article_id = path_list |> Enum.at(2)
158+
159+
with {:ok, info} <- match(thread) do
160+
ORM.find(info.model, article_id)
161+
end
162+
end
163+
164+
defp run_tasks(:mention) do
165+
#
166+
end
167+
168+
# 还是单抽一个模块吧
169+
defp run_tasks(:danger_words) do
170+
# title & body
171+
end
172+
173+
defp parse_blocks(%{body: body} = article) do
174+
with {:ok, body_map} <- Jason.decode(body) do
175+
#
176+
end
177+
end
178+
end
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
defmodule GroupherServer.CMS.Model.CitedContent do
2+
@moduledoc false
3+
alias __MODULE__
4+
5+
use Ecto.Schema
6+
use Accessible
7+
8+
import Ecto.Changeset
9+
import GroupherServer.CMS.Helper.Macros
10+
11+
alias GroupherServer.{Accounts, CMS}
12+
alias Accounts.Model.User
13+
14+
alias CMS.Model.{ArticleComment, Embeds}
15+
16+
@timestamps_opts [type: :utc_datetime_usec]
17+
18+
@required_fields ~w(cited_by_type cited_by_id user_id)a
19+
@article_cast_fields general_article_fields(:cast)
20+
@optional_fields ~w(article_comment_id block_linkers)a ++ @article_cast_fields
21+
22+
@type t :: %CitedContent{}
23+
schema "cited_contents" do
24+
field(:cited_by_type, :string)
25+
field(:cited_by_id, :id)
26+
27+
belongs_to(:author, User, foreign_key: :user_id)
28+
belongs_to(:article_comment, ArticleComment, foreign_key: :article_comment_id)
29+
30+
article_belongs_to_fields()
31+
32+
field(:block_linkers, {:array, :string})
33+
# content.block_linker = ["block-eee_block-bbb", "block-eee_block-bbb"]
34+
timestamps()
35+
end
36+
37+
@doc false
38+
def changeset(%CitedContent{} = cited_content, attrs) do
39+
cited_content
40+
|> cast(attrs, @optional_fields ++ @required_fields)
41+
|> validate_required(@required_fields)
42+
end
43+
44+
@doc false
45+
def update_changeset(%CitedContent{} = cited_content, attrs) do
46+
cited_content
47+
|> cast(attrs, @optional_fields ++ @required_fields)
48+
end
49+
end

lib/groupher_server/cms/models/embeds/block_task_runner.ex

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@ defmodule GroupherServer.CMS.Model.Embeds.BlockTaskRunner do
88

99
alias GroupherServer.CMS.Model.Embeds
1010

11-
@optional_fields ~w(bi_link_tasks mention_user_tasks)a
11+
@optional_fields ~w(bi_link_tasks)a
12+
# @optional_fields ~w(bi_link_tasks mention_user_tasks)a
1213

1314
@doc "for test usage"
1415
def default_meta() do
1516
%{
16-
bi_link_tasks: [],
17-
mention_user_tasks: []
17+
bi_link_tasks: []
18+
# mention_user_tasks: []
1819
}
1920
end
2021

2122
embedded_schema do
22-
embeds_many(:cite_tasks, Embeds.CitedTask, on_replace: :delete)
23+
embeds_many(:reference_tasks, Embeds.ReferenceTask, on_replace: :delete)
2324
# embeds_many(:mention_user_tasks, Embeds.MentionUserTask, on_replace: :delete)
2425
end
2526

lib/groupher_server/cms/models/embeds/cite_task.ex renamed to lib/groupher_server/cms/models/embeds/reference_task.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule GroupherServer.CMS.Model.Embeds.CiteTask do
1+
defmodule GroupherServer.CMS.Model.Embeds.ReferenceTask do
22
@moduledoc """
33
general article meta info for article-like content, like post, job, works ...
44
"""
@@ -22,9 +22,9 @@ defmodule GroupherServer.CMS.Model.Embeds.CiteTask do
2222
field(:article_id, :id)
2323
field(:block_id, :string)
2424

25-
field(:cited_article_id, :id)
25+
field(:reference_article_id, :id)
2626
# 可选
27-
field(:cited_block_id, :string)
27+
field(:reference_block_id, :string)
2828

2929
field(:is_finished, :boolean, default: false)
3030
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
defmodule GroupherServer.Repo.Migrations.CreateCitedArticles do
2+
use Ecto.Migration
3+
4+
def change do
5+
create table(:cited_contents) do
6+
# cited_type, cited_content_id, [contents]_id, [block_id, cited_block_id],
7+
add(:cited_by_type, :string)
8+
add(:cited_by_id, :id)
9+
10+
add(:user_id, references(:users, on_delete: :delete_all), null: false)
11+
add(:article_comment_id, references(:articles_comments, on_delete: :delete_all))
12+
13+
add(:post_id, references(:cms_posts, on_delete: :delete_all))
14+
add(:repo_id, references(:cms_posts, on_delete: :delete_all))
15+
add(:job_id, references(:cms_posts, on_delete: :delete_all))
16+
add(:blog_id, references(:cms_posts, on_delete: :delete_all))
17+
18+
add(:block_linker, {:array, :string})
19+
end
20+
21+
create(index(:cited_contents, [:cited_by_type, :cited_by_id]))
22+
end
23+
end

test/groupher_server/cms/articles/blog_test.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ defmodule GroupherServer.Test.Articles.Blog do
2222
end
2323

2424
describe "[cms blogs curd]" do
25-
@tag :wip
2625
test "can create blog with valid attrs", ~m(user community blog_attrs)a do
2726
assert {:error, _} = ORM.find_by(Author, user_id: user.id)
2827
{:ok, blog} = CMS.create_article(community, :blog, blog_attrs, user)

test/groupher_server/cms/articles/job_test.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ defmodule GroupherServer.Test.Articles.Job do
2323
end
2424

2525
describe "[cms jobs curd]" do
26-
@tag :wip
2726
test "can create job with valid attrs", ~m(user community job_attrs)a do
2827
assert {:error, _} = ORM.find_by(Author, user_id: user.id)
2928
{:ok, job} = CMS.create_article(community, :job, job_attrs, user)

test/groupher_server/cms/articles/post_test.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ defmodule GroupherServer.Test.CMS.Articles.Post do
2323
end
2424

2525
describe "[cms post curd]" do
26-
@tag :wip
2726
test "can create post with valid attrs", ~m(user community post_attrs)a do
2827
assert {:error, _} = ORM.find_by(Author, user_id: user.id)
2928
{:ok, post} = CMS.create_article(community, :post, post_attrs, user)

0 commit comments

Comments
 (0)