+
+ def parse_bio(bio, user \\ %User{info: %{source_data: %{}}})
+ def parse_bio(nil, _user), do: ""
+ def parse_bio(bio, _user) when bio == "", do: bio
+
+ def parse_bio(bio, user) do
+ mentions = Formatter.parse_mentions(bio)
+ tags = Formatter.parse_tags(bio)
+
+ emoji =
+ (user.info.source_data["tag"] || [])
+ |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
+ |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
+ {String.trim(name, ":"), url}
+ end)
+
+ bio
+ |> CommonUtils.format_input(mentions, tags, "text/plain", user_links: [format: :full])
+ |> Formatter.emojify(emoji)
+ end
+
+ def tag(user_identifiers, tags) when is_list(user_identifiers) do
+ Repo.transaction(fn ->
+ for user_identifier <- user_identifiers, do: tag(user_identifier, tags)
+ end)
+ end
+
+ def tag(nickname, tags) when is_binary(nickname),
+ do: tag(User.get_by_nickname(nickname), tags)
+
+ def tag(%User{} = user, tags),
+ do: update_tags(user, Enum.uniq((user.tags || []) ++ normalize_tags(tags)))
+
+ def untag(user_identifiers, tags) when is_list(user_identifiers) do
+ Repo.transaction(fn ->
+ for user_identifier <- user_identifiers, do: untag(user_identifier, tags)
+ end)
+ end
+
+ def untag(nickname, tags) when is_binary(nickname),
+ do: untag(User.get_by_nickname(nickname), tags)
+
+ def untag(%User{} = user, tags),
+ do: update_tags(user, (user.tags || []) -- normalize_tags(tags))
+
+ defp update_tags(%User{} = user, new_tags) do
+ {:ok, updated_user} =
+ user
+ |> change(%{tags: new_tags})
+ |> Repo.update()
+
+ updated_user
+ end
+
+ def bookmark(%User{} = user, status_id) do
+ bookmarks = Enum.uniq(user.bookmarks ++ [status_id])
+ update_bookmarks(user, bookmarks)
+ end
+
+ def unbookmark(%User{} = user, status_id) do
+ bookmarks = Enum.uniq(user.bookmarks -- [status_id])
+ update_bookmarks(user, bookmarks)
+ end
+
+ def update_bookmarks(%User{} = user, bookmarks) do
+ user
+ |> change(%{bookmarks: bookmarks})
+ |> update_and_set_cache
+ end
+
+ defp normalize_tags(tags) do
+ [tags]
+ |> List.flatten()
+ |> Enum.map(&String.downcase(&1))
+ end
+
+ defp local_nickname_regex() do
+ if Pleroma.Config.get([:instance, :extended_nickname_format]) do
+ @extended_local_nickname_regex
+ else
+ @strict_local_nickname_regex
+ end
+ end
+
+ def local_nickname(nickname_or_mention) do
+ nickname_or_mention
+ |> full_nickname()
+ |> String.split("@")
+ |> hd()
+ end
+
+ def full_nickname(nickname_or_mention),
+ do: String.trim_leading(nickname_or_mention, "@")
+
+ def error_user(ap_id) do
+ %User{
+ name: ap_id,
+ ap_id: ap_id,
+ info: %User.Info{},
+ nickname: "erroruser@example.com",
+ inserted_at: NaiveDateTime.utc_now()
+ }
+ end