discourse/lib/tasks/emoji.rake
2017-01-24 16:18:39 +08:00

128 lines
3.5 KiB
Ruby

EMOJI_LIST_URL = "http://unicode.org/emoji/charts/full-emoji-list.html"
EMOJI_KEYWORDS_URL = "https://raw.githubusercontent.com/muan/emojilib/master/emojis.json"
# until MS release the emoji flags, we'll use custom made flags
WINDOWS_FLAGS = Set.new ["1f1e8_1f1f3", "1f1e9_1f1ea", "1f1ea_1f1f8", "1f1eb_1f1f7", "1f1ec_1f1e7", "1f1ee_1f1f9", "1f1ef_1f1f5", "1f1f0_1f1f7", "1f1f7_1f1fa", "1f1fa_1f1f8"]
desc "update emoji images"
task "emoji:update" => :environment do
emojis = {}
puts "Loading local emoji database..."
db = JSON.parse(File.read("lib/emoji/db.json"))
db["emojis"].each do |e|
emojis[e["code"].tr("-", "_")] = { name: e["name"] }
end
aliases = db["aliases"].to_h
puts "Enhancing emoji database with emojilib keywords..."
keywords = JSON.parse(open(EMOJI_KEYWORDS_URL).read)
keywords.keys.each do |k|
next unless char = keywords[k]["char"].presence
code = char.codepoints
.map { |c| c.to_s(16).rjust(4, "0") }
.join("_")
.downcase
.gsub(/_fe0f$/, "")
emojis[code] ||= { name: k }
end
puts "Retrieving remote emoji list..."
list = open(EMOJI_LIST_URL).read
puts "Parsing remote emoji list..."
doc = Nokogiri::HTML(list)
doc.css("tr").each do |row|
cells = row.css("td")
next if cells.size == 0
code = cells[1].at_css("a")["name"]
unless emojis[code]
code = code.gsub(/_fe0f/, "")
next unless emojis[code]
end
apple = cell_to_image(cells[4])
google = cell_to_image(cells[5])
twitter = cell_to_image(cells[6])
one = cell_to_image(cells[7])
if WINDOWS_FLAGS.include?(code)
windows = custom_windows_flag(code)
else
windows = cell_to_image(cells[11])
end
if apple.blank? || google.blank? || twitter.blank? || one.blank? || windows.blank?
emojis.delete(code)
next
end
emojis[code][:apple] = apple
emojis[code][:google] = google
emojis[code][:twitter] = twitter
emojis[code][:one] = one
emojis[code][:windows] = windows
end
puts "Writing emojis..."
write_emojis(emojis, aliases, :apple, "apple")
write_emojis(emojis, aliases, :google, "google")
write_emojis(emojis, aliases, :twitter, "twitter")
write_emojis(emojis, aliases, :one, "emoji_one")
write_emojis(emojis, aliases, :windows, "win10")
puts "Updating db.json..."
db = {
"emojis" => emojis.keys.map { |k| { "code" => k.tr("_", "-"), "name" => emojis[k][:name] } },
"aliases" => aliases,
}
File.write("lib/emoji/db.json", JSON.pretty_generate(db))
puts "Done!"
end
def cell_to_image(cell)
return unless img = cell.at_css("img")
Base64.decode64(img["src"][/base64,(.+)$/, 1])
end
def custom_windows_flag(code)
name = code.upcase.tr("_", "-")
open("https://github.com/discourse/discourse-emoji-extractor/raw/master/win10/72x72/windows_#{name}.png").read
end
def write_emojis(emojis, aliases, style, folder)
path = "public/images/emoji/#{folder}"
# Uncomment to recreate all emojis
# FileUtils.rm_f Dir.glob("#{path}/*")
puts folder
emojis.values.each do |emoji|
next if emoji[style].nil?
write_emoji("#{path}/#{emoji[:name]}.png", emoji[style])
if aliases[emoji[:name]]
aliases[emoji[:name]].each do |new_name|
write_emoji("#{path}/#{new_name}.png", emoji[style])
end
end
end
puts
end
def write_emoji(path, emoji)
open(path, "wb") { |f| f << emoji }
`pngout #{path}`
putc "."
ensure
raise "Failed to write emoji: #{path}" if File.exists?(path) && !File.size?(path)
end