Spaces:
Running
Running
| <!-- livebook:{"app_settings":{"access_type":"public","output_type":"rich","show_source":true,"slug":"elixir-forum-discourse-opml-generator"}} --> | |
| # ElixirForum Discourse RSS OPML Generator | |
| ```elixir | |
| Mix.install([ | |
| {:kino, "~> 0.12.3"} | |
| ]) | |
| ``` | |
| ## Section | |
| ```elixir | |
| defmodule Discourse.OPML do | |
| defmodule Behaviour do | |
| @callback outline(list(String.t())) :: String.t() | |
| end | |
| def generate(usernames, forum_specific_generator) do | |
| outline = forum_specific_generator.outline(usernames) | |
| """ | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <opml version="1.0"> | |
| <head> | |
| <title>RSS OPML Subscriptions</title> | |
| </head> | |
| <body> | |
| #{outline} | |
| </body> | |
| </opml> | |
| """ | |
| end | |
| defmodule ElixirForum do | |
| @behaviour Discourse.OPML.Behaviour | |
| @impl true | |
| def outline(usernames) do | |
| inner_outlines = Enum.map(usernames, &outlines_for_user/1) | |
| """ | |
| <outline title="ElixirForum" text="ElixirForum"> | |
| #{inner_outlines} | |
| </outline> | |
| """ | |
| end | |
| defp outlines_for_user(username) do | |
| """ | |
| <outline | |
| text="Latest posts by @#{username}" | |
| title="Latest posts by @#{username}" | |
| type="rss" | |
| xmlUrl="https://elixirforum.com/users/#{username}/activity.rss" | |
| htmlUrl="https://elixirforum.com/u/#{username}/activity" | |
| /> | |
| <outline | |
| text="Latest topics by @#{username}" | |
| title="Latest topics by @#{username}" | |
| type="rss" | |
| xmlUrl="https://elixirforum.com/users/#{username}/activity/topics.rss" | |
| htmlUrl="https://elixirforum.com/u/#{username}/activity/topics" | |
| /> | |
| """ | |
| end | |
| end | |
| end | |
| ``` | |
| ```elixir | |
| default_usernames = | |
| [ | |
| "josevalim", | |
| "mhanberg", | |
| "wojtekmach", | |
| "nicd", | |
| "dorgan", | |
| "axelson", | |
| "benwilson512", | |
| "LostKobrakai", | |
| "Fl4m3Ph03n1x", | |
| "NobbZ", | |
| "hauleth", | |
| "astonj", | |
| "michalmuskala", | |
| "mbuhot", | |
| "ConnorRigby", | |
| "derpycoder" | |
| ] | |
| |> Enum.join("\n") | |
| form = | |
| Kino.Control.form( | |
| [ | |
| usernames: | |
| Kino.Input.textarea("Elixir forum usernames (one per line)", default: default_usernames) | |
| ], | |
| submit: "Generate OPML" | |
| ) | |
| ``` | |
| ```elixir | |
| output_frame = Kino.Frame.new() | |
| Kino.listen(form, fn event -> | |
| IO.inspect(event) | |
| %{origin: origin, data: %{usernames: usernames}} = event | |
| opml = | |
| usernames | |
| |> String.split() | |
| |> Enum.map(&String.downcase/1) | |
| |> Enum.sort() | |
| |> Discourse.OPML.generate(Discourse.OPML.ElixirForum) | |
| |> Kino.Text.new() | |
| Kino.Frame.render(output_frame, opml, to: origin) | |
| end) | |
| output_frame | |
| ``` | |