From 67f8000f5aec262221ff0eecb5b401a11ecf1601 Mon Sep 17 00:00:00 2001 From: Kieran Eglin Date: Sat, 23 Mar 2024 15:53:20 -0700 Subject: [PATCH] [VERY WIP] basic podcast RSS setup --- config/config.exs | 1 + config/runtime.exs | 53 +----------- lib/pinchflat/podcasts/rss_feed_builder.ex | 95 ++++++++++++++++++++++ 3 files changed, 98 insertions(+), 51 deletions(-) create mode 100644 lib/pinchflat/podcasts/rss_feed_builder.ex diff --git a/config/config.exs b/config/config.exs index e1f5e1d..33fbef8 100644 --- a/config/config.exs +++ b/config/config.exs @@ -21,6 +21,7 @@ config :pinchflat, # If either is unset, basic auth will not be used. basic_auth_username: System.get_env("BASIC_AUTH_USERNAME"), basic_auth_password: System.get_env("BASIC_AUTH_PASSWORD"), + url_base: System.get_env("BASIC_AUTH_PASSWORD") || "http://localhost:4008", file_watcher_poll_interval: 1000 # Configures the endpoint diff --git a/config/runtime.exs b/config/runtime.exs index 89d1d1a..b260571 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -66,7 +66,8 @@ if config_env() == :prod do config :pinchflat, yt_dlp_executable: System.find_executable("yt-dlp"), metadata_directory: metadata_path, - dns_cluster_query: System.get_env("DNS_CLUSTER_QUERY") + dns_cluster_query: System.get_env("DNS_CLUSTER_QUERY"), + url_base: System.get_env("URL_BASE") || "http://localhost:8945" config :pinchflat, Pinchflat.Repo, database: db_path, @@ -123,54 +124,4 @@ if config_env() == :prod do formatter: Logger.Formatter.new() }} ] - - # ## SSL Support - # - # To get SSL working, you will need to add the `https` key - # to your endpoint configuration: - # - # config :pinchflat, PinchflatWeb.Endpoint, - # https: [ - # ..., - # port: 443, - # cipher_suite: :strong, - # keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), - # certfile: System.get_env("SOME_APP_SSL_CERT_PATH") - # ] - # - # The `cipher_suite` is set to `:strong` to support only the - # latest and more secure SSL ciphers. This means old browsers - # and clients may not be supported. You can set it to - # `:compatible` for wider support. - # - # `:keyfile` and `:certfile` expect an absolute path to the key - # and cert in disk or a relative path inside priv, for example - # "priv/ssl/server.key". For all supported SSL configuration - # options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1 - # - # We also recommend setting `force_ssl` in your endpoint, ensuring - # no data is ever sent via http, always redirecting to https: - # - # config :pinchflat, PinchflatWeb.Endpoint, - # force_ssl: [hsts: true] - # - # Check `Plug.SSL` for all available options in `force_ssl`. - - # ## Configuring the mailer - # - # In production you need to configure the mailer to use a different adapter. - # Also, you may need to configure the Swoosh API client of your choice if you - # are not using SMTP. Here is an example of the configuration: - # - # config :pinchflat, Pinchflat.Mailer, - # adapter: Swoosh.Adapters.Mailgun, - # api_key: System.get_env("MAILGUN_API_KEY"), - # domain: System.get_env("MAILGUN_DOMAIN") - # - # For this example you need include a HTTP client required by Swoosh API client. - # Swoosh supports Hackney and Finch out of the box: - # - # config :swoosh, :api_client, Swoosh.ApiClient.Hackney - # - # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details. end diff --git a/lib/pinchflat/podcasts/rss_feed_builder.ex b/lib/pinchflat/podcasts/rss_feed_builder.ex new file mode 100644 index 0000000..45f07ed --- /dev/null +++ b/lib/pinchflat/podcasts/rss_feed_builder.ex @@ -0,0 +1,95 @@ +defmodule Pinchflat.Podcasts.RssFeedBuilder do + @datetime_format "%a, %d %b %Y %H:%M:%S %z" + + # TODO: only MIs that are confirmed to exist on-disk should be provided + def build(source, media_items) do + media_item_xml = Enum.map(media_items, &build_media_item_xml(source, &1)) + + build_source_xml(source, media_item_xml) + end + + defp build_media_item_xml(source, media_item) do + # NOTE: improvements for future: + # - Add + # - Serve proper images instead of the placeholders + """ + + #{media_item.uuid} + #{media_item.title} + #{media_item.original_url} + #{media_item.description} + #{generate_upload_date(media_item)} + + + #{source.custom_name} + #{media_item.title} + + + false + + """ + end + + defp build_source_xml(source, media_item_xml) do + # Useful: https://validator.w3.org/feed/#validate_by_input + # NOTE: improvements for future: + # - Add real + # - Add + # - Serve proper images instead of the placeholders + # - Ass + """ + + + + #{source.custom_name} + #{source.original_url} + #{source.custom_name} + TV & Film + Generated by Pinchflat + en-us + #{Calendar.strftime(DateTime.utc_now(), @datetime_format)} + #{Calendar.strftime(source.inserted_at, @datetime_format)} + + https://raw.githubusercontent.com/kieraneglin/pinchflat/master/priv/static/images/originals/logo.png + #{source.custom_name} + #{source.original_url} + + #{source.custom_name} + #{source.custom_name} + yes + + false + + + #{Enum.join(media_item_xml, "\n")} + + + + """ + end + + defp generate_media_stream_path(media_item) do + extension = Path.extname(media_item.media_filepath) + + "#{url_base()}/media/#{media_item.uuid}/stream#{extension}" + end + + defp generate_upload_date(media_item) do + media_item.upload_date + |> Date.to_gregorian_days() + |> Kernel.*(86400) + |> DateTime.from_gregorian_seconds() + |> Calendar.strftime(@datetime_format) + end + + defp determine_content_type(media_item) do + MIME.from_path(media_item.media_filepath) + end + + defp url_base do + Application.get_env(:pinchflat, :url_base) + end +end