Class: Factorio::Mod

Inherits:
Object
  • Object
show all
Defined in:
lib/factorio/mod/mod.rb,
lib/factorio/mod/version.rb,
lib/factorio/mod/download.rb

Overview

Info interface

example:

mod = Factorio::Mod.new 'LTN-easier'
puts "The author of #{mod.title} is #{mod.author}"
puts "The #{mod.title} is under #{mod.license}"
puts "It latest version can download at #{mod.latest_download[:uri]}"
puts "It latest version for factorio 0.16 can download at " \
  "#{mod.latest_download('0.16')[:uri]}"

Defined Under Namespace

Classes: Download

Constant Summary collapse

MOD_URI =

factorio Mod portal website URI

'https://mods.factorio.com'
VERSION =
'0.7.3'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, cookie = '') ⇒ Mod

Returns a new instance of Mod.

Parameters:

  • name (String)

    name of the Mod

  • cookie (String) (defaults to: '')

    logged in cookie



26
27
28
29
# File 'lib/factorio/mod/mod.rb', line 26

def initialize(name, cookie = '')
  @name = name
  @mod = Cache.new name, cookie
end

Instance Attribute Details

#nameObject (readonly) Also known as: id, string_id

Returns the value of attribute name.



20
21
22
# File 'lib/factorio/mod/mod.rb', line 20

def name
  @name
end

Class Method Details

.bind_td_to_th(table_header, line) ⇒ Download

Map each value with table header.

Parameters:

  • table_header (Array)

    table header in order

  • line (Nokogiri::HTML)

    <tr>

Returns:



47
48
49
50
51
# File 'lib/factorio/mod/mod.rb', line 47

def self.bind_td_to_th(table_header, line)
  table_header.zip(line.css('td')).inject(Download.new) do |obj, pair|
    obj.set(*pair)
  end
end

.exist?(name) ⇒ Bool

Get mod if exist.

Parameters:

  • name (String)

    name of the mod

Returns:

  • (Bool)

    is exist



142
143
144
145
146
147
148
# File 'lib/factorio/mod/mod.rb', line 142

def self.exist?(name)
  uri = Addressable::URI.encode("mod/#{name}")
  URI.open(Addressable::URI.join(MOD_URI, uri))
  true
rescue OpenURI::HTTPError
  false
end

.extend_uri(rel) ⇒ String

Extend relative links to absolute links

Parameters:

  • rel (String)

    relative link

Returns:

  • (String)

    absolute link

Raises:



154
155
156
157
158
# File 'lib/factorio/mod/mod.rb', line 154

def self.extend_uri(rel)
  raise NotLoginError if rel =~ %r{^/login}

  Addressable::URI.join(MOD_URI, rel)
end

.get_href(item) ⇒ Addressable::URI

Get href in Nokogiri node

Parameters:

  • item (Nokogiri::HTML)

Returns:

  • (Addressable::URI)

    relative link



163
164
165
# File 'lib/factorio/mod/mod.rb', line 163

def self.get_href(item)
  extend_uri(item.xpath('a/@href').text)
end

Get the logged in cookie by username and password.

Examples:

print 'username: '
user = gets.chomp
print 'password: '
pass = gets.chomp
cookie = Factorio::Mod. user, pass

Parameters:

  • username (String)
  • password (String)

Returns:

  • (String)

    The logged in cookie



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/factorio/mod/mod.rb', line 99

def self.(username, password)
  csrf_token, cookie = csrf_and_cookie
  data = Addressable::URI.form_encode(
    'csrf_token' => csrf_token,
    'username' => username,
    'password' => password
  )
  Net::HTTP.post(Addressable::URI.join(MOD_URI, '/login'),
                 data, 'Cookie' => cookie) \
           .response['set-cookie'].split('; ').first
end

Get the logged in cookie by webdriver.

Examples:

# use firefox nightly
Selenium::WebDriver::Firefox::Binary.path =
  `which firefox-nightly`.chomp
# open firefox
driver = Selenium::WebDriver.for :firefox
cookie = Factorio::Mod.(driver)
# the browser will automatically close

Parameters:

  • driver (Selenium::WebDriver::Driver)

    Web Driver

  • autoclose (Bool) (defaults to: true)

    automatically close the browser after logging in

Returns:

  • (String)

    The logged in cookie



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/factorio/mod/mod.rb', line 66

def self.(driver, autoclose = true)
  begin
    driver.navigate.to 'https://mods.factorio.com/login'
  rescue Net::ReadTimeout
    retry
  end
  sleep(1) while driver.current_url == 'https://mods.factorio.com/login'

  "session=#{driver.manage.cookie_named('session')[:value]}" \
    .tap { driver.quit if autoclose }
end

.name_from_card(card) ⇒ String

Get mod name from mod card.

Parameters:

  • card (Nokogiri::HTML)

Returns:

  • (String)

    The name in



115
116
117
118
# File 'lib/factorio/mod/mod.rb', line 115

def self.name_from_card(card)
  card.xpath('.//h2[@class="mod-card-title"]/a/@href').text \
      .split('/').last.then(&Addressable::URI.method(:unencode))
end

.search(keyword, cookie = '', version: 'any') ⇒ Array<Mod>

Search mod.

Parameters:

  • keyword (String)

    search keyword

  • cookie (String) (defaults to: '')

    cookie

  • version (String) (defaults to: 'any')

    factorio version, any for any version

Returns:

  • (Array<Mod>)

    all mod searched on the first page with card cache



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/factorio/mod/mod.rb', line 126

def self.search(keyword, cookie = '', version: 'any')
  uri = Addressable::URI.join(
    MOD_URI, "/query/#{Addressable::URI.encode keyword}?version=#{version}"
  )
  Nokogiri::HTML(URI.open(uri, 'Cookie' => cookie)) \
          .css('.mod-card').map do |card|
    Mod.new(name_from_card(card), cookie).tap do |mod|
      mod.instance_eval { @mod.cache[:card] = card.clone }
    end
  end
end

Instance Method Details

#authorString

Get the author of the Mod.

Returns:

  • (String)

    author



208
209
210
# File 'lib/factorio/mod/mod.rb', line 208

def author
  @mod.any.xpath('.//div[@class="mod-card-author"]/a').text
end

#deprecated?Bool

Whether Mod is deprecated

Returns:

  • (Bool)

    is deprecated



214
215
216
# File 'lib/factorio/mod/mod.rb', line 214

def deprecated?
  @mod.any.xpath('.//span[@class="mod-card-title-deprecated"]').any?
end

#download_listArray<Download>

Get the download for all of version.

Returns:



235
236
237
238
239
# File 'lib/factorio/mod/mod.rb', line 235

def download_list
  table = @mod.downloads.css 'table.mod-page-downloads-table'
  head = table.css('thead tr th').map(&:text)
  table.css('tbody tr').map { |line| Mod.bind_td_to_th(head, line) }
end

#download_timesInteger

Get the totle number of downloads of Mod.

Returns:

  • (Integer)

    number of downloads



220
221
222
223
# File 'lib/factorio/mod/mod.rb', line 220

def download_times
  xpath = ".//span[@class='mod-card-info-tag'][@title='Downloads']/div"
  @mod.any.xpath(xpath).text.to_i
end

#gitAddressable::URI

Get the git repo URI that can be cloned.

Returns:

  • (Addressable::URI)

    git URI



189
190
191
# File 'lib/factorio/mod/mod.rb', line 189

def git
  github&.to_s&.+('.git')&.then(&Addressable::URI.method(:parse))
end

#githubAddressable::URI

Get the GitHub URI.

Returns:

  • (Addressable::URI)

    GitHub URI



182
183
184
185
# File 'lib/factorio/mod/mod.rb', line 182

def github
  @mod.any.xpath('.//a[@class="source-code-link"]/@href').text.presence \
    &.then(&Addressable::URI.method(:parse))
end

#latest_download(version = nil, ifnone = nil) ⇒ Download

Get the latest download of the Mod.

Parameters:

  • version (String) (defaults to: nil)

    factorio version

Returns:



228
229
230
231
# File 'lib/factorio/mod/mod.rb', line 228

def latest_download(version = nil, ifnone = nil)
  version.blank? && download_list.first ||
    download_list.find(ifnone) { |d| d.game_version == version.to_s }
end

#latest_download_uriAddressable::URI Also known as: latest_download_link

Get latest download uri by download button in card

Returns:

  • (Addressable::URI)

    download uri



243
244
245
# File 'lib/factorio/mod/mod.rb', line 243

def latest_download_uri
  Mod.get_href(@mod.any.css('.mod-download-button'))
end

#licenseString

Get the license that the Mod use.

Returns:

  • (String)

    license name



195
196
197
# File 'lib/factorio/mod/mod.rb', line 195

def license
  data_table('License').xpath('a').text
end

#license_uriAddressable::URI Also known as: license_link

Get the license URI.

Returns:

  • (Addressable::URI)

    license URI



201
202
203
# File 'lib/factorio/mod/mod.rb', line 201

def license_uri
  Addressable::URI.parse(data_table('License').xpath('a/@href').text)
end

#summaryString

Get the summary of the Mod

Returns:

  • (String)

    summary



176
177
178
# File 'lib/factorio/mod/mod.rb', line 176

def summary
  @mod.any.css('.mod-card-summary').text
end

#titleString Also known as: display_name

Get the title (also known as display name) of the Mod

Returns:

  • (String)

    title



169
170
171
# File 'lib/factorio/mod/mod.rb', line 169

def title
  @mod.any.css('.mod-card-title *').text
end