berklee-valencia 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 652e951a9218cd0b5c2c2090e548b0e87280b29f2e69e6fc294666b424682cac
4
+ data.tar.gz: 8a5972d1d46680b7a4a7b2a87253fe13e3d4713b3715de9b0c7faff286dc35fd
5
+ SHA512:
6
+ metadata.gz: 9a89957b9d1fd8d9fc65e28410eafc0a5e3e61e69310b89aa4a8dd199ed93df2a0e95d7498c3db970617880239af660c0759d68f3fc0fc83955ee9cb43800145
7
+ data.tar.gz: 224ec32ca96b0ff2951b0995c3ab8dd9d519b772dd0764c26f5cf54ae39a59ec895f389046404882016f6eaf19261e0f8530a7b7aec66539520a8cb81e82aac9
@@ -0,0 +1,22 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ require_relative '../lib/berklee_valencia'
4
+ #
5
+ BerkleeValencia::CLI.new.call
6
+
7
+
8
+ # ||
9
+ # ||
10
+ # || /||
11
+ # || //||
12
+ # || // ||
13
+ # ||// ||
14
+ # ||/ ||
15
+ # || ||
16
+ # || /||
17
+ # || //||
18
+ # || // ||
19
+ # ||// ||
20
+ # ||/ ||
21
+ # ||
22
+ # ||
@@ -0,0 +1,13 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+ require "open_uri_redirections"
4
+
5
+ require_relative "../lib/berklee_valencia/version"
6
+ require_relative '../lib/berklee_valencia/cli'
7
+ require_relative '../lib/berklee_valencia/scraper'
8
+ require_relative '../lib/berklee_valencia/news_article'
9
+ require_relative '../lib/berklee_valencia/program'
10
+ require_relative '../lib/berklee_valencia/printer'
11
+ require_relative '../lib/berklee_valencia/formatter'
12
+ require_relative '../lib/berklee_valencia/printer'
13
+ require_relative '../lib/berklee_valencia/news_article'
@@ -0,0 +1,4 @@
1
+ module BerkleeValencia
2
+ end
3
+
4
+ require_relative '../config/environment'
@@ -0,0 +1,152 @@
1
+ class BerkleeValencia::CLI
2
+ def call
3
+ puts ""
4
+ puts "||"
5
+ puts "||"
6
+ puts "|| /|| Buenos Dias!"
7
+ puts "|| //||"
8
+ puts "|| // || Berklee Valencia is Berklee College of Music's"
9
+ puts "||// || graduate campus located in Valencia, Spain"
10
+ puts "||/ ||"
11
+ puts "|| || Filled with the"
12
+ puts "|| /|| musicians"
13
+ puts "|| //|| business moguls"
14
+ puts "|| // || and technologists"
15
+ puts "||// || of today and tomorrow..."
16
+ puts "||/ ||"
17
+ puts " || ...there is a wealth of things to discover here!"
18
+ puts " ||"
19
+ menu
20
+ end
21
+
22
+ def menu
23
+ puts ""
24
+ puts " Would you like to see the latest news or are you"
25
+ puts " interested in seeing what programs are on offer?"
26
+ 2.times {puts ""}
27
+ puts " 1. Meet the people and read the latest news"
28
+ puts " 2. See the available Programs"
29
+ puts ""
30
+ list_news_or_programs
31
+ end
32
+
33
+ def list_news_or_programs
34
+ input = gets.strip.downcase
35
+ if input.match(/hasta luego|exit|bye|ciao/)
36
+ goodbye
37
+ else
38
+ puts ""
39
+ puts " Please be patient whilst we get up to date with all our news!"
40
+ puts ""
41
+ puts " ... ... ..."
42
+ puts ""
43
+ if input == "1"
44
+ show_news_categories
45
+ elsif input == "2"
46
+ show_programs
47
+ elsif input == "programs"
48
+ what_next
49
+ else
50
+ say_what
51
+ end
52
+ end
53
+ end
54
+
55
+ def list_news_articles
56
+ puts ""
57
+ input = gets.strip.downcase
58
+ if input.to_i > 0
59
+ puts ""
60
+ puts "----------------------------------------------------------"
61
+ puts "Enter the number of the article you'd like to read in full"
62
+ puts " or type 'menu' to see all options"
63
+ puts "----------------------------------------------------------"
64
+ BerkleeValencia::NEWS_ARTICLE.list_news_articles(input)
65
+ show_article
66
+ elsif input == "programs"
67
+ show_programs
68
+ else
69
+ say_what
70
+ end
71
+ end
72
+
73
+ def show_news_categories
74
+ BerkleeValencia::NEWS_ARTICLE.get_news_categories
75
+ puts ""
76
+ puts "----------------------------------------------"
77
+ puts " Which kind of article are you interested in?"
78
+ puts " Type 'programs' to browse programs instead"
79
+ puts "----------------------------------------------"
80
+ BerkleeValencia::NEWS_ARTICLE.list_news_categories
81
+ list_news_articles
82
+ end
83
+
84
+ def show_programs
85
+ BerkleeValencia::PROGRAM.get_programs
86
+ puts ""
87
+ puts "----------------------------------------------------------------"
88
+ puts " Enter the number of the program you'd like to read more about"
89
+ puts " or type 'news' to browse our latest news and articles."
90
+ puts "----------------------------------------------------------------"
91
+ puts "Graduate Programs"
92
+ BerkleeValencia::PROGRAM.list_programs("grad")
93
+ puts ""
94
+ puts "Other Programs"
95
+ BerkleeValencia::PROGRAM.list_programs("other")
96
+ show_program
97
+ end
98
+
99
+ def show_article
100
+ puts ""
101
+ input = gets.strip.downcase
102
+ if input.to_i > 0
103
+ if BerkleeValencia::NEWS_ARTICLE.print_article(input) == "abort mission!"
104
+ menu
105
+ else
106
+ what_next
107
+ end
108
+ elsif input == "menu"
109
+ what_next
110
+ else
111
+ say_what
112
+ end
113
+ end
114
+
115
+ def show_program
116
+ puts ""
117
+ input = gets.strip.downcase
118
+ if input.to_i > 0
119
+ BerkleeValencia::PROGRAM.print_program(input)
120
+ what_next
121
+ elsif input == "news"
122
+ show_news_categories
123
+ else
124
+ say_what
125
+ end
126
+ end
127
+
128
+ def say_what
129
+ puts ""
130
+ puts "Sorry, I didn't understand that!"
131
+ what_next
132
+ end
133
+
134
+ def what_next
135
+ puts ""
136
+ puts "What would you like to do next?"
137
+ puts "1. See news articles"
138
+ puts "2. See programs"
139
+ puts ""
140
+ puts " If you're all set, you can just say ciao for now and we will "
141
+ puts " see you next time with the latest news from Berklee Valencia!"
142
+ puts ""
143
+ list_news_or_programs
144
+ end
145
+
146
+
147
+ def goodbye
148
+ puts ""
149
+ puts "Hasta luego!"
150
+ puts ""
151
+ end
152
+ end
@@ -0,0 +1,121 @@
1
+ class Formatter
2
+
3
+ def self.wrap(text, width=80)
4
+ text.gsub(/(.{1,#{width}})(\s+|\Z)/, "\\1\n")
5
+ end
6
+
7
+ class Article < Formatter
8
+ def self.header(article, article_extended)
9
+ border = border_maker(article, article_extended)
10
+ puts ""
11
+ 2.times {puts "#{border}"}
12
+ puts "#{wrap(article[:title])}"
13
+ gap = gap_maker(article, article_extended, border)
14
+ puts "#{article_extended[:author]}#{gap}#{article[:date]}"
15
+ 2.times {puts "#{border}"}
16
+ end
17
+
18
+ def self.border_maker(article, article_extended)
19
+ border = ""
20
+ if article[:title].length < (article_extended[:author].length + article[:date].length)
21
+ borderlength = article_extended[:author].length + article[:date].length + 5
22
+ borderlength.times {border << "-"}
23
+ elsif article[:title].length > 80
24
+ 80.times {border << "-"}
25
+ else
26
+ borderlength = article[:title].length
27
+ borderlength.times {border << "-"}
28
+ end
29
+ border
30
+ end
31
+
32
+ def self.gap_maker(article, article_extended, border)
33
+ gap = ""
34
+ if border.length > article[:title].length
35
+ 5.times {gap << " "}
36
+ else
37
+ (article[:title].length - article_extended[:author].length - article[:date].length).times {gap << " "}
38
+ end
39
+ gap
40
+ end
41
+
42
+ def self.body(article, article_extended)
43
+ article_extended[:body].each do |paragraph|
44
+ if paragraph.match(/-{3} /)
45
+ puts " ______________________________________________________________________________"
46
+ puts " || Press enter to scroll to the next section ||"
47
+ puts " || or type 'menu' to see all options ||"
48
+ puts " ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
49
+ input = gets.strip
50
+ if input == "menu"
51
+ return "abort mission!"
52
+ end
53
+ end
54
+
55
+ if !paragraph.downcase.match(/click here/)
56
+ if paragraph.match(/below/)
57
+ puts "#{wrap(paragraph)}"
58
+ puts " Vist #{article_extended[:related_links].shift}"
59
+ elsif paragraph == " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
60
+ puts " Vist #{article_extended[:related_links].shift}"
61
+ puts paragraph
62
+ else
63
+ puts "#{wrap(paragraph)}"
64
+ puts ""
65
+ end #nestedif
66
+ end #if
67
+ end #do
68
+ end #print_body method
69
+
70
+ def self.end
71
+ puts ""
72
+ puts " ______________________________________________________________________________"
73
+ puts " || END OF ARTICLE ||"
74
+ puts " ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾"
75
+ 2.times {puts ""}
76
+ end
77
+ end
78
+
79
+ class Program < Formatter
80
+ def self.header(program)
81
+ border = ""
82
+ (program[:name].gsub("#{program[:detail]}", "").length + 4).times {border << "-"}
83
+ puts ""
84
+ 2.times {puts border}
85
+ puts " #{program[:name].gsub("#{program[:detail]}", "")}"
86
+ if program[:detail] != ""
87
+ puts " (#{program[:detail]})"
88
+ end
89
+ end
90
+
91
+ def self.intro(program_extended)
92
+ puts "--------------------------------------------------------------------------------"
93
+ puts " Introduction"
94
+ puts "--------------------------------------------------------------------------------"
95
+ puts "#{wrap(program_extended[:introduction])}"
96
+ puts ""
97
+ end
98
+
99
+ def self.highlights(program_extended)
100
+ puts "--------------------------------------------------------------------------------"
101
+ puts " Program Highlights"
102
+ puts "--------------------------------------------------------------------------------"
103
+ program_extended[:highlights].each do |highlight|
104
+ puts "| #{highlight[:hl_title]} |"
105
+ puts "#{wrap(highlight[:hl_body])}"
106
+ puts ""
107
+ end
108
+ end
109
+
110
+ def self.more_info(program)
111
+ puts "--------------------------------------------------------------------------------"
112
+ puts " For full program information:"
113
+ puts "--------------------------------------------------------------------------------"
114
+ puts "Visit #{program[:url]}"
115
+ 2.times {puts "--------------------------------------------------------------------------------"}
116
+ 2.times {puts ""}
117
+ end
118
+
119
+ end #Program class
120
+
121
+ end #Formatter
@@ -0,0 +1,39 @@
1
+ class BerkleeValencia::NEWS_ARTICLE
2
+ @@categories
3
+ @@articles
4
+ @@matches
5
+
6
+ def self.get_news_categories
7
+ @@articles = BerkleeValencia::SCRAPER.scrape_news
8
+ @@categories = []
9
+ @@articles.each do |article|
10
+ @@categories.push(article[:category])
11
+ end
12
+ @@categories.uniq!
13
+ end
14
+
15
+ def self.list_news_categories
16
+ @@categories.each.with_index(1) do |category, i|
17
+ puts "#{i}. #{category}"
18
+ end
19
+ end
20
+
21
+ def self.list_news_articles(input)
22
+ @@matches = @@articles.find_all {|article| article[:category] == @@categories[input.to_i-1]}
23
+ @@matches.each.with_index(1) do |article, i|
24
+ puts "#{i}: #{Formatter.wrap(article[:title])}"
25
+ puts " // Posted on #{article[:date]}"
26
+ puts "#{Formatter.wrap(article[:excerpt])}"
27
+ puts ""
28
+ article[:i] = i
29
+ end
30
+ end
31
+
32
+ def self.print_article(input)
33
+ article = @@articles.find { |article| article[:i] == input.to_i }
34
+ url = article[:url]
35
+ article_extended = BerkleeValencia::SCRAPER.scrape_article(url)
36
+ BerkleeValencia::PRINTER.print_article(article, article_extended)
37
+ end
38
+
39
+ end
@@ -0,0 +1,16 @@
1
+ class BerkleeValencia::PRINTER
2
+ def self.print_article(article, article_extended)
3
+ Formatter::Article.header(article, article_extended)
4
+ Formatter::Article.body(article, article_extended)
5
+ Formatter::Article.end
6
+ end
7
+
8
+ def self.print_program(program, program_extended)
9
+ Formatter::Program.header(program)
10
+ Formatter::Program.intro(program_extended)
11
+ if program_extended[:highlights].length > 0
12
+ Formatter::Program.highlights(program_extended)
13
+ end
14
+ Formatter::Program.more_info(program)
15
+ end
16
+ end #class
@@ -0,0 +1,28 @@
1
+ class BerkleeValencia::PROGRAM
2
+ @@grad_programs
3
+ @@other_programs
4
+
5
+ def self.get_programs
6
+ @@grad_programs = BerkleeValencia::SCRAPER.scrape_programs("grad")
7
+ @@other_programs = BerkleeValencia::SCRAPER.scrape_programs("other")
8
+ end
9
+
10
+ def self.list_programs(type)
11
+ type == "grad" ? programs = @@grad_programs : programs = @@other_programs
12
+ programs == @@grad_programs ? i = 1 : i = (@@grad_programs.length + 1)
13
+ programs.each.with_index(i) do |program, i|
14
+ (program[:detail] != "") ? (puts "#{i}: #{program[:name].gsub("#{program[:detail]}", "")} (#{program[:detail]})") : (puts "#{i}: #{program[:name]}")
15
+ program[:i] = i
16
+ end# do
17
+ end #list programs method
18
+
19
+ def self.print_program(input)
20
+ programs = @@grad_programs
21
+ @@other_programs.each { |program| programs << program }
22
+ program = programs.find { |program| program[:i] == input.to_i }
23
+ url = program[:url]
24
+ program_extended = BerkleeValencia::SCRAPER.scrape_program(url)
25
+ BerkleeValencia::PRINTER.print_program(program, program_extended)
26
+ end #method
27
+
28
+ end #class
@@ -0,0 +1,96 @@
1
+ class BerkleeValencia::SCRAPER
2
+ @bv_news = "https://valencia.berklee.edu/news/"
3
+ @bv_programs = "https://valencia.berklee.edu/academic-programs/"
4
+
5
+ def self.scrape_news
6
+ news = Nokogiri::HTML(open(@bv_news))
7
+ articles = []
8
+ news.css("div#news_container div.content").each do |article|
9
+ articles << {
10
+ date: article.css("div.news_excerpt span.date").text,
11
+ title: article.css("div.news_excerpt h3 a").text,
12
+ excerpt: article.css("div.news_excerpt p").text,
13
+ url: article.css("div.news_excerpt h3 a").attribute("href").value,
14
+ category: article.css("span.category_name").text
15
+ }
16
+ end
17
+ articles
18
+ end
19
+
20
+ def self.scrape_programs(type)
21
+ type == "grad" ? academics = Nokogiri::HTML(open(@bv_programs)).css("div.col-3-5").first : academics = Nokogiri::HTML(open(@bv_programs)).css("div.col-3-5").last
22
+ programs = []
23
+ academics.css("ul a").each do |program|
24
+ programs << {
25
+ name: program.text,
26
+ detail: program.css("span").text,
27
+ url: program.attribute("href").value
28
+ }
29
+ end
30
+ programs
31
+ end
32
+
33
+ def self.scrape_article(url)
34
+ article = Nokogiri::HTML(open(url))
35
+ extended_info = {
36
+ author: article.css("span.author").text,
37
+ related_links: [],
38
+ body: []
39
+ }
40
+ sort_content(article, extended_info)
41
+ end
42
+
43
+ def self.sort_content(article, extended_info)
44
+ article.css("div#tab_intro p").each do |para|
45
+ if para.css("iframe").length == 0 && para.css("em").text.length < 30 && para.css("strong").text == "" && !para.text.match(/•/)
46
+ extended_info[:body] << para.text
47
+ elsif para.css("strong").text != ""
48
+ extended_info[:body] << " --- #{para.text} ---"
49
+ elsif para.css("em").text != ""
50
+ comment = "#{para.text}"
51
+ extended_info[:body] << " - - - - - - - - - - - - - - - - - Media - - - - - - - - - - - - - - - - - - -"
52
+ extended_info[:body] << comment
53
+ extended_info[:body] << " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
54
+ elsif para.css("iframe").length > 0
55
+ extended_info[:related_links] << para.css("iframe").attribute("src").value
56
+ end
57
+ end
58
+ extended_info
59
+ end
60
+
61
+ def self.scrape_program(url)
62
+ program = Nokogiri::HTML(open(url, :allow_redirections => :all))
63
+ extended_info = {
64
+ highlights: [],
65
+ list: []
66
+ }
67
+ scrape_program_intro(program, extended_info)
68
+ scrape_program_highlights(program, extended_info)
69
+ end
70
+
71
+ def self.scrape_program_intro(program, extended_info)
72
+ # scrape intro
73
+ if program.css("div#tab_intro p").first.text.length > 0
74
+ extended_info[:introduction] = program.css("div#tab_intro p").first.text
75
+ elsif program.css("div#tab_intro h4").length > 0
76
+ extended_info[:introduction] = program.css("div#tab_intro h4").first.text
77
+ else
78
+ intro = program.css("div#tab_intro p").detect {|p| p.text.length > 150}
79
+ extended_info[:introduction] = intro.text
80
+ end
81
+ end
82
+
83
+ def self.scrape_program_highlights(program, extended_info)
84
+ program.css("div#tab_intro div.block_content").each do |highlight|
85
+ hl_title = highlight.css("p.block_content_item_title").text
86
+ hl_body = highlight.css("div.bk_txt").text
87
+ extended_info[:highlights] << {
88
+ hl_title: hl_title,
89
+ hl_body: hl_body
90
+ }
91
+ end
92
+ extended_info
93
+ end
94
+
95
+
96
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: berklee-valencia
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gingertonic
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-01 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: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.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: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
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: nokogiri
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '1.8'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '1.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: open_uri_redirections
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: |-
98
+ Hello! Berklee Valencia is Berklee College of Music's graduate campus located in Valencia, Spain.
99
+ Filled with the musicians, business moguls and technologists of today and tomorrow, there is a wealth of things to discover here.
100
+ email: bethmschofield@gmail.com
101
+ executables:
102
+ - berklee-valencia
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - bin/berklee-valencia
107
+ - config/environment.rb
108
+ - lib/berklee_valencia.rb
109
+ - lib/berklee_valencia/cli.rb
110
+ - lib/berklee_valencia/formatter.rb
111
+ - lib/berklee_valencia/news_article.rb
112
+ - lib/berklee_valencia/printer.rb
113
+ - lib/berklee_valencia/program.rb
114
+ - lib/berklee_valencia/scraper.rb
115
+ homepage: http://rubygems.org/gems/berklee-valencia
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.7.6
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: CLI gem for user to read latest Berklee Valencia news and about programs
139
+ offered.
140
+ test_files: []