romloader 1.2.0 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/LICENSE +21 -21
- data/README.md +41 -39
- data/bin/romloader +2 -2
- data/lib/romloader.rb +22 -22
- data/lib/romloader/archive_extractor.rb +61 -61
- data/lib/romloader/freeroms_scraper.rb +107 -91
- data/lib/romloader/game_rom.rb +29 -29
- data/lib/romloader/game_system.rb +55 -55
- data/lib/romloader/romloader_cli.rb +222 -222
- data/lib/romloader/scraping_error/errors.rb +7 -7
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 447d07953556ab02a8e8ef0556a89809ba8277f8
|
4
|
+
data.tar.gz: 5b2aec9a0b2cc5a3e3c8fbd6ba5a0278d8027f50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5827a960f1ba204b627f9395912575da64ef6a64017d601b9c1f4ee2689405e81846b6d479f7f8fa0c6d884249306f8e3e10e494f6fbba961c190e2ec77d444
|
7
|
+
data.tar.gz: 6cd992084b3b65d03d418900189d980df064380bc1865f492979705daa8f2299a11c75bdbc7de8d0e322e41d2b78473faf3ddbb5584eab93565ac6a36cbd255c
|
data/Gemfile
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
3
|
gemspec
|
data/LICENSE
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
MIT License
|
2
|
-
|
3
|
-
Copyright (c) 2016 Efrain Perez Jr
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
SOFTWARE.
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2016 Efrain Perez Jr
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,40 +1,42 @@
|
|
1
|
-
# RomLoader
|
2
|
-
|
3
|
-
A Ruby Gem for downloading videogame roms, powered by freeroms.com.
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
$ gem install romloader
|
8
|
-
|
9
|
-
## Usage
|
10
|
-
|
11
|
-
Type the command below into your shell and follow the on screen prompts.
|
12
|
-
|
13
|
-
$ romloader
|
14
|
-
|
15
|
-
## Development
|
16
|
-
|
17
|
-
To develop further upon this gem, fork and clone the repository located at https://github.com/jinstrider2000/romloader-cli-gem.
|
18
|
-
Be sure to have the Bundler gem installed, and run:
|
19
|
-
|
20
|
-
$ bundle install
|
21
|
-
|
22
|
-
This will download any dependencies for development. Rspec is among the dependencies, however, there are no tests included in the repo. I intend to add some eventually.
|
23
|
-
|
24
|
-
## Contributing
|
25
|
-
|
26
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/jinstrider2000/romloader-cli-gem.
|
27
|
-
|
28
|
-
## Version Changes
|
29
|
-
|
30
|
-
v. 1.2:
|
31
|
-
|
32
|
-
v. 1.
|
33
|
-
|
34
|
-
v. 1.
|
35
|
-
|
36
|
-
v.
|
37
|
-
|
38
|
-
|
39
|
-
|
1
|
+
# RomLoader
|
2
|
+
|
3
|
+
A Ruby Gem for downloading videogame roms, powered by freeroms.com.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
$ gem install romloader
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
Type the command below into your shell and follow the on screen prompts.
|
12
|
+
|
13
|
+
$ romloader
|
14
|
+
|
15
|
+
## Development
|
16
|
+
|
17
|
+
To develop further upon this gem, fork and clone the repository located at https://github.com/jinstrider2000/romloader-cli-gem.
|
18
|
+
Be sure to have the Bundler gem installed, and run:
|
19
|
+
|
20
|
+
$ bundle install
|
21
|
+
|
22
|
+
This will download any dependencies for development. Rspec is among the dependencies, however, there are no tests included in the repo. I intend to add some eventually.
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
|
26
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jinstrider2000/romloader-cli-gem.
|
27
|
+
|
28
|
+
## Version Changes
|
29
|
+
|
30
|
+
v. 1.2.2: Updated web scraping function
|
31
|
+
|
32
|
+
v. 1.2: Added basic file managment capability for Windows (requires Powershell v 3.0 or higher). Also updated UI slightly.
|
33
|
+
|
34
|
+
v. 1.1: Added basic rom download capability for Windows (requires Powershell v 3.0 or higher)
|
35
|
+
|
36
|
+
v. 1.0: Changed the namespacing of classes, added zip/7-zip extraction and rom download directory management. Also, added the ability to open the newly downloaded game from the command line (requires a emulator)
|
37
|
+
|
38
|
+
v. 0.0: Basic rom listing from Freeroms.com, and rom download feature
|
39
|
+
|
40
|
+
## License
|
41
|
+
|
40
42
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/bin/romloader
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require_relative "../lib/romloader.rb"
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative "../lib/romloader.rb"
|
3
3
|
run
|
data/lib/romloader.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
|
-
module RomLoader
|
2
|
-
|
3
|
-
end
|
4
|
-
|
5
|
-
require 'open-uri'
|
6
|
-
require 'nokogiri'
|
7
|
-
require 'cgi'
|
8
|
-
unless /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
9
|
-
require 'zip'
|
10
|
-
require 'seven_zip_ruby'
|
11
|
-
end
|
12
|
-
require 'fileutils'
|
13
|
-
require_relative 'romloader/game_rom.rb'
|
14
|
-
require_relative 'romloader/game_system.rb'
|
15
|
-
require_relative 'romloader/archive_extractor.rb'
|
16
|
-
require_relative 'romloader/freeroms_scraper.rb'
|
17
|
-
require_relative 'romloader/scraping_error/errors.rb'
|
18
|
-
require_relative 'romloader/romloader_cli.rb'
|
19
|
-
|
20
|
-
def run
|
21
|
-
Dir.mkdir(File.join(Dir.home,"videogame_roms")) unless Dir.exist?(File.join(Dir.home,"videogame_roms"))
|
22
|
-
RomLoader::RomLoaderCli.new.start
|
1
|
+
module RomLoader
|
2
|
+
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'open-uri'
|
6
|
+
require 'nokogiri'
|
7
|
+
require 'cgi'
|
8
|
+
unless /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
9
|
+
require 'zip'
|
10
|
+
require 'seven_zip_ruby'
|
11
|
+
end
|
12
|
+
require 'fileutils'
|
13
|
+
require_relative 'romloader/game_rom.rb'
|
14
|
+
require_relative 'romloader/game_system.rb'
|
15
|
+
require_relative 'romloader/archive_extractor.rb'
|
16
|
+
require_relative 'romloader/freeroms_scraper.rb'
|
17
|
+
require_relative 'romloader/scraping_error/errors.rb'
|
18
|
+
require_relative 'romloader/romloader_cli.rb'
|
19
|
+
|
20
|
+
def run
|
21
|
+
Dir.mkdir(File.join(Dir.home,"videogame_roms")) unless Dir.exist?(File.join(Dir.home,"videogame_roms"))
|
22
|
+
RomLoader::RomLoaderCli.new.start
|
23
23
|
end
|
@@ -1,62 +1,62 @@
|
|
1
|
-
|
2
|
-
class RomLoader::ArchiveExtractor
|
3
|
-
|
4
|
-
#Extracts zip or 7-zip rom files, manages the extracted dirs, then deletes archive files
|
5
|
-
def self.extract(archive_dir,extract_dir,game_obj)
|
6
|
-
file_or_dir_to_open = nil
|
7
|
-
dir_game_name = game_obj.filename.split(game_obj.file_ext)[0]
|
8
|
-
|
9
|
-
if game_obj.file_ext == ".zip"
|
10
|
-
puts "Extracting #{game_obj.filename}"
|
11
|
-
Zip::File.open(archive_dir) do |zip_archive|
|
12
|
-
zip_archive.glob("*htm").each { |entry| zip_archive.remove(entry) }
|
13
|
-
Dir.mkdir(File.join(extract_dir,dir_game_name)) if zip_archive.size > 1 && !Dir.exist?(File.join(extract_dir,dir_game_name))
|
14
|
-
zip_archive.each_entry do |rom|
|
15
|
-
if Dir.exist?(File.join(extract_dir,dir_game_name))
|
16
|
-
rom.extract(File.join(extract_dir,dir_game_name,rom.name)) unless File.exist?(File.join(extract_dir,dir_game_name,rom.name))
|
17
|
-
else
|
18
|
-
rom.extract(File.join(extract_dir,rom.name)) unless File.exist?(File.join(extract_dir,rom.name))
|
19
|
-
end
|
20
|
-
zip_archive.size == 1 ? file_or_dir_to_open = File.join(extract_dir,"\"#{rom.name}\"") : file_or_dir_to_open = File.join(extract_dir,dir_game_name)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
elsif game_obj.file_ext == ".7z"
|
24
|
-
puts "Extracting #{game_obj.filename}"
|
25
|
-
File.open(archive_dir, "rb") do |seven_zip_archive|
|
26
|
-
SevenZipRuby::Reader.open(seven_zip_archive) do |szr|
|
27
|
-
if szr.entries.size > 2
|
28
|
-
Dir.mkdir(File.join(extract_dir,dir_game_name)) unless Dir.exist?(File.join(extract_dir,dir_game_name))
|
29
|
-
szr.extract_if(File.join(extract_dir,dir_game_name)) { |entry| !/\.htm/.match(entry.inspect) }
|
30
|
-
file_or_dir_to_open = File.join(extract_dir,dir_game_name)
|
31
|
-
else
|
32
|
-
szr.extract_if(extract_dir) do |entry|
|
33
|
-
game_name = /(?<=file, |dir, |anti, )[.[^\.]]+\..+(?=>)/.match(entry.inspect)[0] unless /\.htm/.match(entry.inspect)
|
34
|
-
!/\.htm/.match(entry.inspect)
|
35
|
-
end
|
36
|
-
file_or_dir_to_open = File.join(extract_dir,"\"#{game_name}\"")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
else
|
41
|
-
puts "NOTE: No archive extraction. Only Zip and 7-Zip extraction is supported."
|
42
|
-
file_or_dir_to_open = extract_dir
|
43
|
-
end
|
44
|
-
file_or_dir_to_open
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.create_extract_dir(game_obj)
|
48
|
-
/(?<=\().+(?=\))/.match(game_obj.system.name) ? system_name = /(?<=\().+(?=\))/.match(game_obj.system.name)[0].downcase : system_name = game_obj.system.name.rstrip.gsub(/[[[:space:]]\/]/, "_").downcase
|
49
|
-
dir_w_system = File.join(Dir.home,"videogame_roms",system_name)
|
50
|
-
Dir.mkdir(dir_w_system) unless Dir.exist?(dir_w_system)
|
51
|
-
dir_w_system
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.move_archive(src,dest)
|
55
|
-
FileUtils.move src, dest
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.delete_archive(dir)
|
59
|
-
File.delete(dir)
|
60
|
-
end
|
61
|
-
|
1
|
+
|
2
|
+
class RomLoader::ArchiveExtractor
|
3
|
+
|
4
|
+
#Extracts zip or 7-zip rom files, manages the extracted dirs, then deletes archive files
|
5
|
+
def self.extract(archive_dir,extract_dir,game_obj)
|
6
|
+
file_or_dir_to_open = nil
|
7
|
+
dir_game_name = game_obj.filename.split(game_obj.file_ext)[0]
|
8
|
+
|
9
|
+
if game_obj.file_ext == ".zip"
|
10
|
+
puts "Extracting #{game_obj.filename}"
|
11
|
+
Zip::File.open(archive_dir) do |zip_archive|
|
12
|
+
zip_archive.glob("*htm").each { |entry| zip_archive.remove(entry) }
|
13
|
+
Dir.mkdir(File.join(extract_dir,dir_game_name)) if zip_archive.size > 1 && !Dir.exist?(File.join(extract_dir,dir_game_name))
|
14
|
+
zip_archive.each_entry do |rom|
|
15
|
+
if Dir.exist?(File.join(extract_dir,dir_game_name))
|
16
|
+
rom.extract(File.join(extract_dir,dir_game_name,rom.name)) unless File.exist?(File.join(extract_dir,dir_game_name,rom.name))
|
17
|
+
else
|
18
|
+
rom.extract(File.join(extract_dir,rom.name)) unless File.exist?(File.join(extract_dir,rom.name))
|
19
|
+
end
|
20
|
+
zip_archive.size == 1 ? file_or_dir_to_open = File.join(extract_dir,"\"#{rom.name}\"") : file_or_dir_to_open = File.join(extract_dir,dir_game_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
elsif game_obj.file_ext == ".7z"
|
24
|
+
puts "Extracting #{game_obj.filename}"
|
25
|
+
File.open(archive_dir, "rb") do |seven_zip_archive|
|
26
|
+
SevenZipRuby::Reader.open(seven_zip_archive) do |szr|
|
27
|
+
if szr.entries.size > 2
|
28
|
+
Dir.mkdir(File.join(extract_dir,dir_game_name)) unless Dir.exist?(File.join(extract_dir,dir_game_name))
|
29
|
+
szr.extract_if(File.join(extract_dir,dir_game_name)) { |entry| !/\.htm/.match(entry.inspect) }
|
30
|
+
file_or_dir_to_open = File.join(extract_dir,dir_game_name)
|
31
|
+
else
|
32
|
+
szr.extract_if(extract_dir) do |entry|
|
33
|
+
game_name = /(?<=file, |dir, |anti, )[.[^\.]]+\..+(?=>)/.match(entry.inspect)[0] unless /\.htm/.match(entry.inspect)
|
34
|
+
!/\.htm/.match(entry.inspect)
|
35
|
+
end
|
36
|
+
file_or_dir_to_open = File.join(extract_dir,"\"#{game_name}\"")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
puts "NOTE: No archive extraction. Only Zip and 7-Zip extraction is supported."
|
42
|
+
file_or_dir_to_open = extract_dir
|
43
|
+
end
|
44
|
+
file_or_dir_to_open
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.create_extract_dir(game_obj)
|
48
|
+
/(?<=\().+(?=\))/.match(game_obj.system.name) ? system_name = /(?<=\().+(?=\))/.match(game_obj.system.name)[0].downcase : system_name = game_obj.system.name.rstrip.gsub(/[[[:space:]]\/]/, "_").downcase
|
49
|
+
dir_w_system = File.join(Dir.home,"videogame_roms",system_name)
|
50
|
+
Dir.mkdir(dir_w_system) unless Dir.exist?(dir_w_system)
|
51
|
+
dir_w_system
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.move_archive(src,dest)
|
55
|
+
FileUtils.move src, dest
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.delete_archive(dir)
|
59
|
+
File.delete(dir)
|
60
|
+
end
|
61
|
+
|
62
62
|
end
|
@@ -1,91 +1,107 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
game_name
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
{}.tap do |game|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
game[:
|
62
|
-
game[:
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
1
|
+
# The class which facilitates scraping freeroms.com. Uses the nokogiri gem to scrape the site
|
2
|
+
class RomLoader::FreeromsScraper
|
3
|
+
|
4
|
+
def self.system_scrape(url)
|
5
|
+
|
6
|
+
system_list = Nokogiri::HTML(open(url)).css("dt.leftside > a")
|
7
|
+
[].tap do |game_system|
|
8
|
+
system_list.each do |system_info|
|
9
|
+
if system_info.text != "Links" && system_info.text != "Flash Games" && system_info.text != ""
|
10
|
+
system_name = system_info.text
|
11
|
+
begin
|
12
|
+
system_rom_url = system_info.attribute("href").value
|
13
|
+
rescue NoMethodError
|
14
|
+
|
15
|
+
else
|
16
|
+
game_system << {name: system_name, rom_index_url: system_rom_url}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# To retrieve the names and main rom urls of the individual games currently begin served by freeroms.com.
|
24
|
+
# Returns this information in the form of an array of hashes
|
25
|
+
def self.rom_scrape(url)
|
26
|
+
|
27
|
+
game_list = Nokogiri::HTML(open(url)).css("tr[class^=\"game\"] > td[align=\"left\"]")
|
28
|
+
[].tap do |rom_list|
|
29
|
+
game_list.each do |game_info|
|
30
|
+
begin
|
31
|
+
download_link = game_info.css("a").attribute("href").value
|
32
|
+
rescue NoMethodError
|
33
|
+
|
34
|
+
else
|
35
|
+
game_name = game_info.css("span").text
|
36
|
+
unless game_name == ""
|
37
|
+
game_name.gsub!(/[[:space:]]{2,}/) {|white_spaces| " "}
|
38
|
+
download_link.gsub!(/[[:space:]]/) {|white_space| CGI::escape(white_space)} unless download_link.ascii_only?
|
39
|
+
rom_list << {name: game_name, rom_detail_url: download_link}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# To retrieve the detailed information of individual games currently begin served by freeroms.com.
|
47
|
+
# Returns this information in the form of a hash
|
48
|
+
def self.rom_details(url)
|
49
|
+
|
50
|
+
direct_download = Nokogiri::HTML(open(url))
|
51
|
+
|
52
|
+
{}.tap do |game|
|
53
|
+
if !direct_download.css("td#rom > script").empty?
|
54
|
+
begin
|
55
|
+
game_url = /http:\/\/.+(\.zip|\.7z)/.match(direct_download.css("td#rom > script").first.children.first.text)
|
56
|
+
rescue NoMethodError
|
57
|
+
|
58
|
+
else
|
59
|
+
if game_url
|
60
|
+
game[:download_url] = game_url[0]
|
61
|
+
game[:file_ext] = game_url[1]
|
62
|
+
game[:filename] = /[.[^\/]]+(\.zip|\.7z)\Z/.match(game_url[0])[0]
|
63
|
+
begin
|
64
|
+
game[:size] = direct_download.css("td#rom + td[colspan=\"2\"]").first.children.first.text.strip
|
65
|
+
rescue NoMethodError
|
66
|
+
game[:size] = "N/A"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
elsif !direct_download.css("script").empty?
|
71
|
+
begin
|
72
|
+
direct_download.css("script").each { |script| game_url = /http:\/\/.+(\.zip|\.7z)/.match(script.children.text) if /http:\/\/.+(\.zip|\.7z)/.match(script.children.text) }
|
73
|
+
rescue NoMethodError
|
74
|
+
|
75
|
+
else
|
76
|
+
if game_url
|
77
|
+
game[:download_url] = game_url[0]
|
78
|
+
game[:file_ext] = game_url[1]
|
79
|
+
game[:filename] = /[.[^\/]]+(\.zip|\.7z)\Z/.match(game_url[0])[0]
|
80
|
+
begin
|
81
|
+
game[:size] = direct_download.css("td#rom + td[colspan=\"2\"]").first.children.first.text.strip
|
82
|
+
rescue NoMethodError
|
83
|
+
game[:size] = "N/A"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# To retrieve the letter indices for the roms of the game systems currently begin served by freeroms.com.
|
92
|
+
# Returns this information in the form of a hash
|
93
|
+
def self.rom_index_scrape(url)
|
94
|
+
|
95
|
+
rom_letter_list = Nokogiri::HTML(open(url)).css("tr.letters > td[align=\"center\"] > font > a")
|
96
|
+
{}.tap do |letter_hash|
|
97
|
+
rom_letter_list.each do |letter_list|
|
98
|
+
letter = letter_list.text.strip
|
99
|
+
begin
|
100
|
+
letter_hash[letter] = letter_list.attribute("href").value if letter =~ /\A[A-Z#]\Z/
|
101
|
+
rescue NoMethodError
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/romloader/game_rom.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
|
2
|
-
# The class whose instances represent an individual game rom
|
3
|
-
# (e.g. Chrono Trigger object)
|
4
|
-
class RomLoader::GameRom
|
5
|
-
|
6
|
-
attr_accessor :name, :system
|
7
|
-
attr_reader :rom_detail_url ,:download_url, :size, :file_ext, :filename
|
8
|
-
|
9
|
-
# Create individual game rom objects from information scraped from freeroms.com,
|
10
|
-
# then sets the required name and rom_detail_url instance variables
|
11
|
-
def initialize(name:, rom_detail_url:)
|
12
|
-
@name = name
|
13
|
-
@rom_detail_url = rom_detail_url
|
14
|
-
end
|
15
|
-
|
16
|
-
# Creates an array of GameRom objects from an array
|
17
|
-
def self.create_collection(game_array)
|
18
|
-
game_array.collect {|game_details| self.new(game_details)}
|
19
|
-
end
|
20
|
-
|
21
|
-
# Sets all additional, optional rom details
|
22
|
-
def set_rom_details(download_url: nil, size: nil, file_ext: nil, filename: nil)
|
23
|
-
@download_url = download_url
|
24
|
-
@size = size
|
25
|
-
@file_ext = file_ext
|
26
|
-
@filename = filename
|
27
|
-
nil
|
28
|
-
end
|
29
|
-
|
1
|
+
|
2
|
+
# The class whose instances represent an individual game rom
|
3
|
+
# (e.g. Chrono Trigger object)
|
4
|
+
class RomLoader::GameRom
|
5
|
+
|
6
|
+
attr_accessor :name, :system
|
7
|
+
attr_reader :rom_detail_url ,:download_url, :size, :file_ext, :filename
|
8
|
+
|
9
|
+
# Create individual game rom objects from information scraped from freeroms.com,
|
10
|
+
# then sets the required name and rom_detail_url instance variables
|
11
|
+
def initialize(name:, rom_detail_url:)
|
12
|
+
@name = name
|
13
|
+
@rom_detail_url = rom_detail_url
|
14
|
+
end
|
15
|
+
|
16
|
+
# Creates an array of GameRom objects from an array
|
17
|
+
def self.create_collection(game_array)
|
18
|
+
game_array.collect {|game_details| self.new(game_details)}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Sets all additional, optional rom details
|
22
|
+
def set_rom_details(download_url: nil, size: nil, file_ext: nil, filename: nil)
|
23
|
+
@download_url = download_url
|
24
|
+
@size = size
|
25
|
+
@file_ext = file_ext
|
26
|
+
@filename = filename
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
30
|
end
|
@@ -1,56 +1,56 @@
|
|
1
|
-
|
2
|
-
# The class whose instances represent an individual game system
|
3
|
-
# (e.g. Sega Genesis object)
|
4
|
-
class RomLoader::GameSystem
|
5
|
-
|
6
|
-
attr_accessor :name, :rom_index_url
|
7
|
-
attr_writer :rom_indices
|
8
|
-
|
9
|
-
@@all = []
|
10
|
-
|
11
|
-
# Create individual game system objects from information scraped from http://freeroms.com, sets all instance variables
|
12
|
-
def initialize(name:, rom_index_url:)
|
13
|
-
@name = name
|
14
|
-
@rom_index_url = rom_index_url
|
15
|
-
@rom_indices = {}
|
16
|
-
@roms = {}
|
17
|
-
@@all << self
|
18
|
-
end
|
19
|
-
|
20
|
-
# Creates multiple GameSystem objects from information scraped from http://freeroms.com
|
21
|
-
def self.create_from_collection(system_array)
|
22
|
-
system_array.each { |system_details| self.new(system_details)}
|
23
|
-
nil
|
24
|
-
end
|
25
|
-
|
26
|
-
# Retrieves an array of all GameSystem objects
|
27
|
-
def self.all
|
28
|
-
@@all
|
29
|
-
end
|
30
|
-
|
31
|
-
# Retrieves an array of all GameRom objects starting which the provided letter index
|
32
|
-
# (e.g. [Sonic the Hedgehog, Streets of Rage,...])
|
33
|
-
def get_roms_by_letter(letter_index)
|
34
|
-
@roms[letter_index]
|
35
|
-
end
|
36
|
-
|
37
|
-
# Retrieves an array of the indicies for the roms
|
38
|
-
# (i.e. ["A","B","C"...])
|
39
|
-
def get_rom_indices
|
40
|
-
@rom_indices.keys
|
41
|
-
end
|
42
|
-
|
43
|
-
# Retrieves the url for roms of a particular letter index
|
44
|
-
# (e.g. "A" => "http://freeroms.com/genesis_games_that_start_with_a.html")
|
45
|
-
def get_rom_collection_url(letter_index)
|
46
|
-
@rom_indices[letter_index]
|
47
|
-
end
|
48
|
-
|
49
|
-
# Add the game collection scraped from http://freeroms.com to the GameSystem object to the roms Hash
|
50
|
-
def add_roms_to_collection_by_letter(letter_index, game_obj_array)
|
51
|
-
|
52
|
-
game_obj_array.each { |game| game.system = self }
|
53
|
-
@roms[letter_index] = game_obj_array
|
54
|
-
end
|
55
|
-
|
1
|
+
|
2
|
+
# The class whose instances represent an individual game system
|
3
|
+
# (e.g. Sega Genesis object)
|
4
|
+
class RomLoader::GameSystem
|
5
|
+
|
6
|
+
attr_accessor :name, :rom_index_url
|
7
|
+
attr_writer :rom_indices
|
8
|
+
|
9
|
+
@@all = []
|
10
|
+
|
11
|
+
# Create individual game system objects from information scraped from http://freeroms.com, sets all instance variables
|
12
|
+
def initialize(name:, rom_index_url:)
|
13
|
+
@name = name
|
14
|
+
@rom_index_url = rom_index_url
|
15
|
+
@rom_indices = {}
|
16
|
+
@roms = {}
|
17
|
+
@@all << self
|
18
|
+
end
|
19
|
+
|
20
|
+
# Creates multiple GameSystem objects from information scraped from http://freeroms.com
|
21
|
+
def self.create_from_collection(system_array)
|
22
|
+
system_array.each { |system_details| self.new(system_details)}
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves an array of all GameSystem objects
|
27
|
+
def self.all
|
28
|
+
@@all
|
29
|
+
end
|
30
|
+
|
31
|
+
# Retrieves an array of all GameRom objects starting which the provided letter index
|
32
|
+
# (e.g. [Sonic the Hedgehog, Streets of Rage,...])
|
33
|
+
def get_roms_by_letter(letter_index)
|
34
|
+
@roms[letter_index]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Retrieves an array of the indicies for the roms
|
38
|
+
# (i.e. ["A","B","C"...])
|
39
|
+
def get_rom_indices
|
40
|
+
@rom_indices.keys
|
41
|
+
end
|
42
|
+
|
43
|
+
# Retrieves the url for roms of a particular letter index
|
44
|
+
# (e.g. "A" => "http://freeroms.com/genesis_games_that_start_with_a.html")
|
45
|
+
def get_rom_collection_url(letter_index)
|
46
|
+
@rom_indices[letter_index]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Add the game collection scraped from http://freeroms.com to the GameSystem object to the roms Hash
|
50
|
+
def add_roms_to_collection_by_letter(letter_index, game_obj_array)
|
51
|
+
|
52
|
+
game_obj_array.each { |game| game.system = self }
|
53
|
+
@roms[letter_index] = game_obj_array
|
54
|
+
end
|
55
|
+
|
56
56
|
end
|
@@ -1,222 +1,222 @@
|
|
1
|
-
|
2
|
-
# The CLI class
|
3
|
-
class RomLoader::RomLoaderCli
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
RomLoader::GameSystem.create_from_collection(RomLoader::FreeromsScraper.system_scrape("http://freeroms.com"))
|
7
|
-
raise RomLoader::ScrapingError::NoElementFound.exception("System index is currently unavailable. Exiting the program.") if RomLoader::GameSystem.all.size == 0
|
8
|
-
end
|
9
|
-
|
10
|
-
# Starts the CLI, called in romloader.rb
|
11
|
-
def start
|
12
|
-
input_stack = []
|
13
|
-
control_flow_level = 1
|
14
|
-
|
15
|
-
puts "Thanks for using RomLoader, powered by freeroms.com!\nNOTE: To play the games, please download an emulator for the desired system.\nConnecting to freeroms.com and retrieving the systems index...\n\n"
|
16
|
-
sleep 3
|
17
|
-
while control_flow_level > 0
|
18
|
-
case control_flow_level
|
19
|
-
when 1
|
20
|
-
list_systems
|
21
|
-
input = input_prompt("Select a system (1-#{RomLoader::GameSystem.all.size}) [exit]:",1..RomLoader::GameSystem.all.size)
|
22
|
-
if input == "exit"
|
23
|
-
control_flow_level = 0
|
24
|
-
else
|
25
|
-
input_stack.unshift(input)
|
26
|
-
control_flow_level += 1
|
27
|
-
end
|
28
|
-
when 2
|
29
|
-
system = select_system(input_stack[0].to_i)
|
30
|
-
list_system_index(system)
|
31
|
-
if system.get_rom_indices.empty?
|
32
|
-
begin
|
33
|
-
raise RomLoader::ScrapingError::NoElementFound.exception("Requested system is currently unavailable. Try another one.")
|
34
|
-
rescue
|
35
|
-
control_flow_level -= 1
|
36
|
-
input_stack.shift
|
37
|
-
end
|
38
|
-
else
|
39
|
-
input = input_prompt("Select a letter [back|exit]:", /[#{system.get_rom_indices.join.downcase}]/,control_flow_level)
|
40
|
-
control_flow_level = flow_controller(input,control_flow_level,input_stack)
|
41
|
-
end
|
42
|
-
when 3
|
43
|
-
game_collection = select_game_collection_by_index(system,input_stack[0].upcase)
|
44
|
-
if game_collection.empty?
|
45
|
-
begin
|
46
|
-
raise RomLoader::ScrapingError::NoElementFound.exception("Requested game index is currently unavailable. Try another one.")
|
47
|
-
rescue
|
48
|
-
control_flow_level -= 1
|
49
|
-
input_stack.shift
|
50
|
-
end
|
51
|
-
else
|
52
|
-
list_games(game_collection)
|
53
|
-
input = input_prompt("Select a game (1-#{game_collection.size}) [back|exit]", 1..game_collection.size,control_flow_level)
|
54
|
-
control_flow_level = flow_controller(input,control_flow_level,input_stack)
|
55
|
-
end
|
56
|
-
when 4
|
57
|
-
game = select_game(game_collection,input_stack[0].to_i)
|
58
|
-
if game.download_url == nil
|
59
|
-
begin
|
60
|
-
raise RomLoader::ScrapingError::NoElementFound.exception("Requested game is currently unavailable. Try another one.")
|
61
|
-
rescue
|
62
|
-
control_flow_level -= 1
|
63
|
-
input_stack.shift
|
64
|
-
end
|
65
|
-
else
|
66
|
-
display_rom_details(game)
|
67
|
-
input = input_prompt("Download? (Y/n) [exit]:", /[yn]/, control_flow_level)
|
68
|
-
if input == 'y' || input == ""
|
69
|
-
file_or_dir_to_open = download_rom(game)
|
70
|
-
if file_or_dir_to_open
|
71
|
-
if /\".+\"/.match(file_or_dir_to_open)
|
72
|
-
game_file = /\".+\"/.match(file_or_dir_to_open)[0]
|
73
|
-
input = input_prompt("Play #{game_file}? (y/N) [exit]:", /[yn]/,control_flow_level)
|
74
|
-
else
|
75
|
-
input = input_prompt("Open #{file_or_dir_to_open}? (y/N) [exit]:", /[yn]/,control_flow_level)
|
76
|
-
end
|
77
|
-
|
78
|
-
if !isWindows?
|
79
|
-
system("open #{file_or_dir_to_open}") if input == 'y'
|
80
|
-
else
|
81
|
-
system("powershell -command \"& { Invoke-Item '#{file_or_dir_to_open}' }\"") if input == 'y'
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
input_stack.shift
|
86
|
-
input == "exit" ? control_flow_level = 0 : control_flow_level -= 1
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
puts "Happy Gaming!"
|
92
|
-
end
|
93
|
-
|
94
|
-
# Sets control_flow_level in RomLoaderCli#start, manipulates input_stack in RomLoaderCli#start
|
95
|
-
def flow_controller(input,control_flow_level,input_stack)
|
96
|
-
if input == "exit"
|
97
|
-
0
|
98
|
-
elsif input == "back"
|
99
|
-
input_stack.shift
|
100
|
-
control_flow_level - 1
|
101
|
-
else
|
102
|
-
input_stack.unshift(input)
|
103
|
-
control_flow_level + 1
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Lists the game systems scraped from http://freeroms.com and saved in Romloader::GameSystem.all
|
108
|
-
# (e.g. 1. Amiga, 2. Atari, etc...)
|
109
|
-
def list_systems
|
110
|
-
RomLoader::GameSystem.all.each_with_index { |game_system, index| puts "#{index+1}. #{game_system.name}"}
|
111
|
-
print "\n"
|
112
|
-
end
|
113
|
-
|
114
|
-
# Retrieves an individual Romloader::GameSystem object from Romloader::GameSystem.all
|
115
|
-
def select_system(index)
|
116
|
-
RomLoader::GameSystem.all[index-1]
|
117
|
-
end
|
118
|
-
|
119
|
-
# List game index for the selected system by letter
|
120
|
-
# (e.g. A B C D...)
|
121
|
-
def list_system_index(selected_system)
|
122
|
-
if selected_system.get_rom_indices.empty?
|
123
|
-
selected_system.rom_indices = RomLoader::FreeromsScraper.rom_index_scrape(selected_system.rom_index_url)
|
124
|
-
end
|
125
|
-
|
126
|
-
puts "#{selected_system.name} index:"
|
127
|
-
selected_system.get_rom_indices.each {|letter| print letter + " "}
|
128
|
-
puts "\n\n"
|
129
|
-
end
|
130
|
-
|
131
|
-
# Retrieves all the games available for the selected system under the selected index
|
132
|
-
# (e.g. NES,"G")
|
133
|
-
def select_game_collection_by_index(system, letter)
|
134
|
-
puts "Loading roms...\n"
|
135
|
-
games_list = system.get_roms_by_letter(letter)
|
136
|
-
games_list ||= system.add_roms_to_collection_by_letter(letter,RomLoader::GameRom.create_collection(RomLoader::FreeromsScraper.rom_scrape(system.get_rom_collection_url(letter))))
|
137
|
-
end
|
138
|
-
|
139
|
-
# List all the games available for the selected index
|
140
|
-
# (e.g. "S": 1. Super Castlevania, 2. Super Mario World, etc...)
|
141
|
-
def list_games(games)
|
142
|
-
games.each_with_index {|game,index| puts "#{index+1}. #{game.name}"}
|
143
|
-
print "\n"
|
144
|
-
end
|
145
|
-
|
146
|
-
# Selects an individual game from the provided collection via index
|
147
|
-
def select_game(game_collection,index)
|
148
|
-
game_collection[index-1].set_rom_details(RomLoader::FreeromsScraper.rom_details(game_collection[index-1].rom_detail_url))
|
149
|
-
game_collection[index-1]
|
150
|
-
end
|
151
|
-
|
152
|
-
# List the details of the selected game
|
153
|
-
# (e.g. Chrono Trigger | SNES | 5.38 MB | .zip)
|
154
|
-
def display_rom_details(game)
|
155
|
-
puts "Rom details:"
|
156
|
-
puts "#{game.name} | System: #{game.system.name} | File size: #{game.size} | File type: #{game.file_ext}"
|
157
|
-
print "\n"
|
158
|
-
end
|
159
|
-
|
160
|
-
# Prints a custom message, takes user input, asesses whether the input is valid, and returns the input
|
161
|
-
def input_prompt(message,accepted_input,control_flow_level=nil)
|
162
|
-
valid = false
|
163
|
-
until valid
|
164
|
-
print message + " "
|
165
|
-
input = gets.chomp.strip.downcase
|
166
|
-
if accepted_input.class == Regexp && accepted_input.match(input)
|
167
|
-
valid = true
|
168
|
-
elsif accepted_input.class == Range && /\A\d+\Z/.match(input) && accepted_input.include?(input.to_i)
|
169
|
-
valid = true
|
170
|
-
elsif input == "exit" || (input == "back" && control_flow_level && control_flow_level.between?(2,3))
|
171
|
-
valid = true
|
172
|
-
elsif input == "" && control_flow_level == 4
|
173
|
-
valid = true
|
174
|
-
else
|
175
|
-
print "Invalid input! "
|
176
|
-
end
|
177
|
-
end
|
178
|
-
print "\n"
|
179
|
-
input
|
180
|
-
end
|
181
|
-
|
182
|
-
def isWindows?
|
183
|
-
/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
184
|
-
end
|
185
|
-
|
186
|
-
# Downloads the selected game to the local directory (~/videogame_roms)
|
187
|
-
def download_rom(game)
|
188
|
-
file_or_dir_to_open = nil
|
189
|
-
extract_dir = RomLoader::ArchiveExtractor.create_extract_dir(game)
|
190
|
-
if !File.exist?(File.join(extract_dir,game.filename))
|
191
|
-
puts "Downloading #{game.name} (#{game.size})..."
|
192
|
-
if isWindows?
|
193
|
-
result = Dir.chdir(extract_dir) { system("powershell -command \"& { Invoke-WebRequest '#{game.download_url}' -OutFile '#{game.filename}' }\"") }
|
194
|
-
else
|
195
|
-
result = Dir.chdir(extract_dir) { system("curl -Og# \"#{game.download_url}\"") }
|
196
|
-
end
|
197
|
-
|
198
|
-
if result && !isWindows? && game.system.name != "MAME"
|
199
|
-
puts "Finished downloading #{game.filename} to #{extract_dir}. Extracting..."
|
200
|
-
file_or_dir_to_open = RomLoader::ArchiveExtractor.extract(File.join(extract_dir,game.filename),extract_dir,game)
|
201
|
-
RomLoader::ArchiveExtractor.delete_archive(File.join(extract_dir,game.filename))
|
202
|
-
elsif result && !isWindows? && game.system.name == "MAME"
|
203
|
-
puts "Finished downloading #{game.filename} to #{extract_dir}."
|
204
|
-
puts "NOTE: No archive extraction. MAME roms must remain zipped to play."
|
205
|
-
file_or_dir_to_open = extract_dir
|
206
|
-
elsif result && isWindows?
|
207
|
-
puts "Finished downloading #{game.filename} to #{extract_dir}."
|
208
|
-
file_or_dir_to_open = extract_dir
|
209
|
-
else
|
210
|
-
puts "An error occured, the rom couldn't be downloaded.\n\n"
|
211
|
-
end
|
212
|
-
else
|
213
|
-
puts "File already exists.\n\n"
|
214
|
-
end
|
215
|
-
|
216
|
-
sleep 2
|
217
|
-
file_or_dir_to_open
|
218
|
-
end
|
219
|
-
|
220
|
-
end
|
221
|
-
|
222
|
-
|
1
|
+
|
2
|
+
# The CLI class
|
3
|
+
class RomLoader::RomLoaderCli
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
RomLoader::GameSystem.create_from_collection(RomLoader::FreeromsScraper.system_scrape("http://freeroms.com"))
|
7
|
+
raise RomLoader::ScrapingError::NoElementFound.exception("System index is currently unavailable. Exiting the program.") if RomLoader::GameSystem.all.size == 0
|
8
|
+
end
|
9
|
+
|
10
|
+
# Starts the CLI, called in romloader.rb
|
11
|
+
def start
|
12
|
+
input_stack = []
|
13
|
+
control_flow_level = 1
|
14
|
+
|
15
|
+
puts "Thanks for using RomLoader, powered by freeroms.com!\nNOTE: To play the games, please download an emulator for the desired system.\nConnecting to freeroms.com and retrieving the systems index...\n\n"
|
16
|
+
sleep 3
|
17
|
+
while control_flow_level > 0
|
18
|
+
case control_flow_level
|
19
|
+
when 1
|
20
|
+
list_systems
|
21
|
+
input = input_prompt("Select a system (1-#{RomLoader::GameSystem.all.size}) [exit]:",1..RomLoader::GameSystem.all.size)
|
22
|
+
if input == "exit"
|
23
|
+
control_flow_level = 0
|
24
|
+
else
|
25
|
+
input_stack.unshift(input)
|
26
|
+
control_flow_level += 1
|
27
|
+
end
|
28
|
+
when 2
|
29
|
+
system = select_system(input_stack[0].to_i)
|
30
|
+
list_system_index(system)
|
31
|
+
if system.get_rom_indices.empty?
|
32
|
+
begin
|
33
|
+
raise RomLoader::ScrapingError::NoElementFound.exception("Requested system is currently unavailable. Try another one.")
|
34
|
+
rescue
|
35
|
+
control_flow_level -= 1
|
36
|
+
input_stack.shift
|
37
|
+
end
|
38
|
+
else
|
39
|
+
input = input_prompt("Select a letter [back|exit]:", /[#{system.get_rom_indices.join.downcase}]/,control_flow_level)
|
40
|
+
control_flow_level = flow_controller(input,control_flow_level,input_stack)
|
41
|
+
end
|
42
|
+
when 3
|
43
|
+
game_collection = select_game_collection_by_index(system,input_stack[0].upcase)
|
44
|
+
if game_collection.empty?
|
45
|
+
begin
|
46
|
+
raise RomLoader::ScrapingError::NoElementFound.exception("Requested game index is currently unavailable. Try another one.")
|
47
|
+
rescue
|
48
|
+
control_flow_level -= 1
|
49
|
+
input_stack.shift
|
50
|
+
end
|
51
|
+
else
|
52
|
+
list_games(game_collection)
|
53
|
+
input = input_prompt("Select a game (1-#{game_collection.size}) [back|exit]", 1..game_collection.size,control_flow_level)
|
54
|
+
control_flow_level = flow_controller(input,control_flow_level,input_stack)
|
55
|
+
end
|
56
|
+
when 4
|
57
|
+
game = select_game(game_collection,input_stack[0].to_i)
|
58
|
+
if game.download_url == nil
|
59
|
+
begin
|
60
|
+
raise RomLoader::ScrapingError::NoElementFound.exception("Requested game is currently unavailable. Try another one.")
|
61
|
+
rescue
|
62
|
+
control_flow_level -= 1
|
63
|
+
input_stack.shift
|
64
|
+
end
|
65
|
+
else
|
66
|
+
display_rom_details(game)
|
67
|
+
input = input_prompt("Download? (Y/n) [exit]:", /[yn]/, control_flow_level)
|
68
|
+
if input == 'y' || input == ""
|
69
|
+
file_or_dir_to_open = download_rom(game)
|
70
|
+
if file_or_dir_to_open
|
71
|
+
if /\".+\"/.match(file_or_dir_to_open)
|
72
|
+
game_file = /\".+\"/.match(file_or_dir_to_open)[0]
|
73
|
+
input = input_prompt("Play #{game_file}? (y/N) [exit]:", /[yn]/,control_flow_level)
|
74
|
+
else
|
75
|
+
input = input_prompt("Open #{file_or_dir_to_open}? (y/N) [exit]:", /[yn]/,control_flow_level)
|
76
|
+
end
|
77
|
+
|
78
|
+
if !isWindows?
|
79
|
+
system("open #{file_or_dir_to_open}") if input == 'y'
|
80
|
+
else
|
81
|
+
system("powershell -command \"& { Invoke-Item '#{file_or_dir_to_open}' }\"") if input == 'y'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
input_stack.shift
|
86
|
+
input == "exit" ? control_flow_level = 0 : control_flow_level -= 1
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
puts "Happy Gaming!"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Sets control_flow_level in RomLoaderCli#start, manipulates input_stack in RomLoaderCli#start
|
95
|
+
def flow_controller(input,control_flow_level,input_stack)
|
96
|
+
if input == "exit"
|
97
|
+
0
|
98
|
+
elsif input == "back"
|
99
|
+
input_stack.shift
|
100
|
+
control_flow_level - 1
|
101
|
+
else
|
102
|
+
input_stack.unshift(input)
|
103
|
+
control_flow_level + 1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Lists the game systems scraped from http://freeroms.com and saved in Romloader::GameSystem.all
|
108
|
+
# (e.g. 1. Amiga, 2. Atari, etc...)
|
109
|
+
def list_systems
|
110
|
+
RomLoader::GameSystem.all.each_with_index { |game_system, index| puts "#{index+1}. #{game_system.name}"}
|
111
|
+
print "\n"
|
112
|
+
end
|
113
|
+
|
114
|
+
# Retrieves an individual Romloader::GameSystem object from Romloader::GameSystem.all
|
115
|
+
def select_system(index)
|
116
|
+
RomLoader::GameSystem.all[index-1]
|
117
|
+
end
|
118
|
+
|
119
|
+
# List game index for the selected system by letter
|
120
|
+
# (e.g. A B C D...)
|
121
|
+
def list_system_index(selected_system)
|
122
|
+
if selected_system.get_rom_indices.empty?
|
123
|
+
selected_system.rom_indices = RomLoader::FreeromsScraper.rom_index_scrape(selected_system.rom_index_url)
|
124
|
+
end
|
125
|
+
|
126
|
+
puts "#{selected_system.name} index:"
|
127
|
+
selected_system.get_rom_indices.each {|letter| print letter + " "}
|
128
|
+
puts "\n\n"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Retrieves all the games available for the selected system under the selected index
|
132
|
+
# (e.g. NES,"G")
|
133
|
+
def select_game_collection_by_index(system, letter)
|
134
|
+
puts "Loading roms...\n"
|
135
|
+
games_list = system.get_roms_by_letter(letter)
|
136
|
+
games_list ||= system.add_roms_to_collection_by_letter(letter,RomLoader::GameRom.create_collection(RomLoader::FreeromsScraper.rom_scrape(system.get_rom_collection_url(letter))))
|
137
|
+
end
|
138
|
+
|
139
|
+
# List all the games available for the selected index
|
140
|
+
# (e.g. "S": 1. Super Castlevania, 2. Super Mario World, etc...)
|
141
|
+
def list_games(games)
|
142
|
+
games.each_with_index {|game,index| puts "#{index+1}. #{game.name}"}
|
143
|
+
print "\n"
|
144
|
+
end
|
145
|
+
|
146
|
+
# Selects an individual game from the provided collection via index
|
147
|
+
def select_game(game_collection,index)
|
148
|
+
game_collection[index-1].set_rom_details(RomLoader::FreeromsScraper.rom_details(game_collection[index-1].rom_detail_url))
|
149
|
+
game_collection[index-1]
|
150
|
+
end
|
151
|
+
|
152
|
+
# List the details of the selected game
|
153
|
+
# (e.g. Chrono Trigger | SNES | 5.38 MB | .zip)
|
154
|
+
def display_rom_details(game)
|
155
|
+
puts "Rom details:"
|
156
|
+
puts "#{game.name} | System: #{game.system.name} | File size: #{game.size} | File type: #{game.file_ext}"
|
157
|
+
print "\n"
|
158
|
+
end
|
159
|
+
|
160
|
+
# Prints a custom message, takes user input, asesses whether the input is valid, and returns the input
|
161
|
+
def input_prompt(message,accepted_input,control_flow_level=nil)
|
162
|
+
valid = false
|
163
|
+
until valid
|
164
|
+
print message + " "
|
165
|
+
input = gets.chomp.strip.downcase
|
166
|
+
if accepted_input.class == Regexp && accepted_input.match(input)
|
167
|
+
valid = true
|
168
|
+
elsif accepted_input.class == Range && /\A\d+\Z/.match(input) && accepted_input.include?(input.to_i)
|
169
|
+
valid = true
|
170
|
+
elsif input == "exit" || (input == "back" && control_flow_level && control_flow_level.between?(2,3))
|
171
|
+
valid = true
|
172
|
+
elsif input == "" && control_flow_level == 4
|
173
|
+
valid = true
|
174
|
+
else
|
175
|
+
print "Invalid input! "
|
176
|
+
end
|
177
|
+
end
|
178
|
+
print "\n"
|
179
|
+
input
|
180
|
+
end
|
181
|
+
|
182
|
+
def isWindows?
|
183
|
+
/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
|
184
|
+
end
|
185
|
+
|
186
|
+
# Downloads the selected game to the local directory (~/videogame_roms)
|
187
|
+
def download_rom(game)
|
188
|
+
file_or_dir_to_open = nil
|
189
|
+
extract_dir = RomLoader::ArchiveExtractor.create_extract_dir(game)
|
190
|
+
if !File.exist?(File.join(extract_dir,game.filename))
|
191
|
+
puts "Downloading #{game.name} (#{game.size})..."
|
192
|
+
if isWindows?
|
193
|
+
result = Dir.chdir(extract_dir) { system("powershell -command \"& { Invoke-WebRequest '#{game.download_url}' -OutFile '#{game.filename}' }\"") }
|
194
|
+
else
|
195
|
+
result = Dir.chdir(extract_dir) { system("curl -Og# \"#{game.download_url}\"") }
|
196
|
+
end
|
197
|
+
|
198
|
+
if result && !isWindows? && game.system.name != "MAME"
|
199
|
+
puts "Finished downloading #{game.filename} to #{extract_dir}. Extracting..."
|
200
|
+
file_or_dir_to_open = RomLoader::ArchiveExtractor.extract(File.join(extract_dir,game.filename),extract_dir,game)
|
201
|
+
RomLoader::ArchiveExtractor.delete_archive(File.join(extract_dir,game.filename))
|
202
|
+
elsif result && !isWindows? && game.system.name == "MAME"
|
203
|
+
puts "Finished downloading #{game.filename} to #{extract_dir}."
|
204
|
+
puts "NOTE: No archive extraction. MAME roms must remain zipped to play."
|
205
|
+
file_or_dir_to_open = extract_dir
|
206
|
+
elsif result && isWindows?
|
207
|
+
puts "Finished downloading #{game.filename} to #{extract_dir}."
|
208
|
+
file_or_dir_to_open = extract_dir
|
209
|
+
else
|
210
|
+
puts "An error occured, the rom couldn't be downloaded.\n\n"
|
211
|
+
end
|
212
|
+
else
|
213
|
+
puts "File already exists.\n\n"
|
214
|
+
end
|
215
|
+
|
216
|
+
sleep 2
|
217
|
+
file_or_dir_to_open
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
|
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
|
-
module RomLoader::ScrapingError
|
3
|
-
|
4
|
-
class NoElementFound < StandardError
|
5
|
-
|
6
|
-
end
|
7
|
-
|
1
|
+
|
2
|
+
module RomLoader::ScrapingError
|
3
|
+
|
4
|
+
class NoElementFound < StandardError
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
8
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: romloader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Efrain Perez Jr
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -133,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
133
133
|
version: '0'
|
134
134
|
requirements: []
|
135
135
|
rubyforge_project:
|
136
|
-
rubygems_version: 2.
|
136
|
+
rubygems_version: 2.6.7
|
137
137
|
signing_key:
|
138
138
|
specification_version: 4
|
139
139
|
summary: A videogame rom downloader powered by freeroms.com!
|