Exoplanet

Exoplanet is an Elixir library that aggregates multiple RSS and Atom feeds into a single, unified feed sorted by publication date (descending).

It downloads each source concurrently, applies optional per-feed content filters (category allow/block lists, image stripping, summary excerpts), caps the contribution from any one feed, and returns a flat list of %Exoplanet.Post{} structs ready to render.

Inspired by Planet Venus and NimblePublisher.

Installation

Add :exoplanet to your dependencies in mix.exs:

def deps do
  [
    {:exoplanet, "~> 0.4"}
  ]
end

Documentation is published at https://hexdocs.pm/exoplanet.

Quick start

Describe your feeds in an .exs file that returns a map:

# planet.exs
%{
  items: 60,
  new_feed_items: 4,
  default_filters: %{
    allow_categories: ["elixir", "erlang"],
    block_categories: [],
    strip_images: false,
    excerpt_length: nil,
    sanitize_html: true,
    drop_tags: ~w(iframe script object embed style base),
    drop_attrs: ~w(style)
  },
  sources: %{
    "https://milmazz.uno/atom.xml" => %{name: "Milton Mazzarri"},
    "https://www.theerlangelist.com/rss" => %{name: "Saša Jurić"}
  }
}

Load it and build the merged feed:

config = Exoplanet.Config.from_file("planet.exs")
posts  = Exoplanet.build(config)

posts is a list of Exoplanet.Post structs sorted newest-first. See example/planet_beam.exs for a fuller config that exercises every supported field, and Exoplanet.Filters for the filter semantics.

HTTP caching (optional)

Exoplanet can issue conditional If-None-Match / If-Modified-Since requests and fall back to a cached body on transient errors. Implement the Exoplanet.Cache behaviour and register the adapter:

Application.put_env(:exoplanet, :cache_adapter, MyApp.FeedCache)

See the Exoplanet.Cache module docs for the callback contract and the optional on_success/2 / on_error/3 notification hooks.

Migration from 0.2.x

Exoplanet.Config was slimmed down in 0.3.0 to hold only fields the library itself reads. Site-presentation metadata (name, link, owner_name, owner_email, about, code_of_conduct, activity_threshold, related_sites) and vestigial Venus-era settings (cache_directory, output_dir, output_theme, log_level) are no longer part of the struct.

Exoplanet.Config.from_file/1 ignores keys it doesn't recognise, so a single .exs file can still serve both Exoplanet and a consumer-side config (for example a static-site generator) — keep the extra fields in the same map and read them yourself.

See the CHANGELOG for the full list of changes.

License

Apache-2.0. See LICENSE.