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]))
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!(src_url).body
64 archive_md5 = :crypto.hash(:md5, binary_archive) |> Base.encode16()
66 md5_status_text = ["MD5 of ", :bright, pack_name, :normal, " source file is ", :bright]
68 if archive_md5 == String.upcase(pack["src_md5"]) do
69 IO.puts(IO.ANSI.format(md5_status_text ++ [:green, "OK"]))
71 IO.puts(IO.ANSI.format(md5_status_text ++ [:red, "BAD"]))
73 raise "Bad MD5 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!(files_url).body |> Poison.decode!()
93 IO.puts(IO.ANSI.format(["Unpacking ", :bright, pack_name]))
95 static_path = Path.join(:code.priv_dir(:pleroma), "static")
100 Pleroma.Config.get!([:instance, :static_dir]),
108 fn {_, f} -> to_charlist(f) end
112 :zip.unzip(binary_archive,
114 file_list: files_to_unzip
117 IO.puts(IO.ANSI.format(["Writing emoji.txt for ", :bright, pack_name]))
122 Pleroma.Config.get!([:instance, :static_dir]),
130 fn {shortcode, path} ->
131 "#{shortcode}, #{Path.join(common_pack_path, path)}"
136 File.write!(Path.join(pack_path, "emoji.txt"), emoji_txt_str)
138 IO.puts(IO.ANSI.format([:bright, :red, "No pack named \"#{pack_name}\" found"]))
143 def run(["gen-pack", src]) do
144 Application.ensure_all_started(:hackney)
146 proposed_name = Path.basename(src) |> Path.rootname()
147 name = String.trim(IO.gets("Pack name [#{proposed_name}]: "))
148 # If there's no name, use the default one
149 name = if String.length(name) > 0, do: name, else: proposed_name
151 license = String.trim(IO.gets("License: "))
152 homepage = String.trim(IO.gets("Homepage: "))
153 description = String.trim(IO.gets("Description: "))
155 proposed_files_name = "#{name}.json"
156 files_name = String.trim(IO.gets("Save file list to [#{proposed_files_name}]: "))
157 files_name = if String.length(files_name) > 0, do: files_name, else: proposed_files_name
159 default_exts = [".png", ".gif"]
160 default_exts_str = Enum.join(default_exts, " ")
164 IO.gets("Emoji file extensions (separated with spaces) [#{default_exts_str}]: ")
168 if String.length(exts) > 0 do
169 String.split(exts, " ")
170 |> Enum.filter(fn e -> e |> String.trim() |> String.length() > 0 end)
175 IO.puts("Downloading the pack and generating MD5")
177 binary_archive = Tesla.get!(src).body
178 archive_md5 = :crypto.hash(:md5, binary_archive) |> Base.encode16()
180 IO.puts("MD5 is #{archive_md5}")
186 description: description,
188 src_md5: archive_md5,
193 tmp_pack_dir = Path.join(System.tmp_dir!(), "emoji-pack-#{name}")
201 emoji_map = Pleroma.Emoji.make_shortcode_to_file_map(tmp_pack_dir, exts)
203 File.write!(files_name, Poison.encode!(emoji_map, pretty: true))
207 #{files_name} has been created and contains the list of all found emojis in the pack.
208 Please review the files in the remove those not needed.
211 if File.exists?("index.json") do
212 existing_data = File.read!("index.json") |> Poison.decode!()
225 IO.puts("index.json file has been update with the #{name} pack")
227 File.write!("index.json", Poison.encode!(pack_json, pretty: true))
229 IO.puts("index.json has been created with the #{name} pack")
233 defp fetch_manifest(from) do
235 if String.starts_with?(from, "http") do
236 Tesla.get!(from).body
243 defp parse_global_opts(args) do