star-wars-comics 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e050291c64e63027619ea94728f49ff0468a00b5ff69c9011da8cd674bafe91d
4
+ data.tar.gz: e6cbdfd86d8c9eea0ed1c28a602b7c1329ab8b9641e0cf2cb81d089e6779dc20
5
+ SHA512:
6
+ metadata.gz: 9bef8b69f27dcc12d1fc877eb4e638a40513a4f460f5c25df92bf381475bd5f9784eb7f05b74adeddd9900e744c1d0878931ab14ecaa13864917a135b7829470
7
+ data.tar.gz: 4df989ceabaa001d7a2ce52ec4cfacfd78e77f242d514fec8dc2d4f8799df50656538e39f9ef73afee07689e33c7ab2075170264a6a1ea76f8a10c3251dfde2e
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/star-wars-comics'
4
+
5
+ StarWarsComics::CLI.new.call
@@ -0,0 +1,20 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+ require 'pry'
4
+
5
+ module StarWarsComics
6
+ end
7
+
8
+ module Concerns
9
+ end
10
+
11
+ require_relative 'star-wars-comics/concerns/findable.rb'
12
+
13
+ require_relative 'star-wars-comics/artist.rb'
14
+ require_relative 'star-wars-comics/artists.rb'
15
+ require_relative 'star-wars-comics/cli.rb'
16
+ require_relative 'star-wars-comics/issue.rb'
17
+ require_relative 'star-wars-comics/scraper.rb'
18
+ require_relative 'star-wars-comics/series.rb'
19
+
20
+ BASE_PATH = "http://starwars.wikia.com"
@@ -0,0 +1,64 @@
1
+ class StarWarsComics::Artist
2
+ extend Concerns::Findable
3
+
4
+ attr_accessor :name, :issues, :path
5
+
6
+ @@all = []
7
+
8
+ def initialize(name = "", path = "")
9
+ @name = name
10
+ @path = path
11
+ @issues = []
12
+ end
13
+
14
+ def add_issue(issue)
15
+ artist_var = self.class.to_s.sub("StarWarsComics::Artists::", "").downcase
16
+ issue.send("#{artist_var}") || issue.send("#{artist_var}=", self)
17
+ self.issues << issue unless self.issues.include?(issue)
18
+ end
19
+
20
+ def frequent_collaborators
21
+ collabs_hist = {}
22
+
23
+ self.issues.each do |issue|
24
+ if collabs_hist.has_key?(issue.writer)
25
+ collabs_hist[issue.writer] += 1
26
+ elsif issue.writer != self
27
+ collabs_hist[issue.writer] = 0
28
+ end
29
+
30
+ if collabs_hist.has_key?(issue.penciller)
31
+ collabs_hist[issue.penciller] += 1
32
+ elsif issue.penciller != self
33
+ collabs_hist[issue.penciller] = 0
34
+ end
35
+
36
+ if collabs_hist.has_key?(issue.letterer)
37
+ collabs_hist[issue.letterer] += 1
38
+ elsif issue.letterer != self
39
+ collabs_hist[issue.letterer] = 0
40
+ end
41
+
42
+ if collabs_hist.has_key?(issue.colorist)
43
+ collabs_hist[issue.colorist] += 1
44
+ elsif issue.colorist != self
45
+ collabs_hist[issue.colorist] = 0
46
+ end
47
+
48
+ end
49
+
50
+ collabs_hist.sort_by {|collab, times| times}.each do |collab, times|
51
+ puts "#{collab.name}: #{times} times" unless times < 2
52
+ end
53
+
54
+ end
55
+
56
+ def self.sort_alpha
57
+ self.all.sort_by! {|artist| artist.name}
58
+ end
59
+
60
+ def self.all
61
+ @@all
62
+ end
63
+
64
+ end
@@ -0,0 +1,14 @@
1
+ module StarWarsComics::Artists
2
+ class Writer < StarWarsComics::Artist
3
+ end
4
+
5
+ class Penciller < StarWarsComics::Artist
6
+ end
7
+
8
+ class Letterer < StarWarsComics::Artist
9
+ end
10
+
11
+ class Colorist < StarWarsComics::Artist
12
+ end
13
+
14
+ end
@@ -0,0 +1,213 @@
1
+ class StarWarsComics::CLI
2
+ def call
3
+ start
4
+ end
5
+
6
+ def start
7
+ puts " . . . . . ."
8
+ puts " . . . . . . ."
9
+ puts " _________________ ____ __________"
10
+ puts " . . / | / \\ . | \\"
11
+ puts " . / ______ _____| . / \\ | ___ | . ."
12
+ puts " \\ \\ | | / /\\ \\ | |___> |"
13
+ puts " . \\ \\ | | / /__\\ \\ . | _/ ."
14
+ puts " . ________> | | | . / \\ | |\\ \\_______ ."
15
+ puts " | / | | / ______ \\ | | \\ |"
16
+ puts " |___________/ |___| /____/ \\____\\ |___| \\__________| ."
17
+ puts " . ____ __ . _____ ____ . __________ . _________"
18
+ puts " \\ \\ / \\ / / / \\ | \\ / | ."
19
+ puts " \\ \\/ \\/ / / \\ | ___ | / ______| ."
20
+ puts " \\ / / /\\ \\ . | |___> | \\ \\"
21
+ puts " . \\ / / /__\\ \\ | _/. \\ \\ +"
22
+ puts " \\ /\\ / / \\ | |\\ \\______> | ."
23
+ puts " \\ / \\ / / ______ \\ | | \\ / ."
24
+ puts " . . \\/ \\/ /____/ \\____\\ |___| \\____________/ LS"
25
+ puts " . ."
26
+ puts " . . . . ."
27
+ puts " . . ."
28
+
29
+ puts "Welcome to Star Wars Comics! Getting all the series..."
30
+ StarWarsComics::Series.all
31
+ puts "Done!"
32
+
33
+ loop do
34
+ puts "\nWould you like to list series (fast) or by artist (will need additional download)?"
35
+ puts "Or, type \"exit\" to quit."
36
+ input = gets.strip
37
+ input.downcase!
38
+
39
+ if input == "exit" || input == "quit"
40
+ exit
41
+ elsif input.include?("series")
42
+ list_all_series
43
+ elsif input.include?("artist")
44
+ list_all_artists
45
+ else
46
+ puts "\nPlease enter \"series,\" \"artist,\" or \"exit.\""
47
+ sleep(2)
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ def list_all_series
54
+ puts " _____________________________________________________________________________ "
55
+ puts "|:.. ``:::%%%%%%HH|"
56
+ puts "|%%%:::::.. C o m i c B o o k S e r i e s `:::::%%%%|"
57
+ puts "|HH%%%%%:::::.....______________________________________________________::::::|\n\n"
58
+
59
+ sleep(1)
60
+
61
+ StarWarsComics::Series.all.each_with_index do |series, i|
62
+ puts "#{i+1}. #{series.name}"
63
+ end
64
+
65
+ loop do
66
+ input = get_input("a series", 1, StarWarsComics::Series.all.length)
67
+
68
+ if input.class == Integer
69
+ list_issues_for_series(StarWarsComics::Series.find(input))
70
+ list_all_series
71
+ break
72
+ elsif input == "back"
73
+ break
74
+ elsif StarWarsComics::Series.find_by_name(input) != nil
75
+ list_issues_for_series(StarWarsComics::Series.find_by_name(input))
76
+ list_all_series
77
+ break
78
+ else
79
+ puts "Could not find a series with that name. Please try again!"
80
+ sleep(1)
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ def list_issues_for_series(series)
87
+ if series.issues.empty?
88
+ puts "\nGetting issues for #{series.name}..."
89
+ StarWarsComics::Scraper.scrape_issues(series)
90
+ puts "Done! Listing...\n\n"
91
+ sleep(2)
92
+ end
93
+
94
+ put_title(series.name)
95
+
96
+ series.issues.each_with_index do |issue, i|
97
+ puts "#{i+1}. #{issue.name}"
98
+ end
99
+
100
+ loop do
101
+ input = get_input("an issue", 1, series.issues.length)
102
+
103
+ if input.class == Integer
104
+ show_info_for_issue(series.issues[input-1])
105
+ list_issues_for_series(series)
106
+ break
107
+ elsif input == "back"
108
+ break
109
+ elsif StarWarsComics::Issue.find_by_name(input)
110
+ show_info_for_issue(StarWarsComics::Issue.find_by_name(input))
111
+ list_issues_for_series(series)
112
+ break
113
+ else
114
+ puts "\nCould not find an issue with that name. Please try again!"
115
+ sleep(1)
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ def show_info_for_issue(issue)
122
+ puts "\nIssue: #{issue.name}"
123
+ puts " Series: #{issue.series.name}"
124
+ puts " Publication date: #{issue.pub_date}"
125
+ puts " Pages: #{issue.pages}"
126
+ puts " Artists:"
127
+ puts " Writer: #{issue.writer.name if issue.writer}"
128
+ puts " Penciller: #{issue.penciller.name if issue.penciller}"
129
+ puts " Letterer: #{issue.letterer.name if issue.letterer}"
130
+ puts " Colorist: #{issue.colorist.name if issue.colorist}"
131
+ puts "\nPress \[Enter\] to return to the previous menu."
132
+ gets
133
+ end
134
+
135
+ def list_all_artists
136
+ puts " _____________________________________________________________________________ "
137
+ puts "|:.. ``:::%%%%%%HH|"
138
+ puts "|%%%:::::.. C o m i c B o o k A r t i s t s `:::::%%%%|"
139
+ puts "|HH%%%%%:::::.....______________________________________________________::::::|\n\n"
140
+ puts "Downloading all artist info. This could take a while..."
141
+
142
+ StarWarsComics::Series.all.each do |series|
143
+ StarWarsComics::Scraper.scrape_issues(series) if series.issues.empty?
144
+ end
145
+
146
+ StarWarsComics::Artist.sort_alpha
147
+
148
+ puts "Done! Listing...\n\n"
149
+ sleep(2)
150
+
151
+ StarWarsComics::Artist.all.each_with_index do |artist, i|
152
+ puts "#{i+1}. #{artist.name}"
153
+ end
154
+
155
+ loop do
156
+ input = get_input("an artist", 1, StarWarsComics::Artist.all.length)
157
+
158
+ if input.class == Integer
159
+ show_info_for_artist(StarWarsComics::Artist.find(input))
160
+ list_all_artists
161
+ break
162
+ elsif input == "back"
163
+ break
164
+ elsif StarWarsComics::Artist.find_by_name(input) != nil
165
+ show_info_for_artist(StarWarsComics::Artist.find_by_name(input))
166
+ list_all_artists
167
+ break
168
+ else
169
+ puts "Could not find an artist with that name. Please try again!"
170
+ sleep(1)
171
+ end
172
+ end
173
+
174
+ end
175
+
176
+ def show_info_for_artist(artist)
177
+ puts "Artist: #{artist.name}"
178
+ puts " Artist type: #{artist.class}".gsub("StarWarsComics::Artists::", "")
179
+ puts " Issues:"
180
+
181
+ artist.issues.each {|issue| puts " #{issue.name}"}
182
+
183
+ puts "\nPress \[Enter\] to return to the previous menu."
184
+ gets
185
+ end
186
+
187
+
188
+ def get_input(picking, min, max)
189
+ puts "\nPick #{picking}--please enter by number or name. Type \"exit\" to quit."
190
+
191
+ loop do
192
+ input = gets.strip
193
+
194
+ if input.downcase == "exit" || input.downcase == "quit"
195
+ exit
196
+ elsif input.to_i.between?(min, max)
197
+ return input.to_i
198
+ elsif !input.match?(/0+/) && input.to_i == 0
199
+ return input
200
+ else
201
+ puts "Please enter a name, a number between #{min} and #{max}, or type \"exit.\""
202
+ end
203
+ end
204
+ end
205
+
206
+ def put_title(title)
207
+ puts " ______________________________________________________________________"
208
+ puts "|:.. ``:::%%%%%%HH|"
209
+ puts "|%%%:::::.." + title.center(50) + "`:::::%%%%|"
210
+ puts "|HH%%%%%:::::....._______________________________________________::::::|\n\n"
211
+ end
212
+
213
+ end
@@ -0,0 +1,15 @@
1
+ module Concerns::Findable
2
+
3
+ def find(input)
4
+ self.all[input-1]
5
+ end
6
+
7
+ def find_or_create_by_name(name, path)
8
+ self.find_by_name(name) || self.new(name, path)
9
+ end
10
+
11
+ def find_by_name(name)
12
+ self.all.detect {|obj| obj.name.downcase == name.downcase}
13
+ end
14
+
15
+ end
@@ -0,0 +1,55 @@
1
+ class StarWarsComics::Issue
2
+ extend Concerns::Findable
3
+
4
+ attr_accessor :name, :path, :pub_date, :pages, :next_issue, :last_issue
5
+
6
+ attr_reader :series, :writer, :penciller, :letterer, :colorist
7
+
8
+ @@all = []
9
+
10
+ def initialize(name = nil, path = nil)
11
+ @name = name
12
+ @path = path
13
+ @writer = nil
14
+ @penciller = nil
15
+ @letterer = nil
16
+ @colorist = nil
17
+ @next_issue = nil
18
+ @last_issue = nil
19
+ StarWarsComics::Scraper.scrape_issue_info(self)
20
+ end
21
+
22
+ def series=(series)
23
+ @series = series
24
+ series.add_issue(self)
25
+ end
26
+
27
+ def writer=(writer)
28
+ @writer = writer
29
+ writer.add_issue(self)
30
+ end
31
+
32
+ def penciller=(penciller)
33
+ @penciller = penciller
34
+ penciller.add_issue(self)
35
+ end
36
+
37
+ def letterer=(letterer)
38
+ @letterer = letterer
39
+ letterer.add_issue(self)
40
+ end
41
+
42
+ def colorist=(colorist)
43
+ @colorist = colorist
44
+ colorist.add_issue(self)
45
+ end
46
+
47
+ def add_issue(issue)
48
+ self.issues << issue unless self.issues.include?(issue)
49
+ end
50
+
51
+ def self.all
52
+ @@all
53
+ end
54
+
55
+ end
@@ -0,0 +1,81 @@
1
+ class StarWarsComics::Scraper
2
+
3
+ def self.scrape_series(path, all_series)
4
+ categories = Nokogiri::HTML(open(BASE_PATH + path)).css("div.CategoryTreeItem a")
5
+
6
+ categories.each do |category|
7
+ self.scrape_series(category["href"], all_series) unless self.dont_include(category)
8
+ end
9
+
10
+ series_link = Nokogiri::HTML(open(BASE_PATH + path)).css("div#mw-pages div a").first
11
+
12
+ unless series_link == nil
13
+ series = StarWarsComics::Series.new(series_link.text, series_link["href"])
14
+ series.desc = Nokogiri::HTML(open(BASE_PATH + series.path)).css("div#mw-content-text p").first.text.sub(/\[.*\]/, "")
15
+ all_series << series
16
+ end
17
+
18
+ all_series
19
+ end
20
+
21
+ def self.scrape_issues(series)
22
+ issues = Nokogiri::HTML(open(BASE_PATH + series.path)).css('td[style*="background-color:"] + td i a')
23
+
24
+ last_issue = nil
25
+ issues.each do |issue_link|
26
+ issue = StarWarsComics::Issue.find_or_create_by_name(issue_link["title"], issue_link["href"])
27
+ issue.series = series
28
+ issue.last_issue = last_issue
29
+ issue.last_issue.next_issue = issue unless last_issue == nil
30
+ last_issue = issue
31
+ end
32
+ end
33
+
34
+ def self.scrape_issue_info(issue)
35
+ issue_info = Nokogiri::HTML(open(BASE_PATH + issue.path)).css(
36
+ "aside.portable-infobox")
37
+
38
+ issue.name = issue_info.css("h2.pi-title").text
39
+
40
+ attributions = issue_info.css("section.pi-item.pi-group div.pi-item")
41
+
42
+ attributions.each do |attrib|
43
+ attrib_type = attrib.css("h3.pi-data-label").text
44
+ attrib_value = attrib.css("div.pi-data-value").text.sub(/\[.*\]/, "")
45
+
46
+ unless attrib.css("div.pi-data-value a").empty?
47
+ attrib_link = attrib.css("div.pi-data-value a").attribute("href").value
48
+ end
49
+
50
+ if attrib_type == "Writer"
51
+ issue.writer = StarWarsComics::Artists::Writer.find_or_create_by_name(
52
+ attrib_value, attrib_link)
53
+ elsif attrib_type == "Penciller"
54
+ issue.penciller = StarWarsComics::Artists::Penciller.find_or_create_by_name(
55
+ attrib_value, attrib_link)
56
+ elsif attrib_type == "Letterer"
57
+ issue.letterer = StarWarsComics::Artists::Letterer.find_or_create_by_name(
58
+ attrib_value, attrib_link)
59
+ elsif attrib_type == "Colorist"
60
+ issue.colorist = StarWarsComics::Artists::Colorist.find_or_create_by_name(
61
+ attrib_value, attrib_link)
62
+
63
+ elsif attrib_type == "Publication date"
64
+ issue.pub_date = attrib_value
65
+ elsif attrib_type == "Pages"
66
+ issue.pages = attrib_value
67
+ end
68
+
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def self.dont_include(category)
75
+ category.text == "Canon comic strips" ||
76
+ category.text == "Star Wars Rebels Magazine comics" ||
77
+ category.text == "Star Wars Adventures artists" ||
78
+ category.text == "Star Wars Adventures stories" ||
79
+ category.text == "Star Wars Adventures writers"
80
+ end
81
+ end
@@ -0,0 +1,22 @@
1
+ class StarWarsComics::Series
2
+ extend Concerns::Findable
3
+
4
+ attr_accessor :name, :start_date, :end_date, :status, :stories, :path,
5
+ :issues, :desc
6
+
7
+ def initialize(name = nil, path = nil)
8
+ @name = name
9
+ @path = path
10
+ @issues = []
11
+ end
12
+
13
+ def add_issue(issue)
14
+ issue.series ||= self
15
+ self.issues << issue unless self.issues.include?(issue)
16
+ end
17
+
18
+ def self.all
19
+ @@all ||= StarWarsComics::Scraper::scrape_series("/wiki/Category:Canon_comics", [])
20
+ end
21
+
22
+ end
@@ -0,0 +1,3 @@
1
+ module StarWarsComics
2
+ VERSION = "1.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: star-wars-comics
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sam Kalum
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: vcr
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: webmock
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Much longer explanation coming soon...
112
+ email: stkalum@gmail.com
113
+ executables:
114
+ - star-wars-comics
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - bin/star-wars-comics
119
+ - lib/star-wars-comics.rb
120
+ - lib/star-wars-comics/artist.rb
121
+ - lib/star-wars-comics/artists.rb
122
+ - lib/star-wars-comics/cli.rb
123
+ - lib/star-wars-comics/concerns/findable.rb
124
+ - lib/star-wars-comics/issue.rb
125
+ - lib/star-wars-comics/scraper.rb
126
+ - lib/star-wars-comics/series.rb
127
+ - lib/star-wars-comics/version.rb
128
+ homepage:
129
+ licenses:
130
+ - MIT
131
+ metadata:
132
+ source_code_uri: https://github.com/skalum/star-wars-comics
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 2.7.4
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: CLI for info about canon Star Wars comics
153
+ test_files: []