5e82ed8e2c261ea4478dc67f79044b6aa9329767
[akkoma] / lib / pleroma / clippy.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Clippy do
6 @moduledoc false
7 # No software is complete until they have a Clippy implementation.
8 # A ballmer peak _may_ be required to change this module.
9
10 def tip() do
11 tips()
12 |> Enum.random()
13 |> puts()
14 end
15
16 def tips() do
17 host = Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host])
18
19 [
20 "“πλήρωμα” is “pleroma” in greek",
21 "For an extended Pleroma Clippy Experience, use the “Redmond” themes in Pleroma FE settings",
22 "Staff accounts and MRF policies of Pleroma instances are disclosed on the NodeInfo endpoints for easy transparency!\n
23 - https://catgirl.science/misc/nodeinfo.lua?#{host}
24 - https://fediverse.network/#{host}/federation",
25 "Pleroma can federate to the Dark Web!\n
26 - Tor: https://git.pleroma.social/pleroma/pleroma/wikis/Easy%20Onion%20Federation%20(Tor)
27 - i2p: https://git.pleroma.social/pleroma/pleroma/wikis/I2p%20federation",
28 "Lists of Pleroma instances are available at:\n\n- http://distsn.org/pleroma-instances.html\n- https://fediverse.network/pleroma\n- https://the-federation.info/pleroma",
29 "Pleroma uses the LitePub protocol - https://litepub.social",
30 "To receive more federated posts, subscribe to relays!\n
31 - How-to: https://git.pleroma.social/pleroma/pleroma/wikis/Admin%20tasks#relay-managment
32 - Relays: https://fediverse.network/activityrelay"
33 ]
34 end
35
36 @spec puts(String.t() | [[IO.ANSI.ansicode() | String.t(), ...], ...]) :: nil
37 def puts(text_or_lines) do
38 import IO.ANSI
39
40 lines =
41 if is_binary(text_or_lines) do
42 String.split(text_or_lines, ~r/\n/)
43 else
44 text_or_lines
45 end
46
47 longest_line_size =
48 lines
49 |> Enum.map(&charlist_count_text/1)
50 |> Enum.sort(&>=/2)
51 |> List.first()
52
53 pad_text = longest_line_size
54
55 pad =
56 for(_ <- 1..pad_text, do: "_")
57 |> Enum.join("")
58
59 pad_spaces =
60 for(_ <- 1..pad_text, do: " ")
61 |> Enum.join("")
62
63 spaces = " "
64
65 pre_lines = [
66 " / \\#{spaces} _#{pad}___",
67 " | |#{spaces} / #{pad_spaces} \\"
68 ]
69
70 for l <- pre_lines do
71 IO.puts(l)
72 end
73
74 clippy_lines = [
75 " #{bright()}@ @#{reset()}#{spaces} ",
76 " || ||#{spaces}",
77 " || || <--",
78 " |\\_/| ",
79 " \\___/ "
80 ]
81
82 noclippy_line = " "
83
84 env = %{
85 max_size: pad_text,
86 pad: pad,
87 pad_spaces: pad_spaces,
88 spaces: spaces,
89 pre_lines: pre_lines,
90 noclippy_line: noclippy_line
91 }
92
93 clippy_line(lines, clippy_lines, env)
94 rescue
95 e ->
96 IO.puts("(Clippy crashed, sorry: #{inspect(e)})")
97 IO.puts(text_or_lines)
98 end
99
100 defp clippy_line([line | lines], [prefix | clippy_lines], env) do
101 IO.puts([prefix <> "| ", rpad_line(line, env.max_size)])
102 clippy_line(lines, clippy_lines, env)
103 end
104
105 # more text lines but clippy's complete
106 defp clippy_line([line | lines], [], env) do
107 IO.puts([env.noclippy_line, "| ", rpad_line(line, env.max_size)])
108
109 if lines == [] do
110 IO.puts(env.noclippy_line <> "\\_#{env.pad}___/")
111 end
112
113 clippy_line(lines, [], env)
114 end
115
116 # no more text lines but clippy's not complete
117 defp clippy_line([], [clippy | clippy_lines], env) do
118 if env.pad do
119 IO.puts(clippy <> "\\_#{env.pad}___/")
120 clippy_line([], clippy_lines, %{env | pad: nil})
121 else
122 IO.puts(clippy)
123 clippy_line([], clippy_lines, env)
124 end
125 end
126
127 defp clippy_line(_, _, _) do
128 end
129
130 defp rpad_line(line, max) do
131 pad = max - (charlist_count_text(line) - 2)
132 pads = Enum.join(for(_ <- 1..pad, do: " "))
133 [IO.ANSI.format(line), pads <> " |"]
134 end
135
136 defp charlist_count_text(line) do
137 if is_list(line) do
138 text = Enum.join(Enum.filter(line, &is_binary/1))
139 String.length(text)
140 else
141 String.length(line)
142 end
143 end
144 end