gamerom 0.3.0 → 0.4.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.
@@ -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