emoji_api_controller.ex (8439B)
1 defmodule Pleroma.Web.PleromaAPI.EmojiAPIController do 2 use Pleroma.Web, :controller 3 4 alias Pleroma.Emoji.Pack 5 6 plug( 7 Pleroma.Plugs.OAuthScopesPlug, 8 %{scopes: ["write"], admin: true} 9 when action in [ 10 :import_from_filesystem, 11 :remote, 12 :download, 13 :create, 14 :update, 15 :delete, 16 :add_file, 17 :update_file, 18 :delete_file 19 ] 20 ) 21 22 plug( 23 :skip_plug, 24 [Pleroma.Plugs.OAuthScopesPlug, Pleroma.Plugs.ExpectPublicOrAuthenticatedCheckPlug] 25 when action in [:archive, :show, :list] 26 ) 27 28 def remote(conn, %{"url" => url}) do 29 with {:ok, packs} <- Pack.list_remote(url) do 30 json(conn, packs) 31 else 32 {:shareable, _} -> 33 conn 34 |> put_status(:internal_server_error) 35 |> json(%{error: "The requested instance does not support sharing emoji packs"}) 36 end 37 end 38 39 def list(conn, _params) do 40 emoji_path = 41 Path.join( 42 Pleroma.Config.get!([:instance, :static_dir]), 43 "emoji" 44 ) 45 46 with {:ok, packs} <- Pack.list_local() do 47 json(conn, packs) 48 else 49 {:create_dir, {:error, e}} -> 50 conn 51 |> put_status(:internal_server_error) 52 |> json(%{error: "Failed to create the emoji pack directory at #{emoji_path}: #{e}"}) 53 54 {:ls, {:error, e}} -> 55 conn 56 |> put_status(:internal_server_error) 57 |> json(%{ 58 error: "Failed to get the contents of the emoji pack directory at #{emoji_path}: #{e}" 59 }) 60 end 61 end 62 63 def show(conn, %{"name" => name}) do 64 name = String.trim(name) 65 66 with {:ok, pack} <- Pack.show(name) do 67 json(conn, pack) 68 else 69 {:loaded, _} -> 70 conn 71 |> put_status(:not_found) 72 |> json(%{error: "Pack #{name} does not exist"}) 73 74 {:error, :empty_values} -> 75 conn 76 |> put_status(:bad_request) 77 |> json(%{error: "pack name cannot be empty"}) 78 end 79 end 80 81 def archive(conn, %{"name" => name}) do 82 with {:ok, archive} <- Pack.get_archive(name) do 83 send_download(conn, {:binary, archive}, filename: "#{name}.zip") 84 else 85 {:can_download?, _} -> 86 conn 87 |> put_status(:forbidden) 88 |> json(%{ 89 error: 90 "Pack #{name} cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing" 91 }) 92 93 {:exists?, _} -> 94 conn 95 |> put_status(:not_found) 96 |> json(%{error: "Pack #{name} does not exist"}) 97 end 98 end 99 100 def download(conn, %{"url" => url, "name" => name} = params) do 101 with :ok <- Pack.download(name, url, params["as"]) do 102 json(conn, "ok") 103 else 104 {:shareable, _} -> 105 conn 106 |> put_status(:internal_server_error) 107 |> json(%{error: "The requested instance does not support sharing emoji packs"}) 108 109 {:checksum, _} -> 110 conn 111 |> put_status(:internal_server_error) 112 |> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"}) 113 114 {:error, e} -> 115 conn 116 |> put_status(:internal_server_error) 117 |> json(%{error: e}) 118 end 119 end 120 121 def create(conn, %{"name" => name}) do 122 name = String.trim(name) 123 124 with :ok <- Pack.create(name) do 125 json(conn, "ok") 126 else 127 {:error, :eexist} -> 128 conn 129 |> put_status(:conflict) 130 |> json(%{error: "A pack named \"#{name}\" already exists"}) 131 132 {:error, :empty_values} -> 133 conn 134 |> put_status(:bad_request) 135 |> json(%{error: "pack name cannot be empty"}) 136 137 {:error, _} -> 138 render_error( 139 conn, 140 :internal_server_error, 141 "Unexpected error occurred while creating pack." 142 ) 143 end 144 end 145 146 def delete(conn, %{"name" => name}) do 147 name = String.trim(name) 148 149 with {:ok, deleted} when deleted != [] <- Pack.delete(name) do 150 json(conn, "ok") 151 else 152 {:ok, []} -> 153 conn 154 |> put_status(:not_found) 155 |> json(%{error: "Pack #{name} does not exist"}) 156 157 {:error, :empty_values} -> 158 conn 159 |> put_status(:bad_request) 160 |> json(%{error: "pack name cannot be empty"}) 161 162 {:error, _, _} -> 163 conn 164 |> put_status(:internal_server_error) 165 |> json(%{error: "Couldn't delete the pack #{name}"}) 166 end 167 end 168 169 def update(conn, %{"name" => name, "metadata" => metadata}) do 170 with {:ok, pack} <- Pack.update_metadata(name, metadata) do 171 json(conn, pack.pack) 172 else 173 {:has_all_files?, _} -> 174 conn 175 |> put_status(:bad_request) 176 |> json(%{error: "The fallback archive does not have all files specified in pack.json"}) 177 178 {:error, _} -> 179 render_error( 180 conn, 181 :internal_server_error, 182 "Unexpected error occurred while updating pack metadata." 183 ) 184 end 185 end 186 187 def add_file(conn, %{"name" => name} = params) do 188 filename = params["filename"] || get_filename(params["file"]) 189 shortcode = params["shortcode"] || Path.basename(filename, Path.extname(filename)) 190 191 with {:ok, pack} <- Pack.add_file(name, shortcode, filename, params["file"]) do 192 json(conn, pack.files) 193 else 194 {:exists, _} -> 195 conn 196 |> put_status(:conflict) 197 |> json(%{error: "An emoji with the \"#{shortcode}\" shortcode already exists"}) 198 199 {:loaded, _} -> 200 conn 201 |> put_status(:bad_request) 202 |> json(%{error: "pack \"#{name}\" is not found"}) 203 204 {:error, :empty_values} -> 205 conn 206 |> put_status(:bad_request) 207 |> json(%{error: "pack name, shortcode or filename cannot be empty"}) 208 209 {:error, _} -> 210 render_error( 211 conn, 212 :internal_server_error, 213 "Unexpected error occurred while adding file to pack." 214 ) 215 end 216 end 217 218 def update_file(conn, %{"name" => name, "shortcode" => shortcode} = params) do 219 new_shortcode = params["new_shortcode"] 220 new_filename = params["new_filename"] 221 force = params["force"] == true 222 223 with {:ok, pack} <- Pack.update_file(name, shortcode, new_shortcode, new_filename, force) do 224 json(conn, pack.files) 225 else 226 {:exists, _} -> 227 conn 228 |> put_status(:bad_request) 229 |> json(%{error: "Emoji \"#{shortcode}\" does not exist"}) 230 231 {:not_used, _} -> 232 conn 233 |> put_status(:conflict) 234 |> json(%{ 235 error: 236 "New shortcode \"#{new_shortcode}\" is already used. If you want to override emoji use 'force' option" 237 }) 238 239 {:loaded, _} -> 240 conn 241 |> put_status(:bad_request) 242 |> json(%{error: "pack \"#{name}\" is not found"}) 243 244 {:error, :empty_values} -> 245 conn 246 |> put_status(:bad_request) 247 |> json(%{error: "new_shortcode or new_filename cannot be empty"}) 248 249 {:error, _} -> 250 render_error( 251 conn, 252 :internal_server_error, 253 "Unexpected error occurred while updating file in pack." 254 ) 255 end 256 end 257 258 def delete_file(conn, %{"name" => name, "shortcode" => shortcode}) do 259 with {:ok, pack} <- Pack.delete_file(name, shortcode) do 260 json(conn, pack.files) 261 else 262 {:exists, _} -> 263 conn 264 |> put_status(:bad_request) 265 |> json(%{error: "Emoji \"#{shortcode}\" does not exist"}) 266 267 {:loaded, _} -> 268 conn 269 |> put_status(:bad_request) 270 |> json(%{error: "pack \"#{name}\" is not found"}) 271 272 {:error, :empty_values} -> 273 conn 274 |> put_status(:bad_request) 275 |> json(%{error: "pack name or shortcode cannot be empty"}) 276 277 {:error, _} -> 278 render_error( 279 conn, 280 :internal_server_error, 281 "Unexpected error occurred while removing file from pack." 282 ) 283 end 284 end 285 286 def import_from_filesystem(conn, _params) do 287 with {:ok, names} <- Pack.import_from_filesystem() do 288 json(conn, names) 289 else 290 {:error, :no_read_write} -> 291 conn 292 |> put_status(:internal_server_error) 293 |> json(%{error: "Error: emoji pack directory must be writable"}) 294 295 {:error, _} -> 296 conn 297 |> put_status(:internal_server_error) 298 |> json(%{error: "Error accessing emoji pack directory"}) 299 end 300 end 301 302 defp get_filename(%Plug.Upload{filename: filename}), do: filename 303 defp get_filename(url) when is_binary(url), do: Path.basename(url) 304 end