livebook / public-apps /elixir_forum_discourse_rss_opml_generator.livemd
hugobarauna's picture
Create elixir_forum_discourse_rss_opml_generator.livemd
347b321 verified
<!-- 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
```