factorio-mod 0.7.4 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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