1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Clippy do
8 # No software is complete until they have a Clippy implementation.
9 # A ballmer peak _may_ be required to change this module.
18 host = Pleroma.Config.get([Pleroma.Web.Endpoint, :url, :host])
21 "“πλήρωμα” is “pleroma” in greek",
22 "For an extended Pleroma Clippy Experience, use the “Redmond” themes in Pleroma FE settings",
23 "Staff accounts and MRF policies of Pleroma instances are disclosed on the NodeInfo endpoints for easy transparency!\n
24 - https://catgirl.science/misc/nodeinfo.lua?#{host}
25 - https://fediverse.network/#{host}/federation",
26 "Pleroma can federate to the Dark Web!\n
27 - Tor: https://git.pleroma.social/pleroma/pleroma/wikis/Easy%20Onion%20Federation%20(Tor)
28 - i2p: https://git.pleroma.social/pleroma/pleroma/wikis/I2p%20federation",
29 "Lists of Pleroma instances:\n\n- http://distsn.org/pleroma-instances.html\n- https://fediverse.network/pleroma\n- https://the-federation.info/pleroma",
30 "Pleroma uses the LitePub protocol - https://litepub.social",
31 "To receive more federated posts, subscribe to relays!\n
32 - How-to: https://git.pleroma.social/pleroma/pleroma/wikis/Admin%20tasks#relay-managment
33 - Relays: https://fediverse.network/activityrelay"
37 @spec puts(String.t() | [[IO.ANSI.ansicode() | String.t(), ...], ...]) :: nil
38 def puts(text_or_lines) do
42 if is_binary(text_or_lines) do
43 String.split(text_or_lines, ~r/\n/)
50 |> Enum.map(&charlist_count_text/1)
54 pad_text = longest_line_size
57 for(_ <- 1..pad_text, do: "_")
61 for(_ <- 1..pad_text, do: " ")
67 " / \\#{spaces} _#{pad}___",
68 " | |#{spaces} / #{pad_spaces} \\"
76 " #{bright()}@ @#{reset()}#{spaces} ",
88 pad_spaces: pad_spaces,
91 noclippy_line: noclippy_line
94 # surrond one/five line clippy with blank lines around to not fuck up the layout
96 # yes this fix sucks but it's good enough, have you ever seen a release of windows
97 # without some butched features anyway?
99 if length(lines) == 1 or length(lines) == 5 do
100 [""] ++ lines ++ [""]
105 clippy_line(lines, clippy_lines, env)
108 IO.puts("(Clippy crashed, sorry: #{inspect(e)})")
109 IO.puts(text_or_lines)
112 defp clippy_line([line | lines], [prefix | clippy_lines], env) do
113 IO.puts([prefix <> "| ", rpad_line(line, env.max_size)])
114 clippy_line(lines, clippy_lines, env)
117 # more text lines but clippy's complete
118 defp clippy_line([line | lines], [], env) do
119 IO.puts([env.noclippy_line, "| ", rpad_line(line, env.max_size)])
122 IO.puts(env.noclippy_line <> "\\_#{env.pad}___/")
125 clippy_line(lines, [], env)
128 # no more text lines but clippy's not complete
129 defp clippy_line([], [clippy | clippy_lines], env) do
131 IO.puts(clippy <> "\\_#{env.pad}___/")
132 clippy_line([], clippy_lines, %{env | pad: nil})
135 clippy_line([], clippy_lines, env)
139 defp clippy_line(_, _, _) do
142 defp rpad_line(line, max) do
143 pad = max - (charlist_count_text(line) - 2)
144 pads = Enum.join(for(_ <- 1..pad, do: " "))
145 [IO.ANSI.format(line), pads <> " |"]
148 defp charlist_count_text(line) do
150 text = Enum.join(Enum.filter(line, &is_binary/1))