factorio-mod 0.7.4 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99e67714c5a8a7065d398ce3856cb0fc16e77552f835932105e9c5c7ea04bc4f
4
- data.tar.gz: 68b1348aa4cbd5b6ff81b130e2dc161473e22209531bd4d3bec7b02834282e1e
3
+ metadata.gz: a64dc6e5adbfe4c002f365d4e2cec5a840c21af956eea41028f6a3e22effb371
4
+ data.tar.gz: 1b045b86aa35cf8c77c9d623be325b1d1d415b7a74f97d25c56748218dc4d93e
5
5
  SHA512:
6
- metadata.gz: 5d6ff848f61f0240103459bab49d5ddda23c1feb90fc6a5a33b808c21a6186754143c741003c9ba06bb38547b1e5d477e414379b028f313834840c234d0c8fe6
7
- data.tar.gz: d554ecbdf77d1bc6be66b79b22fc7f103457c67ee4d626d2d82033edfd52ecc56b7e2dc9f7145635ff63ba53ae292f54d5e8050cfa7a2a696e08030d321c085e
6
+ metadata.gz: 30a22a49ac54d74bf802163ca09db375545d5788f69e565dd786bca3fef53e7db1fcccabd36e42e226f9ff439f868586351857826dd4728bd674ac9736c91b33
7
+ data.tar.gz: d4292069cda2d153f26903a188e744f5b52a68457280629fd70b97af36d880d48f8a538e15d63d50d64472aae910067e1b435db72c5038bd61c2d6748f810d38
@@ -1,4 +1,4 @@
1
- image: ruby:2.6.0
1
+ image: ruby:2.7.0
2
2
  before_script:
3
3
  - ruby -v
4
4
  - which ruby
@@ -1,4 +1,16 @@
1
1
  AllCops:
2
- TargetRubyVersion: '2.6.0'
2
+ TargetRubyVersion: '2.7.0'
3
3
  Metrics/ClassLength:
4
4
  Enabled: false
5
+ Style/TrailingCommaInArguments:
6
+ EnforcedStyleForMultiline: comma
7
+ Style/TrailingCommaInArrayLiteral:
8
+ EnforcedStyleForMultiline: comma
9
+ Style/TrailingCommaInHashLiteral:
10
+ EnforcedStyleForMultiline: comma
11
+ Style/HashEachMethods:
12
+ Enabled: True
13
+ Style/HashTransformKeys:
14
+ Enabled: True
15
+ Style/HashTransformValues:
16
+ Enabled: True
@@ -1,82 +1,116 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- factorio-mod (0.7.4)
5
- activesupport (~> 5.2)
6
- addressable (~> 2.6)
4
+ factorio-mod (0.8.0)
5
+ activesupport (~> 6.0)
6
+ addressable (~> 2.7)
7
7
  nokogiri (~> 1.10)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activesupport (5.2.3)
12
+ activesupport (6.0.2.1)
13
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
14
  i18n (>= 0.7, < 2)
15
15
  minitest (~> 5.1)
16
16
  tzinfo (~> 1.1)
17
- addressable (2.6.0)
18
- public_suffix (>= 2.0.2, < 4.0)
17
+ zeitwerk (~> 2.2)
18
+ addressable (2.7.0)
19
+ public_suffix (>= 2.0.2, < 5.0)
19
20
  ast (2.4.0)
20
- bump (0.8.0)
21
- coco (0.15.0)
21
+ backport (1.1.2)
22
+ benchmark (0.1.0)
23
+ bump (0.9.0)
22
24
  coderay (1.1.2)
23
- concurrent-ruby (1.1.5)
25
+ concurrent-ruby (1.1.6)
24
26
  diff-lcs (1.3)
25
- i18n (1.6.0)
27
+ docile (1.3.2)
28
+ e2mmap (0.1.0)
29
+ i18n (1.8.2)
26
30
  concurrent-ruby (~> 1.0)
27
- jaro_winkler (1.5.3)
31
+ jaro_winkler (1.5.4)
32
+ maruku (0.7.3)
28
33
  method_source (0.9.2)
29
34
  mini_portile2 (2.4.0)
30
- minitest (5.11.3)
31
- nokogiri (1.10.3)
35
+ minitest (5.14.0)
36
+ nokogiri (1.10.8)
32
37
  mini_portile2 (~> 2.4.0)
33
- parallel (1.17.0)
34
- parser (2.6.3.0)
38
+ parallel (1.19.1)
39
+ parser (2.7.0.3)
35
40
  ast (~> 2.4.0)
36
41
  pry (0.12.2)
37
42
  coderay (~> 1.1.0)
38
43
  method_source (~> 0.9.0)
39
- public_suffix (3.1.1)
44
+ public_suffix (4.0.3)
40
45
  rainbow (3.0.0)
41
- rake (12.3.2)
42
- rspec (3.8.0)
43
- rspec-core (~> 3.8.0)
44
- rspec-expectations (~> 3.8.0)
45
- rspec-mocks (~> 3.8.0)
46
- rspec-core (3.8.2)
47
- rspec-support (~> 3.8.0)
48
- rspec-expectations (3.8.4)
46
+ rake (13.0.1)
47
+ reverse_markdown (1.4.0)
48
+ nokogiri
49
+ rexml (3.2.4)
50
+ rspec (3.9.0)
51
+ rspec-core (~> 3.9.0)
52
+ rspec-expectations (~> 3.9.0)
53
+ rspec-mocks (~> 3.9.0)
54
+ rspec-core (3.9.1)
55
+ rspec-support (~> 3.9.1)
56
+ rspec-expectations (3.9.0)
49
57
  diff-lcs (>= 1.2.0, < 2.0)
50
- rspec-support (~> 3.8.0)
51
- rspec-mocks (3.8.1)
58
+ rspec-support (~> 3.9.0)
59
+ rspec-mocks (3.9.1)
52
60
  diff-lcs (>= 1.2.0, < 2.0)
53
- rspec-support (~> 3.8.0)
54
- rspec-support (3.8.2)
55
- rubocop (0.72.0)
61
+ rspec-support (~> 3.9.0)
62
+ rspec-support (3.9.2)
63
+ rubocop (0.80.0)
56
64
  jaro_winkler (~> 1.5.1)
57
65
  parallel (~> 1.10)
58
- parser (>= 2.6)
66
+ parser (>= 2.7.0.1)
59
67
  rainbow (>= 2.2.2, < 4.0)
68
+ rexml
60
69
  ruby-progressbar (~> 1.7)
61
70
  unicode-display_width (>= 1.4.0, < 1.7)
62
71
  ruby-progressbar (1.10.1)
72
+ simplecov (0.18.2)
73
+ docile (~> 1.1)
74
+ simplecov-html (~> 0.11)
75
+ simplecov-html (0.12.0)
76
+ simplecov-lcov (0.8.0)
77
+ solargraph (0.38.5)
78
+ backport (~> 1.1)
79
+ benchmark
80
+ bundler (>= 1.17.2)
81
+ e2mmap
82
+ jaro_winkler (~> 1.5)
83
+ maruku (~> 0.7, >= 0.7.3)
84
+ nokogiri (~> 1.9, >= 1.9.1)
85
+ parser (~> 2.3)
86
+ reverse_markdown (~> 1.0, >= 1.0.5)
87
+ rubocop (~> 0.52)
88
+ thor (~> 1.0)
89
+ tilt (~> 2.0)
90
+ yard (~> 0.9)
91
+ thor (1.0.1)
63
92
  thread_safe (0.3.6)
64
- tzinfo (1.2.5)
93
+ tilt (2.0.10)
94
+ tzinfo (1.2.6)
65
95
  thread_safe (~> 0.1)
66
- unicode-display_width (1.6.0)
96
+ unicode-display_width (1.6.1)
97
+ yard (0.9.24)
98
+ zeitwerk (2.2.2)
67
99
 
68
100
  PLATFORMS
69
101
  ruby
70
102
 
71
103
  DEPENDENCIES
72
104
  bump
73
- bundler (~> 2.0)
74
- coco
105
+ bundler (~> 2.1)
75
106
  factorio-mod!
76
107
  pry
77
- rake (~> 12.3)
78
- rspec (~> 3.8)
108
+ rake (~> 13.0)
109
+ rspec (~> 3.9)
79
110
  rubocop
111
+ simplecov
112
+ simplecov-lcov
113
+ solargraph
80
114
 
81
115
  BUNDLED WITH
82
- 2.0.1
116
+ 2.1.4
@@ -4,7 +4,6 @@ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'factorio/mod/version'
6
6
 
7
- # rubocop:disable Metrics/BlockLength
8
7
  Gem::Specification.new do |spec|
9
8
  spec.name = 'factorio-mod'
10
9
  spec.version = Factorio::Mod::VERSION
@@ -25,19 +24,20 @@ Gem::Specification.new do |spec|
25
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
25
  spec.require_paths = ['lib']
27
26
 
28
- spec.required_ruby_version = '>= 2.6.0'
27
+ spec.required_ruby_version = '>= 2.7.0'
29
28
 
30
- spec.add_development_dependency 'bundler', '~> 2.0'
31
- spec.add_development_dependency 'rake', '~> 12.3'
32
- spec.add_development_dependency 'rspec', '~> 3.8'
29
+ spec.add_development_dependency 'bundler', '~> 2.1'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
31
+ spec.add_development_dependency 'rspec', '~> 3.9'
33
32
 
34
33
  spec.add_development_dependency 'bump'
35
- spec.add_development_dependency 'coco'
36
34
  spec.add_development_dependency 'pry'
37
35
  spec.add_development_dependency 'rubocop'
36
+ spec.add_development_dependency 'simplecov'
37
+ spec.add_development_dependency 'simplecov-lcov'
38
+ spec.add_development_dependency 'solargraph'
38
39
 
39
- spec.add_dependency 'activesupport', '~> 5.2'
40
- spec.add_dependency 'addressable', '~> 2.6'
40
+ spec.add_dependency 'activesupport', '~> 6.0'
41
+ spec.add_dependency 'addressable', '~> 2.7'
41
42
  spec.add_dependency 'nokogiri', '~> 1.10'
42
43
  end
43
- # rubocop:enable Metrics/BlockLength
@@ -13,7 +13,7 @@ require 'open-uri'
13
13
  require 'net/http'
14
14
  require 'nokogiri'
15
15
  require 'addressable'
16
+ require 'json'
16
17
 
17
18
  require 'active_support'
18
19
  require 'active_support/core_ext/object/blank.rb'
19
- require 'active_support/core_ext/array/access.rb'
@@ -3,56 +3,36 @@
3
3
  module Factorio
4
4
  # Cache mod info
5
5
  class Cache
6
- PAGES = %i[information downloads].freeze
7
-
8
6
  attr_reader :cache
9
7
 
10
8
  # @param name [String] Mod name
11
- def initialize(name, cookie = '')
9
+ def initialize(name)
12
10
  @name = name
13
- @uri = Addressable::URI.encode("mod/#{@name}")
14
- @cookie = cookie
15
- @cache = {}
16
- end
17
-
18
- # Get the `Information` page.
19
- # @return [Nokogiri::HTML]
20
- def information
21
- get :information, Addressable::URI.join(Mod::MOD_URI, @uri)
11
+ @uri = Mod::API_URI % Addressable::URI.encode(@name)
12
+ @cache = nil
22
13
  end
23
14
 
24
- # Get the `Downloads` page.
25
- # @return [Nokogiri::HTML]
26
- def downloads
27
- get :downloads, Addressable::URI.join(Mod::MOD_URI, "#{@uri}/downloads")
28
- end
29
-
30
- # Get any page that already downloads.
31
- # Get _better_(default information) mod page if none of the pages exist.
32
- # @param better [Symbol] get which page if none of the pages exist.
33
- # @return [Nokogiri::HTML]
34
- def any(better = :information)
35
- unless PAGES.include? better
36
- raise NoPageError, "page #{better.to_s.capitalize} not exist"
37
- end
38
-
39
- if @cache.key? better
40
- @cache[better]
41
- elsif @cache.any?
42
- @cache.first.second
43
- else
44
- public_method(better).call
45
- end
15
+ # Get from cache or download
16
+ # @param key [Symbol]
17
+ # @return [Hash]
18
+ def get(*key)
19
+ @cache ||= URI.open(@uri)
20
+ .then(&Nokogiri.method(:HTML))
21
+ .then { JSON.parse(_1, symbolize_names: true) }
22
+ .then(&method(:deep_freeze)) # rubocop:disable Layout/MultilineMethodCallIndentation
23
+ key.empty? ? @cache : @cache.dig(*key.map(&:to_sym))
24
+ rescue OpenURI::HTTPError => e
25
+ raise NoModError.new "MOD #{@name} not found", e.io
46
26
  end
47
27
 
48
28
  private
49
29
 
50
- # Get from cache or download page
51
- def get(symbol, uri)
52
- symbol = symbol.to_sym
53
- @cache[symbol] ||= Nokogiri::HTML(URI.open(uri, 'Cookie' => @cookie))
54
- rescue OpenURI::HTTPError => e
55
- raise NoModError.new "MOD #{@name} not found", e.io
30
+ def deep_freeze(sth)
31
+ case sth
32
+ when Hash then sth.each_value(&method(:deep_freeze))
33
+ when Array then sth.each(&method(:deep_freeze))
34
+ end
35
+ sth.freeze
56
36
  end
57
37
  end
58
38
  end
@@ -3,28 +3,18 @@
3
3
  module Factorio
4
4
  class Mod
5
5
  # store the entry of the _download_
6
- Download = Struct.new(:version, :game_version, :uri, :date, :times) do
7
- # `Download` page table header to attribute symbol
8
- TABLE_HEADER_TO_SYM = {
9
- 'Version' => :version,
10
- 'Game Version' => :game_version,
11
- 'Download' => :uri,
12
- 'Release Date' => :date,
13
- 'Downloads' => :times
14
- }.freeze
6
+ Download = Struct.new(:version, :factorio_version, :download_url,
7
+ :file_name, :released_at, :dependencies, :sha1) do
8
+ alias_method :game_version, :factorio_version
9
+ alias_method :uri, :download_url
15
10
 
16
- HANDLE_VALUE = {
17
- version: :text.to_proc,
18
- game_version: :text.to_proc,
19
- uri: Mod.method(:get_href).to_proc,
20
- date: :text.to_proc,
21
- times: :text.to_proc >> :to_i.to_proc
22
- }.freeze
23
-
24
- # set value by table header
25
- def set(name, value)
26
- sym = TABLE_HEADER_TO_SYM[name]
27
- tap { |a| a[sym] = HANDLE_VALUE[sym].call value }
11
+ def self.create(release)
12
+ d = release.merge(release[:info_json])
13
+ d.merge(download_url: Mod.extend_uri(d[:download_url]),
14
+ released_at: DateTime.parse(d[:released_at]),
15
+ dependencies: d[:dependencies].map(&Mod.method(:new)))
16
+ .values_at(*Download.members)
17
+ .then { Download.new(*_1) }
28
18
  end
29
19
  end
30
20
  end
@@ -10,13 +10,6 @@ module Factorio
10
10
  end
11
11
  end
12
12
 
13
- # The Exception that not logged in
14
- class NotLoginError < StandardError
15
- def initialize(msg = 'not logged in')
16
- super
17
- end
18
- end
19
-
20
13
  # The Exception that try to visit not exist page
21
14
  class NoPageError < StandardError
22
15
  def initialize(msg)
@@ -16,96 +16,39 @@ module Factorio
16
16
  class Mod
17
17
  # factorio Mod portal website URI
18
18
  MOD_URI = 'https://mods.factorio.com'
19
+ API_URI = 'https://mods.factorio.com/api/mods/%s/full'
19
20
 
20
21
  attr_reader :name
21
22
  alias id name
22
23
  alias string_id name
23
24
 
24
25
  # @param name [String] name of the Mod
25
- # @param cookie [String] logged in cookie
26
- def initialize(name, cookie = '')
26
+ def initialize(name)
27
27
  @name = name
28
- @mod = Cache.new name, cookie
28
+ @mod = Cache.new name
29
29
  end
30
30
 
31
- private
32
-
33
- # Get the meta table from Information page.
34
- def data_table(key = nil)
35
- table = @mod.information.xpath(".//div[@class='mod-page-data-table']")
36
- return table if key.blank?
37
-
38
- table.xpath ".//td[../td[@class='data-name'][.='#{key}:']]"
39
- end
40
-
41
- public
42
-
43
- # Map each value with table header.
44
- # @param table_header [Array] table header in order
45
- # @param line [Nokogiri::HTML] `<tr>`
46
- # @return [Download] _download_
47
- def self.bind_td_to_th(table_header, line)
48
- table_header.zip(line.css('td')).inject(Download.new) do |obj, pair|
49
- obj.set(*pair)
50
- end
51
- end
52
-
53
- # Get the logged in cookie by webdriver.
54
- #
55
- # @example
56
- # # use firefox nightly
57
- # Selenium::WebDriver::Firefox::Binary.path =
58
- # `which firefox-nightly`.chomp
59
- # # open firefox
60
- # driver = Selenium::WebDriver.for :firefox
61
- # cookie = Factorio::Mod.login_cookie_webdriver(driver)
62
- # # the browser will automatically close
63
- # @param driver [Selenium::WebDriver::Driver] Web Driver
64
- # @param autoclose [Bool] automatically close the browser after logging in
65
- # @return [String] The logged in cookie
66
- def self.login_cookie_webdirver(driver, autoclose = true)
67
- begin
68
- driver.navigate.to 'https://mods.factorio.com/login'
69
- rescue Net::ReadTimeout
70
- retry
71
- end
72
- sleep(1) while driver.current_url == 'https://mods.factorio.com/login'
73
-
74
- "session=#{driver.manage.cookie_named('session')[:value]}" \
75
- .tap { driver.quit if autoclose }
76
- end
77
-
78
- # @return [String, String] `csrf_token` and cookie
79
- def self.csrf_and_cookie
80
- resp = open 'https://mods.factorio.com/login'
81
- cookie = resp.metas['set-cookie'] \
82
- .map { |a| a.split('; ').first }.join('; ')
83
- csrf_token = Nokogiri::HTML(resp).css('#csrf_token @value').to_s
84
- [csrf_token, cookie]
85
- end
86
- private_class_method :csrf_and_cookie
87
-
88
- # Get the logged in cookie by username and password.
31
+ # Get the log in token by username and password.
89
32
  #
90
33
  # @example
91
34
  # print 'username: '
92
35
  # user = gets.chomp
93
36
  # print 'password: '
94
37
  # pass = gets.chomp
95
- # cookie = Factorio::Mod.login_cookie user, pass
38
+ # token = Factorio::Mod.login user, pass
96
39
  # @param username [String]
97
40
  # @param password [String]
98
- # @return [String] The logged in cookie
99
- def self.login_cookie(username, password)
100
- csrf_token, cookie = csrf_and_cookie
41
+ # @return [String] The log in token
42
+ def self.login(username, password)
101
43
  data = Addressable::URI.form_encode(
102
- 'csrf_token' => csrf_token,
103
44
  'username' => username,
104
- 'password' => password
45
+ 'password' => password,
105
46
  )
106
- Net::HTTP.post(Addressable::URI.join(MOD_URI, '/login'),
107
- data, 'Cookie' => cookie) \
108
- .response['set-cookie'].split('; ').first
47
+ result = Net::HTTP.post('https://auth.factorio.com/api-login', data)
48
+ .then(JSON.method(:parse))
49
+ result.first
50
+ rescue OpenURI::HTTPError
51
+ raise result['message']
109
52
  end
110
53
 
111
54
  # Get mod name from mod card.
@@ -120,18 +63,14 @@ module Factorio
120
63
  # Search mod.
121
64
  #
122
65
  # @param keyword [String] search keyword
123
- # @param cookie [String] cookie
124
66
  # @param version [String] factorio version, `any` for any version
125
67
  # @return [Array<Mod>] all mod searched on the first page with card cache
126
- def self.search(keyword, cookie = '', version: 'any')
68
+ def self.search(keyword, version: 'any')
127
69
  uri = Addressable::URI.join(
128
70
  MOD_URI, "/query/#{Addressable::URI.encode keyword}?version=#{version}"
129
71
  )
130
- Nokogiri::HTML(URI.open(uri, 'Cookie' => cookie)) \
131
- .css('.mod-card').map do |card|
132
- Mod.new(name_from_card(card), cookie).tap do |mod|
133
- mod.instance_eval { @mod.cache[:card] = card.clone }
134
- end
72
+ Nokogiri::HTML(URI.open(uri)).css('.mod-card').map do |card|
73
+ Mod.new(name_from_card(card))
135
74
  end
136
75
  end
137
76
 
@@ -140,8 +79,8 @@ module Factorio
140
79
  # @param name [String] name of the mod
141
80
  # @return [Bool] is exist
142
81
  def self.exist?(name)
143
- uri = Addressable::URI.encode("mod/#{name}")
144
- URI.open(Addressable::URI.join(MOD_URI, uri))
82
+ name = Addressable::URI.encode(name)
83
+ URI.open(API_URI % name)
145
84
  true
146
85
  rescue OpenURI::HTTPError
147
86
  false
@@ -152,36 +91,28 @@ module Factorio
152
91
  # @return [String] absolute link
153
92
  # @raise [NotLoginError]
154
93
  def self.extend_uri(rel)
155
- raise NotLoginError if rel =~ %r{^/login}
156
-
157
94
  Addressable::URI.join(MOD_URI, rel)
158
95
  end
159
96
 
160
- # Get href in Nokogiri node
161
- # @param item [Nokogiri::HTML]
162
- # @return [Addressable::URI] relative link
163
- def self.get_href(item)
164
- extend_uri(item.xpath('a/@href').text)
165
- end
166
-
167
97
  # Get the title (also known as _display name_) of the Mod
168
98
  # @return [String] title
169
99
  def title
170
- @mod.any.css('.mod-card-title *').text
100
+ @mod.get[:title]
171
101
  end
172
102
  alias display_name title
173
103
 
174
104
  # Get the summary of the Mod
175
105
  # @return [String] summary
176
106
  def summary
177
- @mod.any.css('.mod-card-summary').text
107
+ @mod.get[:summary]
178
108
  end
179
109
 
180
110
  # Get the GitHub URI.
181
111
  # @return [Addressable::URI] GitHub URI
182
112
  def github
183
- @mod.any.xpath('.//a[@class="source-code-link"]/@href').text.presence \
184
- &.then(&Addressable::URI.method(:parse))
113
+ @mod.get[:github_path].presence&.then do
114
+ Addressable::URI.join('https://github.com', _1)
115
+ end
185
116
  end
186
117
 
187
118
  # Get the git repo URI that can be cloned.
@@ -193,55 +124,54 @@ module Factorio
193
124
  # Get the license that the Mod use.
194
125
  # @return [String] license name
195
126
  def license
196
- data_table('License').xpath('a').text
127
+ @mod.get(:license, :name)
197
128
  end
198
129
 
199
130
  # Get the license URI.
200
131
  # @return [Addressable::URI] license URI
201
132
  def license_uri
202
- Addressable::URI.parse(data_table('License').xpath('a/@href').text)
133
+ Addressable::URI.parse(@mod.get(:license, :url))
203
134
  end
204
135
  alias license_link license_uri
205
136
 
206
137
  # Get the author of the Mod.
207
138
  # @return [String] author
208
139
  def author
209
- @mod.any.xpath('.//div[@class="mod-card-author"]/a').text
140
+ @mod.get[:owner]
210
141
  end
142
+ alias owner author
211
143
 
212
144
  # Whether Mod is deprecated
213
- # @return [Bool] is deprecated
145
+ # @return [Boolean] is deprecated
214
146
  def deprecated?
215
- @mod.any.xpath('.//span[@class="mod-card-title-deprecated"]').any?
147
+ @mod.get[:deprecated] || false
216
148
  end
217
149
 
218
150
  # Get the totle number of downloads of Mod.
219
151
  # @return [Integer] number of downloads
220
152
  def download_times
221
- xpath = ".//span[@class='mod-card-info-tag'][@title='Downloads']/div"
222
- @mod.any.xpath(xpath).text.to_i
153
+ @mod.get[:downloads_count]
223
154
  end
155
+ alias downloads_count download_times
224
156
 
225
157
  # Get the latest _download_ of the Mod.
226
158
  # @param version [String] factorio version
227
159
  # @return [Download]
228
160
  def latest_download(version = nil, ifnone = nil)
229
- version.blank? && download_list.first ||
230
- download_list.find(ifnone) { |d| d.game_version == version.to_s }
161
+ version.blank? && download_list.last ||
162
+ download_list.reverse.find(ifnone) { _1.game_version == version.to_s }
231
163
  end
232
164
 
233
165
  # Get the _download_ for all of version.
234
166
  # @return [Array<Download>]
235
167
  def download_list
236
- table = @mod.downloads.css 'table.mod-page-downloads-table'
237
- head = table.css('thead tr th').map(&:text)
238
- table.css('tbody tr').map { |line| Mod.bind_td_to_th(head, line) }
168
+ @mod.get[:releases].dup.map(&Download.method(:create))
239
169
  end
240
170
 
241
171
  # Get latest download uri by download button in card
242
172
  # @return [Addressable::URI] download uri
243
173
  def latest_download_uri
244
- Mod.get_href(@mod.any.css('.mod-download-button'))
174
+ Mod.extend_uri(latest_download[:download_url])
245
175
  end
246
176
  alias latest_download_link latest_download_uri
247
177
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Factorio
4
4
  class Mod
5
- VERSION = '0.7.4'
5
+ VERSION = '0.8.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: factorio-mod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - 71e6fd52
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-15 00:00:00.000000000 Z
11
+ date: 2020-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '2.1'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '12.3'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '12.3'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.8'
47
+ version: '3.9'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.8'
54
+ version: '3.9'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bump
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: coco
70
+ name: pry
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: pry
84
+ name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,35 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: rubocop
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov-lcov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: solargraph
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
129
  - - ">="
@@ -114,28 +142,28 @@ dependencies:
114
142
  requirements:
115
143
  - - "~>"
116
144
  - !ruby/object:Gem::Version
117
- version: '5.2'
145
+ version: '6.0'
118
146
  type: :runtime
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
- version: '5.2'
152
+ version: '6.0'
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: addressable
127
155
  requirement: !ruby/object:Gem::Requirement
128
156
  requirements:
129
157
  - - "~>"
130
158
  - !ruby/object:Gem::Version
131
- version: '2.6'
159
+ version: '2.7'
132
160
  type: :runtime
133
161
  prerelease: false
134
162
  version_requirements: !ruby/object:Gem::Requirement
135
163
  requirements:
136
164
  - - "~>"
137
165
  - !ruby/object:Gem::Version
138
- version: '2.6'
166
+ version: '2.7'
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: nokogiri
141
169
  requirement: !ruby/object:Gem::Requirement
@@ -157,7 +185,6 @@ executables: []
157
185
  extensions: []
158
186
  extra_rdoc_files: []
159
187
  files:
160
- - ".coco.yml"
161
188
  - ".gitignore"
162
189
  - ".gitlab-ci.yml"
163
190
  - ".rspec"
@@ -189,14 +216,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
189
216
  requirements:
190
217
  - - ">="
191
218
  - !ruby/object:Gem::Version
192
- version: 2.6.0
219
+ version: 2.7.0
193
220
  required_rubygems_version: !ruby/object:Gem::Requirement
194
221
  requirements:
195
222
  - - ">="
196
223
  - !ruby/object:Gem::Version
197
224
  version: '0'
198
225
  requirements: []
199
- rubygems_version: 3.0.4
226
+ rubygems_version: 3.1.2
200
227
  signing_key:
201
228
  specification_version: 4
202
229
  summary: Get the info of Factorio's MOD.
data/.coco.yml DELETED
@@ -1,8 +0,0 @@
1
- :exclude:
2
- - lib/factorio/mod.rb
3
- - lib/factorio/mod/version.rb
4
- - lib/factorio/mod/exception.rb
5
- - spec
6
- :single_line_report: false
7
- :exclude_above_threshold: false
8
- :show_link_in_terminal: true