Fast indexing (#58)
* Made method to getting singular media details; Renamed other related method * Takes a fun and flirty digression to remove abstractions around yt-dlp since I'm 100% committed to using it exclusively * Removed commented test code * Lays the groundwork for fast indexing * Added module for working with youtube RSS feed * Added methods to kick off indexing workers from RSS response * Improve short detection (#59) * Made media attribute-related yt-dlp calls return a struct * Added shorts attribute to media items * Added ability to discern a short from yt-dlp response * Updated search to use new shorts attribute * Fast index UI (#63) * Added fast_index field and adds it to source form * Added fast indexing to source changeset operations * Added fast indexing worker and updated other modules to start using it * Handled fast index worker on source update * Add support modals (#65) * Added fast indexing upgrade modal * Improved modal on smaller screens * Updated links to work again * Added donation modal * Reverted source fast index to 15 minutes * Removed unneeded HTML attributes from old alpine approach
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||
<div class="flex gap-3 items-center">
|
||||
<.link navigate={~p"/sources/#{@media_item.source_id}"}>
|
||||
<.link href={~p"/sources/#{@media_item.source_id}"}>
|
||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||
</.link>
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||
<.link navigate={~p"/media_profiles"}>
|
||||
<.link href={~p"/media_profiles"}>
|
||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||
</.link>
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">Edit Media Profile</h2>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Media Profiles
|
||||
</h2>
|
||||
<nav>
|
||||
<.link navigate={~p"/media_profiles/new"}>
|
||||
<.link href={~p"/media_profiles/new"}>
|
||||
<.button color="bg-primary" rounding="rounded-full">
|
||||
<span class="font-bold text-xl mx-2">+</span> New <span class="hidden sm:inline pl-1">Media Profile</span>
|
||||
</.button>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||
<.link :if={!Settings.get!(:onboarding)} navigate={~p"/media_profiles"}>
|
||||
<.link :if={!Settings.get!(:onboarding)} href={~p"/media_profiles"}>
|
||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||
</.link>
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Media Profile</h2>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<.link navigate={~p"/media_profiles"}>
|
||||
<.link href={~p"/media_profiles"}>
|
||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||
</.link>
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-2">
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<.link navigate={~p"/media_profiles/#{@media_profile}/edit"}>
|
||||
<.link href={~p"/media_profiles/#{@media_profile}/edit"}>
|
||||
<.button color="bg-primary" rounding="rounded-full">
|
||||
<.icon name="hero-pencil-square" class="mr-2" />Edit <span class="hidden sm:inline pl-1">Media Profile</span>
|
||||
</.button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<p class="text-md text-bodydark">Media Profiles set your preferences for fetching and downloading media.</p>
|
||||
<p class="text-md text-bodydark">Don't worry, you can create more Media Profiles later!</p>
|
||||
<div class="mt-8">
|
||||
<.link navigate={~p"/media_profiles/new"}>
|
||||
<.link href={~p"/media_profiles/new"}>
|
||||
<.button color="bg-primary" rounding="rounded-full" disabled={@media_profiles_exist}>
|
||||
<span class="font-bold mx-2">+</span> New Media Profile
|
||||
</.button>
|
||||
@@ -24,7 +24,7 @@
|
||||
Each Media Profile can control many Sources so it's easy to add more content!
|
||||
</p>
|
||||
<div class="mt-8">
|
||||
<.link navigate={~p"/sources/new"}>
|
||||
<.link href={~p"/sources/new"}>
|
||||
<.button color="bg-primary" rounding="rounded-full" disabled={not @media_profiles_exist}>
|
||||
<span class="font-bold mx-2">+</span> New Source
|
||||
</.button>
|
||||
@@ -39,7 +39,7 @@
|
||||
</p>
|
||||
<p class="text-md text-bodydark">Feel free to add more Media Profiles or Sources in the meantime!</p>
|
||||
<div class="mt-8">
|
||||
<.link navigate={~p"/"}>
|
||||
<.link href={~p"/"}>
|
||||
<.button color="bg-primary" rounding="rounded-full" disabled={not @sources_exist}>
|
||||
Let's Go <span class="font-bold mx-2">🚀</span>
|
||||
</.button>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</:col>
|
||||
<:col :let={result} label="" class="flex place-content-evenly">
|
||||
<.link
|
||||
navigate={~p"/sources/#{result.source_id}/media/#{result.id}"}
|
||||
href={~p"/sources/#{result.source_id}/media/#{result.id}"}
|
||||
class="hover:text-secondary duration-200 ease-in-out mx-0.5"
|
||||
>
|
||||
<.icon name="hero-eye" />
|
||||
|
||||
@@ -3,8 +3,9 @@ defmodule PinchflatWeb.Sources.SourceController do
|
||||
|
||||
alias Pinchflat.Repo
|
||||
alias Pinchflat.Media
|
||||
alias Pinchflat.Profiles
|
||||
alias Pinchflat.Tasks
|
||||
alias Pinchflat.Sources
|
||||
alias Pinchflat.Profiles
|
||||
alias Pinchflat.Sources.Source
|
||||
|
||||
def index(conn, _params) do
|
||||
@@ -43,15 +44,18 @@ defmodule PinchflatWeb.Sources.SourceController do
|
||||
end
|
||||
|
||||
def show(conn, %{"id" => id}) do
|
||||
source =
|
||||
id
|
||||
|> Sources.get_source!()
|
||||
|> Repo.preload([:media_profile, tasks: [:job]])
|
||||
source = Repo.preload(Sources.get_source!(id), :media_profile)
|
||||
|
||||
pending_tasks = Repo.preload(Tasks.list_pending_tasks_for(:source_id, source.id), :job)
|
||||
pending_media = Media.list_pending_media_items_for(source, limit: 100)
|
||||
downloaded_media = Media.list_downloaded_media_items_for(source, limit: 100)
|
||||
|
||||
render(conn, :show, source: source, pending_media: pending_media, downloaded_media: downloaded_media)
|
||||
render(conn, :show,
|
||||
source: source,
|
||||
pending_tasks: pending_tasks,
|
||||
pending_media: pending_media,
|
||||
downloaded_media: downloaded_media
|
||||
)
|
||||
end
|
||||
|
||||
def edit(conn, %{"id" => id}) do
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||
<.link navigate={~p"/sources"}>
|
||||
<.link href={~p"/sources"}>
|
||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||
</.link>
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">Edit Source</h2>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<aside>
|
||||
<h2 class="text-xl font-bold mb-2">What is fast indexing (experimental)?</h2>
|
||||
<section class="ml-2 md:ml-4 mb-4 max-w-prose">
|
||||
<p>
|
||||
Indexing is the act of scanning a channel or playlist (aka: source) for new media.
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
Normal indexing uses <code class="text-sm">yt-dlp</code>
|
||||
to scan the entire source on your specified frequency, but it's very slow for large sources. This is the most accurate way to find uploaded media with the tradeoff being that pairing a large source with a low index frequency will result in you spending most of your time indexing. Only so many indexing operations can be running at the same time, so this can impact your other source's ability to index.
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
Fast indexing takes a different approach. It still does an initial scan the slow way but after that it uses an RSS feed to frequently check for new videos. This has the potential to be hundreds of times faster, but it can miss videos if the uploader un-privates an old video or uploads dozens of videos in the space of a few minutes. It works well for most channels or playlists but it's not perfect.
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
To make up for this limitation, a normal index is still run monthly to catch any videos that were missed by fast indexing. Fast indexing overrides the normal index frequency.
|
||||
</p>
|
||||
<p class="mt-2">
|
||||
Fast indexing is experimental so please report any issues on GitHub. It's only recommended for sources with over 200-ish videos and that upload frequently. Not recommended for small or inactive sources.
|
||||
</p>
|
||||
</section>
|
||||
</aside>
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white">Sources</h2>
|
||||
<nav>
|
||||
<.link navigate={~p"/sources/new"}>
|
||||
<.link href={~p"/sources/new"}>
|
||||
<.button color="bg-primary" rounding="rounded-full">
|
||||
<span class="font-bold mx-2">+</span> New <span class="hidden sm:inline pl-1">Source</span>
|
||||
</.button>
|
||||
@@ -22,7 +22,7 @@
|
||||
</:col>
|
||||
<:col :let={source} label="Media Profile">
|
||||
<.link
|
||||
navigate={~p"/media_profiles/#{source.media_profile_id}"}
|
||||
href={~p"/media_profiles/#{source.media_profile_id}"}
|
||||
class="hover:text-secondary duration-200 ease-in-out"
|
||||
>
|
||||
<%= source.media_profile.name %>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||
<.link :if={!Settings.get!(:onboarding)} navigate={~p"/sources"}>
|
||||
<.link :if={!Settings.get!(:onboarding)} href={~p"/sources"}>
|
||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||
</.link>
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Source</h2>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||
<div class="flex gap-3 items-center">
|
||||
<.link navigate={~p"/sources"}>
|
||||
<.link href={~p"/sources"}>
|
||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||
</.link>
|
||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<.link navigate={~p"/sources/#{@source}/edit"}>
|
||||
<.link href={~p"/sources/#{@source}/edit"}>
|
||||
<.button color="bg-primary" rounding="rounded-full">
|
||||
<.icon name="hero-pencil-square" class="mr-2" /> Edit <span class="hidden sm:inline pl-1">Source</span>
|
||||
</.button>
|
||||
@@ -84,9 +84,9 @@
|
||||
<p class="text-black dark:text-white">Nothing Here!</p>
|
||||
<% end %>
|
||||
</:tab>
|
||||
<:tab title="Tasks">
|
||||
<%= if match?([_|_], @source.tasks) do %>
|
||||
<.table rows={@source.tasks} table_class="text-black dark:text-white">
|
||||
<:tab title="Pending Tasks">
|
||||
<%= if match?([_|_], @pending_tasks) do %>
|
||||
<.table rows={@pending_tasks} table_class="text-black dark:text-white">
|
||||
<:col :let={task} label="Worker">
|
||||
<%= task.job.worker %>
|
||||
</:col>
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
Oops, something went wrong! Please check the errors below.
|
||||
</.error>
|
||||
|
||||
<h3 class="mt-8 text-2xl text-black dark:text-white">
|
||||
General Options
|
||||
</h3>
|
||||
|
||||
<.input
|
||||
field={f[:custom_name]}
|
||||
type="text"
|
||||
@@ -19,6 +23,10 @@
|
||||
label="Media Profile"
|
||||
/>
|
||||
|
||||
<h3 class="mt-8 text-2xl text-black dark:text-white">
|
||||
Indexing Options
|
||||
</h3>
|
||||
|
||||
<.input
|
||||
field={f[:index_frequency_minutes]}
|
||||
options={friendly_index_frequencies()}
|
||||
@@ -27,6 +35,21 @@
|
||||
help="Time between one index of this source finishing and the next one starting. Setting to 'On Create' will still run an initial index but no subsequent ones"
|
||||
/>
|
||||
|
||||
<%!-- TODO: use Alpine to disable the index frequency when fast indexing is enabled --%>
|
||||
<div phx-click={show_modal("upgrade-modal")}>
|
||||
<.input
|
||||
field={f[:fast_index]}
|
||||
type="toggle"
|
||||
label="Use Fast Indexing?"
|
||||
label_suffix="(pro)"
|
||||
help="Experimental. Ignores 'Index Frequency'. Recommended for large channels that upload frequently. See below for more info"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 class="mt-8 text-2xl text-black dark:text-white">
|
||||
Downloading Options
|
||||
</h3>
|
||||
|
||||
<.input
|
||||
field={f[:download_media]}
|
||||
type="toggle"
|
||||
@@ -34,7 +57,9 @@
|
||||
help="Unchecking still indexes media but it won't be downloaded until you enable this option"
|
||||
/>
|
||||
|
||||
<:actions>
|
||||
<.button class="my-10 sm:mb-7.5 w-full sm:w-auto">Save Source</.button>
|
||||
</:actions>
|
||||
<.button class="my-10 sm:mb-7.5 w-full sm:w-auto">Save Source</.button>
|
||||
|
||||
<div class="rounded-sm dark:bg-meta-4 p-4 md:p-6 mb-5">
|
||||
<.fast_indexing_help />
|
||||
</div>
|
||||
</.simple_form>
|
||||
|
||||
Reference in New Issue
Block a user