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 | |
``` | |