Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
4.0KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.BBS.Handler do
  5. use Sshd.ShellHandler
  6. alias Pleroma.Activity
  7. alias Pleroma.HTML
  8. alias Pleroma.Web.ActivityPub.ActivityPub
  9. alias Pleroma.Web.CommonAPI
  10. def on_shell(username, _pubkey, _ip, _port) do
  11. :ok = IO.puts("Welcome to #{Pleroma.Config.get([:instance, :name])}!")
  12. user = Pleroma.User.get_cached_by_nickname(to_string(username))
  13. Logger.debug("#{inspect(user)}")
  14. loop(run_state(user: user))
  15. end
  16. def on_connect(username, ip, port, method) do
  17. Logger.debug(fn ->
  18. """
  19. Incoming SSH shell #{inspect(self())} requested for #{username} from #{inspect(ip)}:#{
  20. inspect(port)
  21. } using #{inspect(method)}
  22. """
  23. end)
  24. end
  25. def on_disconnect(username, ip, port) do
  26. Logger.debug(fn ->
  27. "Disconnecting SSH shell for #{username} from #{inspect(ip)}:#{inspect(port)}"
  28. end)
  29. end
  30. defp loop(state) do
  31. self_pid = self()
  32. counter = state.counter
  33. prefix = state.prefix
  34. user = state.user
  35. input = spawn(fn -> io_get(self_pid, prefix, counter, user.nickname) end)
  36. wait_input(state, input)
  37. end
  38. def puts_activity(activity) do
  39. status = Pleroma.Web.MastodonAPI.StatusView.render("show.json", %{activity: activity})
  40. IO.puts("-- #{status.id} by #{status.account.display_name} (#{status.account.acct})")
  41. IO.puts(HTML.strip_tags(status.content))
  42. IO.puts("")
  43. end
  44. def handle_command(state, "help") do
  45. IO.puts("Available commands:")
  46. IO.puts("help - This help")
  47. IO.puts("home - Show the home timeline")
  48. IO.puts("p <text> - Post the given text")
  49. IO.puts("r <id> <text> - Reply to the post with the given id")
  50. IO.puts("quit - Quit")
  51. state
  52. end
  53. def handle_command(%{user: user} = state, "r " <> text) do
  54. text = String.trim(text)
  55. [activity_id, rest] = String.split(text, " ", parts: 2)
  56. with %Activity{} <- Activity.get_by_id(activity_id),
  57. {:ok, _activity} <-
  58. CommonAPI.post(user, %{status: rest, in_reply_to_status_id: activity_id}) do
  59. IO.puts("Replied!")
  60. else
  61. _e -> IO.puts("Could not reply...")
  62. end
  63. state
  64. end
  65. def handle_command(%{user: user} = state, "p " <> text) do
  66. text = String.trim(text)
  67. with {:ok, _activity} <- CommonAPI.post(user, %{status: text}) do
  68. IO.puts("Posted!")
  69. else
  70. _e -> IO.puts("Could not post...")
  71. end
  72. state
  73. end
  74. def handle_command(state, "home") do
  75. user = state.user
  76. params =
  77. %{}
  78. |> Map.put(:type, ["Create"])
  79. |> Map.put(:blocking_user, user)
  80. |> Map.put(:muting_user, user)
  81. |> Map.put(:user, user)
  82. activities =
  83. [user.ap_id | Pleroma.User.following(user)]
  84. |> ActivityPub.fetch_activities(params)
  85. Enum.each(activities, fn activity ->
  86. puts_activity(activity)
  87. end)
  88. state
  89. end
  90. def handle_command(state, command) do
  91. IO.puts("Unknown command '#{command}'")
  92. state
  93. end
  94. defp wait_input(state, input) do
  95. receive do
  96. {:input, ^input, "quit\n"} ->
  97. IO.puts("Exiting...")
  98. {:input, ^input, code} when is_binary(code) ->
  99. code = String.trim(code)
  100. state = handle_command(state, code)
  101. loop(%{state | counter: state.counter + 1})
  102. {:error, :interrupted} ->
  103. IO.puts("Caught Ctrl+C...")
  104. loop(%{state | counter: state.counter + 1})
  105. {:input, ^input, msg} ->
  106. :ok = Logger.warn("received unknown message: #{inspect(msg)}")
  107. loop(%{state | counter: state.counter + 1})
  108. end
  109. end
  110. defp run_state(opts) do
  111. %{prefix: "pleroma", counter: 1, user: opts[:user]}
  112. end
  113. defp io_get(pid, prefix, counter, username) do
  114. prompt = prompt(prefix, counter, username)
  115. send(pid, {:input, self(), IO.gets(:stdio, prompt)})
  116. end
  117. defp prompt(prefix, counter, username) do
  118. prompt = "#{username}@#{prefix}:#{counter}>"
  119. prompt <> " "
  120. end
  121. end