1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Mix.Tasks.Pleroma.Emoji do
8 @shortdoc "Manages emoji packs"
9 @moduledoc File.read!("docs/administration/CLI_tasks/emoji.md")
11 def run(["ls-packs" | args]) do
12 Application.ensure_all_started(:hackney)
14 {options, [], []} = parse_global_opts(args)
17 fetch_manifest(if options[:manifest], do: options[:manifest], else: default_manifest())
19 Enum.each(manifest, fn {name, info} ->
22 {"Homepage", info["homepage"]},
23 {"Description", info["description"]},
24 {"License", info["license"]},
25 {"Source", info["src"]}
28 for {param, value} <- to_print do
29 IO.puts(IO.ANSI.format([:bright, param, :normal, ": ", value]))
37 def run(["get-packs" | args]) do
38 Application.ensure_all_started(:hackney)
40 {options, pack_names, []} = parse_global_opts(args)
42 manifest_url = if options[:manifest], do: options[:manifest], else: default_manifest()
44 manifest = fetch_manifest(manifest_url)
46 for pack_name <- pack_names do
47 if Map.has_key?(manifest, pack_name) do
48 pack = manifest[pack_name]
63 binary_archive = Tesla.get!(client(), src_url).body
64 archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16()
66 sha_status_text = ["SHA256 of ", :bright, pack_name, :normal, " source file is ", :bright]
68 if archive_sha == String.upcase(pack["src_sha256"]) do
69 IO.puts(IO.ANSI.format(sha_status_text ++ [:green, "OK"]))
71 IO.puts(IO.ANSI.format(sha_status_text ++ [:red, "BAD"]))
73 raise "Bad SHA256 for #{pack_name}"
76 # The url specified in files should be in the same directory
77 files_url = Path.join(Path.dirname(manifest_url), pack["files"])
81 "Fetching the file list for ",
91 files = Tesla.get!(client(), files_url).body |> Jason.decode!()
93 IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name]))
97 Pleroma.Config.get!([:instance, :static_dir]),
105 fn {_, f} -> to_charlist(f) end
109 :zip.unzip(binary_archive,
111 file_list: files_to_unzip
114 IO.puts(IO.ANSI.format(["Writing pack.json for ", :bright, pack_name]))
118 "license" => pack["license"],
119 "homepage" => pack["homepage"],
120 "description" => pack["description"],
121 "fallback-src" => pack["src"],
122 "fallback-src-sha256" => pack["src_sha256"],
123 "share-files" => true
128 File.write!(Path.join(pack_path, "pack.json"), Jason.encode!(pack_json, pretty: true))
130 IO.puts(IO.ANSI.format([:bright, :red, "No pack named \"#{pack_name}\" found"]))
135 def run(["gen-pack", src]) do
136 Application.ensure_all_started(:hackney)
138 proposed_name = Path.basename(src) |> Path.rootname()
139 name = String.trim(IO.gets("Pack name [#{proposed_name}]: "))
140 # If there's no name, use the default one
141 name = if String.length(name) > 0, do: name, else: proposed_name
143 license = String.trim(IO.gets("License: "))
144 homepage = String.trim(IO.gets("Homepage: "))
145 description = String.trim(IO.gets("Description: "))
147 proposed_files_name = "#{name}.json"
148 files_name = String.trim(IO.gets("Save file list to [#{proposed_files_name}]: "))
149 files_name = if String.length(files_name) > 0, do: files_name, else: proposed_files_name
151 default_exts = [".png", ".gif"]
152 default_exts_str = Enum.join(default_exts, " ")
156 IO.gets("Emoji file extensions (separated with spaces) [#{default_exts_str}]: ")
160 if String.length(exts) > 0 do
161 String.split(exts, " ")
162 |> Enum.filter(fn e -> e |> String.trim() |> String.length() > 0 end)
167 IO.puts("Downloading the pack and generating SHA256")
169 binary_archive = Tesla.get!(client(), src).body
170 archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16()
172 IO.puts("SHA256 is #{archive_sha}")
178 description: description,
180 src_sha256: archive_sha,
185 tmp_pack_dir = Path.join(System.tmp_dir!(), "emoji-pack-#{name}")
193 emoji_map = Pleroma.Emoji.Loader.make_shortcode_to_file_map(tmp_pack_dir, exts)
195 File.write!(files_name, Jason.encode!(emoji_map, pretty: true))
199 #{files_name} has been created and contains the list of all found emojis in the pack.
200 Please review the files in the remove those not needed.
203 if File.exists?("index.json") do
204 existing_data = File.read!("index.json") |> Jason.decode!()
217 IO.puts("index.json file has been update with the #{name} pack")
219 File.write!("index.json", Jason.encode!(pack_json, pretty: true))
221 IO.puts("index.json has been created with the #{name} pack")
225 defp fetch_manifest(from) do
227 if String.starts_with?(from, "http") do
228 Tesla.get!(client(), from).body
235 defp parse_global_opts(args) do
249 {Tesla.Middleware.FollowRedirects, [max_redirects: 3]}
252 Tesla.client(middleware)
255 defp default_manifest, do: Pleroma.Config.get!([:emoji, :default_manifest])