gamerom 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- # 'frozen_string_literal' => true
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'fileutils'
4
4
  require 'logger'
@@ -6,7 +6,7 @@ require 'rest-client'
6
6
  require 'mechanize'
7
7
 
8
8
  module Gamerom
9
- ROM_ROOT = ENV['ROM_ROOT'] || File.expand_path("~/.gamerom")
9
+ ROM_ROOT = ENV['ROM_ROOT'] || File.expand_path('~/.gamerom')
10
10
  CACHE_DIR = ENV['CACHE_DIR'] || "#{ROM_ROOT}/cache"
11
11
  GAME_DIR = ENV['GAME_DIR'] || "#{ROM_ROOT}/games"
12
12
  LOG_DIR = ENV['LOG_DIR'] || "#{ROM_ROOT}/logs"
data/lib/gamerom/game.rb CHANGED
@@ -1,54 +1,56 @@
1
- # 'frozen_string_literal' => true
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'fileutils'
4
4
  require 'ostruct'
5
5
  require 'yaml'
6
6
 
7
7
  module Gamerom
8
+ # Game - Represents a game ROM
8
9
  class Game < OpenStruct
9
10
  def filenames
10
- YAML.load_file(self.state_filename).map do |filename|
11
- "#{self.filepath}/#{filename}"
11
+ YAML.load_file(state_filename).map do |filename|
12
+ "#{filepath}/#{filename}"
12
13
  end
13
14
  end
14
15
 
15
16
  def filepath
16
- "#{Gamerom::GAME_DIR}/#{self.repo.name}/#{self.platform}/#{self.region}"
17
+ "#{Gamerom::GAME_DIR}/#{repo.name}/#{platform}/#{region}"
17
18
  end
18
19
 
19
20
  def install
20
- self.repo.install self do |filenames|
21
- self.update_state filenames
21
+ repo.install self do |filenames|
22
+ update_state filenames
22
23
  end
23
24
  end
24
25
 
25
26
  def installed?
26
- File.exists? self.state_filename
27
+ File.exist? state_filename
27
28
  end
28
29
 
29
30
  def state_filename
30
- "#{Gamerom::STATE_DIR}/#{self.repo.name}/#{self.platform}/#{self.region}/#{self.id}"
31
+ "#{Gamerom::STATE_DIR}/#{repo.name}/#{platform}/#{region}/#{id}"
31
32
  end
32
33
 
33
34
  def to_s
34
35
  install_status = ''
35
- install_status = " (#{shell.set_color 'installed', :green})" if self.installed?
36
+ install_status = " (#{shell.set_color "installed", :green})" if installed?
36
37
  tags = ''
37
- tags = " - tags: #{self.tags.join(", ")}" if self.respond_to?(:tags) && !self.tags.empty?
38
- "#{self.id} - #{self.name} - #{self.region}#{install_status}#{tags}"
38
+ tags = " - tags: #{tags.join(", ")}" if respond_to?(:tags) && !tags.empty?
39
+ "#{id} - #{name} - #{region}#{install_status}#{tags}"
39
40
  end
40
41
 
41
42
  def uninstall
42
- FileUtils.rm_rf self.filenames
43
- FileUtils.rm_rf self.state_filename
43
+ FileUtils.rm_rf filenames
44
+ FileUtils.rm_rf state_filename
44
45
  end
45
46
 
46
- def update_state filenames
47
- FileUtils.mkdir_p("#{Gamerom::STATE_DIR}/#{self.repo.name}/#{self.platform}/#{self.region}")
48
- File.write(self.state_filename, filenames.to_yaml)
47
+ def update_state(filenames)
48
+ FileUtils.mkdir_p("#{Gamerom::STATE_DIR}/#{repo.name}/#{platform}/#{region}")
49
+ File.write(state_filename, filenames.to_yaml)
49
50
  end
50
51
 
51
52
  private
53
+
52
54
  def shell
53
55
  @shell ||= Thor::Shell::Color.new
54
56
  end
@@ -1,6 +1,7 @@
1
- # 'frozen_string_literal' => true
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Gamerom
4
+ # GameInfo - Extracts region and tags from game name
4
5
  class GameInfo
5
6
  REGIONS = {
6
7
  '1' => 'Japan & Korea',
@@ -33,13 +34,13 @@ module Gamerom
33
34
  'S' => 'Spain',
34
35
  'Sw' => 'Sweden',
35
36
  'SW' => 'Sweden',
36
- 'U' => "USA",
37
+ 'U' => 'USA',
37
38
  'UK' => 'England',
38
39
  'Unk' => 'Unknown Country',
39
40
  'Unl' => 'Unlicensed',
40
41
  'PAL' => 'PAL regions (Australia, Europe)',
41
42
  'NTSC' => 'NTSC regions (Japan, USA, Latin America)',
42
- }
43
+ }.freeze
43
44
 
44
45
  TAGS = {
45
46
  '!' => :good,
@@ -61,23 +62,21 @@ module Gamerom
61
62
  'T+' => :newer_translation,
62
63
  'VS' => :vs,
63
64
  'x' => :bad_checksum,
64
- }
65
+ }.freeze
66
+
67
+ attr_reader :name
65
68
 
66
69
  def initialize(name)
67
70
  @name = name
68
71
  end
69
72
 
70
- def name
71
- @name
72
- end
73
-
74
73
  def region
75
74
  identifiers = @name.scan(/\((?<region>[A-Za-z0-9]+)\)/).flatten
76
75
  region_id = identifiers.find { |i| REGIONS.include? i }
77
76
  if region_id
78
77
  REGIONS[region_id]
79
78
  else
80
- "USA"
79
+ 'USA'
81
80
  end
82
81
  end
83
82
 
@@ -85,7 +84,7 @@ module Gamerom
85
84
  tags = []
86
85
  codes = @name.scan(/\[(?<code>[^\]]+)\]/).flatten
87
86
  codes.each do |code|
88
- code = $1 if code.match /^(?<code>[abcfhop])[0-9]*/
87
+ code = Regexp.last_match(1) if code.match /^(?<code>[abcfhop])[0-9]*/
89
88
  tags << TAGS[code] if TAGS.include?(code)
90
89
  end
91
90
  tags
data/lib/gamerom/repo.rb CHANGED
@@ -1,4 +1,4 @@
1
- # 'frozen_string_literal' => true
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'yaml'
4
4
 
@@ -6,30 +6,34 @@ REPOSITORIES = Dir["#{File.dirname(__FILE__)}/repo_adapters/*"].map do |file|
6
6
  File.basename(file, '.rb')
7
7
  end
8
8
 
9
+ require_relative 'repo_adapter'
9
10
  REPOSITORIES.each do |repo|
10
11
  require_relative "repo_adapters/#{repo}"
11
12
  end
12
13
 
13
14
  module Gamerom
15
+ # Repo - Represents a game ROM repository
14
16
  class Repo
17
+ attr_reader :name
18
+
15
19
  def self.list
16
20
  REPOSITORIES.map do |repo|
17
- self.new repo
21
+ new repo
18
22
  end
19
23
  end
20
24
 
21
- def initialize name
25
+ def initialize(name)
22
26
  @name = name
23
27
  @repo = Gamerom::RepoAdapters.const_get(name.capitalize)
24
28
  end
25
29
 
26
- def install game, &block
30
+ def install(game, &block)
27
31
  @repo.install game, &block
28
32
  end
29
33
 
30
- def find platform, game_identifier
34
+ def find(platform, game_identifier)
31
35
  games(platform).find do |game|
32
- if Float(game_identifier, exception: false)
36
+ if Integer(game_identifier, exception: false)
33
37
  game.id == game_identifier.to_i
34
38
  else
35
39
  game.name.downcase == game_identifier.downcase
@@ -37,45 +41,41 @@ module Gamerom
37
41
  end
38
42
  end
39
43
 
40
- def games platform, options={}
44
+ def games(platform, options = {})
41
45
  platform_database = "#{Gamerom::CACHE_DIR}/#{@name}/#{platform}.yml"
42
- update_database platform unless File.exists? platform_database
43
- games = YAML.load_file(platform_database).map { |game|
46
+ update_database platform unless File.exist? platform_database
47
+ games = YAML.load_file(platform_database).map do |game|
44
48
  Game.new(game.merge(platform: platform, repo: self))
45
- }
49
+ end
46
50
 
47
- if !options[:region].nil?
48
- games = games.select { |game|
49
- options[:region].nil? || game.region == options[:region]
50
- }
51
+ unless options[:region].nil?
52
+ games.select! do |game|
53
+ game.region == options[:region]
54
+ end
51
55
  end
52
56
 
53
- if !options[:keyword].nil?
54
- games = games.select { |game|
57
+ unless options[:keyword].nil?
58
+ games.select! do |game|
55
59
  game.name =~ /#{options[:keyword]}/i
56
- }
60
+ end
57
61
  end
58
62
 
59
63
  games
60
64
  end
61
65
 
62
- def name
63
- @name
64
- end
65
-
66
66
  def platforms
67
67
  @repo.platforms
68
68
  end
69
69
 
70
- def regions platform
71
- games(platform).map { |game| game.region }.sort.uniq
70
+ def regions(platform)
71
+ games(platform).map(&:region).sort.uniq
72
72
  end
73
73
 
74
74
  def to_s
75
75
  @name
76
76
  end
77
77
 
78
- def update_database platform
78
+ def update_database(platform)
79
79
  games = @repo.games platform
80
80
  FileUtils.mkdir_p("#{Gamerom::CACHE_DIR}/#{@name}")
81
81
  File.write("#{Gamerom::CACHE_DIR}/#{@name}/#{platform}.yml", games.to_yaml)
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'rest-client'
5
+
6
+ module Gamerom
7
+ # RepoAdapter - Common adapter methods
8
+ module RepoAdapter
9
+ def nokogiri_get(url)
10
+ Nokogiri::HTML(RestClient.get(url))
11
+ end
12
+
13
+ def games(platform)
14
+ games = []
15
+ progress_bar = ProgressBar.new(platform, sections.count)
16
+
17
+ extract_games(platform) do |section_games, section_index|
18
+ games.append(*section_games)
19
+ progress_bar.set(section_index + 1)
20
+ end
21
+
22
+ progress_bar.finish
23
+ games
24
+ end
25
+ end
26
+ end
@@ -3,12 +3,13 @@
3
3
  require 'mechanize'
4
4
  require 'mechanize/progressbar'
5
5
  require 'mechanizeprogress'
6
- require 'nokogiri'
7
- require 'rest-client'
8
6
 
9
7
  module Gamerom
10
8
  module RepoAdapters
9
+ # Coolrom - An adapter for the CoolROM repository website
11
10
  class Coolrom
11
+ extend Gamerom::RepoAdapter
12
+
12
13
  PLATFORM = {
13
14
  'atari2600' => 'Atari 2600',
14
15
  'atari5200' => 'Atari 5200',
@@ -33,32 +34,33 @@ module Gamerom
33
34
  'psx' => 'Sony Playstation',
34
35
  'ps2' => 'Sony Playstation 2',
35
36
  'psp' => 'Sony Playstation Portable',
36
- }
37
+ }.freeze
37
38
 
38
39
  def self.platforms
39
40
  PLATFORM
40
41
  end
41
42
 
42
- def self.games(platform)
43
- games = []
44
- sections = ('a'..'z').to_a.unshift("0")
45
- progress_bar = ProgressBar.new(platform, sections.count)
43
+ def self.sections
44
+ ('a'..'z').to_a.unshift('0')
45
+ end
46
+
47
+ def self.extract_games(platform)
46
48
  sections.each_with_index do |section, index|
47
- page = Nokogiri::HTML(RestClient.get("https://coolrom.com.au/roms/#{platform}/#{section}/"))
48
- regions = page.css('input.region').map { |i| i["name"] }
49
+ page = nokogiri_get("https://coolrom.com.au/roms/#{platform}/#{section}/")
50
+ regions = page.css('input.region').map { |i| i['name'] }
49
51
  regions.each do |region|
50
- games.append *page.css("div.#{region} a").map { |game|
51
- {
52
- id: game['href'].split('/')[3].to_i,
53
- name: game.text,
54
- region: region,
55
- }
56
- }
52
+ game_links = page.css("div.#{region} a")
53
+ yield game_links.map { |game_link| game(game_link, region) }, index
57
54
  end
58
- progress_bar.set(index+1)
59
55
  end
60
- progress_bar.finish
61
- games
56
+ end
57
+
58
+ def self.game(game_link, region)
59
+ {
60
+ id: game_link['href'].split('/')[3].to_i,
61
+ name: game_link.text,
62
+ region: region,
63
+ }
62
64
  end
63
65
 
64
66
  def self.install(game)
@@ -67,15 +69,16 @@ module Gamerom
67
69
  agent.user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'
68
70
 
69
71
  response = nil
70
- agent.progressbar{
72
+ agent.progressbar do
71
73
  response = agent.get("https://coolrom.com.au/downloader.php?id=#{game.id}")
72
- }
73
- if response.code.to_i == 200
74
- filename = response.filename
75
- FileUtils.mkdir_p(game.filepath)
76
- response.save!("#{game.filepath}/#{filename}")
77
- yield [filename]
78
74
  end
75
+
76
+ return unless response.code.to_i == 200
77
+
78
+ filename = response.filename
79
+ FileUtils.mkdir_p(game.filepath)
80
+ response.save!("#{game.filepath}/#{filename}")
81
+ yield [filename]
79
82
  end
80
83
  end
81
84
  end
@@ -4,12 +4,13 @@ require 'cgi'
4
4
  require 'mechanize'
5
5
  require 'mechanize/progressbar'
6
6
  require 'mechanizeprogress'
7
- require 'nokogiri'
8
- require 'rest-client'
9
7
 
10
8
  module Gamerom
11
9
  module RepoAdapters
10
+ # Romnation - An adapter for the ROMNation repository website
12
11
  class Romnation
12
+ extend Gamerom::RepoAdapter
13
+
13
14
  PLATFORM = {
14
15
  'amstrad' => 'Amstrad',
15
16
  'atari2600' => 'Atari 2600',
@@ -44,36 +45,46 @@ module Gamerom
44
45
  'virtualboy' => 'Virtual Boy',
45
46
  'watara' => 'Watara Supervision',
46
47
  'wonderswan' => 'WonderSwan',
47
- }
48
+ }.freeze
48
49
 
49
50
  def self.platforms
50
51
  PLATFORM
51
52
  end
52
53
 
53
- def self.games(platform)
54
- games = []
55
- sections = ('a'..'z').to_a.unshift("0")
56
- progress_bar = ProgressBar.new(platform, sections.count)
54
+ def self.sections
55
+ ('a'..'z').to_a.unshift('0')
56
+ end
57
+
58
+ def self.extract_games(platform)
57
59
  sections.each_with_index do |section, index|
58
- page = Nokogiri::HTML(RestClient.get("https://www.romnation.net/srv/roms/#{platform}/#{section}/sort-title.html"))
59
- pages = ['1']
60
- pages = page.css('.pagination').first.css('a').map(&:text).map(&:strip).reject(&:empty?) unless page.css('.pagination').empty?
61
- pages.each do |p|
62
- page = Nokogiri::HTML(RestClient.get("https://www.romnation.net/srv/roms/#{platform}/#{section}/page-#{p}_sort-title.html"))
63
- games.append *page.css('table.listings td.title a').map { |game|
64
- game_info = GameInfo.new(game.text)
65
- {
66
- id: game['href'].split('/')[3].to_i,
67
- name: game.text,
68
- region: game_info.region,
69
- tags: game_info.tags,
70
- }
71
- }
72
- end
73
- progress_bar.set(index+1)
60
+ pages = extract_pages(platform, section)
61
+ yield extract_games_from_section_pages(platform, section, pages), index
62
+ end
63
+ end
64
+
65
+ def self.extract_pages(platform, section)
66
+ page = nokogiri_get("https://www.romnation.net/srv/roms/#{platform}/#{section}/sort-title.html")
67
+ pages = ['1']
68
+ pages = page.css('.pagination').first.css('a').map(&:text).map(&:strip).reject(&:empty?) unless page.css('.pagination').empty?
69
+ pages
70
+ end
71
+
72
+ def self.extract_games_from_section_pages(platform, section, pages)
73
+ pages.reduce([]) do |section_games, p|
74
+ page = nokogiri_get("https://www.romnation.net/srv/roms/#{platform}/#{section}/page-#{p}_sort-title.html")
75
+ games_links = page.css('table.listings td.title a')
76
+ section_games.append(*games_links.map { |game_link| game(game_link) })
74
77
  end
75
- progress_bar.finish
76
- games
78
+ end
79
+
80
+ def self.game(game_link)
81
+ game_info = GameInfo.new(game_link.text)
82
+ {
83
+ id: game_link['href'].split('/')[3].to_i,
84
+ name: game_link.text,
85
+ region: game_info.region,
86
+ tags: game_info.tags,
87
+ }
77
88
  end
78
89
 
79
90
  def self.install(game)
@@ -83,15 +94,16 @@ module Gamerom
83
94
  page = agent.get("https://www.romnation.net/download/rom/#{game.id}")
84
95
 
85
96
  response = nil
86
- agent.progressbar{
87
- response = page.link_with(:text => 'Download This Rom').click
88
- }
89
- if response.code.to_i == 200
90
- filename = CGI.unescape(response.filename.split('_host=').first)
91
- FileUtils.mkdir_p(game.filepath)
92
- response.save!("#{game.filepath}/#{filename}")
93
- yield [filename]
97
+ agent.progressbar do
98
+ response = page.link_with(text: 'Download This Rom').click
94
99
  end
100
+
101
+ return unless response.code.to_i == 200
102
+
103
+ filename = CGI.unescape(response.filename.split('_host=').first)
104
+ FileUtils.mkdir_p(game.filepath)
105
+ response.save!("#{game.filepath}/#{filename}")
106
+ yield [filename]
95
107
  end
96
108
  end
97
109
  end