-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Bugfix] Properly escape NFO files (#168)
* Properly escaped NFO file contents * Added an NFO backfill worker * Added a try-catch to the backfill since I _really_ don't want failures to halt app boot
- Loading branch information
1 parent
24875ea
commit 81b49f5
Showing
7 changed files
with
149 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
defmodule Pinchflat.Boot.NfoBackfillWorker do | ||
@moduledoc false | ||
|
||
use Oban.Worker, | ||
queue: :local_metadata, | ||
# This should have it running once _ever_ (until the job is pruned, anyway) | ||
# NOTE: remove within the next month | ||
unique: [period: :infinity, states: Oban.Job.states()], | ||
tags: ["media_item", "media_metadata", "local_metadata", "data_backfill"] | ||
|
||
import Ecto.Query, warn: false | ||
require Logger | ||
|
||
alias Pinchflat.Repo | ||
alias Pinchflat.Media | ||
alias Pinchflat.Media.MediaItem | ||
alias Pinchflat.Metadata.NfoBuilder | ||
alias Pinchflat.Metadata.MetadataFileHelpers | ||
|
||
@doc """ | ||
Runs a one-off backfill job to regenerate NFO files for media items that have | ||
both an NFO file and a metadata file. This is needed because NFO files weren't | ||
escaping characters properly so we need to regenerate them. | ||
This job will only run once as long as I remove it before the jobs are pruned in a month. | ||
Returns :ok | ||
""" | ||
@impl Oban.Worker | ||
def perform(%Oban.Job{}) do | ||
Logger.info("Running NFO backfill worker") | ||
|
||
media_items = get_media_items_to_backfill() | ||
|
||
Enum.each(media_items, fn media_item -> | ||
nfo_exists = File.exists?(media_item.nfo_filepath) | ||
metadata_exists = File.exists?(media_item.metadata.metadata_filepath) | ||
|
||
if nfo_exists && metadata_exists do | ||
Logger.info("NFO and metadata exist for media item #{media_item.id} - proceeding") | ||
|
||
regenerate_nfo_for_media_item(media_item) | ||
end | ||
end) | ||
|
||
:ok | ||
end | ||
|
||
defp get_media_items_to_backfill do | ||
from(m in MediaItem, where: not is_nil(m.nfo_filepath)) | ||
|> Repo.all() | ||
|> Repo.preload([:metadata, source: :media_profile]) | ||
end | ||
|
||
defp regenerate_nfo_for_media_item(media_item) do | ||
try do | ||
case MetadataFileHelpers.read_compressed_metadata(media_item.metadata.metadata_filepath) do | ||
{:ok, metadata} -> | ||
Media.update_media_item(media_item, %{ | ||
nfo_filepath: NfoBuilder.build_and_store_for_media_item(media_item.nfo_filepath, metadata) | ||
}) | ||
|
||
_err -> | ||
Logger.error("Failed to read metadata for media item #{media_item.id}") | ||
end | ||
rescue | ||
e -> Logger.error("Unknown error regenerating NFO file for MI ##{media_item.id}: #{inspect(e)}") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
defmodule Pinchflat.Utils.XmlUtils do | ||
@moduledoc """ | ||
Utility methods for working with XML documents | ||
""" | ||
|
||
@doc """ | ||
Escapes invalid XML characters in a string | ||
Returns binary() | ||
""" | ||
def safe(value) do | ||
value | ||
|> to_string() | ||
|> Phoenix.HTML.html_escape() | ||
|> Phoenix.HTML.safe_to_string() | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
defmodule Pinchflat.Utils.XmlUtilsTest do | ||
use ExUnit.Case, async: true | ||
|
||
alias Pinchflat.Utils.XmlUtils | ||
|
||
describe "safe/1" do | ||
test "escapes invalid characters" do | ||
assert XmlUtils.safe("hello' & <world>") == "hello' & <world>" | ||
end | ||
|
||
test "converts input to string" do | ||
assert XmlUtils.safe(42) == "42" | ||
assert XmlUtils.safe(nil) == "" | ||
end | ||
end | ||
end |