emojidex 0.0.23 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.rubocop.yml +3 -0
  4. data/.travis.yml +7 -6
  5. data/Gemfile +0 -2
  6. data/Guardfile +17 -8
  7. data/README.md +54 -17
  8. data/emojidex.gemspec +4 -1
  9. data/lib/emojidex.rb +12 -10
  10. data/lib/emojidex/{categories.rb → data/categories.rb} +3 -4
  11. data/lib/emojidex/{category.rb → data/category.rb} +1 -1
  12. data/lib/emojidex/data/collection.rb +158 -0
  13. data/lib/emojidex/data/collection/asset_information.rb +52 -0
  14. data/lib/emojidex/data/collection/cache.rb +137 -0
  15. data/lib/emojidex/{collection → data/collection}/moji_data.rb +1 -1
  16. data/lib/emojidex/data/collection/static_collection.rb +35 -0
  17. data/lib/emojidex/data/collection_checker.rb +94 -0
  18. data/lib/emojidex/{emoji.rb → data/emoji.rb} +3 -2
  19. data/lib/emojidex/data/emoji/asset_information.rb +45 -0
  20. data/lib/emojidex/data/extended.rb +18 -0
  21. data/lib/emojidex/data/utf.rb +18 -0
  22. data/lib/emojidex/defaults.rb +21 -0
  23. data/lib/emojidex/env_helper.rb +11 -0
  24. data/lib/emojidex/service/collection.rb +67 -0
  25. data/lib/emojidex/service/error.rb +9 -0
  26. data/lib/emojidex/service/indexes.rb +43 -0
  27. data/lib/emojidex/service/search.rb +82 -0
  28. data/lib/emojidex/service/transactor.rb +100 -0
  29. data/lib/emojidex/service/user.rb +233 -0
  30. data/spec/{categories_spec.rb → emojidex/data/categories_spec.rb} +4 -3
  31. data/spec/{collection_checker_spec.rb → emojidex/data/collection_checker_spec.rb} +12 -15
  32. data/spec/{collection_spec.rb → emojidex/data/collection_spec.rb} +40 -23
  33. data/spec/{emoji_spec.rb → emojidex/data/emoji_spec.rb} +2 -2
  34. data/spec/{extended_spec.rb → emojidex/data/extended_spec.rb} +21 -10
  35. data/spec/{utf_spec.rb → emojidex/data/utf_spec.rb} +22 -17
  36. data/spec/emojidex/service/collection_spec.rb +20 -0
  37. data/spec/emojidex/service/error_spec.rb +17 -0
  38. data/spec/emojidex/service/indexes_spec.rb +62 -0
  39. data/spec/emojidex/service/search_spec.rb +87 -0
  40. data/spec/emojidex/service/transactor_spec.rb +11 -0
  41. data/spec/emojidex/service/user_spec.rb +128 -0
  42. data/spec/spec_helper.rb +9 -62
  43. metadata +36 -31
  44. data/lib/emojidex/api/categories.rb +0 -16
  45. data/lib/emojidex/api/emoji.rb +0 -26
  46. data/lib/emojidex/api/search/emoji.rb +0 -16
  47. data/lib/emojidex/client.rb +0 -60
  48. data/lib/emojidex/collection.rb +0 -156
  49. data/lib/emojidex/collection/asset_information.rb +0 -49
  50. data/lib/emojidex/collection/cache.rb +0 -78
  51. data/lib/emojidex/collection_checker.rb +0 -93
  52. data/lib/emojidex/emoji/asset_information.rb +0 -20
  53. data/lib/emojidex/error.rb +0 -15
  54. data/lib/emojidex/extended.rb +0 -19
  55. data/lib/emojidex/service.rb +0 -32
  56. data/lib/emojidex/utf.rb +0 -19
  57. data/spec/api/categories_spec.rb +0 -49
  58. data/spec/api/emoji_spec.rb +0 -89
  59. data/spec/api/search/emoji_spec.rb +0 -30
  60. data/spec/client_spec.rb +0 -24
@@ -0,0 +1,137 @@
1
+ require 'json'
2
+ require 'fileutils'
3
+ require_relative 'asset_information'
4
+ require_relative '../../service/transactor'
5
+ require_relative '../../defaults'
6
+
7
+ module Emojidex
8
+ module Data
9
+ # local caching functionality for collections
10
+ module CollectionCache
11
+ include Emojidex::Data::CollectionAssetInformation
12
+ attr_reader :cache_path, :download_queue
13
+ attr_accessor :download_threads
14
+
15
+ def setup_cache(path = nil)
16
+ @download_queue = []
17
+ @download_threads = 8
18
+ # check if cache dir is already set
19
+ return @cache_path if @cache_path && path.nil?
20
+ # setup cache
21
+ @cache_path = File.expand_path((path || ENV['EMOJI_CACHE'] || "#{ENV['HOME']}/.emojidex/") + '/emoji')
22
+ # ENV['EMOJI_CACHE'] = @cache_path
23
+ FileUtils.mkdir_p(@cache_path)
24
+ Emojidex::Defaults.sizes.keys.each do |size|
25
+ FileUtils.mkdir_p(@cache_path + "/#{size}")
26
+ end
27
+ @cache_path
28
+ end
29
+
30
+ # Caches emoji to local emoji storage cache
31
+ # Options:
32
+ # cache_path: manually specify cache location
33
+ # (default is ENV['EMOJI_CACHE'] or '$HOME/.emoji_cache')
34
+ # formats: formats to cache (default is SVG only)
35
+ # sizes: sizes to cache (default is px32, but this is irrelivant for SVG)
36
+ def cache!(options = {})
37
+ setup_cache options[:cache_path]
38
+ formats = options[:formats] || Emojidex::Defaults.selected_formats
39
+ sizes = options[:sizes] || Emojidex::Defaults.selected_sizes
40
+ @emoji.values.each do |moji|
41
+ _svg_check_copy(moji) if formats.include? :svg
42
+ _raster_check_copy(moji, :png, sizes) if formats.include? :png
43
+ end
44
+ _process_download_queue
45
+ cache_index
46
+ end
47
+
48
+ # Updates an index in the specified destination (or the cache path if not specified).
49
+ # This method reads the existing index, combines the contents with this collection, and
50
+ # writes the results.
51
+ def cache_index(destination = nil)
52
+ destination ||= @cache_path
53
+ idx = Emojidex::Data::Collection.new
54
+ idx.load_local_collection(destination) if FileTest.exist? "#{destination}/emoji.json"
55
+ idx.add_emoji @emoji.values
56
+ File.open("#{destination}/emoji.json", 'w') { |f| f.write idx.emoji.values.to_json }
57
+ end
58
+
59
+ # [over]writes a sanitized index to the specified destination.
60
+ # WARNING: This method destroys any index files in the destination.
61
+ def write_index(destination)
62
+ idx = @emoji.values.to_json
63
+ idx = JSON.parse idx
64
+ idx.each { |moji| moji.delete_if{ |k, v| v.nil? }}
65
+ File.open("#{destination}/emoji.json", 'w') { |f| f.write idx.to_json }
66
+ end
67
+
68
+ private
69
+
70
+ def _svg_check_copy(moji)
71
+ @download_queue << { moji: moji, formats: :svg, sizes: [] } if @vector_source_path.nil? && @source_path.nil?
72
+ @vector_source_path = @source_path if @vector_source_path.nil?
73
+ src = "#{@vector_source_path}/#{moji.code}.svg"
74
+ if File.exist? "#{src}"
75
+ unless File.exist?("#{@cache_path}/#{moji.code}") &&
76
+ FileUtils.compare_file("#{src}", "#{@cache_path}/#{moji.code}.svg")
77
+ FileUtils.cp("#{src}", @cache_path)
78
+ end
79
+ else
80
+ _cache_svg_from_net(moji)
81
+ end
82
+ FileUtils.cp_r src, @cache_path if File.directory? src
83
+ end
84
+
85
+ def _raster_check_copy(moji, format, sizes)
86
+ @download_queue << { moji: moji, formats: [format], sizes: sizes } if @raster_source_path.nil? && @source_path.nil?
87
+ @raster_source_path = @source_path if @raster_source_path.nil?
88
+ _cache_raster_from_net(moji, format, sizes) if @raster_source_path.nil?
89
+ sizes.each do |size|
90
+ src = "#{@raster_source_path}/#{size}/#{moji.code}"
91
+ if FileTest.exist? "#{src}.#{format}"
92
+ FileUtils.cp("#{src}.#{format}", ("#{@cache_path}/#{size}"))
93
+ else
94
+ _cache_raster_from_net(moji, format, sizes)
95
+ end
96
+ FileUtils.cp_r(src, @cache_path) if File.directory? src
97
+ end
98
+ end
99
+
100
+ def _process_download_queue
101
+ thr = []
102
+ @download_queue.each do |dl|
103
+ thr << Thread.new { _cache_from_net(dl[:moji], dl[:formats], dl[:sizes]) }
104
+ thr.each { |t| t.join } if thr.length >= @download_threads
105
+ end
106
+ end
107
+
108
+ def _cache_from_net(moji, formats, sizes)
109
+ formats = *formats unless formats.class == Array
110
+ dls = []
111
+ dls << Thread.new { _cache_svg_from_net(moji) } if formats.include? :svg
112
+ dls << Thread.new { _cache_raster_from_net(moji, :png, sizes) } if formats.include? :png
113
+ dls.each { |t| t.join }
114
+ end
115
+
116
+ def _cache_svg_from_net(moji)
117
+ target = "#{@cache_path}/#{moji.code}.svg"
118
+ if File.exist? target # check for an existing copy so we don't double downlaod
119
+ return if moji.checksum?(:svg).nil? # no updates if we didn't get details
120
+ # if the checksums are the same there is no reason to update
121
+ return if moji.checksum?(:svg) == get_checksums(moji, [:svg])[:svg]
122
+ end
123
+ response = Emojidex::Service::Transactor.download("#{moji.code}.svg")
124
+ File.open(target, 'wb') { |fp|
125
+ fp.write(response.body) }
126
+ end
127
+
128
+ def _cache_raster_from_net(moji, format, sizes)
129
+ sizes.each do |size|
130
+ response = Emojidex::Service::Transactor.download("#{size}/#{moji.code}.#{format.to_s}")
131
+ File.open("#{@cache_path}/#{size}/#{moji.code}.#{format.to_s}", 'wb') { |fp|
132
+ fp.write(response.body) }
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -1,4 +1,4 @@
1
- module Emojidex
1
+ module Emojidex::Data
2
2
  # collects and condenses UTF moji codes within a collection
3
3
  module CollectionMojiData
4
4
  attr_reader :moji_code_string, :moji_code_index
@@ -0,0 +1,35 @@
1
+ require_relative '../../service/transactor'
2
+ require_relative '../../env_helper'
3
+
4
+ module Emojidex
5
+ module Data
6
+ # mixin module to enable static collections
7
+ module StaticCollection
8
+ def load_from_server(detailed = true, locale = '??')
9
+ locale = Emojidex::EnvHelper.lang? if locale == '??'
10
+ begin
11
+ res = Emojidex::Service::Transactor.get(@endpoint, {detailed: detailed, locale: locale})
12
+ rescue
13
+ return false
14
+ end
15
+ add_emoji(res)
16
+ return true
17
+ end
18
+
19
+ def check_and_load_static(collection)
20
+ loaded = false
21
+ if defined? Emojidex::Vectors
22
+ @vector_source_path = Emojidex::Vectors.path + "/#{collection}/"
23
+ load_local_collection @vector_source_path
24
+ loaded = true
25
+ end
26
+ if defined? Emojidex::Rasters
27
+ @raster_source_path = Emojidex::Rasters.path + "/#{collection}/"
28
+ load_local_collection @raster_source_path
29
+ loaded = true
30
+ end
31
+ loaded
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,94 @@
1
+ require 'find'
2
+ require_relative '../defaults.rb'
3
+
4
+ module Emojidex
5
+ module Data
6
+ # Check collections for presence of image assets and discrepencies in emoji indexes.
7
+ class CollectionChecker
8
+ attr_reader :index_only, :asset_only
9
+
10
+ def initialize(collections, options = {})
11
+ collections = *collections
12
+ @index_only = {}
13
+ @asset_only = {}
14
+ asset_path = options[:asset_path] || collections.first.source_path
15
+ sizes = options[:sizes] || Emojidex::Defaults.sizes.keys
16
+ formats = options[:formats] || Emojidex::Defaults.formats
17
+
18
+ asset_files = create_asset_file_list(asset_path, sizes, formats)
19
+ check_for_index_only(collections, asset_files, sizes, formats)
20
+ check_for_asset_only(collections, asset_files)
21
+ end
22
+
23
+ private
24
+
25
+ def create_asset_file_list(dir, sizes, formats)
26
+ result = {}
27
+ result.merge!(create_file_list(dir, '.svg', '')) if formats.include?(:svg)
28
+ if formats.include?(:png)
29
+ sizes.each do |size|
30
+ result.merge!(create_file_list("#{dir}/#{size}", '.png', "#{size}/"))
31
+ end
32
+ end
33
+ result
34
+ end
35
+
36
+ def create_file_list(dir, ext, prefix)
37
+ result = {}
38
+ return result unless Dir.exists?(dir)
39
+ Dir.foreach(dir) do |file|
40
+ result["#{prefix}#{File.basename(file, '.*')}".to_sym] =
41
+ "#{prefix}#{file}" if File.extname(file) == ext
42
+ end
43
+ result
44
+ end
45
+
46
+ def check_for_index_only(collections, asset_files, sizes, formats)
47
+ collections.each do |collection|
48
+ collection.emoji.values.each do |emoji|
49
+ tmp = []
50
+ tmp += create_svg_array(emoji, asset_files) if formats.include?(:svg)
51
+ tmp += create_png_array(emoji, asset_files, sizes) if formats.include?(:png)
52
+ @index_only[emoji.code.to_sym] = tmp unless tmp.empty?
53
+ end
54
+ end
55
+ end
56
+
57
+ def create_svg_array(emoji, asset_files)
58
+ result = []
59
+ asset_file = asset_files[emoji.code.to_sym]
60
+ result << "#{emoji.code}.svg" if asset_files[emoji.code.to_sym].nil?
61
+ result
62
+ end
63
+
64
+ def create_png_array(emoji, asset_files, sizes)
65
+ result = []
66
+ sizes.each do |size|
67
+ name = "#{size}/#{emoji.code}"
68
+ result << "#{name}.png" if asset_files[name.to_sym].nil?
69
+ end
70
+ result
71
+ end
72
+
73
+ def check_for_asset_only(collections, asset_files)
74
+ asset_files.each do |_key, value|
75
+ code = File.basename(value, '.*')
76
+
77
+ next if find_emoji_from_collections(collections, code)
78
+
79
+ symbol = code.to_sym
80
+ @asset_only[symbol] = [] if @asset_only[symbol].nil?
81
+ @asset_only[symbol] << value
82
+ end
83
+ end
84
+
85
+ def find_emoji_from_collections(collections, code)
86
+ symbol = code.to_sym
87
+ collections.each do |collection|
88
+ return true unless collection.emoji[symbol].nil?
89
+ end
90
+ false
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,14 +1,15 @@
1
1
  require_relative 'emoji/asset_information'
2
2
 
3
- module Emojidex
3
+ module Emojidex::Data
4
4
  # emoji base class
5
5
  class Emoji
6
6
  attr_accessor :moji, :category, :code, :code_ja,
7
7
  :unicode, :tags, :emoticon, :variants, :base
8
8
 
9
- include Emojidex::EmojiAssetInformation
9
+ include Emojidex::Data::EmojiAssetInformation
10
10
 
11
11
  def initialize(details = {})
12
+ init_asset_info(details)
12
13
  @moji = details[:moji]
13
14
  @code, @code_ja = details[:code], details[:code_ja]
14
15
  @unicode, @full_name = details[:unicode], details[:full_name]
@@ -0,0 +1,45 @@
1
+ require_relative '../../defaults'
2
+
3
+ module Emojidex
4
+ module Data
5
+ # Asset information for emoji
6
+ module EmojiAssetInformation
7
+ attr_accessor :checksums, :paths
8
+
9
+ def init_asset_info(details)
10
+ blank_checksums
11
+ fill_checksums(details[:checksums]) if details.include? :checksums
12
+ end
13
+
14
+ # returns asset checksum
15
+ def checksum?(format, size = nil)
16
+ puts @checksums
17
+ return @checksums[format][size] unless size.nil?
18
+ @checksums[format]
19
+ end
20
+
21
+ def blank_checksums
22
+ @checksums = {}
23
+ @checksums[:svg] = nil
24
+ @checksums[:png] = {}
25
+ Emojidex::Defaults.sizes.keys.each do |size|
26
+ @checksums[:png][size] = nil
27
+ end
28
+ end
29
+
30
+ def fill_checksums(checksums)
31
+ @checksums[:svg] = checksums[:svg] if checksums.include? :svg
32
+ return unless checksums.include? :png
33
+ Emojidex::Defaults.sizes.keys.each do |size|
34
+ @checksums[:png][size] = checksums[:png][size] if checksums[:png].include? size
35
+ end
36
+ end
37
+
38
+ # returns asset path
39
+ def path?(format, size = nil)
40
+ return @paths[format][size] unless size.nil?
41
+ @paths[format]
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'collection'
2
+ require_relative 'collection/static_collection'
3
+
4
+ module Emojidex
5
+ module Data
6
+ # listing and search of extended emoji from the emojidex set
7
+ class Extended < Collection
8
+ include Emojidex::Data::StaticCollection
9
+
10
+ def initialize
11
+ super
12
+ @endpoint = 'extended_emoji'
13
+ load_from_server unless check_and_load_static('extended')
14
+ @emoji
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'collection'
2
+ require_relative 'collection/static_collection'
3
+
4
+ module Emojidex
5
+ module Data
6
+ # listing and search of standard UTF emoji
7
+ class UTF < Collection
8
+ include Emojidex::Data::StaticCollection
9
+
10
+ def initialize
11
+ super
12
+ @endpoint = 'utf_emoji'
13
+ load_from_server unless check_and_load_static('utf')
14
+ @emoji
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,14 +1,35 @@
1
1
  module Emojidex
2
2
  # Global defines for emojidex
3
3
  class Defaults
4
+ @@selected_sizes = [:mdpi, :px32]
5
+ @@selected_formats = [:png]
6
+
4
7
  def self.sizes
5
8
  { ldpi: 13, mdpi: 18, hdpi: 27, xhdpi: 36, xxhdpi: 54, xxxhdpi: 72,
6
9
  px8: 8, px16: 16, px32: 32, px64: 64, px128: 128, px256: 256, px512: 512,
7
10
  hanko: 90, seal: 320 }
8
11
  end
9
12
 
13
+ def self.selected_sizes(sizes = nil)
14
+ @@selected_sizes = sizes unless sizes.nil?
15
+ @@selected_sizes
16
+ end
17
+
10
18
  def self.formats
11
19
  [:svg, :png]
12
20
  end
21
+
22
+ def self.selected_formats(formats = nil)
23
+ @@selected_formats = formats unless formats.nil?
24
+ @@selected_formats
25
+ end
26
+
27
+ def self.limit
28
+ 50
29
+ end
30
+
31
+ def self.lang
32
+ 'en'
33
+ end
13
34
  end
14
35
  end
@@ -0,0 +1,11 @@
1
+ module Emojidex
2
+ # Obtains and parses local environment variables
3
+ module EnvHelper
4
+
5
+ def self.lang?
6
+ lang = ENV['LANG'].match('^..')
7
+ lang = 'en' unless lang.to_s == 'ja'
8
+ lang
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,67 @@
1
+ require_relative '../data/collection'
2
+ require_relative 'transactor'
3
+ require_relative '../defaults'
4
+
5
+ module Emojidex
6
+ module Service
7
+ # A modified collection class for collections tied to the emojidex service
8
+ class Collection < Emojidex::Data::Collection
9
+ attr_reader :endpoint, :page, :limit, :detailed, :auto_cache
10
+
11
+ def initialize(opts = {})
12
+ @emoji = {}
13
+ add_emoji(opts[:emoji]) && opts.delete(:emoji) if opts.include? :emoji
14
+
15
+ @username = opts[:username] || nil
16
+ opts.delete(:username)
17
+ @auth_token = opts[:auth_token] || nil
18
+ opts.delete(:auth_token)
19
+
20
+ @endpoint = opts[:endpoint] || 'emoji'
21
+ opts.delete(:endpoint)
22
+ @page = opts[:page] || 0
23
+ opts.delete(:page)
24
+ @limit = opts[:limit] || Emojidex::Defaults.limit
25
+ opts.delete(:limit)
26
+ @detailed = opts[:detailed] || false
27
+ opts.delete(:detailed)
28
+
29
+ @auto_cache = opts[:auto_cache] || true
30
+ opts.delete(:auto_cache)
31
+
32
+ auto_init = opts[:auto_init] || true
33
+ opts.delete(:auto_init)
34
+
35
+ @opts = opts
36
+
37
+ more if auto_init
38
+ @emoji
39
+ end
40
+
41
+ # Get the next page worth of emoji and add them to the collection
42
+ def more()
43
+ @page += 1
44
+
45
+ opts = { page: @page, limit: @limit, detailed: @detailed }
46
+ opts[:username] = @username unless @username.nil?
47
+ opts[:auth_token] = @auth_token unless @auth_token.nil?
48
+ opts.merge! @opts
49
+
50
+ page_moji = Emojidex::Service::Transactor.get(@endpoint, opts)
51
+
52
+ if page_moji.is_a? Hash
53
+ unless page_moji.key? :emoji
54
+ @page -= 1 # reset page beacuse we failed
55
+ return {}
56
+ end
57
+
58
+ add_emoji(page_moji[:emoji])
59
+ return page_moji[:emoji]
60
+ end
61
+ add_emoji(page_moji)
62
+ cache! if @auto_cache
63
+ page_moji
64
+ end
65
+ end
66
+ end
67
+ end