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"
10 def run(["ls-packs" | args]) do
11 Application.ensure_all_started(:hackney)
13 {options, [], []} = parse_global_opts(args)
16 fetch_manifest(if options[:manifest], do: options[:manifest], else: default_manifest())
18 Enum.each(manifest, fn {name, info} ->
21 {"Homepage", info["homepage"]},
22 {"Description", info["description"]},
23 {"License", info["license"]},
24 {"Source", info["src"]}
27 for {param, value} <- to_print do
28 IO.puts(IO.ANSI.format([:bright, param, :normal, ": ", value]))
36 def run(["get-packs" | args]) do
37 Application.ensure_all_started(:hackney)
39 {options, pack_names, []} = parse_global_opts(args)
41 manifest_url = if options[:manifest], do: options[:manifest], else: default_manifest()
43 manifest = fetch_manifest(manifest_url)
45 for pack_name <- pack_names do
46 if Map.has_key?(manifest, pack_name) do
47 pack = manifest[pack_name]
62 binary_archive = Tesla.get!(client(), src_url).body
63 archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16()
65 sha_status_text = ["SHA256 of ", :bright, pack_name, :normal, " source file is ", :bright]
67 if archive_sha == String.upcase(pack["src_sha256"]) do
68 IO.puts(IO.ANSI.format(sha_status_text ++ [:green, "OK"]))
70 IO.puts(IO.ANSI.format(sha_status_text ++ [:red, "BAD"]))
72 raise "Bad SHA256 for #{pack_name}"
75 # The url specified in files should be in the same directory
76 files_url = Path.join(Path.dirname(manifest_url), pack["files"])
80 "Fetching the file list for ",
90 files = Tesla.get!(client(), files_url).body |> Jason.decode!()
92 IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name]))
96 Pleroma.Config.get!([:instance, :static_dir]),
104 fn {_, f} -> to_charlist(f) end
108 :zip.unzip(binary_archive,
110 file_list: files_to_unzip
113 IO.puts(IO.ANSI.format(["Writing emoji.txt for ", :bright, pack_name]))
118 fn {shortcode, path} ->
119 emojo_path = Path.join("/emoji/#{pack_name}", path)
120 "#{shortcode}, #{emojo_path}"
125 File.write!(Path.join(pack_path, "emoji.txt"), emoji_txt_str)
127 IO.puts(IO.ANSI.format([:bright, :red, "No pack named \"#{pack_name}\" found"]))
132 def run(["gen-pack", src]) do
133 Application.ensure_all_started(:hackney)
135 proposed_name = Path.basename(src) |> Path.rootname()
136 name = String.trim(IO.gets("Pack name [#{proposed_name}]: "))
137 # If there's no name, use the default one
138 name = if String.length(name) > 0, do: name, else: proposed_name
140 license = String.trim(IO.gets("License: "))
141 homepage = String.trim(IO.gets("Homepage: "))
142 description = String.trim(IO.gets("Description: "))
144 proposed_files_name = "#{name}.json"
145 files_name = String.trim(IO.gets("Save file list to [#{proposed_files_name}]: "))
146 files_name = if String.length(files_name) > 0, do: files_name, else: proposed_files_name
148 default_exts = [".png", ".gif"]
149 default_exts_str = Enum.join(default_exts, " ")
153 IO.gets("Emoji file extensions (separated with spaces) [#{default_exts_str}]: ")
157 if String.length(exts) > 0 do
158 String.split(exts, " ")
159 |> Enum.filter(fn e -> e |> String.trim() |> String.length() > 0 end)
164 IO.puts("Downloading the pack and generating SHA256")
166 binary_archive = Tesla.get!(client(), src).body
167 archive_sha = :crypto.hash(:sha256, binary_archive) |> Base.encode16()
169 IO.puts("SHA256 is #{archive_sha}")
175 description: description,
177 src_sha256: archive_sha,
182 tmp_pack_dir = Path.join(System.tmp_dir!(), "emoji-pack-#{name}")
190 emoji_map = Pleroma.Emoji.Loader.make_shortcode_to_file_map(tmp_pack_dir, exts)
192 File.write!(files_name, Jason.encode!(emoji_map, pretty: true))
196 #{files_name} has been created and contains the list of all found emojis in the pack.
197 Please review the files in the remove those not needed.
200 if File.exists?("index.json") do
201 existing_data = File.read!("index.json") |> Jason.decode!()
214 IO.puts("index.json file has been update with the #{name} pack")
216 File.write!("index.json", Jason.encode!(pack_json, pretty: true))
218 IO.puts("index.json has been created with the #{name} pack")
222 defp fetch_manifest(from) do
224 if String.starts_with?(from, "http") do
225 Tesla.get!(client(), from).body
232 defp parse_global_opts(args) do
246 {Tesla.Middleware.FollowRedirects, [max_redirects: 3]}
249 Tesla.client(middleware)
252 defp default_manifest, do: Pleroma.Config.get!([:emoji, :default_manifest])