chore: added more @spec
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -39,64 +39,93 @@ defmodule BDS.Scripting.Capabilities do
|
||||
projects: %{
|
||||
create: zero_or_one_arg(fn attrs -> create_project(attrs) end),
|
||||
delete: one_arg(fn project_id_to_delete -> delete_project(project_id_to_delete) end),
|
||||
delete_with_data: one_arg(fn project_id_to_delete -> delete_project_with_data(project_id_to_delete) end),
|
||||
delete_with_data:
|
||||
one_arg(fn project_id_to_delete -> delete_project_with_data(project_id_to_delete) end),
|
||||
get: one_arg(fn project_id_to_load -> load_project(project_id_to_load) end),
|
||||
get_all: zero_or_one_arg(fn _args -> list_projects() end),
|
||||
get_active: zero_or_one_arg(fn _args -> load_project(project_id) end),
|
||||
set_active: one_arg(fn project_id_to_activate -> set_active_project(project_id_to_activate) end),
|
||||
update: two_arg(fn project_id_to_update, attrs -> update_project(project_id_to_update, attrs) end)
|
||||
set_active:
|
||||
one_arg(fn project_id_to_activate -> set_active_project(project_id_to_activate) end),
|
||||
update:
|
||||
two_arg(fn project_id_to_update, attrs ->
|
||||
update_project(project_id_to_update, attrs)
|
||||
end)
|
||||
},
|
||||
meta: %{
|
||||
get_project_metadata: zero_or_one_arg(fn _args -> load_metadata(project_id) end),
|
||||
update_project_metadata: one_arg(fn attrs -> update_project_metadata(project_id, attrs) end),
|
||||
update_project_metadata:
|
||||
one_arg(fn attrs -> update_project_metadata(project_id, attrs) end),
|
||||
add_category: one_arg(fn name -> add_category(project_id, name) end),
|
||||
remove_category: one_arg(fn name -> remove_category(project_id, name) end),
|
||||
add_tag: one_arg(fn name -> add_meta_tag(project_id, name) end),
|
||||
get_categories: zero_or_one_arg(fn _args -> metadata_categories(project_id) end),
|
||||
set_project_metadata: one_arg(fn attrs -> update_project_metadata(project_id, attrs) end),
|
||||
get_publishing_preferences: zero_or_one_arg(fn _args -> publishing_preferences(project_id) end),
|
||||
get_publishing_preferences:
|
||||
zero_or_one_arg(fn _args -> publishing_preferences(project_id) end),
|
||||
get_tags: zero_or_one_arg(fn _args -> metadata_tags(project_id) end),
|
||||
remove_tag: one_arg(fn name -> remove_meta_tag(project_id, name) end),
|
||||
set_publishing_preferences: one_arg(fn prefs -> set_publishing_preferences(project_id, prefs) end),
|
||||
clear_publishing_preferences: zero_or_one_arg(fn _args -> clear_publishing_preferences(project_id) end),
|
||||
set_publishing_preferences:
|
||||
one_arg(fn prefs -> set_publishing_preferences(project_id, prefs) end),
|
||||
clear_publishing_preferences:
|
||||
zero_or_one_arg(fn _args -> clear_publishing_preferences(project_id) end),
|
||||
sync_on_startup: zero_or_one_arg(fn _args -> sync_meta_on_startup(project_id) end)
|
||||
},
|
||||
posts: %{
|
||||
create: one_arg(fn attrs -> create_post(project_id, attrs) end),
|
||||
discard: one_arg(fn post_id -> discard_post(project_id, post_id) end),
|
||||
filter: one_arg(fn filters -> filter_posts(project_id, filters) end),
|
||||
generate_unique_slug: two_arg(fn title, exclude_post_id -> generate_unique_post_slug(project_id, title, exclude_post_id) end),
|
||||
generate_unique_slug:
|
||||
two_arg(fn title, exclude_post_id ->
|
||||
generate_unique_post_slug(project_id, title, exclude_post_id)
|
||||
end),
|
||||
get_by_status: one_arg(fn status -> posts_by_status(project_id, status) end),
|
||||
get_by_year_month: zero_or_one_arg(fn _args -> post_counts_by_year_month(project_id) end),
|
||||
get_dashboard_stats: zero_or_one_arg(fn _args -> post_dashboard_stats(project_id) end),
|
||||
get_linked_by: one_arg(fn post_id -> linked_posts_for(project_id, post_id, :incoming) end),
|
||||
get_linked_by:
|
||||
one_arg(fn post_id -> linked_posts_for(project_id, post_id, :incoming) end),
|
||||
get_links_to: one_arg(fn post_id -> linked_posts_for(project_id, post_id, :outgoing) end),
|
||||
get_preview_url: two_arg(fn post_id, options -> preview_url(project_id, post_id, options) end),
|
||||
get_preview_url:
|
||||
two_arg(fn post_id, options -> preview_url(project_id, post_id, options) end),
|
||||
update: two_arg(fn post_id, attrs -> update_post(project_id, post_id, attrs) end),
|
||||
delete: one_arg(fn post_id -> delete_post(project_id, post_id) end),
|
||||
get: one_arg(fn post_id -> load_post(project_id, post_id) end),
|
||||
get_all: zero_or_one_arg(fn _args -> list_posts(project_id) end),
|
||||
get_by_slug: one_arg(fn slug -> load_post_by_slug(project_id, slug) end),
|
||||
get_categories: zero_or_one_arg(fn _args -> post_categories(project_id) end),
|
||||
get_categories_with_counts: zero_or_one_arg(fn _args -> post_categories_with_counts(project_id) end),
|
||||
get_categories_with_counts:
|
||||
zero_or_one_arg(fn _args -> post_categories_with_counts(project_id) end),
|
||||
get_tags: zero_or_one_arg(fn _args -> post_tags(project_id) end),
|
||||
get_tags_with_counts: zero_or_one_arg(fn _args -> post_tags_with_counts(project_id) end),
|
||||
get_translation: two_arg(fn post_id, language -> load_post_translation(project_id, post_id, language) end),
|
||||
get_translation:
|
||||
two_arg(fn post_id, language ->
|
||||
load_post_translation(project_id, post_id, language)
|
||||
end),
|
||||
get_translations: one_arg(fn post_id -> list_post_translations(project_id, post_id) end),
|
||||
has_published_version: one_arg(fn post_id -> has_published_post_version(project_id, post_id) end),
|
||||
is_slug_available: two_arg(fn slug, exclude_post_id -> post_slug_available?(project_id, slug, exclude_post_id) end),
|
||||
has_published_version:
|
||||
one_arg(fn post_id -> has_published_post_version(project_id, post_id) end),
|
||||
is_slug_available:
|
||||
two_arg(fn slug, exclude_post_id ->
|
||||
post_slug_available?(project_id, slug, exclude_post_id)
|
||||
end),
|
||||
publish: one_arg(fn post_id -> publish_post(project_id, post_id) end),
|
||||
publish_translation: two_arg(fn post_id, language -> publish_post_translation(project_id, post_id, language) end),
|
||||
publish_translation:
|
||||
two_arg(fn post_id, language ->
|
||||
publish_post_translation(project_id, post_id, language)
|
||||
end),
|
||||
rebuild_from_files: zero_or_one_arg(fn _args -> rebuild_posts_from_files(project_id) end),
|
||||
rebuild_links: zero_or_one_arg(fn _args -> rebuild_post_links(project_id) end),
|
||||
reindex_text: zero_or_one_arg(fn _args -> reindex_project_search(project_id) end),
|
||||
search: one_arg(fn query -> search_posts(project_id, query) end)
|
||||
},
|
||||
media: %{
|
||||
delete_translation: two_arg(fn media_id, language -> delete_media_translation(project_id, media_id, language) end),
|
||||
delete_translation:
|
||||
two_arg(fn media_id, language ->
|
||||
delete_media_translation(project_id, media_id, language)
|
||||
end),
|
||||
filter: one_arg(fn filters -> filter_media(project_id, filters) end),
|
||||
import: one_arg(fn attrs -> import_media(project_id, attrs) end),
|
||||
get_by_year_month: zero_or_one_arg(fn _args -> media_counts_by_year_month(project_id) end),
|
||||
get_by_year_month:
|
||||
zero_or_one_arg(fn _args -> media_counts_by_year_month(project_id) end),
|
||||
get_file_path: one_arg(fn media_id -> media_file_path(project_id, media_id) end),
|
||||
update: two_arg(fn media_id, attrs -> update_media(project_id, media_id, attrs) end),
|
||||
delete: one_arg(fn media_id -> delete_media(project_id, media_id) end),
|
||||
@@ -104,17 +133,30 @@ defmodule BDS.Scripting.Capabilities do
|
||||
get_all: zero_or_one_arg(fn _args -> list_media(project_id) end),
|
||||
get_tags: zero_or_one_arg(fn _args -> media_tags(project_id) end),
|
||||
get_tags_with_counts: zero_or_one_arg(fn _args -> media_tags_with_counts(project_id) end),
|
||||
get_thumbnail: two_arg(fn media_id, size -> media_thumbnail(project_id, media_id, size) end),
|
||||
get_translation: two_arg(fn media_id, language -> load_media_translation(project_id, media_id, language) end),
|
||||
get_translations: one_arg(fn media_id -> list_media_translations(project_id, media_id) end),
|
||||
get_thumbnail:
|
||||
two_arg(fn media_id, size -> media_thumbnail(project_id, media_id, size) end),
|
||||
get_translation:
|
||||
two_arg(fn media_id, language ->
|
||||
load_media_translation(project_id, media_id, language)
|
||||
end),
|
||||
get_translations:
|
||||
one_arg(fn media_id -> list_media_translations(project_id, media_id) end),
|
||||
get_url: one_arg(fn media_id -> media_url(project_id, media_id) end),
|
||||
rebuild_from_files: zero_or_one_arg(fn _args -> rebuild_media_from_files(project_id) end),
|
||||
regenerate_missing_thumbnails: zero_or_one_arg(fn _args -> regenerate_missing_thumbnails(project_id) end),
|
||||
regenerate_thumbnails: one_arg(fn media_id -> regenerate_media_thumbnails(project_id, media_id) end),
|
||||
regenerate_missing_thumbnails:
|
||||
zero_or_one_arg(fn _args -> regenerate_missing_thumbnails(project_id) end),
|
||||
regenerate_thumbnails:
|
||||
one_arg(fn media_id -> regenerate_media_thumbnails(project_id, media_id) end),
|
||||
reindex_text: zero_or_one_arg(fn _args -> reindex_project_search(project_id) end),
|
||||
replace_file: two_arg(fn media_id, source_path -> replace_media_file(project_id, media_id, source_path) end),
|
||||
replace_file:
|
||||
two_arg(fn media_id, source_path ->
|
||||
replace_media_file(project_id, media_id, source_path)
|
||||
end),
|
||||
search: one_arg(fn query -> search_media(project_id, query) end),
|
||||
upsert_translation: three_arg(fn media_id, language, attrs -> upsert_media_translation(project_id, media_id, language, attrs) end)
|
||||
upsert_translation:
|
||||
three_arg(fn media_id, language, attrs ->
|
||||
upsert_media_translation(project_id, media_id, language, attrs)
|
||||
end)
|
||||
},
|
||||
scripts: %{
|
||||
create: one_arg(fn attrs -> create_script(project_id, attrs) end),
|
||||
@@ -123,17 +165,20 @@ defmodule BDS.Scripting.Capabilities do
|
||||
get: one_arg(fn script_id -> load_script(project_id, script_id) end),
|
||||
get_all: zero_or_one_arg(fn _args -> list_scripts(project_id) end),
|
||||
publish: one_arg(fn script_id -> publish_script(project_id, script_id) end),
|
||||
rebuild_from_files: zero_or_one_arg(fn _args -> rebuild_scripts_from_files(project_id) end)
|
||||
rebuild_from_files:
|
||||
zero_or_one_arg(fn _args -> rebuild_scripts_from_files(project_id) end)
|
||||
},
|
||||
templates: %{
|
||||
create: one_arg(fn attrs -> create_template(project_id, attrs) end),
|
||||
update: two_arg(fn template_id, attrs -> update_template(project_id, template_id, attrs) end),
|
||||
update:
|
||||
two_arg(fn template_id, attrs -> update_template(project_id, template_id, attrs) end),
|
||||
delete: one_arg(fn template_id -> delete_template(project_id, template_id) end),
|
||||
get: one_arg(fn template_id -> load_template(project_id, template_id) end),
|
||||
get_all: zero_or_one_arg(fn _args -> list_templates(project_id) end),
|
||||
publish: one_arg(fn template_id -> publish_template(project_id, template_id) end),
|
||||
get_enabled_by_kind: one_arg(fn kind -> list_enabled_templates(project_id, kind) end),
|
||||
rebuild_from_files: zero_or_one_arg(fn _args -> rebuild_templates_from_files(project_id) end),
|
||||
rebuild_from_files:
|
||||
zero_or_one_arg(fn _args -> rebuild_templates_from_files(project_id) end),
|
||||
validate: one_arg(fn source -> validate_template_source(source) end)
|
||||
},
|
||||
tags: %{
|
||||
@@ -145,7 +190,10 @@ defmodule BDS.Scripting.Capabilities do
|
||||
get_by_name: one_arg(fn tag_name -> load_tag_by_name(project_id, tag_name) end),
|
||||
get_posts_with_tag: one_arg(fn tag_id -> tag_post_ids(project_id, tag_id) end),
|
||||
get_with_counts: zero_or_one_arg(fn _args -> tags_with_counts(project_id) end),
|
||||
merge: two_arg(fn source_tag_ids, target_tag_id -> merge_tags(project_id, source_tag_ids, target_tag_id) end),
|
||||
merge:
|
||||
two_arg(fn source_tag_ids, target_tag_id ->
|
||||
merge_tags(project_id, source_tag_ids, target_tag_id)
|
||||
end),
|
||||
rename: two_arg(fn tag_id, new_name -> rename_tag(project_id, tag_id, new_name) end),
|
||||
sync_from_posts: zero_or_one_arg(fn _args -> sync_tags_from_posts(project_id) end)
|
||||
},
|
||||
@@ -172,23 +220,30 @@ defmodule BDS.Scripting.Capabilities do
|
||||
upload_site: one_arg(fn credentials -> upload_site(project_id, credentials, opts) end)
|
||||
},
|
||||
chat: %{
|
||||
detect_post_language: two_arg(fn title, content -> detect_post_language(title, content, opts) end),
|
||||
detect_post_language:
|
||||
two_arg(fn title, content -> detect_post_language(title, content, opts) end),
|
||||
analyze_post: one_arg(fn post_id -> analyze_post(post_id, opts) end),
|
||||
translate_post: two_arg(fn post_id, language -> translate_post(post_id, language, opts) end),
|
||||
translate_post:
|
||||
two_arg(fn post_id, language -> translate_post(post_id, language, opts) end),
|
||||
analyze_media_image: one_arg(fn media_id -> analyze_media_image(media_id, opts) end),
|
||||
detect_media_language: three_arg(fn title, alt, caption -> detect_media_language(title, alt, caption, opts) end),
|
||||
translate_media_metadata: two_arg(fn media_id, language -> translate_media_metadata(media_id, language, opts) end)
|
||||
detect_media_language:
|
||||
three_arg(fn title, alt, caption ->
|
||||
detect_media_language(title, alt, caption, opts)
|
||||
end),
|
||||
translate_media_metadata:
|
||||
two_arg(fn media_id, language -> translate_media_metadata(media_id, language, opts) end)
|
||||
},
|
||||
embeddings: %{
|
||||
get_progress: zero_or_one_arg(fn _args -> embedding_progress(project_id) end),
|
||||
find_similar: two_arg(fn post_id, limit -> find_similar(post_id, limit) end),
|
||||
compute_similarities: two_arg(fn post_id, target_ids -> compute_similarities(post_id, target_ids) end),
|
||||
suggest_tags: two_arg(fn post_id, exclude_tags -> suggest_tags(post_id, exclude_tags) end),
|
||||
compute_similarities:
|
||||
two_arg(fn post_id, target_ids -> compute_similarities(post_id, target_ids) end),
|
||||
suggest_tags:
|
||||
two_arg(fn post_id, exclude_tags -> suggest_tags(post_id, exclude_tags) end),
|
||||
find_duplicates: zero_or_one_arg(fn _args -> find_duplicates(project_id) end),
|
||||
dismiss_pair: two_arg(fn post_id_a, post_id_b -> dismiss_pair(post_id_a, post_id_b) end),
|
||||
index_unindexed_posts: zero_or_one_arg(fn _args -> index_unindexed_posts(project_id) end)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -22,9 +22,23 @@ defmodule BDS.Scripting.Capabilities.AppShell do
|
||||
command = string_or_nil(text)
|
||||
|
||||
case :os.type() do
|
||||
{:unix, :darwin} -> match?({_output, 0}, System.cmd("pbcopy", [], input: command, stderr_to_stdout: true))
|
||||
{:unix, _other} -> match?({_output, 0}, System.cmd("xclip", ["-selection", "clipboard"], input: command, stderr_to_stdout: true))
|
||||
{:win32, _other} -> match?({_output, 0}, System.cmd("cmd", ["/c", "clip"], input: command, stderr_to_stdout: true))
|
||||
{:unix, :darwin} ->
|
||||
match?({_output, 0}, System.cmd("pbcopy", [], input: command, stderr_to_stdout: true))
|
||||
|
||||
{:unix, _other} ->
|
||||
match?(
|
||||
{_output, 0},
|
||||
System.cmd("xclip", ["-selection", "clipboard"],
|
||||
input: command,
|
||||
stderr_to_stdout: true
|
||||
)
|
||||
)
|
||||
|
||||
{:win32, _other} ->
|
||||
match?(
|
||||
{_output, 0},
|
||||
System.cmd("cmd", ["/c", "clip"], input: command, stderr_to_stdout: true)
|
||||
)
|
||||
end
|
||||
end
|
||||
rescue
|
||||
@@ -94,7 +108,11 @@ defmodule BDS.Scripting.Capabilities.AppShell do
|
||||
end
|
||||
|
||||
def set_preview_post_target(post_id) do
|
||||
:persistent_term.put({BDS.Scripting.Capabilities, :preview_post_target}, string_or_nil(post_id))
|
||||
:persistent_term.put(
|
||||
{BDS.Scripting.Capabilities, :preview_post_target},
|
||||
string_or_nil(post_id)
|
||||
)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
@@ -98,7 +98,11 @@ defmodule BDS.Scripting.Capabilities.Bridges do
|
||||
end
|
||||
|
||||
def detect_media_language(title, alt, caption, opts) do
|
||||
text = Enum.join([string_or_nil(title) || "", string_or_nil(alt) || "", string_or_nil(caption) || ""], "\n")
|
||||
text =
|
||||
Enum.join(
|
||||
[string_or_nil(title) || "", string_or_nil(alt) || "", string_or_nil(caption) || ""],
|
||||
"\n"
|
||||
)
|
||||
|
||||
case AI.detect_language(text, ai_opts(opts)) do
|
||||
{:ok, %{language_code: language_code}} -> %{"success" => true, "language" => language_code}
|
||||
@@ -125,7 +129,8 @@ defmodule BDS.Scripting.Capabilities.Bridges do
|
||||
|
||||
# --- Embeddings ---
|
||||
|
||||
def embedding_progress(project_id), do: project_id |> Embeddings.get_indexing_progress() |> unwrap_result()
|
||||
def embedding_progress(project_id),
|
||||
do: project_id |> Embeddings.get_indexing_progress() |> unwrap_result()
|
||||
|
||||
def find_similar(post_id, limit) do
|
||||
post_id
|
||||
@@ -148,9 +153,21 @@ defmodule BDS.Scripting.Capabilities.Bridges do
|
||||
|> unwrap_result()
|
||||
end
|
||||
|
||||
def find_duplicates(project_id), do: project_id |> Embeddings.find_duplicates() |> unwrap_result()
|
||||
def dismiss_pair(post_id_a, post_id_b), do: atom_result(Embeddings.dismiss_duplicate_pair(string_or_nil(post_id_a) || "", string_or_nil(post_id_b) || ""), :ok)
|
||||
def index_unindexed_posts(project_id), do: project_id |> Embeddings.index_unindexed() |> unwrap_result()
|
||||
def find_duplicates(project_id),
|
||||
do: project_id |> Embeddings.find_duplicates() |> unwrap_result()
|
||||
|
||||
def dismiss_pair(post_id_a, post_id_b),
|
||||
do:
|
||||
atom_result(
|
||||
Embeddings.dismiss_duplicate_pair(
|
||||
string_or_nil(post_id_a) || "",
|
||||
string_or_nil(post_id_b) || ""
|
||||
),
|
||||
:ok
|
||||
)
|
||||
|
||||
def index_unindexed_posts(project_id),
|
||||
do: project_id |> Embeddings.index_unindexed() |> unwrap_result()
|
||||
|
||||
# --- Opt builders ---
|
||||
|
||||
|
||||
@@ -47,7 +47,10 @@ defmodule BDS.Scripting.Capabilities.Crud do
|
||||
|
||||
def list_scripts(project_id) do
|
||||
Repo.all(
|
||||
from(script in Script, where: script.project_id == ^project_id, order_by: [asc: script.created_at])
|
||||
from(script in Script,
|
||||
where: script.project_id == ^project_id,
|
||||
order_by: [asc: script.created_at]
|
||||
)
|
||||
)
|
||||
|> Enum.map(&sanitize/1)
|
||||
end
|
||||
@@ -68,7 +71,8 @@ defmodule BDS.Scripting.Capabilities.Crud do
|
||||
def fetch_script(project_id, script_id) do
|
||||
Repo.one(
|
||||
from(script in Script,
|
||||
where: script.project_id == ^project_id and script.id == ^(string_or_nil(script_id) || ""),
|
||||
where:
|
||||
script.project_id == ^project_id and script.id == ^(string_or_nil(script_id) || ""),
|
||||
limit: 1
|
||||
)
|
||||
)
|
||||
@@ -86,8 +90,11 @@ defmodule BDS.Scripting.Capabilities.Crud do
|
||||
|
||||
def update_template(project_id, template_id, attrs) do
|
||||
case fetch_template(project_id, template_id) do
|
||||
%Template{} -> Templates.update_template(template_id, normalize_map(attrs)) |> unwrap_result()
|
||||
_other -> nil
|
||||
%Template{} ->
|
||||
Templates.update_template(template_id, normalize_map(attrs)) |> unwrap_result()
|
||||
|
||||
_other ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -105,7 +112,10 @@ defmodule BDS.Scripting.Capabilities.Crud do
|
||||
|
||||
def list_templates(project_id) do
|
||||
Repo.all(
|
||||
from(template in Template, where: template.project_id == ^project_id, order_by: [asc: template.created_at])
|
||||
from(template in Template,
|
||||
where: template.project_id == ^project_id,
|
||||
order_by: [asc: template.created_at]
|
||||
)
|
||||
)
|
||||
|> Enum.map(&sanitize/1)
|
||||
end
|
||||
@@ -146,7 +156,9 @@ defmodule BDS.Scripting.Capabilities.Crud do
|
||||
def fetch_template(project_id, template_id) do
|
||||
Repo.one(
|
||||
from(template in Template,
|
||||
where: template.project_id == ^project_id and template.id == ^(string_or_nil(template_id) || ""),
|
||||
where:
|
||||
template.project_id == ^project_id and
|
||||
template.id == ^(string_or_nil(template_id) || ""),
|
||||
limit: 1
|
||||
)
|
||||
)
|
||||
@@ -233,8 +245,14 @@ defmodule BDS.Scripting.Capabilities.Crud do
|
||||
|
||||
def merge_tags(project_id, source_tag_ids, target_tag_id) do
|
||||
case fetch_tag(project_id, target_tag_id) do
|
||||
%Tag{} -> atom_result(Tags.merge_tags(normalize_string_list(source_tag_ids), target_tag_id), :merged)
|
||||
_other -> false
|
||||
%Tag{} ->
|
||||
atom_result(
|
||||
Tags.merge_tags(normalize_string_list(source_tag_ids), target_tag_id),
|
||||
:merged
|
||||
)
|
||||
|
||||
_other ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -21,8 +21,12 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
|
||||
def update_media(project_id, media_id, attrs) do
|
||||
case fetch_media(project_id, media_id) do
|
||||
%MediaRecord{} -> Media.update_media(media_id, attrs |> normalize_map() |> normalize_media_attrs()) |> unwrap_result()
|
||||
_other -> nil
|
||||
%MediaRecord{} ->
|
||||
Media.update_media(media_id, attrs |> normalize_map() |> normalize_media_attrs())
|
||||
|> unwrap_result()
|
||||
|
||||
_other ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,7 +44,10 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
|
||||
def list_media(project_id) do
|
||||
Repo.all(
|
||||
from(media in MediaRecord, where: media.project_id == ^project_id, order_by: [asc: media.created_at])
|
||||
from(media in MediaRecord,
|
||||
where: media.project_id == ^project_id,
|
||||
order_by: [asc: media.created_at]
|
||||
)
|
||||
)
|
||||
|> Enum.map(&sanitize/1)
|
||||
end
|
||||
@@ -82,7 +89,11 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
def upsert_media_translation(project_id, media_id, language, attrs) do
|
||||
case fetch_media(project_id, media_id) do
|
||||
%MediaRecord{} ->
|
||||
Media.upsert_media_translation(media_id, string_or_nil(language) || "", normalize_media_translation_attrs(normalize_map(attrs)))
|
||||
Media.upsert_media_translation(
|
||||
media_id,
|
||||
string_or_nil(language) || "",
|
||||
normalize_media_translation_attrs(normalize_map(attrs))
|
||||
)
|
||||
|> unwrap_result()
|
||||
|
||||
_other ->
|
||||
@@ -117,7 +128,9 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
key = {datetime.year, datetime.month}
|
||||
Map.update(acc, key, 1, &(&1 + 1))
|
||||
end)
|
||||
|> Enum.map(fn {{year, month}, count} -> %{"year" => year, "month" => month, "count" => count} end)
|
||||
|> Enum.map(fn {{year, month}, count} ->
|
||||
%{"year" => year, "month" => month, "count" => count}
|
||||
end)
|
||||
|> Enum.sort_by(fn row -> {-row["year"], -row["month"]} end)
|
||||
end
|
||||
|
||||
@@ -131,7 +144,12 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
def media_tags(project_id), do: media_tags_with_counts(project_id) |> Enum.map(& &1["tag"])
|
||||
|
||||
def media_tags_with_counts(project_id) do
|
||||
Repo.all(from(media in MediaRecord, where: media.project_id == ^project_id, order_by: [asc: media.created_at]))
|
||||
Repo.all(
|
||||
from(media in MediaRecord,
|
||||
where: media.project_id == ^project_id,
|
||||
order_by: [asc: media.created_at]
|
||||
)
|
||||
)
|
||||
|> Enum.flat_map(&(&1.tags || []))
|
||||
|> Enum.reduce(%{}, fn tag, acc -> Map.update(acc, tag, 1, &(&1 + 1)) end)
|
||||
|> Enum.map(fn {tag, count} -> %{"tag" => tag, "count" => count} end)
|
||||
@@ -174,7 +192,9 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
case Media.regenerate_thumbnails(media.id) do
|
||||
{:ok, _media} ->
|
||||
Media.thumbnail_paths(media)
|
||||
|> Enum.map(fn {size, relative_path} -> {to_string(size), Path.join(project_path(project_id), relative_path)} end)
|
||||
|> Enum.map(fn {size, relative_path} ->
|
||||
{to_string(size), Path.join(project_path(project_id), relative_path)}
|
||||
end)
|
||||
|> Map.new()
|
||||
|
||||
{:error, _reason} ->
|
||||
@@ -227,14 +247,40 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
tags = Map.get(media, "tags", [])
|
||||
language = Map.get(media, "language")
|
||||
|
||||
matches_year = compare_optional(Map.get(filters, "year"), fn year -> created_at.year == integer_or_default(year, created_at.year) end)
|
||||
matches_month = compare_optional(Map.get(filters, "month"), fn month -> created_at.month == integer_or_default(month, created_at.month) end)
|
||||
matches_language = compare_optional(blank_to_nil(Map.get(filters, "language")), fn value -> language == value end)
|
||||
matches_tags = compare_optional(Map.get(filters, "tags"), fn required_tags -> Enum.all?(normalize_string_list(required_tags), &(&1 in tags)) end)
|
||||
matches_from = compare_optional(parse_datetime(Map.get(filters, "from") || Map.get(filters, "start_date")), fn from_dt -> DateTime.compare(created_at, from_dt) != :lt end)
|
||||
matches_to = compare_optional(parse_datetime(Map.get(filters, "to") || Map.get(filters, "end_date")), fn to_dt -> DateTime.compare(created_at, to_dt) != :gt end)
|
||||
matches_year =
|
||||
compare_optional(Map.get(filters, "year"), fn year ->
|
||||
created_at.year == integer_or_default(year, created_at.year)
|
||||
end)
|
||||
|
||||
matches_year and matches_month and matches_language and matches_tags and matches_from and matches_to
|
||||
matches_month =
|
||||
compare_optional(Map.get(filters, "month"), fn month ->
|
||||
created_at.month == integer_or_default(month, created_at.month)
|
||||
end)
|
||||
|
||||
matches_language =
|
||||
compare_optional(blank_to_nil(Map.get(filters, "language")), fn value ->
|
||||
language == value
|
||||
end)
|
||||
|
||||
matches_tags =
|
||||
compare_optional(Map.get(filters, "tags"), fn required_tags ->
|
||||
Enum.all?(normalize_string_list(required_tags), &(&1 in tags))
|
||||
end)
|
||||
|
||||
matches_from =
|
||||
compare_optional(
|
||||
parse_datetime(Map.get(filters, "from") || Map.get(filters, "start_date")),
|
||||
fn from_dt -> DateTime.compare(created_at, from_dt) != :lt end
|
||||
)
|
||||
|
||||
matches_to =
|
||||
compare_optional(
|
||||
parse_datetime(Map.get(filters, "to") || Map.get(filters, "end_date")),
|
||||
fn to_dt -> DateTime.compare(created_at, to_dt) != :gt end
|
||||
)
|
||||
|
||||
matches_year and matches_month and matches_language and matches_tags and matches_from and
|
||||
matches_to
|
||||
end
|
||||
|
||||
def media_datetime(media) do
|
||||
@@ -247,8 +293,11 @@ defmodule BDS.Scripting.Capabilities.Media do
|
||||
_other -> DateTime.utc_now()
|
||||
end
|
||||
|
||||
value when is_integer(value) -> DateTime.from_unix!(value, :millisecond)
|
||||
_other -> DateTime.utc_now()
|
||||
value when is_integer(value) ->
|
||||
DateTime.from_unix!(value, :millisecond)
|
||||
|
||||
_other ->
|
||||
DateTime.utc_now()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,8 +22,11 @@ defmodule BDS.Scripting.Capabilities.Posts do
|
||||
|
||||
def update_post(project_id, post_id, attrs) do
|
||||
case fetch_post(project_id, post_id) do
|
||||
%Post{} -> Posts.update_post(post_id, normalize_map(attrs)) |> unwrap_result(&post_payload/1)
|
||||
_other -> nil
|
||||
%Post{} ->
|
||||
Posts.update_post(post_id, normalize_map(attrs)) |> unwrap_result(&post_payload/1)
|
||||
|
||||
_other ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +45,9 @@ defmodule BDS.Scripting.Capabilities.Posts do
|
||||
end
|
||||
|
||||
def list_posts(project_id) do
|
||||
Repo.all(from(post in Post, where: post.project_id == ^project_id, order_by: [asc: post.created_at]))
|
||||
Repo.all(
|
||||
from(post in Post, where: post.project_id == ^project_id, order_by: [asc: post.created_at])
|
||||
)
|
||||
|> Enum.map(&post_payload/1)
|
||||
end
|
||||
|
||||
@@ -80,13 +85,19 @@ defmodule BDS.Scripting.Capabilities.Posts do
|
||||
end
|
||||
|
||||
def generate_unique_post_slug(project_id, title, exclude_post_id) do
|
||||
Posts.unique_slug_for_title(project_id, string_or_nil(title) || "", string_or_nil(exclude_post_id))
|
||||
Posts.unique_slug_for_title(
|
||||
project_id,
|
||||
string_or_nil(title) || "",
|
||||
string_or_nil(exclude_post_id)
|
||||
)
|
||||
end
|
||||
|
||||
def posts_by_status(project_id, status) do
|
||||
normalized_status = string_or_nil(status) || ""
|
||||
|
||||
Repo.all(from(post in Post, where: post.project_id == ^project_id, order_by: [asc: post.created_at]))
|
||||
Repo.all(
|
||||
from(post in Post, where: post.project_id == ^project_id, order_by: [asc: post.created_at])
|
||||
)
|
||||
|> Enum.filter(&(to_string(&1.status) == normalized_status))
|
||||
|> Enum.map(&post_payload/1)
|
||||
end
|
||||
@@ -143,8 +154,11 @@ defmodule BDS.Scripting.Capabilities.Posts do
|
||||
|
||||
def publish_post_translation(project_id, post_id, language) do
|
||||
case fetch_post(project_id, post_id) do
|
||||
%Post{} -> Posts.publish_post_translation(post_id, string_or_nil(language) || "") |> unwrap_result()
|
||||
_other -> nil
|
||||
%Post{} ->
|
||||
Posts.publish_post_translation(post_id, string_or_nil(language) || "") |> unwrap_result()
|
||||
|
||||
_other ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -174,7 +188,10 @@ defmodule BDS.Scripting.Capabilities.Posts do
|
||||
|
||||
def post_tags(project_id), do: names_with_counts(project_id, :tags) |> Enum.map(& &1["name"])
|
||||
def post_tags_with_counts(project_id), do: names_with_counts(project_id, :tags)
|
||||
def post_categories(project_id), do: names_with_counts(project_id, :categories) |> Enum.map(& &1["name"])
|
||||
|
||||
def post_categories(project_id),
|
||||
do: names_with_counts(project_id, :categories) |> Enum.map(& &1["name"])
|
||||
|
||||
def post_categories_with_counts(project_id), do: names_with_counts(project_id, :categories)
|
||||
|
||||
def list_post_translations(project_id, post_id) do
|
||||
@@ -209,9 +226,14 @@ defmodule BDS.Scripting.Capabilities.Posts do
|
||||
|
||||
def has_published_post_version(project_id, post_id) do
|
||||
case fetch_post(project_id, post_id) do
|
||||
%Post{status: :published} -> true
|
||||
%Post{published_at: published_at, file_path: file_path} -> not is_nil(published_at) or file_path not in [nil, ""]
|
||||
_other -> false
|
||||
%Post{status: :published} ->
|
||||
true
|
||||
|
||||
%Post{published_at: published_at, file_path: file_path} ->
|
||||
not is_nil(published_at) or file_path not in [nil, ""]
|
||||
|
||||
_other ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -10,9 +10,11 @@ defmodule BDS.Scripting.Capabilities.Projects do
|
||||
alias BDS.Repo
|
||||
alias BDS.Tags
|
||||
|
||||
def create_project(attrs), do: attrs |> normalize_map() |> ProjectsCtx.create_project() |> unwrap_result()
|
||||
def create_project(attrs),
|
||||
do: attrs |> normalize_map() |> ProjectsCtx.create_project() |> unwrap_result()
|
||||
|
||||
def delete_project(project_id), do: boolean_result(ProjectsCtx.delete_project(string_or_nil(project_id)))
|
||||
def delete_project(project_id),
|
||||
do: boolean_result(ProjectsCtx.delete_project(string_or_nil(project_id)))
|
||||
|
||||
def delete_project_with_data(project_id) do
|
||||
case string_or_nil(project_id) && ProjectsCtx.get_project(string_or_nil(project_id)) do
|
||||
@@ -113,8 +115,12 @@ defmodule BDS.Scripting.Capabilities.Projects do
|
||||
normalized_name = string_or_nil(name) |> to_string() |> String.trim()
|
||||
|
||||
cond do
|
||||
normalized_name == "" -> metadata_tags(project_id)
|
||||
load_tag_by_name(project_id, normalized_name) -> metadata_tags(project_id)
|
||||
normalized_name == "" ->
|
||||
metadata_tags(project_id)
|
||||
|
||||
load_tag_by_name(project_id, normalized_name) ->
|
||||
metadata_tags(project_id)
|
||||
|
||||
true ->
|
||||
create_tag(project_id, %{"name" => normalized_name})
|
||||
metadata_tags(project_id)
|
||||
|
||||
@@ -46,7 +46,13 @@ defmodule BDS.Scripting.Capabilities.Util do
|
||||
end
|
||||
|
||||
def normalize_input(list) when is_list(list) do
|
||||
if Enum.all?(list, &match?({key, _value} when is_integer(key) or is_float(key) or is_binary(key) or is_atom(key), &1)) do
|
||||
if Enum.all?(
|
||||
list,
|
||||
&match?(
|
||||
{key, _value} when is_integer(key) or is_float(key) or is_binary(key) or is_atom(key),
|
||||
&1
|
||||
)
|
||||
) do
|
||||
normalized =
|
||||
Map.new(list, fn {key, value} -> {normalize_input_key(key), normalize_input(value)} end)
|
||||
|
||||
|
||||
@@ -85,7 +85,8 @@ defmodule BDS.Scripting.Lua do
|
||||
|
||||
defp install_capability(path, value, state) when is_map(value) do
|
||||
with {:ok, seeded_state} <- set_capability(path, %{}, state) do
|
||||
Enum.reduce_while(value, {:ok, seeded_state}, fn {name, nested_value}, {:ok, current_state} ->
|
||||
Enum.reduce_while(value, {:ok, seeded_state}, fn {name, nested_value},
|
||||
{:ok, current_state} ->
|
||||
case install_capability(path ++ [to_string(name)], nested_value, current_state) do
|
||||
{:ok, next_state} -> {:cont, {:ok, next_state}}
|
||||
{:error, reason} -> {:halt, {:error, reason}}
|
||||
@@ -142,7 +143,10 @@ defmodule BDS.Scripting.Lua do
|
||||
defp sandbox_run(script, flags, state), do: apply(:luerl_sandbox, :run, [script, flags, state])
|
||||
|
||||
defp normalize_sandbox_result({:ok, result, next_state}), do: {:ok, result, next_state}
|
||||
defp normalize_sandbox_result({:error, {:reductions, count}}), do: {:error, {:reductions_exceeded, count}}
|
||||
|
||||
defp normalize_sandbox_result({:error, {:reductions, count}}),
|
||||
do: {:error, {:reductions_exceeded, count}}
|
||||
|
||||
defp normalize_sandbox_result({:error, :timeout}), do: {:error, :timeout}
|
||||
defp normalize_sandbox_result({:error, reason}), do: {:error, reason}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user