1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Mix.Tasks.Pleroma.Emoji do
8 @shortdoc "Manages Pleroma instance"
12 @default_manifest Pleroma.Config.get!([:emoji, :default_manifest])
14 def run(["ls-packs" | args]) do
15 Application.ensure_all_started(:hackney)
17 {options, [], []} = parse_global_opts(args)
20 fetch_manifest(if options[:manifest], do: options[:manifest], else: @default_manifest)
22 Enum.each(manifest, fn {name, info} ->
25 {"Homepage", info["homepage"]},
26 {"Description", info["description"]},
27 {"License", info["license"]},
28 {"Source", info["src"]}
31 for {param, value} <- to_print do
32 IO.puts(IO.ANSI.format([:bright, param, :normal, ": ", value]))
40 def run(["get-packs" | args]) do
41 Application.ensure_all_started(:hackney)
43 {options, pack_names, []} = parse_global_opts(args)
45 manifest_url = if options[:manifest], do: options[:manifest], else: @default_manifest
47 manifest = fetch_manifest(manifest_url)
49 for pack_name <- pack_names do
50 if Map.has_key?(manifest, pack_name) do
51 pack = manifest[pack_name]
66 binary_archive = Tesla.get!(src_url).body
67 archive_md5 = :crypto.hash(:md5, binary_archive) |> Base.encode16()
69 md5_status_text = ["MD5 of ", :bright, pack_name, :normal, " source file is ", :bright]
71 if archive_md5 == String.upcase(pack["src_md5"]) do
72 IO.puts(IO.ANSI.format(md5_status_text ++ [:green, "OK"]))
74 IO.puts(IO.ANSI.format(md5_status_text ++ [:red, "BAD"]))
76 raise "Bad MD5 for #{pack_name}"
79 # The url specified in files should be in the same directory
80 files_url = Path.join(Path.dirname(manifest_url), pack["files"])
84 "Fetching the file list for ",
94 files = Tesla.get!(files_url).body |> Poison.decode!()
96 IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name]))
98 static_path = Path.join(:code.priv_dir(:pleroma), "static")
103 Pleroma.Config.get!([:instance, :static_dir]),
111 fn {_, f} -> to_charlist(f) end
115 :zip.unzip(binary_archive,
117 file_list: files_to_unzip
120 IO.puts(IO.ANSI.format(["Writing emoji.txt for ", :bright, pack_name]))
125 Pleroma.Config.get!([:instance, :static_dir]),
133 fn {shortcode, path} ->
134 "#{shortcode}, #{Path.join(common_pack_path, path)}"
139 File.write!(Path.join(pack_path, "emoji.txt"), emoji_txt_str)
141 IO.puts(IO.ANSI.format([:bright, :red, "No pack named \"#{pack_name}\" found"]))
146 def run(["gen-pack", src]) do
147 Application.ensure_all_started(:hackney)
149 proposed_name = Path.basename(src) |> Path.rootname()
150 name = String.trim(IO.gets("Pack name [#{proposed_name}]: "))
151 # If there's no name, use the default one
152 name = if String.length(name) > 0, do: name, else: proposed_name
154 license = String.trim(IO.gets("License: "))
155 homepage = String.trim(IO.gets("Homepage: "))
156 description = String.trim(IO.gets("Description: "))
158 proposed_files_name = "#{name}.json"
159 files_name = String.trim(IO.gets("Save file list to [#{proposed_files_name}]: "))
160 files_name = if String.length(files_name) > 0, do: files_name, else: proposed_files_name
162 default_exts = [".png", ".gif"]
163 default_exts_str = Enum.join(default_exts, " ")
167 IO.gets("Emoji file extensions (separated with spaces) [#{default_exts_str}]: ")
171 if String.length(exts) > 0 do
172 String.split(exts, " ")
173 |> Enum.filter(fn e -> e |> String.trim() |> String.length() > 0 end)
178 IO.puts("Downloading the pack and generating MD5")
180 binary_archive = Tesla.get!(src).body
181 archive_md5 = :crypto.hash(:md5, binary_archive) |> Base.encode16()
183 IO.puts("MD5 is #{archive_md5}")
189 description: description,
191 src_md5: archive_md5,
196 tmp_pack_dir = Path.join(System.tmp_dir!(), "emoji-pack-#{name}")
204 emoji_map = Pleroma.Emoji.make_shortcode_to_file_map(tmp_pack_dir, exts)
206 File.write!(files_name, Poison.encode!(emoji_map, pretty: true))
210 #{files_name} has been created and contains the list of all found emojis in the pack.
211 Please review the files in the remove those not needed.
214 if File.exists?("index.json") do
215 existing_data = File.read!("index.json") |> Poison.decode!()
228 IO.puts("index.json file has been update with the #{name} pack")
230 File.write!("index.json", Poison.encode!(pack_json, pretty: true))
232 IO.puts("index.json has been created with the #{name} pack")
236 defp fetch_manifest(from) do
238 if String.starts_with?(from, "http") do
239 Tesla.get!(from).body
246 defp parse_global_opts(args) do