Source title regex filtering (#98)
* Added a basic/advanced mode to source form * Added regex field and UI to source form * Implemented title regex filtering
This commit is contained in:
parent
087c9c2d0f
commit
3db2e8190f
33 changed files with 95 additions and 11 deletions
|
|
@ -25,6 +25,21 @@ config :pinchflat,
|
||||||
basic_auth_username: System.get_env("BASIC_AUTH_USERNAME"),
|
basic_auth_username: System.get_env("BASIC_AUTH_USERNAME"),
|
||||||
basic_auth_password: System.get_env("BASIC_AUTH_PASSWORD")
|
basic_auth_password: System.get_env("BASIC_AUTH_PASSWORD")
|
||||||
|
|
||||||
|
arch_string = to_string(:erlang.system_info(:system_architecture))
|
||||||
|
|
||||||
|
system_arch =
|
||||||
|
cond do
|
||||||
|
String.contains?(arch_string, "arm") -> "arm"
|
||||||
|
String.contains?(arch_string, "aarch") -> "arm"
|
||||||
|
String.contains?(arch_string, "x86") -> "x86"
|
||||||
|
true -> "unknown"
|
||||||
|
end
|
||||||
|
|
||||||
|
config :pinchflat, Pinchflat.Repo,
|
||||||
|
load_extensions: [
|
||||||
|
Path.join([:code.priv_dir(:pinchflat), "repo", "extensions", "sqlean-linux-#{system_arch}", "sqlean"])
|
||||||
|
]
|
||||||
|
|
||||||
if config_env() == :prod do
|
if config_env() == :prod do
|
||||||
config_path =
|
config_path =
|
||||||
System.get_env("CONFIG_PATH") ||
|
System.get_env("CONFIG_PATH") ||
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ defmodule Pinchflat.Media do
|
||||||
|> where([mi], mi.source_id == ^source.id and is_nil(mi.media_filepath))
|
|> where([mi], mi.source_id == ^source.id and is_nil(mi.media_filepath))
|
||||||
|> where(^build_format_clauses(media_profile))
|
|> where(^build_format_clauses(media_profile))
|
||||||
|> where(^maybe_apply_cutoff_date(source))
|
|> where(^maybe_apply_cutoff_date(source))
|
||||||
|
|> where(^maybe_apply_title_regex(source))
|
||||||
|> Repo.maybe_limit(limit)
|
|> Repo.maybe_limit(limit)
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
@ -247,6 +248,14 @@ defmodule Pinchflat.Media do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp maybe_apply_title_regex(source) do
|
||||||
|
if source.title_filter_regex do
|
||||||
|
dynamic([mi], fragment("regexp_like(?, ?)", mi.title, ^source.title_filter_regex))
|
||||||
|
else
|
||||||
|
dynamic(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp build_format_clauses(media_profile) do
|
defp build_format_clauses(media_profile) do
|
||||||
mapped_struct = Map.from_struct(media_profile)
|
mapped_struct = Map.from_struct(media_profile)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ defmodule Pinchflat.Sources.Source do
|
||||||
last_indexed_at
|
last_indexed_at
|
||||||
original_url
|
original_url
|
||||||
download_cutoff_date
|
download_cutoff_date
|
||||||
|
title_filter_regex
|
||||||
media_profile_id
|
media_profile_id
|
||||||
)a
|
)a
|
||||||
|
|
||||||
|
|
@ -57,11 +58,6 @@ defmodule Pinchflat.Sources.Source do
|
||||||
field :collection_name, :string
|
field :collection_name, :string
|
||||||
field :collection_id, :string
|
field :collection_id, :string
|
||||||
field :collection_type, Ecto.Enum, values: [:channel, :playlist]
|
field :collection_type, Ecto.Enum, values: [:channel, :playlist]
|
||||||
field :nfo_filepath, :string
|
|
||||||
field :poster_filepath, :string
|
|
||||||
field :fanart_filepath, :string
|
|
||||||
field :banner_filepath, :string
|
|
||||||
field :series_directory, :string
|
|
||||||
field :index_frequency_minutes, :integer, default: 60 * 24
|
field :index_frequency_minutes, :integer, default: 60 * 24
|
||||||
field :fast_index, :boolean, default: false
|
field :fast_index, :boolean, default: false
|
||||||
field :download_media, :boolean, default: true
|
field :download_media, :boolean, default: true
|
||||||
|
|
@ -69,6 +65,13 @@ defmodule Pinchflat.Sources.Source do
|
||||||
# Only download media items that were published after this date
|
# Only download media items that were published after this date
|
||||||
field :download_cutoff_date, :date
|
field :download_cutoff_date, :date
|
||||||
field :original_url, :string
|
field :original_url, :string
|
||||||
|
field :title_filter_regex, :string
|
||||||
|
|
||||||
|
field :series_directory, :string
|
||||||
|
field :nfo_filepath, :string
|
||||||
|
field :poster_filepath, :string
|
||||||
|
field :fanart_filepath, :string
|
||||||
|
field :banner_filepath, :string
|
||||||
|
|
||||||
belongs_to :media_profile, MediaProfile
|
belongs_to :media_profile, MediaProfile
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<.button class="my-10 sm:mb-7.5 w-full sm:w-auto">Save Media profile</.button>
|
<.button class="my-10 sm:mb-7.5 w-full sm:w-auto" rounding="rounded-lg">Save Media profile</.button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="rounded-sm dark:bg-meta-4 p-4 md:p-6 mb-5">
|
<div class="rounded-sm dark:bg-meta-4 p-4 md:p-6 mb-5">
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,22 @@
|
||||||
<.simple_form :let={f} for={@changeset} action={@action}>
|
<.simple_form
|
||||||
|
:let={f}
|
||||||
|
for={@changeset}
|
||||||
|
action={@action}
|
||||||
|
x-data="{ advancedMode: !!JSON.parse(localStorage.getItem('advancedMode')) }"
|
||||||
|
x-init="$watch('advancedMode', value => localStorage.setItem('advancedMode', JSON.stringify(value)))"
|
||||||
|
>
|
||||||
<.error :if={@changeset.action}>
|
<.error :if={@changeset.action}>
|
||||||
Oops, something went wrong! Please check the errors below.
|
Oops, something went wrong! Please check the errors below.
|
||||||
</.error>
|
</.error>
|
||||||
|
|
||||||
<h3 class="mt-8 text-2xl text-black dark:text-white">
|
<section class="flex justify-between items-center mt-8">
|
||||||
General Options
|
<h3 class=" text-2xl text-black dark:text-white">
|
||||||
</h3>
|
General Options
|
||||||
|
</h3>
|
||||||
|
<span class="cursor-pointer hover:underline" x-on:click="advancedMode = !advancedMode">
|
||||||
|
Editing Mode: <span x-text="advancedMode ? 'Advanced' : 'Basic'"></span>
|
||||||
|
</span>
|
||||||
|
</section>
|
||||||
|
|
||||||
<.input
|
<.input
|
||||||
field={f[:custom_name]}
|
field={f[:custom_name]}
|
||||||
|
|
@ -69,7 +80,24 @@
|
||||||
help="Only download media uploaded after this date. Leave blank to download all media. Must be in YYYY-MM-DD format"
|
help="Only download media uploaded after this date. Leave blank to download all media. Must be in YYYY-MM-DD format"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<.button class="my-10 sm:mb-7.5 w-full sm:w-auto">Save Source</.button>
|
<section x-show="advancedMode">
|
||||||
|
<h3 class="mt-8 text-2xl text-black dark:text-white">
|
||||||
|
Advanced Options
|
||||||
|
</h3>
|
||||||
|
<p class="text-sm mt-2">
|
||||||
|
Tread carefully
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<.input
|
||||||
|
field={f[:title_filter_regex]}
|
||||||
|
type="text"
|
||||||
|
label="Title Filter Regex"
|
||||||
|
placeholder="(?i)^How to Bike$"
|
||||||
|
help="A PCRE-compatible regex. Only media with titles that match this regex will be downloaded. Look up 'SQLean Regex docs' for more"
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<.button class="my-10 sm:mb-7.5 w-full sm:w-auto" rounding="rounded-lg">Save Source</.button>
|
||||||
|
|
||||||
<div class="rounded-sm dark:bg-meta-4 p-4 md:p-6 mb-5">
|
<div class="rounded-sm dark:bg-meta-4 p-4 md:p-6 mb-5">
|
||||||
<.fast_indexing_help />
|
<.fast_indexing_help />
|
||||||
|
|
|
||||||
BIN
priv/repo/extensions/sqlean-linux-arm/crypto.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/crypto.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/define.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/define.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/fileio.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/fileio.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/fuzzy.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/fuzzy.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/ipaddr.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/ipaddr.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/math.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/math.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/regexp.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/regexp.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/sqlean.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/sqlean.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/stats.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/stats.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/text.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/text.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/unicode.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/unicode.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/uuid.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/uuid.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-arm/vsv.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-arm/vsv.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/crypto.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/crypto.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/define.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/define.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/fileio.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/fileio.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/fuzzy.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/fuzzy.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/ipaddr.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/ipaddr.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/math.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/math.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/regexp.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/regexp.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/sqlean.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/sqlean.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/stats.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/stats.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/text.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/text.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/unicode.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/unicode.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/uuid.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/uuid.so
Executable file
Binary file not shown.
BIN
priv/repo/extensions/sqlean-linux-x86/vsv.so
Executable file
BIN
priv/repo/extensions/sqlean-linux-x86/vsv.so
Executable file
Binary file not shown.
|
|
@ -0,0 +1,9 @@
|
||||||
|
defmodule Pinchflat.Repo.Migrations.AddTitleRegexToSource do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
alter table(:sources) do
|
||||||
|
add :title_filter_regex, :string
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -239,6 +239,26 @@ defmodule Pinchflat.MediaTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "list_pending_media_items_for/1 when testing title regex" do
|
||||||
|
test "returns only media items that match the title regex" do
|
||||||
|
source = source_fixture(%{title_filter_regex: "(?i)^FOO$"})
|
||||||
|
|
||||||
|
matching_media_item = media_item_fixture(%{source_id: source.id, media_filepath: nil, title: "foo"})
|
||||||
|
_non_matching_media_item = media_item_fixture(%{source_id: source.id, media_filepath: nil, title: "bar"})
|
||||||
|
|
||||||
|
assert Media.list_pending_media_items_for(source) == [matching_media_item]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not apply a regex if none is specified" do
|
||||||
|
source = source_fixture(%{title_filter_regex: nil})
|
||||||
|
|
||||||
|
media_item_one = media_item_fixture(%{source_id: source.id, media_filepath: nil, title: "foo"})
|
||||||
|
media_item_two = media_item_fixture(%{source_id: source.id, media_filepath: nil, title: "bar"})
|
||||||
|
|
||||||
|
assert Media.list_pending_media_items_for(source) == [media_item_one, media_item_two]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "list_downloaded_media_items_for/1" do
|
describe "list_downloaded_media_items_for/1" do
|
||||||
test "returns only media items with a media_filepath" do
|
test "returns only media items with a media_filepath" do
|
||||||
source = source_fixture()
|
source = source_fixture()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue