[VERY WIP] basic podcast RSS setup
This commit is contained in:
parent
0d9003cffd
commit
67f8000f5a
3 changed files with 98 additions and 51 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
95
lib/pinchflat/podcasts/rss_feed_builder.ex
Normal file
95
lib/pinchflat/podcasts/rss_feed_builder.ex
Normal file
|
|
@ -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 <itunes:duration>
|
||||
# - Serve proper images instead of the placeholders
|
||||
"""
|
||||
<item>
|
||||
<guid isPermaLink="false">#{media_item.uuid}</guid>
|
||||
<title>#{media_item.title}</title>
|
||||
<link>#{media_item.original_url}</link>
|
||||
<description>#{media_item.description}</description>
|
||||
<pubDate>#{generate_upload_date(media_item)}</pubDate>
|
||||
<enclosure
|
||||
url="#{generate_media_stream_path(media_item)}"
|
||||
length="#{media_item.media_size_bytes}"
|
||||
type="#{determine_content_type(media_item)}">
|
||||
</enclosure>
|
||||
<itunes:author>#{source.custom_name}</itunes:author>
|
||||
<itunes:subtitle>#{media_item.title}</itunes:subtitle>
|
||||
<itunes:summary><![CDATA[#{media_item.description}]]></itunes:summary>
|
||||
<itunes:image href="https://raw.githubusercontent.com/kieraneglin/pinchflat/master/priv/static/images/originals/logo.png"></itunes:image>
|
||||
<itunes:explicit>false</itunes:explicit>
|
||||
</item>
|
||||
"""
|
||||
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 <description>
|
||||
# - Add <itunes:summary>
|
||||
# - Serve proper images instead of the placeholders
|
||||
# - Ass <atom:link href="<LINK TO FEED>" rel="self" type="application/rss+xml" />
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
|
||||
<channel>
|
||||
<title>#{source.custom_name}</title>
|
||||
<link>#{source.original_url}</link>
|
||||
<description>#{source.custom_name}</description>
|
||||
<category>TV & Film</category>
|
||||
<generator>Generated by Pinchflat</generator>
|
||||
<language>en-us</language>
|
||||
<lastBuildDate>#{Calendar.strftime(DateTime.utc_now(), @datetime_format)}</lastBuildDate>
|
||||
<pubDate>#{Calendar.strftime(source.inserted_at, @datetime_format)}</pubDate>
|
||||
<image>
|
||||
<url>https://raw.githubusercontent.com/kieraneglin/pinchflat/master/priv/static/images/originals/logo.png</url>
|
||||
<title>#{source.custom_name}</title>
|
||||
<link>#{source.original_url}</link>
|
||||
</image>
|
||||
<itunes:author>#{source.custom_name}</itunes:author>
|
||||
<itunes:subtitle>#{source.custom_name}</itunes:subtitle>
|
||||
<itunes:block>yes</itunes:block>
|
||||
<itunes:image href="https://raw.githubusercontent.com/kieraneglin/pinchflat/master/priv/static/images/originals/logo.png"></itunes:image>
|
||||
<itunes:explicit>false</itunes:explicit>
|
||||
<itunes:category text="TV & Film"></itunes:category>
|
||||
|
||||
#{Enum.join(media_item_xml, "\n")}
|
||||
|
||||
</channel>
|
||||
</rss>
|
||||
"""
|
||||
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
|
||||
Loading…
Reference in a new issue