File size: 2,592 Bytes
347b321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<!-- 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
```