romloader 1.2.0 → 1.2.2
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.
- 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!
|