From b2e5b23780bf1662c5a4f8a7768ccd3b28c96892 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Thu, 10 Jun 2021 16:37:53 +0800 Subject: [PATCH 01/10] chore: basic thought --- .../cms/models/embeds/block_task_runner.ex | 30 ++++++++++++++++ .../cms/models/embeds/cite_task.ex | 36 +++++++++++++++++++ lib/groupher_server/cms/models/post.ex | 3 ++ 3 files changed, 69 insertions(+) create mode 100644 lib/groupher_server/cms/models/embeds/block_task_runner.ex create mode 100644 lib/groupher_server/cms/models/embeds/cite_task.ex diff --git a/lib/groupher_server/cms/models/embeds/block_task_runner.ex b/lib/groupher_server/cms/models/embeds/block_task_runner.ex new file mode 100644 index 000000000..f997f4349 --- /dev/null +++ b/lib/groupher_server/cms/models/embeds/block_task_runner.ex @@ -0,0 +1,30 @@ +defmodule GroupherServer.CMS.Model.Embeds.BlockTaskRunner do + @moduledoc """ + general article meta info for article-like content, like post, job, works ... + """ + use Ecto.Schema + use Accessible + import Ecto.Changeset + + alias GroupherServer.CMS.Model.Embeds + + @optional_fields ~w(bi_link_tasks mention_user_tasks)a + + @doc "for test usage" + def default_meta() do + %{ + bi_link_tasks: [], + mention_user_tasks: [] + } + end + + embedded_schema do + embeds_many(:cite_tasks, Embeds.CitedTask, on_replace: :delete) + # embeds_many(:mention_user_tasks, Embeds.MentionUserTask, on_replace: :delete) + end + + def changeset(struct, params) do + struct + |> cast(params, @optional_fields) + end +end diff --git a/lib/groupher_server/cms/models/embeds/cite_task.ex b/lib/groupher_server/cms/models/embeds/cite_task.ex new file mode 100644 index 000000000..ebf0ba53c --- /dev/null +++ b/lib/groupher_server/cms/models/embeds/cite_task.ex @@ -0,0 +1,36 @@ +defmodule GroupherServer.CMS.Model.Embeds.CiteTask do + @moduledoc """ + general article meta info for article-like content, like post, job, works ... + """ + use Ecto.Schema + use Accessible + import Ecto.Changeset + + @optional_fields ~w(bi_link_tasks mention_user_tasks)a + + # thread, article_id, block_id, author_id, cite_thread, cite_article_id, cite_block_id, cite_author_id + + @doc "for test usage" + def default_meta() do + %{ + # bi_link_tasks: [], + # mention_user_tasks: [] + } + end + + embedded_schema do + field(:article_id, :id) + field(:block_id, :string) + + field(:cited_article_id, :id) + # 可选 + field(:cited_block_id, :string) + + field(:is_finished, :boolean, default: false) + end + + def changeset(struct, params) do + struct + |> cast(params, @optional_fields) + end +end diff --git a/lib/groupher_server/cms/models/post.ex b/lib/groupher_server/cms/models/post.ex index d16e5710f..1bedee94c 100644 --- a/lib/groupher_server/cms/models/post.ex +++ b/lib/groupher_server/cms/models/post.ex @@ -30,6 +30,9 @@ defmodule GroupherServer.CMS.Model.Post do field(:is_solved, :boolean, default: false) field(:solution_digest, :string) + # TODO: move to general_article_fields + # embeds_one(:block_task_runner, Embeds.BlockTaskRunner, on_replace: :update) + article_tags_field(:post) article_communities_field(:post) general_article_fields() From e5c76650a920add313a21ea334d8465ea20a3ed3 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Thu, 10 Jun 2021 17:27:49 +0800 Subject: [PATCH 02/10] refactor(article): add thread to meta when create --- lib/groupher_server/cms/delegates/article_curd.ex | 6 ++++-- lib/groupher_server/cms/models/embeds/article_meta.ex | 4 +++- lib/helper/utils/utils.ex | 7 +++++++ test/groupher_server/cms/articles/blog_test.exs | 3 +++ test/groupher_server/cms/articles/job_test.exs | 3 +++ test/groupher_server/cms/articles/post_test.exs | 3 +++ test/groupher_server/cms/articles/repo_test.exs | 4 +++- 7 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/groupher_server/cms/delegates/article_curd.ex b/lib/groupher_server/cms/delegates/article_curd.ex index 21e5fce72..75b161301 100644 --- a/lib/groupher_server/cms/delegates/article_curd.ex +++ b/lib/groupher_server/cms/delegates/article_curd.ex @@ -6,7 +6,8 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do import GroupherServer.CMS.Helper.Matcher - import Helper.Utils, only: [done: 1, pick_by: 2, module_to_atom: 1, get_config: 2, ensure: 2] + import Helper.Utils, + only: [done: 1, pick_by: 2, module_to_atom: 1, get_config: 2, ensure: 2, module_to_upcase: 1] import GroupherServer.CMS.Delegate.Helper, only: [mark_viewer_emotion_states: 2] import Helper.ErrorCode @@ -384,6 +385,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do defp do_create_article(model, attrs, %Author{id: author_id}, %Community{id: community_id}) do # special article like Repo do not have :body, assign it with default-empty rich text body = Map.get(attrs, :body, Converter.Article.default_rich_text()) + meta = @default_article_meta |> Map.merge(%{thread: module_to_upcase(model)}) attrs = attrs |> Map.merge(%{body: body}) with {:ok, attrs} <- add_rich_text_attrs(attrs) do @@ -392,7 +394,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do |> Ecto.Changeset.put_change(:emotions, @default_emotions) |> Ecto.Changeset.put_change(:author_id, author_id) |> Ecto.Changeset.put_change(:original_community_id, community_id) - |> Ecto.Changeset.put_embed(:meta, @default_article_meta) + |> Ecto.Changeset.put_embed(:meta, meta) |> Repo.insert() end end diff --git a/lib/groupher_server/cms/models/embeds/article_meta.ex b/lib/groupher_server/cms/models/embeds/article_meta.ex index 96be1c5f1..9e89c9ef3 100644 --- a/lib/groupher_server/cms/models/embeds/article_meta.ex +++ b/lib/groupher_server/cms/models/embeds/article_meta.ex @@ -6,11 +6,12 @@ defmodule GroupherServer.CMS.Model.Embeds.ArticleMeta do use Accessible import Ecto.Changeset - @optional_fields ~w(is_edited is_comment_locked upvoted_user_ids collected_user_ids viewed_user_ids reported_user_ids reported_count is_sinked can_undo_sink last_active_at)a + @optional_fields ~w(thread is_edited is_comment_locked upvoted_user_ids collected_user_ids viewed_user_ids reported_user_ids reported_count is_sinked can_undo_sink last_active_at)a @doc "for test usage" def default_meta() do %{ + thread: "POST", is_edited: false, is_comment_locked: false, upvoted_user_ids: [], @@ -25,6 +26,7 @@ defmodule GroupherServer.CMS.Model.Embeds.ArticleMeta do end embedded_schema do + field(:thread, :string) field(:is_edited, :boolean, default: false) field(:is_comment_locked, :boolean, default: false) # reaction history diff --git a/lib/helper/utils/utils.ex b/lib/helper/utils/utils.ex index 18885476b..d64a7782b 100644 --- a/lib/helper/utils/utils.ex +++ b/lib/helper/utils/utils.ex @@ -182,6 +182,13 @@ defmodule Helper.Utils do def strip_struct(map) when is_map(map), do: map + @doc """ + get upcase name of a module, most used for store thread in DB + """ + def module_to_upcase(module) do + module |> Module.split() |> List.last() |> String.upcase() + end + @doc """ get atom name of a module """ diff --git a/test/groupher_server/cms/articles/blog_test.exs b/test/groupher_server/cms/articles/blog_test.exs index 3c02b7400..dd7e7ef43 100644 --- a/test/groupher_server/cms/articles/blog_test.exs +++ b/test/groupher_server/cms/articles/blog_test.exs @@ -22,12 +22,15 @@ defmodule GroupherServer.Test.Articles.Blog do end describe "[cms blogs curd]" do + @tag :wip test "can create blog with valid attrs", ~m(user community blog_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, blog} = CMS.create_article(community, :blog, blog_attrs, user) body_map = Jason.decode!(blog.body) + assert blog.meta.thread == "BLOG" + assert blog.title == blog_attrs.title assert body_map |> Validator.is_valid() assert blog.body_html |> String.contains?(~s(
)) diff --git a/test/groupher_server/cms/articles/job_test.exs b/test/groupher_server/cms/articles/job_test.exs index d20c13d8d..cbb39f9e0 100644 --- a/test/groupher_server/cms/articles/job_test.exs +++ b/test/groupher_server/cms/articles/job_test.exs @@ -23,12 +23,15 @@ defmodule GroupherServer.Test.Articles.Job do end describe "[cms jobs curd]" do + @tag :wip test "can create job with valid attrs", ~m(user community job_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, job} = CMS.create_article(community, :job, job_attrs, user) body_map = Jason.decode!(job.body) + assert job.meta.thread == "JOB" + assert job.title == job_attrs.title assert body_map |> Validator.is_valid() assert job.body_html |> String.contains?(~s(
)) diff --git a/test/groupher_server/cms/articles/post_test.exs b/test/groupher_server/cms/articles/post_test.exs index f62ec7dee..81c06a28d 100644 --- a/test/groupher_server/cms/articles/post_test.exs +++ b/test/groupher_server/cms/articles/post_test.exs @@ -23,12 +23,15 @@ defmodule GroupherServer.Test.CMS.Articles.Post do end describe "[cms post curd]" do + @tag :wip test "can create post with valid attrs", ~m(user community post_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, post} = CMS.create_article(community, :post, post_attrs, user) body_map = Jason.decode!(post.body) + assert post.meta.thread == "POST" + assert post.title == post_attrs.title assert body_map |> Validator.is_valid() assert post.body_html |> String.contains?(~s(
)) diff --git a/test/groupher_server/cms/articles/repo_test.exs b/test/groupher_server/cms/articles/repo_test.exs index ea0d68425..ac839d67d 100644 --- a/test/groupher_server/cms/articles/repo_test.exs +++ b/test/groupher_server/cms/articles/repo_test.exs @@ -23,12 +23,15 @@ defmodule GroupherServer.Test.Articles.Repo do end describe "[cms repo curd]" do + @tag :wip test "can create repo with valid attrs", ~m(user community repo_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) body_map = Jason.decode!(repo.body) + assert repo.meta.thread == "REPO" + assert repo.title == repo_attrs.title assert body_map |> Validator.is_valid() assert repo.body_html |> String.contains?(~s(
)) @@ -63,7 +66,6 @@ defmodule GroupherServer.Test.Articles.Repo do assert user2.id in created.meta.viewed_user_ids end - @tag :wip test "read repo should contains viewer_has_xxx state", ~m(repo_attrs community user user2)a do {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) {:ok, repo} = CMS.read_article(:repo, repo.id, user) From b4b9b0d6bb5998fea42eb54f4a5b827b134c6dd6 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Fri, 11 Jun 2021 23:50:52 +0800 Subject: [PATCH 03/10] refactor(cited-article): wip --- config/config.exs | 1 + .../cms/delegates/article_curd.ex | 6 + .../cms/delegates/block_tasks.ex | 178 ++++++++++++++++++ .../cms/models/cited_content.ex | 49 +++++ .../cms/models/embeds/block_task_runner.ex | 9 +- .../{cite_task.ex => reference_task.ex} | 6 +- .../20210611015726_create_cited_articles.exs | 23 +++ .../cms/articles/blog_test.exs | 1 - .../groupher_server/cms/articles/job_test.exs | 1 - .../cms/articles/post_test.exs | 1 - .../cms/articles/repo_test.exs | 1 - .../groupher_server/cms/cite_content_test.exs | 53 ++++++ test/support/factory.ex | 26 +++ 13 files changed, 344 insertions(+), 11 deletions(-) create mode 100644 lib/groupher_server/cms/delegates/block_tasks.ex create mode 100644 lib/groupher_server/cms/models/cited_content.ex rename lib/groupher_server/cms/models/embeds/{cite_task.ex => reference_task.ex} (83%) create mode 100644 priv/repo/migrations/20210611015726_create_cited_articles.exs create mode 100644 test/groupher_server/cms/cite_content_test.exs diff --git a/config/config.exs b/config/config.exs index f3d93ff86..0f38df2fb 100644 --- a/config/config.exs +++ b/config/config.exs @@ -31,6 +31,7 @@ config :pre_commit, commands: ["format"], verbose: false # of this file so it overrides the configuration defined above. config :groupher_server, :general, + site_host: "https://coderplanets.com", page_size: 30, inner_page_size: 5, # today is not include diff --git a/lib/groupher_server/cms/delegates/article_curd.ex b/lib/groupher_server/cms/delegates/article_curd.ex index 75b161301..afb127c90 100644 --- a/lib/groupher_server/cms/delegates/article_curd.ex +++ b/lib/groupher_server/cms/delegates/article_curd.ex @@ -149,6 +149,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do |> Multi.run(:create_article, fn _, _ -> do_create_article(info.model, attrs, author, community) end) + |> Multi.run(:block_tasks, fn _, %{create_article: article} -> + # ArticleCommunity.mirror_article(thread, article.id, community.id) + # Later + # BlockTasks.handle(article) + {:ok, :pass} + end) |> Multi.run(:mirror_article, fn _, %{create_article: article} -> ArticleCommunity.mirror_article(thread, article.id, community.id) end) diff --git a/lib/groupher_server/cms/delegates/block_tasks.ex b/lib/groupher_server/cms/delegates/block_tasks.ex new file mode 100644 index 000000000..200f6cac5 --- /dev/null +++ b/lib/groupher_server/cms/delegates/block_tasks.ex @@ -0,0 +1,178 @@ +defmodule GroupherServer.CMS.Delegate.BlockTasks do + @moduledoc """ + run tasks in every article blocks if need + """ + import Helper.Utils, only: [get_config: 2] + import GroupherServer.CMS.Helper.Matcher + + alias GroupherServer.Repo + + alias GroupherServer.CMS.Model.CitedContent + alias Helper.ORM + + @site_host get_config(:general, :site_host) + @article_threads get_config(:article, :threads) + @valid_article_prefix Enum.map(@article_threads, &"#{@site_host}/#{&1}/") + + """ + 我被谁引用了 是最重要的信息 + 我引用了谁不重要,自己扫帖子就行了 + cited_thread, cited_article_id, [xxx_article]_id, [block_id, cited_block_id], + + POST post_333 -> cited_article_333, [[block_3, cited_block_23]] + + cited_type, cited_content_id, [contents]_id, [block_id, cited_block_id], + + cited_type: thread or comment + content: article or comment + # cited_article_comment_id, [xxx_article]_id, [block_id, cited_block_id], + """ + + # reference + # mention + + def handle(%{body: body} = article) do + with {:ok, body_map} <- Jason.decode(body) do + run_tasks(:cite, article, body_map["blocks"]) + end + end + + defp run_tasks(:cite, article, blocks) do + article = article |> Repo.preload(author: :user) + + # NOTE: + cited_contents = + blocks + |> Enum.reduce([], &(&2 ++ get_cited_contents_per_block(article, &1))) + |> merge_same_cited_article_block + + IO.inspect(cited_contents, label: "fuck all") + + # CitedContent |> ORM.create + end + + @doc """ + e.g: + [ + %{ + block_linker: ["block-zByQI"], + cited_by_id: 190058, + cited_by_type: "POST", + post_id: 190059, + user_id: 1413053 + }, + %{ + block_linker: ["block-zByQI"], + cited_by_id: 190057, + cited_by_type: "POST", + post_id: 190059, + user_id: 1413053 + }, + %{ + block_linker: ["block-ZgKJs"], + cited_by_id: 190057, + cited_by_type: "POST", + post_id: 190059, + user_id: 1413053 + } + ] + into: + [ + %{ + block_linker: ["block-zByQI"], + cited_by_id: 190058, + cited_by_type: "POST", + post_id: 190059, + user_id: 1413053 + }, + %{ + block_linker: ["block-zByQI", "block-ZgKJs"], + cited_by_id: 190057, + cited_by_type: "POST", + post_id: 190059, + user_id: 1413053 + }, + ] + """ + defp merge_same_cited_article_block(cited_contents) do + cited_contents + |> Enum.chunk_by(& &1.cited_by_id) + |> Enum.map(fn content_by_group -> + Enum.reduce(content_by_group, fn content, acc -> + Map.merge(content, %{block_linker: content.block_linker ++ acc.block_linker}) + end) + end) + end + + defp get_cited_contents_per_block(article, %{ + "id" => block_id, + "data" => %{"text" => text} + }) do + # + links_in_block = Floki.find(text, "a[href]") + + Enum.reduce(links_in_block, [], fn link, acc -> + with {:ok, cited_article} <- parse_cited_article(link) do + List.insert_at(acc, 0, shape_cited_content(article, cited_article, block_id)) + else + {:error, _} -> acc + end + end) + |> Enum.uniq() + end + + defp shape_cited_content(article, cited_article, block_id) do + thread = article.meta.thread |> String.downcase() |> String.to_atom() + {:ok, info} = match(thread) + + %{ + cited_by_id: cited_article.id, + cited_by_type: cited_article.meta.thread, + block_linker: [block_id], + user_id: article.author.user.id + } + |> Map.put(info.foreign_key, article.id) + end + + defp parse_cited_article({"a", attrs, _}) do + with {:ok, link} <- get_link(Enum.find(attrs, fn {a, v} -> a == "href" end)), + true <- is_valid_article_link?(link) do + get_cited_article(link) + end + end + + defp get_link({"href", link}), do: {:ok, link} + defp get_link(_), do: {:error, "invalid fmt"} + + defp is_valid_article_link?(url) do + Enum.any?(@valid_article_prefix, &String.starts_with?(url, &1)) + end + + # get cited article from url + # e.g: https://coderplanets.com/post/189993 -> ORM.find(Post, 189993) + defp get_cited_article(url) do + %{path: path} = URI.parse(url) + path_list = path |> String.split("/") + thread = path_list |> Enum.at(1) |> String.downcase() |> String.to_atom() + article_id = path_list |> Enum.at(2) + + with {:ok, info} <- match(thread) do + ORM.find(info.model, article_id) + end + end + + defp run_tasks(:mention) do + # + end + + # 还是单抽一个模块吧 + defp run_tasks(:danger_words) do + # title & body + end + + defp parse_blocks(%{body: body} = article) do + with {:ok, body_map} <- Jason.decode(body) do + # + end + end +end diff --git a/lib/groupher_server/cms/models/cited_content.ex b/lib/groupher_server/cms/models/cited_content.ex new file mode 100644 index 000000000..f98098fb3 --- /dev/null +++ b/lib/groupher_server/cms/models/cited_content.ex @@ -0,0 +1,49 @@ +defmodule GroupherServer.CMS.Model.CitedContent do + @moduledoc false + alias __MODULE__ + + use Ecto.Schema + use Accessible + + import Ecto.Changeset + import GroupherServer.CMS.Helper.Macros + + alias GroupherServer.{Accounts, CMS} + alias Accounts.Model.User + + alias CMS.Model.{ArticleComment, Embeds} + + @timestamps_opts [type: :utc_datetime_usec] + + @required_fields ~w(cited_by_type cited_by_id user_id)a + @article_cast_fields general_article_fields(:cast) + @optional_fields ~w(article_comment_id block_linkers)a ++ @article_cast_fields + + @type t :: %CitedContent{} + schema "cited_contents" do + field(:cited_by_type, :string) + field(:cited_by_id, :id) + + belongs_to(:author, User, foreign_key: :user_id) + belongs_to(:article_comment, ArticleComment, foreign_key: :article_comment_id) + + article_belongs_to_fields() + + field(:block_linkers, {:array, :string}) + # content.block_linker = ["block-eee_block-bbb", "block-eee_block-bbb"] + timestamps() + end + + @doc false + def changeset(%CitedContent{} = cited_content, attrs) do + cited_content + |> cast(attrs, @optional_fields ++ @required_fields) + |> validate_required(@required_fields) + end + + @doc false + def update_changeset(%CitedContent{} = cited_content, attrs) do + cited_content + |> cast(attrs, @optional_fields ++ @required_fields) + end +end diff --git a/lib/groupher_server/cms/models/embeds/block_task_runner.ex b/lib/groupher_server/cms/models/embeds/block_task_runner.ex index f997f4349..d705872b2 100644 --- a/lib/groupher_server/cms/models/embeds/block_task_runner.ex +++ b/lib/groupher_server/cms/models/embeds/block_task_runner.ex @@ -8,18 +8,19 @@ defmodule GroupherServer.CMS.Model.Embeds.BlockTaskRunner do alias GroupherServer.CMS.Model.Embeds - @optional_fields ~w(bi_link_tasks mention_user_tasks)a + @optional_fields ~w(bi_link_tasks)a + # @optional_fields ~w(bi_link_tasks mention_user_tasks)a @doc "for test usage" def default_meta() do %{ - bi_link_tasks: [], - mention_user_tasks: [] + bi_link_tasks: [] + # mention_user_tasks: [] } end embedded_schema do - embeds_many(:cite_tasks, Embeds.CitedTask, on_replace: :delete) + embeds_many(:reference_tasks, Embeds.ReferenceTask, on_replace: :delete) # embeds_many(:mention_user_tasks, Embeds.MentionUserTask, on_replace: :delete) end diff --git a/lib/groupher_server/cms/models/embeds/cite_task.ex b/lib/groupher_server/cms/models/embeds/reference_task.ex similarity index 83% rename from lib/groupher_server/cms/models/embeds/cite_task.ex rename to lib/groupher_server/cms/models/embeds/reference_task.ex index ebf0ba53c..308db8779 100644 --- a/lib/groupher_server/cms/models/embeds/cite_task.ex +++ b/lib/groupher_server/cms/models/embeds/reference_task.ex @@ -1,4 +1,4 @@ -defmodule GroupherServer.CMS.Model.Embeds.CiteTask do +defmodule GroupherServer.CMS.Model.Embeds.ReferenceTask do @moduledoc """ general article meta info for article-like content, like post, job, works ... """ @@ -22,9 +22,9 @@ defmodule GroupherServer.CMS.Model.Embeds.CiteTask do field(:article_id, :id) field(:block_id, :string) - field(:cited_article_id, :id) + field(:reference_article_id, :id) # 可选 - field(:cited_block_id, :string) + field(:reference_block_id, :string) field(:is_finished, :boolean, default: false) end diff --git a/priv/repo/migrations/20210611015726_create_cited_articles.exs b/priv/repo/migrations/20210611015726_create_cited_articles.exs new file mode 100644 index 000000000..582377277 --- /dev/null +++ b/priv/repo/migrations/20210611015726_create_cited_articles.exs @@ -0,0 +1,23 @@ +defmodule GroupherServer.Repo.Migrations.CreateCitedArticles do + use Ecto.Migration + + def change do + create table(:cited_contents) do + # cited_type, cited_content_id, [contents]_id, [block_id, cited_block_id], + add(:cited_by_type, :string) + add(:cited_by_id, :id) + + add(:user_id, references(:users, on_delete: :delete_all), null: false) + add(:article_comment_id, references(:articles_comments, on_delete: :delete_all)) + + add(:post_id, references(:cms_posts, on_delete: :delete_all)) + add(:repo_id, references(:cms_posts, on_delete: :delete_all)) + add(:job_id, references(:cms_posts, on_delete: :delete_all)) + add(:blog_id, references(:cms_posts, on_delete: :delete_all)) + + add(:block_linker, {:array, :string}) + end + + create(index(:cited_contents, [:cited_by_type, :cited_by_id])) + end +end diff --git a/test/groupher_server/cms/articles/blog_test.exs b/test/groupher_server/cms/articles/blog_test.exs index dd7e7ef43..2e1e00deb 100644 --- a/test/groupher_server/cms/articles/blog_test.exs +++ b/test/groupher_server/cms/articles/blog_test.exs @@ -22,7 +22,6 @@ defmodule GroupherServer.Test.Articles.Blog do end describe "[cms blogs curd]" do - @tag :wip test "can create blog with valid attrs", ~m(user community blog_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, blog} = CMS.create_article(community, :blog, blog_attrs, user) diff --git a/test/groupher_server/cms/articles/job_test.exs b/test/groupher_server/cms/articles/job_test.exs index cbb39f9e0..d653a0644 100644 --- a/test/groupher_server/cms/articles/job_test.exs +++ b/test/groupher_server/cms/articles/job_test.exs @@ -23,7 +23,6 @@ defmodule GroupherServer.Test.Articles.Job do end describe "[cms jobs curd]" do - @tag :wip test "can create job with valid attrs", ~m(user community job_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, job} = CMS.create_article(community, :job, job_attrs, user) diff --git a/test/groupher_server/cms/articles/post_test.exs b/test/groupher_server/cms/articles/post_test.exs index 81c06a28d..2e71f92c5 100644 --- a/test/groupher_server/cms/articles/post_test.exs +++ b/test/groupher_server/cms/articles/post_test.exs @@ -23,7 +23,6 @@ defmodule GroupherServer.Test.CMS.Articles.Post do end describe "[cms post curd]" do - @tag :wip test "can create post with valid attrs", ~m(user community post_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, post} = CMS.create_article(community, :post, post_attrs, user) diff --git a/test/groupher_server/cms/articles/repo_test.exs b/test/groupher_server/cms/articles/repo_test.exs index ac839d67d..fb5f006ff 100644 --- a/test/groupher_server/cms/articles/repo_test.exs +++ b/test/groupher_server/cms/articles/repo_test.exs @@ -23,7 +23,6 @@ defmodule GroupherServer.Test.Articles.Repo do end describe "[cms repo curd]" do - @tag :wip test "can create repo with valid attrs", ~m(user community repo_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) diff --git a/test/groupher_server/cms/cite_content_test.exs b/test/groupher_server/cms/cite_content_test.exs new file mode 100644 index 000000000..bfc9c3107 --- /dev/null +++ b/test/groupher_server/cms/cite_content_test.exs @@ -0,0 +1,53 @@ +defmodule GroupherServer.Test.CMS.CiteContent do + use GroupherServer.TestTools + + import Helper.Utils, only: [get_config: 2] + + alias Helper.ORM + alias GroupherServer.CMS + alias Helper.Converter.{EditorToHTML, HtmlSanitizer, Converter} + + alias EditorToHTML.{Class, Validator} + alias CMS.Model.{Author, Community, Post} + + alias CMS.Delegate.BlockTasks + + @site_host get_config(:general, :site_host) + + setup do + {:ok, user} = db_insert(:user) + {:ok, user2} = db_insert(:user) + {:ok, post} = db_insert(:post) + {:ok, post2} = db_insert(:post) + {:ok, post3} = db_insert(:post) + + {:ok, community} = db_insert(:community) + + post_attrs = mock_attrs(:post, %{community_id: community.id}) + + {:ok, ~m(user user2 community post post2 post3 post_attrs)a} + end + + describe "[cite basic]" do + @tag :wip + test "basic", ~m(user community post2 post3 post_attrs)a do + IO.inspect(post2.id, label: "post2.id") + IO.inspect(post3.id, label: "post3.id") + + body = + mock_rich_text( + ~s(the and same la is awesome, the is awesome too.), + # second paragraph + ~s(the paragraph 2 again ) + ) + + post_attrs = post_attrs |> Map.merge(%{body: body}) + + {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + + BlockTasks.handle(post) + end + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index e6086ea3e..a55ffd968 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -47,6 +47,32 @@ defmodule GroupherServer.Support.Factory do """ end + # for link tasks + def mock_rich_text(text1, text2) do + """ + { + "time": 111, + "blocks": [ + { + "id": "lldjfiek", + "type": "paragraph", + "data": { + "text": "#{text1}" + } + }, + { + "id": "llddiekek", + "type": "paragraph", + "data": { + "text": "#{text2}" + } + } + ], + "version": "2.22.0" + } + """ + end + def mock_xss_string(:safe) do mock_rich_text("<script>blackmail</script>") end From 742969dd517b14860a3805055ff7526bfaad6ba4 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sat, 12 Jun 2021 00:37:33 +0800 Subject: [PATCH 04/10] refactor(cited-article): wip --- .../cms/delegates/block_tasks.ex | 20 +++++++++++++++++++ lib/groupher_server/cms/helper/macros.ex | 2 +- .../cms/models/cited_content.ex | 6 +++--- lib/groupher_server/cms/models/post.ex | 1 + ...611160430_add_citing_count_to_articles.exs | 10 ++++++++++ 5 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs diff --git a/lib/groupher_server/cms/delegates/block_tasks.ex b/lib/groupher_server/cms/delegates/block_tasks.ex index 200f6cac5..d0aa91ca7 100644 --- a/lib/groupher_server/cms/delegates/block_tasks.ex +++ b/lib/groupher_server/cms/delegates/block_tasks.ex @@ -2,6 +2,7 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do @moduledoc """ run tasks in every article blocks if need """ + import Ecto.Query, warn: false import Helper.Utils, only: [get_config: 2] import GroupherServer.CMS.Helper.Matcher @@ -48,9 +49,27 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do IO.inspect(cited_contents, label: "fuck all") + CitedContent |> Repo.insert_all(cited_contents) + update_citing_count(cited_contents) + # CitedContent |> ORM.create end + defp update_citing_count(cited_contents) do + Enum.each(cited_contents, fn content -> + count_query = from(c in CitedContent, where: c.cited_by_id == ^content.cited_by_id) + count = Repo.aggregate(count_query, :count) + + IO.inspect(count, label: "the count") + end) + + # count = Repo.aggregate(count_query, :count) + # IO.inspect cited_contents, label: "update_citing_count" + end + + # count_query = from(s in CommunitySubscriber, where: s.user_id == ^user.id) + # count = Repo.aggregate(count_query, :count) + @doc """ e.g: [ @@ -128,6 +147,7 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do %{ cited_by_id: cited_article.id, cited_by_type: cited_article.meta.thread, + # cited_article: cited_article, block_linker: [block_id], user_id: article.author.user.id } diff --git a/lib/groupher_server/cms/helper/macros.ex b/lib/groupher_server/cms/helper/macros.ex index 9d542d641..10a8ab4c5 100644 --- a/lib/groupher_server/cms/helper/macros.ex +++ b/lib/groupher_server/cms/helper/macros.ex @@ -207,8 +207,8 @@ defmodule GroupherServer.CMS.Helper.Macros do article_comment_fields() field(:active_at, :utc_datetime_usec) + field(:citing_count, :integer, default: 0) # TODO: - # reference_articles # related_articles timestamps() end diff --git a/lib/groupher_server/cms/models/cited_content.ex b/lib/groupher_server/cms/models/cited_content.ex index f98098fb3..17f4c2c55 100644 --- a/lib/groupher_server/cms/models/cited_content.ex +++ b/lib/groupher_server/cms/models/cited_content.ex @@ -11,13 +11,13 @@ defmodule GroupherServer.CMS.Model.CitedContent do alias GroupherServer.{Accounts, CMS} alias Accounts.Model.User - alias CMS.Model.{ArticleComment, Embeds} + alias CMS.Model.ArticleComment @timestamps_opts [type: :utc_datetime_usec] @required_fields ~w(cited_by_type cited_by_id user_id)a @article_cast_fields general_article_fields(:cast) - @optional_fields ~w(article_comment_id block_linkers)a ++ @article_cast_fields + @optional_fields ~w(article_comment_id block_linker)a ++ @article_cast_fields @type t :: %CitedContent{} schema "cited_contents" do @@ -29,7 +29,7 @@ defmodule GroupherServer.CMS.Model.CitedContent do article_belongs_to_fields() - field(:block_linkers, {:array, :string}) + field(:block_linker, {:array, :string}) # content.block_linker = ["block-eee_block-bbb", "block-eee_block-bbb"] timestamps() end diff --git a/lib/groupher_server/cms/models/post.ex b/lib/groupher_server/cms/models/post.ex index 1bedee94c..5f2059e64 100644 --- a/lib/groupher_server/cms/models/post.ex +++ b/lib/groupher_server/cms/models/post.ex @@ -32,6 +32,7 @@ defmodule GroupherServer.CMS.Model.Post do # TODO: move to general_article_fields # embeds_one(:block_task_runner, Embeds.BlockTaskRunner, on_replace: :update) + # embeds_many(:citing_contents, CMS.CitedContent, on_replace: :delete) article_tags_field(:post) article_communities_field(:post) diff --git a/priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs b/priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs new file mode 100644 index 000000000..20a8e4aea --- /dev/null +++ b/priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs @@ -0,0 +1,10 @@ +defmodule GroupherServer.Repo.Migrations.AddCitingCountToArticles do + use Ecto.Migration + + def change do + alter(table(:cms_posts), do: add(:citing_count, :integer)) + alter(table(:cms_jobs), do: add(:citing_count, :integer)) + alter(table(:cms_repos), do: add(:citing_count, :integer)) + alter(table(:cms_blogs), do: add(:citing_count, :integer)) + end +end From f173b09b4a4423e786580fef5f31f856ccf2760c Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sat, 12 Jun 2021 12:39:05 +0800 Subject: [PATCH 05/10] refactor(cited-article): wip --- .../cms/delegates/block_tasks.ex | 107 +++++++++++------- lib/groupher_server/cms/helper/macros.ex | 1 - .../cms/models/embeds/article_meta.ex | 1 + ...611160430_add_citing_count_to_articles.exs | 10 -- .../groupher_server/cms/cite_content_test.exs | 22 ++-- 5 files changed, 79 insertions(+), 62 deletions(-) delete mode 100644 priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs diff --git a/lib/groupher_server/cms/delegates/block_tasks.ex b/lib/groupher_server/cms/delegates/block_tasks.ex index d0aa91ca7..336c346c6 100644 --- a/lib/groupher_server/cms/delegates/block_tasks.ex +++ b/lib/groupher_server/cms/delegates/block_tasks.ex @@ -35,24 +35,28 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do def handle(%{body: body} = article) do with {:ok, body_map} <- Jason.decode(body) do run_tasks(:cite, article, body_map["blocks"]) + # run_tasks(:mention, article, body_map["blocks"]) end end defp run_tasks(:cite, article, blocks) do article = article |> Repo.preload(author: :user) - # NOTE: - cited_contents = - blocks - |> Enum.reduce([], &(&2 ++ get_cited_contents_per_block(article, &1))) - |> merge_same_cited_article_block + blocks + |> Enum.reduce([], &(&2 ++ get_cited_contents_per_block(article, &1))) + |> merge_same_cited_article_block + |> update_cited_info + end - IO.inspect(cited_contents, label: "fuck all") + defp update_cited_info(cited_contents) do + # batch update CitedContent List + cited_contents_fields = [:cited_by_id, :cited_by_type, :block_linker, :user_id] + clean_cited_contents = Enum.map(cited_contents, &Map.take(&1, cited_contents_fields)) + IO.inspect(clean_cited_contents, label: "clean_cited_contents") + Repo.insert_all(CitedContent, clean_cited_contents) - CitedContent |> Repo.insert_all(cited_contents) + # update citting count meta update_citing_count(cited_contents) - - # CitedContent |> ORM.create end defp update_citing_count(cited_contents) do @@ -60,16 +64,12 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do count_query = from(c in CitedContent, where: c.cited_by_id == ^content.cited_by_id) count = Repo.aggregate(count_query, :count) - IO.inspect(count, label: "the count") + cited_article = content.cited_article + meta = Map.merge(cited_article.meta, %{citing_count: count}) + cited_article |> ORM.update_meta(meta) end) - - # count = Repo.aggregate(count_query, :count) - # IO.inspect cited_contents, label: "update_citing_count" end - # count_query = from(s in CommunitySubscriber, where: s.user_id == ^user.id) - # count = Repo.aggregate(count_query, :count) - @doc """ e.g: [ @@ -115,14 +115,35 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do """ defp merge_same_cited_article_block(cited_contents) do cited_contents - |> Enum.chunk_by(& &1.cited_by_id) - |> Enum.map(fn content_by_group -> - Enum.reduce(content_by_group, fn content, acc -> - Map.merge(content, %{block_linker: content.block_linker ++ acc.block_linker}) - end) + |> Enum.reduce([], fn content, acc -> + case Enum.find_index(acc, &(&1.cited_by_id == content.cited_by_id)) do + nil -> + acc ++ [content] + + index -> + List.update_at( + acc, + index, + &Map.merge(&1, %{block_linker: &1.block_linker ++ content.block_linker}) + ) + end end) end + @doc """ + return fmt like: + [ + %{ + block_linker: ["block-ZgKJs"], + cited_by_id: 190057, + cited_by_type: "POST", + cited_article: #loaded, + post_id: 190059, + user_id: 1413053 + } + ... + ] + """ defp get_cited_contents_per_block(article, %{ "id" => block_id, "data" => %{"text" => text} @@ -147,7 +168,7 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do %{ cited_by_id: cited_article.id, cited_by_type: cited_article.meta.thread, - # cited_article: cited_article, + cited_article: cited_article, block_linker: [block_id], user_id: article.author.user.id } @@ -155,22 +176,35 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do end defp parse_cited_article({"a", attrs, _}) do - with {:ok, link} <- get_link(Enum.find(attrs, fn {a, v} -> a == "href" end)), - true <- is_valid_article_link?(link) do - get_cited_article(link) + with {:ok, link} <- parse_link(attrs), + true <- is_site_article_link?(link) do + load_cited_article_from_url(link) end end - defp get_link({"href", link}), do: {:ok, link} - defp get_link(_), do: {:error, "invalid fmt"} + @doc """ + parse link from Floki parse result + + e.g: + [{"href", "https://coderplanets.com/post/190220", "bla", "bla"}] -> + {:ok, "https://coderplanets.com/post/190220"} + """ + defp parse_link(attrs) do + with {"href", link} <- Enum.find(attrs, fn {a, v} -> a == "href" end) do + {:ok, link} + else + _ -> {:error, "invalid fmt"} + end + end - defp is_valid_article_link?(url) do + # 检测是否是站内文章的链接 + defp is_site_article_link?(url) do Enum.any?(@valid_article_prefix, &String.starts_with?(url, &1)) end # get cited article from url # e.g: https://coderplanets.com/post/189993 -> ORM.find(Post, 189993) - defp get_cited_article(url) do + defp load_cited_article_from_url(url) do %{path: path} = URI.parse(url) path_list = path |> String.split("/") thread = path_list |> Enum.at(1) |> String.downcase() |> String.to_atom() @@ -180,19 +214,4 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do ORM.find(info.model, article_id) end end - - defp run_tasks(:mention) do - # - end - - # 还是单抽一个模块吧 - defp run_tasks(:danger_words) do - # title & body - end - - defp parse_blocks(%{body: body} = article) do - with {:ok, body_map} <- Jason.decode(body) do - # - end - end end diff --git a/lib/groupher_server/cms/helper/macros.ex b/lib/groupher_server/cms/helper/macros.ex index 10a8ab4c5..5e1cbdf60 100644 --- a/lib/groupher_server/cms/helper/macros.ex +++ b/lib/groupher_server/cms/helper/macros.ex @@ -207,7 +207,6 @@ defmodule GroupherServer.CMS.Helper.Macros do article_comment_fields() field(:active_at, :utc_datetime_usec) - field(:citing_count, :integer, default: 0) # TODO: # related_articles timestamps() diff --git a/lib/groupher_server/cms/models/embeds/article_meta.ex b/lib/groupher_server/cms/models/embeds/article_meta.ex index 9e89c9ef3..75e26536d 100644 --- a/lib/groupher_server/cms/models/embeds/article_meta.ex +++ b/lib/groupher_server/cms/models/embeds/article_meta.ex @@ -40,6 +40,7 @@ defmodule GroupherServer.CMS.Model.Embeds.ArticleMeta do field(:can_undo_sink, :boolean, default: false) # if undo_sink, can recover last active_at from here field(:last_active_at, :utc_datetime_usec) + field(:citing_count, :integer, default: 0) end def changeset(struct, params) do diff --git a/priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs b/priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs deleted file mode 100644 index 20a8e4aea..000000000 --- a/priv/repo/migrations/20210611160430_add_citing_count_to_articles.exs +++ /dev/null @@ -1,10 +0,0 @@ -defmodule GroupherServer.Repo.Migrations.AddCitingCountToArticles do - use Ecto.Migration - - def change do - alter(table(:cms_posts), do: add(:citing_count, :integer)) - alter(table(:cms_jobs), do: add(:citing_count, :integer)) - alter(table(:cms_repos), do: add(:citing_count, :integer)) - alter(table(:cms_blogs), do: add(:citing_count, :integer)) - end -end diff --git a/test/groupher_server/cms/cite_content_test.exs b/test/groupher_server/cms/cite_content_test.exs index bfc9c3107..1d79f0759 100644 --- a/test/groupher_server/cms/cite_content_test.exs +++ b/test/groupher_server/cms/cite_content_test.exs @@ -20,34 +20,42 @@ defmodule GroupherServer.Test.CMS.CiteContent do {:ok, post} = db_insert(:post) {:ok, post2} = db_insert(:post) {:ok, post3} = db_insert(:post) + {:ok, post4} = db_insert(:post) + {:ok, post5} = db_insert(:post) {:ok, community} = db_insert(:community) post_attrs = mock_attrs(:post, %{community_id: community.id}) - {:ok, ~m(user user2 community post post2 post3 post_attrs)a} + {:ok, ~m(user user2 community post post2 post3 post4 post5 post_attrs)a} end describe "[cite basic]" do @tag :wip - test "basic", ~m(user community post2 post3 post_attrs)a do - IO.inspect(post2.id, label: "post2.id") - IO.inspect(post3.id, label: "post3.id") - + test "basic", ~m(user community post2 post3 post4 post5 post_attrs)a do body = mock_rich_text( ~s(the and same la is awesome, the is awesome too.), # second paragraph - ~s(the paragraph 2 again ) + ~s(the paragraph 2 again, the paragraph 2 again, the paragraph 2 again) ) post_attrs = post_attrs |> Map.merge(%{body: body}) {:ok, post} = CMS.create_article(community, :post, post_attrs, user) - BlockTasks.handle(post) + + {:ok, post2} = ORM.find(Post, post2.id) + {:ok, post3} = ORM.find(Post, post3.id) + {:ok, post4} = ORM.find(Post, post4.id) + + assert post2.meta.citing_count == 1 + assert post3.meta.citing_count == 1 + assert post4.meta.citing_count == 1 end end end From e8384e7dc2690634bb953646ad20749e34b20e54 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sat, 12 Jun 2021 17:35:47 +0800 Subject: [PATCH 06/10] refactor(cited-article): wip --- .../cms/delegates/block_tasks.ex | 97 +++++++++++-------- lib/helper/error_code.ex | 1 + lib/helper/orm.ex | 10 ++ lib/helper/utils/utils.ex | 9 ++ 4 files changed, 75 insertions(+), 42 deletions(-) diff --git a/lib/groupher_server/cms/delegates/block_tasks.ex b/lib/groupher_server/cms/delegates/block_tasks.ex index 336c346c6..b91c38444 100644 --- a/lib/groupher_server/cms/delegates/block_tasks.ex +++ b/lib/groupher_server/cms/delegates/block_tasks.ex @@ -3,14 +3,16 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do run tasks in every article blocks if need """ import Ecto.Query, warn: false - import Helper.Utils, only: [get_config: 2] + import Helper.Utils, only: [get_config: 2, thread_of_article: 1, done: 1] import GroupherServer.CMS.Helper.Matcher + import Helper.ErrorCode - alias GroupherServer.Repo - - alias GroupherServer.CMS.Model.CitedContent + alias GroupherServer.{CMS, Repo} + alias CMS.Model.CitedContent alias Helper.ORM + alias Ecto.Multi + @site_host get_config(:general, :site_host) @article_threads get_config(:article, :threads) @valid_article_prefix Enum.map(@article_threads, &"#{@site_host}/#{&1}/") @@ -42,60 +44,64 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do defp run_tasks(:cite, article, blocks) do article = article |> Repo.preload(author: :user) - blocks - |> Enum.reduce([], &(&2 ++ get_cited_contents_per_block(article, &1))) - |> merge_same_cited_article_block - |> update_cited_info + Multi.new() + |> Multi.run(:delete_all_cited_contents, fn _, _ -> + delete_all_cited_contents(article) + end) + |> Multi.run(:update_cited_info, fn _, _ -> + blocks + |> Enum.reduce([], &(&2 ++ parse_cited_info_per_block(article, &1))) + |> merge_same_cited_article_block + |> update_cited_info + end) + |> Repo.transaction() + |> result() + end + + # delete all records before insert_all, this will dynamiclly update + # those cited info when update article + # 插入引用记录之前先全部清除,这样可以在更新文章的时候自动计算引用信息 + defp delete_all_cited_contents(article) do + with {:ok, thread} <- thread_of_article(article), + {:ok, info} <- match(thread) do + query = from(c in CitedContent, where: field(c, ^info.foreign_key) == ^article.id) + + ORM.delete_all(query, :if_exist) + end end + # defp batch_done + defp update_cited_info(cited_contents) do - # batch update CitedContent List - cited_contents_fields = [:cited_by_id, :cited_by_type, :block_linker, :user_id] - clean_cited_contents = Enum.map(cited_contents, &Map.take(&1, cited_contents_fields)) + clean_cited_contents = Enum.map(cited_contents, &Map.delete(&1, :cited_article)) IO.inspect(clean_cited_contents, label: "clean_cited_contents") - Repo.insert_all(CitedContent, clean_cited_contents) - # update citting count meta - update_citing_count(cited_contents) + with true <- {0, nil} !== Repo.insert_all(CitedContent, clean_cited_contents) do + update_citing_count(cited_contents) + else + _ -> {:error, "insert cited content error"} + end end defp update_citing_count(cited_contents) do - Enum.each(cited_contents, fn content -> + Enum.all?(cited_contents, fn content -> count_query = from(c in CitedContent, where: c.cited_by_id == ^content.cited_by_id) count = Repo.aggregate(count_query, :count) cited_article = content.cited_article meta = Map.merge(cited_article.meta, %{citing_count: count}) - cited_article |> ORM.update_meta(meta) + + case cited_article |> ORM.update_meta(meta) do + {:ok, _} -> true + {:error, _} -> false + end end) + |> done end @doc """ + merge same cited article in different blocks e.g: - [ - %{ - block_linker: ["block-zByQI"], - cited_by_id: 190058, - cited_by_type: "POST", - post_id: 190059, - user_id: 1413053 - }, - %{ - block_linker: ["block-zByQI"], - cited_by_id: 190057, - cited_by_type: "POST", - post_id: 190059, - user_id: 1413053 - }, - %{ - block_linker: ["block-ZgKJs"], - cited_by_id: 190057, - cited_by_type: "POST", - post_id: 190059, - user_id: 1413053 - } - ] - into: [ %{ block_linker: ["block-zByQI"], @@ -144,7 +150,7 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do ... ] """ - defp get_cited_contents_per_block(article, %{ + defp parse_cited_info_per_block(article, %{ "id" => block_id, "data" => %{"text" => text} }) do @@ -162,12 +168,13 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do end defp shape_cited_content(article, cited_article, block_id) do - thread = article.meta.thread |> String.downcase() |> String.to_atom() + {:ok, thread} = thread_of_article(article) {:ok, info} = match(thread) %{ cited_by_id: cited_article.id, cited_by_type: cited_article.meta.thread, + # used for updating citing_count, avoid load again cited_article: cited_article, block_linker: [block_id], user_id: article.author.user.id @@ -214,4 +221,10 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do ORM.find(info.model, article_id) end end + + defp result({:ok, %{update_cited_info: result}}), do: {:ok, result} + + defp result({:error, :update_cited_info, _result, _steps}) do + {:error, [message: "cited article", code: ecode(:cite_artilce)]} + end end diff --git a/lib/helper/error_code.ex b/lib/helper/error_code.ex index 825fac99f..302697d65 100644 --- a/lib/helper/error_code.ex +++ b/lib/helper/error_code.ex @@ -51,6 +51,7 @@ defmodule Helper.ErrorCode do def ecode(:undo_sink_old_article), do: @article_base + 7 def ecode(:article_comment_locked), do: @article_base + 8 def ecode(:require_questioner), do: @article_base + 9 + def ecode(:cite_artilce), do: @article_base + 10 # def ecode(:already_solved), do: @article_base + 10 def ecode, do: @default_base diff --git a/lib/helper/orm.ex b/lib/helper/orm.ex index f2145fc94..0167467b9 100644 --- a/lib/helper/orm.ex +++ b/lib/helper/orm.ex @@ -173,6 +173,16 @@ defmodule Helper.ORM do end end + @doc """ + delete all queryable if exist + """ + def delete_all(queryable, :if_exist) do + case Repo.exists?(query) do + true -> {:ok, Repo.delete_all(query)} + false -> {:ok, :pass} + end + end + def findby_or_insert(queryable, clauses, attrs) do case queryable |> find_by(clauses) do {:ok, content} -> diff --git a/lib/helper/utils/utils.ex b/lib/helper/utils/utils.ex index d64a7782b..34cacb414 100644 --- a/lib/helper/utils/utils.ex +++ b/lib/helper/utils/utils.ex @@ -55,6 +55,8 @@ defmodule Helper.Utils do @doc """ handle General {:ok, ..} or {:error, ..} return """ + def done(false), do: {:error, false} + def done(true), do: {:ok, true} def done(nil, :boolean), do: {:ok, false} def done(_, :boolean), do: {:ok, true} def done(nil, err_msg), do: {:error, err_msg} @@ -208,6 +210,13 @@ defmodule Helper.Utils do end end + # get thread of article + def thread_of_article(%{meta: %{thread: thread}}) do + thread |> String.downcase() |> String.to_atom() |> done + end + + def thread_of_article(_), do: {:error, "invalid article"} + def uid(str_len \\ 5) do Nanoid.generate(str_len, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") end From 018d6a40312f0c9cb8b2d2cc449dd8a353a74ee8 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sun, 13 Jun 2021 12:23:06 +0800 Subject: [PATCH 07/10] refactor(cited-article): wip --- .../cms/delegates/block_tasks.ex | 6 ++-- lib/helper/orm.ex | 4 +-- .../groupher_server/cms/cite_content_test.exs | 32 +++++++++++++++---- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/groupher_server/cms/delegates/block_tasks.ex b/lib/groupher_server/cms/delegates/block_tasks.ex index b91c38444..cd3ac8be4 100644 --- a/lib/groupher_server/cms/delegates/block_tasks.ex +++ b/lib/groupher_server/cms/delegates/block_tasks.ex @@ -158,10 +158,12 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do links_in_block = Floki.find(text, "a[href]") Enum.reduce(links_in_block, [], fn link, acc -> - with {:ok, cited_article} <- parse_cited_article(link) do + with {:ok, cited_article} <- parse_cited_article(link), + # do not cite artilce itself + true <- article.id !== cited_article.id do List.insert_at(acc, 0, shape_cited_content(article, cited_article, block_id)) else - {:error, _} -> acc + _ -> acc end end) |> Enum.uniq() diff --git a/lib/helper/orm.ex b/lib/helper/orm.ex index 0167467b9..6e473dceb 100644 --- a/lib/helper/orm.ex +++ b/lib/helper/orm.ex @@ -177,8 +177,8 @@ defmodule Helper.ORM do delete all queryable if exist """ def delete_all(queryable, :if_exist) do - case Repo.exists?(query) do - true -> {:ok, Repo.delete_all(query)} + case Repo.exists?(queryable) do + true -> {:ok, Repo.delete_all(queryable)} false -> {:ok, :pass} end end diff --git a/test/groupher_server/cms/cite_content_test.exs b/test/groupher_server/cms/cite_content_test.exs index 1d79f0759..39d6536d3 100644 --- a/test/groupher_server/cms/cite_content_test.exs +++ b/test/groupher_server/cms/cite_content_test.exs @@ -5,10 +5,8 @@ defmodule GroupherServer.Test.CMS.CiteContent do alias Helper.ORM alias GroupherServer.CMS - alias Helper.Converter.{EditorToHTML, HtmlSanitizer, Converter} - alias EditorToHTML.{Class, Validator} - alias CMS.Model.{Author, Community, Post} + alias CMS.Model.Post alias CMS.Delegate.BlockTasks @@ -31,8 +29,8 @@ defmodule GroupherServer.Test.CMS.CiteContent do end describe "[cite basic]" do - @tag :wip - test "basic", ~m(user community post2 post3 post4 post5 post_attrs)a do + # @tag :wip + test "cited multi post should work", ~m(user community post2 post3 post4 post5 post_attrs)a do body = mock_rich_text( ~s(the and Map.merge(%{body: body}) - {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + + body = mock_rich_text(~s(the )) + post_attrs = post_attrs |> Map.merge(%{body: body}) + {:ok, post_n} = CMS.create_article(community, :post, post_attrs, user) + BlockTasks.handle(post) + BlockTasks.handle(post_n) {:ok, post2} = ORM.find(Post, post2.id) {:ok, post3} = ORM.find(Post, post3.id) {:ok, post4} = ORM.find(Post, post4.id) + {:ok, post5} = ORM.find(Post, post5.id) assert post2.meta.citing_count == 1 - assert post3.meta.citing_count == 1 + assert post3.meta.citing_count == 2 assert post4.meta.citing_count == 1 + assert post5.meta.citing_count == 1 + end + + @tag :wip + test "cited post itself should not work", ~m(user community post post_attrs)a do + {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + + body = mock_rich_text(~s(the )) + {:ok, post} = CMS.update_article(post, %{body: body}) + + BlockTasks.handle(post) + + {:ok, post} = ORM.find(Post, post.id) + assert post.meta.citing_count == 0 end end end From c3e422b2330bfaf702c4717ca72fd11a07d12c99 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sun, 13 Jun 2021 16:16:01 +0800 Subject: [PATCH 08/10] refactor(cited-article): doc & naming adjust --- .../cms/delegates/article_curd.ex | 13 ++- .../{block_tasks.ex => cite_tasks.ex} | 80 +++++++++---------- .../statistics/delegates/contribute.ex | 2 +- lib/helper/later.ex | 6 +- .../cite_post_test.exs} | 10 +-- .../statistics/statistics_test.exs | 2 +- 6 files changed, 53 insertions(+), 60 deletions(-) rename lib/groupher_server/cms/delegates/{block_tasks.ex => cite_tasks.ex} (81%) rename test/groupher_server/cms/{cite_content_test.exs => cite_contents/cite_post_test.exs} (94%) diff --git a/lib/groupher_server/cms/delegates/article_curd.ex b/lib/groupher_server/cms/delegates/article_curd.ex index afb127c90..e5994d163 100644 --- a/lib/groupher_server/cms/delegates/article_curd.ex +++ b/lib/groupher_server/cms/delegates/article_curd.ex @@ -18,7 +18,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do alias Accounts.Model.User alias CMS.Model.{Author, Community, PinnedArticle, Embeds} - alias CMS.Delegate.{ArticleCommunity, ArticleComment, ArticleTag, CommunityCURD} + alias CMS.Delegate.{ArticleCommunity, ArticleComment, ArticleTag, CommunityCURD, CiteTasks} alias Ecto.Multi @@ -149,12 +149,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do |> Multi.run(:create_article, fn _, _ -> do_create_article(info.model, attrs, author, community) end) - |> Multi.run(:block_tasks, fn _, %{create_article: article} -> - # ArticleCommunity.mirror_article(thread, article.id, community.id) - # Later - # BlockTasks.handle(article) - {:ok, :pass} - end) |> Multi.run(:mirror_article, fn _, %{create_article: article} -> ArticleCommunity.mirror_article(thread, article.id, community.id) end) @@ -170,6 +164,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do |> Multi.run(:update_user_published_meta, fn _, _ -> Accounts.update_published_states(uid, thread) end) + |> Multi.run(:block_tasks, fn _, %{create_article: article} -> + Later.run({CiteTasks, :handle, [article]}) + end) # TODO: run mini tasks |> Multi.run(:mention_users, fn _, %{create_article: article} -> # article.body |> Jason.decode!() |> 各种小 task @@ -452,7 +449,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do # create done defp result({:ok, %{set_active_at_timestamp: result}}) do - Later.exec({__MODULE__, :notify_admin_new_article, [result]}) + Later.run({__MODULE__, :notify_admin_new_article, [result]}) {:ok, result} end diff --git a/lib/groupher_server/cms/delegates/block_tasks.ex b/lib/groupher_server/cms/delegates/cite_tasks.ex similarity index 81% rename from lib/groupher_server/cms/delegates/block_tasks.ex rename to lib/groupher_server/cms/delegates/cite_tasks.ex index cd3ac8be4..f108c192f 100644 --- a/lib/groupher_server/cms/delegates/block_tasks.ex +++ b/lib/groupher_server/cms/delegates/cite_tasks.ex @@ -1,7 +1,28 @@ -defmodule GroupherServer.CMS.Delegate.BlockTasks do +defmodule GroupherServer.CMS.Delegate.CiteTasks do @moduledoc """ run tasks in every article blocks if need + + current task: "cite link" and "mention" + + ## cite link + + 我被站内哪些文章或评论引用了,是值得关注的事 + 我引用了谁不重要,帖子里链接已经表明了, 这和 github issue 的双向链接不一样,因为一般不需要关注这个 + 帖子是否解决,是否被 merge 等状态。 + + 基本结构: + + cited_thread, cited_article_id, [xxx_article]_id, [block_id, block2_id], + + POST post_333 -> cited_article_333, [block_id, block2_id]] + + cited_type, cited_content_id, [contents]_id, [block_id, cited_block_id], + + cited_type: thread or comment + content: article or comment + # cited_article_comment_id, [xxx_article]_id, [block_id, block2_id, ...], """ + import Ecto.Query, warn: false import Helper.Utils, only: [get_config: 2, thread_of_article: 1, done: 1] import GroupherServer.CMS.Helper.Matcher @@ -17,47 +38,24 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do @article_threads get_config(:article, :threads) @valid_article_prefix Enum.map(@article_threads, &"#{@site_host}/#{&1}/") - """ - 我被谁引用了 是最重要的信息 - 我引用了谁不重要,自己扫帖子就行了 - cited_thread, cited_article_id, [xxx_article]_id, [block_id, cited_block_id], - - POST post_333 -> cited_article_333, [[block_3, cited_block_23]] - - cited_type, cited_content_id, [contents]_id, [block_id, cited_block_id], - - cited_type: thread or comment - content: article or comment - # cited_article_comment_id, [xxx_article]_id, [block_id, cited_block_id], - """ - - # reference - # mention - def handle(%{body: body} = article) do - with {:ok, body_map} <- Jason.decode(body) do - run_tasks(:cite, article, body_map["blocks"]) - # run_tasks(:mention, article, body_map["blocks"]) + with {:ok, %{"blocks" => blocks}} <- Jason.decode(body), + article <- Repo.preload(article, author: :user) do + Multi.new() + |> Multi.run(:delete_all_cited_contents, fn _, _ -> + delete_all_cited_contents(article) + end) + |> Multi.run(:update_cited_info, fn _, _ -> + blocks + |> Enum.reduce([], &(&2 ++ parse_cited_info_per_block(article, &1))) + |> merge_same_cited_article_block + |> update_cited_info + end) + |> Repo.transaction() + |> result() end end - defp run_tasks(:cite, article, blocks) do - article = article |> Repo.preload(author: :user) - - Multi.new() - |> Multi.run(:delete_all_cited_contents, fn _, _ -> - delete_all_cited_contents(article) - end) - |> Multi.run(:update_cited_info, fn _, _ -> - blocks - |> Enum.reduce([], &(&2 ++ parse_cited_info_per_block(article, &1))) - |> merge_same_cited_article_block - |> update_cited_info - end) - |> Repo.transaction() - |> result() - end - # delete all records before insert_all, this will dynamiclly update # those cited info when update article # 插入引用记录之前先全部清除,这样可以在更新文章的时候自动计算引用信息 @@ -150,11 +148,7 @@ defmodule GroupherServer.CMS.Delegate.BlockTasks do ... ] """ - defp parse_cited_info_per_block(article, %{ - "id" => block_id, - "data" => %{"text" => text} - }) do - # + defp parse_cited_info_per_block(article, %{"id" => block_id, "data" => %{"text" => text}}) do links_in_block = Floki.find(text, "a[href]") Enum.reduce(links_in_block, [], fn link, acc -> diff --git a/lib/groupher_server/statistics/delegates/contribute.ex b/lib/groupher_server/statistics/delegates/contribute.ex index ec072c4ff..6165c7d7a 100644 --- a/lib/groupher_server/statistics/delegates/contribute.ex +++ b/lib/groupher_server/statistics/delegates/contribute.ex @@ -134,7 +134,7 @@ defmodule GroupherServer.Statistics.Delegate.Contribute do end defp cache_contribute_later(%Community{id: id}) do - Later.exec({__MODULE__, :get_contributes_then_cache, [%Community{id: id}]}) + Later.run({__MODULE__, :get_contributes_then_cache, [%Community{id: id}]}) end defp do_get_contributes(%Community{id: id}) do diff --git a/lib/helper/later.ex b/lib/helper/later.ex index 9644b106c..779f5157b 100644 --- a/lib/helper/later.ex +++ b/lib/helper/later.ex @@ -5,10 +5,12 @@ defmodule Helper.Later do @doc """ ## Example - iex> Later.exec({__MODULE__, :get_contributes_then_cache, [%Community{id: id}]}) + iex> Later.run({__MODULE__, :get_contributes_then_cache, [%Community{id: id}]}) {:ok, _} """ - def exec({mod, func, args}) do + def run({mod, func, args}) do Rihanna.enqueue({mod, func, args}) + # weather enqueue success or not, just return {:ok, :pass}, or Multi.Job will be rollback + {:ok, :pass} end end diff --git a/test/groupher_server/cms/cite_content_test.exs b/test/groupher_server/cms/cite_contents/cite_post_test.exs similarity index 94% rename from test/groupher_server/cms/cite_content_test.exs rename to test/groupher_server/cms/cite_contents/cite_post_test.exs index 39d6536d3..a3cfb28d8 100644 --- a/test/groupher_server/cms/cite_content_test.exs +++ b/test/groupher_server/cms/cite_contents/cite_post_test.exs @@ -8,7 +8,7 @@ defmodule GroupherServer.Test.CMS.CiteContent do alias CMS.Model.Post - alias CMS.Delegate.BlockTasks + alias CMS.Delegate.CiteTasks @site_host get_config(:general, :site_host) @@ -29,7 +29,7 @@ defmodule GroupherServer.Test.CMS.CiteContent do end describe "[cite basic]" do - # @tag :wip + @tag :wip test "cited multi post should work", ~m(user community post2 post3 post4 post5 post_attrs)a do body = mock_rich_text( @@ -49,8 +49,8 @@ defmodule GroupherServer.Test.CMS.CiteContent do post_attrs = post_attrs |> Map.merge(%{body: body}) {:ok, post_n} = CMS.create_article(community, :post, post_attrs, user) - BlockTasks.handle(post) - BlockTasks.handle(post_n) + CiteTasks.handle(post) + CiteTasks.handle(post_n) {:ok, post2} = ORM.find(Post, post2.id) {:ok, post3} = ORM.find(Post, post3.id) @@ -70,7 +70,7 @@ defmodule GroupherServer.Test.CMS.CiteContent do body = mock_rich_text(~s(the )) {:ok, post} = CMS.update_article(post, %{body: body}) - BlockTasks.handle(post) + CiteTasks.handle(post) {:ok, post} = ORM.find(Post, post.id) assert post.meta.citing_count == 0 diff --git a/test/groupher_server/statistics/statistics_test.exs b/test/groupher_server/statistics/statistics_test.exs index ebf9ae041..1ddd03718 100644 --- a/test/groupher_server/statistics/statistics_test.exs +++ b/test/groupher_server/statistics/statistics_test.exs @@ -222,7 +222,7 @@ defmodule GroupherServer.Test.Statistics do Statistics.make_contribute(%Community{id: community.id}) - # res = Later.exec({IO, :puts, ["Work, work, work, work, work."]}) + # res = Later.run({IO, :puts, ["Work, work, work, work, work."]}) # Process.sleep(1000) # IO.inspect(res, label: "res") From 7d0d5c5f7155adf4e5f32f562f074c5e827d08ed Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sun, 13 Jun 2021 16:51:21 +0800 Subject: [PATCH 09/10] refactor(cited-article): more test --- .../cms/delegates/cite_tasks.ex | 2 +- .../20210611015726_create_cited_articles.exs | 6 +- .../cms/cite_contents/cite_blog_test.exs | 79 +++++++++++++++++++ .../cms/cite_contents/cite_job_test.exs | 79 +++++++++++++++++++ .../cms/cite_contents/cite_post_test.exs | 4 +- test/support/factory.ex | 6 +- 6 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 test/groupher_server/cms/cite_contents/cite_blog_test.exs create mode 100644 test/groupher_server/cms/cite_contents/cite_job_test.exs diff --git a/lib/groupher_server/cms/delegates/cite_tasks.ex b/lib/groupher_server/cms/delegates/cite_tasks.ex index f108c192f..614e6b3c9 100644 --- a/lib/groupher_server/cms/delegates/cite_tasks.ex +++ b/lib/groupher_server/cms/delegates/cite_tasks.ex @@ -193,7 +193,7 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do {:ok, "https://coderplanets.com/post/190220"} """ defp parse_link(attrs) do - with {"href", link} <- Enum.find(attrs, fn {a, v} -> a == "href" end) do + with {"href", link} <- Enum.find(attrs, fn {a, _v} -> a == "href" end) do {:ok, link} else _ -> {:error, "invalid fmt"} diff --git a/priv/repo/migrations/20210611015726_create_cited_articles.exs b/priv/repo/migrations/20210611015726_create_cited_articles.exs index 582377277..253ff662e 100644 --- a/priv/repo/migrations/20210611015726_create_cited_articles.exs +++ b/priv/repo/migrations/20210611015726_create_cited_articles.exs @@ -11,9 +11,9 @@ defmodule GroupherServer.Repo.Migrations.CreateCitedArticles do add(:article_comment_id, references(:articles_comments, on_delete: :delete_all)) add(:post_id, references(:cms_posts, on_delete: :delete_all)) - add(:repo_id, references(:cms_posts, on_delete: :delete_all)) - add(:job_id, references(:cms_posts, on_delete: :delete_all)) - add(:blog_id, references(:cms_posts, on_delete: :delete_all)) + add(:repo_id, references(:cms_repos, on_delete: :delete_all)) + add(:job_id, references(:cms_jobs, on_delete: :delete_all)) + add(:blog_id, references(:cms_blogs, on_delete: :delete_all)) add(:block_linker, {:array, :string}) end diff --git a/test/groupher_server/cms/cite_contents/cite_blog_test.exs b/test/groupher_server/cms/cite_contents/cite_blog_test.exs new file mode 100644 index 000000000..641d59aee --- /dev/null +++ b/test/groupher_server/cms/cite_contents/cite_blog_test.exs @@ -0,0 +1,79 @@ +defmodule GroupherServer.Test.CMS.CiteContent.Blog do + use GroupherServer.TestTools + + import Helper.Utils, only: [get_config: 2] + + alias Helper.ORM + alias GroupherServer.CMS + + alias CMS.Model.Blog + + alias CMS.Delegate.CiteTasks + + @site_host get_config(:general, :site_host) + + setup do + {:ok, user} = db_insert(:user) + {:ok, user2} = db_insert(:user) + {:ok, blog} = db_insert(:blog) + {:ok, blog2} = db_insert(:blog) + {:ok, blog3} = db_insert(:blog) + {:ok, blog4} = db_insert(:blog) + {:ok, blog5} = db_insert(:blog) + + {:ok, community} = db_insert(:community) + + blog_attrs = mock_attrs(:blog, %{community_id: community.id}) + + {:ok, ~m(user user2 community blog blog2 blog3 blog4 blog5 blog_attrs)a} + end + + describe "[cite basic]" do + @tag :wip + test "cited multi blog should work", ~m(user community blog2 blog3 blog4 blog5 blog_attrs)a do + body = + mock_rich_text( + ~s(the and same la is awesome, the is awesome too.), + # second paragraph + ~s(the paragraph 2 again, the paragraph 2 again, the paragraph 2 again) + ) + + blog_attrs = blog_attrs |> Map.merge(%{body: body}) + {:ok, blog} = CMS.create_article(community, :blog, blog_attrs, user) + + body = mock_rich_text(~s(the )) + blog_attrs = blog_attrs |> Map.merge(%{body: body}) + {:ok, blog_n} = CMS.create_article(community, :blog, blog_attrs, user) + + CiteTasks.handle(blog) + CiteTasks.handle(blog_n) + + {:ok, blog2} = ORM.find(Blog, blog2.id) + {:ok, blog3} = ORM.find(Blog, blog3.id) + {:ok, blog4} = ORM.find(Blog, blog4.id) + {:ok, blog5} = ORM.find(Blog, blog5.id) + + assert blog2.meta.citing_count == 1 + assert blog3.meta.citing_count == 2 + assert blog4.meta.citing_count == 1 + assert blog5.meta.citing_count == 1 + end + + @tag :wip + test "cited blog itself should not work", ~m(user community blog_attrs)a do + {:ok, blog} = CMS.create_article(community, :blog, blog_attrs, user) + + body = mock_rich_text(~s(the )) + {:ok, blog} = CMS.update_article(blog, %{body: body}) + + CiteTasks.handle(blog) + + {:ok, blog} = ORM.find(Blog, blog.id) + assert blog.meta.citing_count == 0 + end + end +end diff --git a/test/groupher_server/cms/cite_contents/cite_job_test.exs b/test/groupher_server/cms/cite_contents/cite_job_test.exs new file mode 100644 index 000000000..2a5091a98 --- /dev/null +++ b/test/groupher_server/cms/cite_contents/cite_job_test.exs @@ -0,0 +1,79 @@ +defmodule GroupherServer.Test.CMS.CiteContent.Job do + use GroupherServer.TestTools + + import Helper.Utils, only: [get_config: 2] + + alias Helper.ORM + alias GroupherServer.CMS + + alias CMS.Model.Job + + alias CMS.Delegate.CiteTasks + + @site_host get_config(:general, :site_host) + + setup do + {:ok, user} = db_insert(:user) + {:ok, user2} = db_insert(:user) + {:ok, job} = db_insert(:job) + {:ok, job2} = db_insert(:job) + {:ok, job3} = db_insert(:job) + {:ok, job4} = db_insert(:job) + {:ok, job5} = db_insert(:job) + + {:ok, community} = db_insert(:community) + + job_attrs = mock_attrs(:job, %{community_id: community.id}) + + {:ok, ~m(user user2 community job job2 job3 job4 job5 job_attrs)a} + end + + describe "[cite basic]" do + @tag :wip + test "cited multi job should work", ~m(user community job2 job3 job4 job5 job_attrs)a do + body = + mock_rich_text( + ~s(the and same la is awesome, the is awesome too.), + # second paragraph + ~s(the paragraph 2 again, the paragraph 2 again, the paragraph 2 again) + ) + + job_attrs = job_attrs |> Map.merge(%{body: body}) + {:ok, job} = CMS.create_article(community, :job, job_attrs, user) + + body = mock_rich_text(~s(the )) + job_attrs = job_attrs |> Map.merge(%{body: body}) + {:ok, job_n} = CMS.create_article(community, :job, job_attrs, user) + + CiteTasks.handle(job) + CiteTasks.handle(job_n) + + {:ok, job2} = ORM.find(Job, job2.id) + {:ok, job3} = ORM.find(Job, job3.id) + {:ok, job4} = ORM.find(Job, job4.id) + {:ok, job5} = ORM.find(Job, job5.id) + + assert job2.meta.citing_count == 1 + assert job3.meta.citing_count == 2 + assert job4.meta.citing_count == 1 + assert job5.meta.citing_count == 1 + end + + @tag :wip + test "cited job itself should not work", ~m(user community job_attrs)a do + {:ok, job} = CMS.create_article(community, :job, job_attrs, user) + + body = mock_rich_text(~s(the )) + {:ok, job} = CMS.update_article(job, %{body: body}) + + CiteTasks.handle(job) + + {:ok, job} = ORM.find(Job, job.id) + assert job.meta.citing_count == 0 + end + end +end diff --git a/test/groupher_server/cms/cite_contents/cite_post_test.exs b/test/groupher_server/cms/cite_contents/cite_post_test.exs index a3cfb28d8..e4402150d 100644 --- a/test/groupher_server/cms/cite_contents/cite_post_test.exs +++ b/test/groupher_server/cms/cite_contents/cite_post_test.exs @@ -1,4 +1,4 @@ -defmodule GroupherServer.Test.CMS.CiteContent do +defmodule GroupherServer.Test.CMS.CiteContent.Post do use GroupherServer.TestTools import Helper.Utils, only: [get_config: 2] @@ -64,7 +64,7 @@ defmodule GroupherServer.Test.CMS.CiteContent do end @tag :wip - test "cited post itself should not work", ~m(user community post post_attrs)a do + test "cited post itself should not work", ~m(user community post_attrs)a do {:ok, post} = CMS.create_article(community, :post, post_attrs, user) body = mock_rich_text(~s(the )) diff --git a/test/support/factory.ex b/test/support/factory.ex index a55ffd968..dbe27ee27 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -113,7 +113,7 @@ defmodule GroupherServer.Support.Factory do desc = Faker.Lorem.sentence(%Range{first: 15, last: 60}) %{ - meta: @default_article_meta, + meta: @default_article_meta |> Map.merge(%{thread: "REPO"}), title: String.slice(desc, 1, 49), owner_name: "coderplanets", owner_url: "http://www.github.com/coderplanets", @@ -183,7 +183,7 @@ defmodule GroupherServer.Support.Factory do text = Faker.Lorem.sentence(%Range{first: 80, last: 120}) %{ - meta: @default_article_meta, + meta: @default_article_meta |> Map.merge(%{thread: "JOB"}), title: String.slice(text, 1, 49), company: Faker.Company.name(), body: mock_rich_text(), @@ -205,7 +205,7 @@ defmodule GroupherServer.Support.Factory do text = Faker.Lorem.sentence(%Range{first: 80, last: 120}) %{ - meta: @default_article_meta, + meta: @default_article_meta |> Map.merge(%{thread: "BLOG"}), title: String.slice(text, 1, 49), body: mock_rich_text(), digest: String.slice(text, 1, 150), From ac186525e19f774923ec59e8766c1f3ff71f02b7 Mon Sep 17 00:00:00 2001 From: mydearxym Date: Sun, 13 Jun 2021 17:07:55 +0800 Subject: [PATCH 10/10] refactor(cited-article): fix default meta && clean up --- lib/groupher_server/cms/delegates/cite_tasks.ex | 3 +-- lib/groupher_server/cms/models/embeds/article_meta.ex | 3 ++- test/groupher_server/cms/articles/post_meta_test.exs | 1 + test/groupher_server/cms/cite_contents/cite_blog_test.exs | 2 -- test/groupher_server/cms/cite_contents/cite_job_test.exs | 2 -- test/groupher_server/cms/cite_contents/cite_post_test.exs | 2 -- 6 files changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/groupher_server/cms/delegates/cite_tasks.ex b/lib/groupher_server/cms/delegates/cite_tasks.ex index 614e6b3c9..f816a4570 100644 --- a/lib/groupher_server/cms/delegates/cite_tasks.ex +++ b/lib/groupher_server/cms/delegates/cite_tasks.ex @@ -72,8 +72,7 @@ defmodule GroupherServer.CMS.Delegate.CiteTasks do defp update_cited_info(cited_contents) do clean_cited_contents = Enum.map(cited_contents, &Map.delete(&1, :cited_article)) - IO.inspect(clean_cited_contents, label: "clean_cited_contents") - + # IO.inspect(clean_cited_contents, label: "clean_cited_contents") with true <- {0, nil} !== Repo.insert_all(CitedContent, clean_cited_contents) do update_citing_count(cited_contents) else diff --git a/lib/groupher_server/cms/models/embeds/article_meta.ex b/lib/groupher_server/cms/models/embeds/article_meta.ex index 75e26536d..7a6132823 100644 --- a/lib/groupher_server/cms/models/embeds/article_meta.ex +++ b/lib/groupher_server/cms/models/embeds/article_meta.ex @@ -21,7 +21,8 @@ defmodule GroupherServer.CMS.Model.Embeds.ArticleMeta do reported_count: 0, is_sinked: false, can_undo_sink: true, - last_active_at: nil + last_active_at: nil, + citing_count: 0 } end diff --git a/test/groupher_server/cms/articles/post_meta_test.exs b/test/groupher_server/cms/articles/post_meta_test.exs index d31e8c7df..fae1d0dbf 100644 --- a/test/groupher_server/cms/articles/post_meta_test.exs +++ b/test/groupher_server/cms/articles/post_meta_test.exs @@ -20,6 +20,7 @@ defmodule GroupherServer.Test.CMS.PostMeta do end describe "[cms post meta info]" do + @tag :wip test "can get default meta info", ~m(user community post_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) diff --git a/test/groupher_server/cms/cite_contents/cite_blog_test.exs b/test/groupher_server/cms/cite_contents/cite_blog_test.exs index 641d59aee..b4188fcff 100644 --- a/test/groupher_server/cms/cite_contents/cite_blog_test.exs +++ b/test/groupher_server/cms/cite_contents/cite_blog_test.exs @@ -29,7 +29,6 @@ defmodule GroupherServer.Test.CMS.CiteContent.Blog do end describe "[cite basic]" do - @tag :wip test "cited multi blog should work", ~m(user community blog2 blog3 blog4 blog5 blog_attrs)a do body = mock_rich_text( @@ -63,7 +62,6 @@ defmodule GroupherServer.Test.CMS.CiteContent.Blog do assert blog5.meta.citing_count == 1 end - @tag :wip test "cited blog itself should not work", ~m(user community blog_attrs)a do {:ok, blog} = CMS.create_article(community, :blog, blog_attrs, user) diff --git a/test/groupher_server/cms/cite_contents/cite_job_test.exs b/test/groupher_server/cms/cite_contents/cite_job_test.exs index 2a5091a98..3bd197b4f 100644 --- a/test/groupher_server/cms/cite_contents/cite_job_test.exs +++ b/test/groupher_server/cms/cite_contents/cite_job_test.exs @@ -29,7 +29,6 @@ defmodule GroupherServer.Test.CMS.CiteContent.Job do end describe "[cite basic]" do - @tag :wip test "cited multi job should work", ~m(user community job2 job3 job4 job5 job_attrs)a do body = mock_rich_text( @@ -63,7 +62,6 @@ defmodule GroupherServer.Test.CMS.CiteContent.Job do assert job5.meta.citing_count == 1 end - @tag :wip test "cited job itself should not work", ~m(user community job_attrs)a do {:ok, job} = CMS.create_article(community, :job, job_attrs, user) diff --git a/test/groupher_server/cms/cite_contents/cite_post_test.exs b/test/groupher_server/cms/cite_contents/cite_post_test.exs index e4402150d..2db3c4a81 100644 --- a/test/groupher_server/cms/cite_contents/cite_post_test.exs +++ b/test/groupher_server/cms/cite_contents/cite_post_test.exs @@ -29,7 +29,6 @@ defmodule GroupherServer.Test.CMS.CiteContent.Post do end describe "[cite basic]" do - @tag :wip test "cited multi post should work", ~m(user community post2 post3 post4 post5 post_attrs)a do body = mock_rich_text( @@ -63,7 +62,6 @@ defmodule GroupherServer.Test.CMS.CiteContent.Post do assert post5.meta.citing_count == 1 end - @tag :wip test "cited post itself should not work", ~m(user community post_attrs)a do {:ok, post} = CMS.create_article(community, :post, post_attrs, user)