meetup-generator 1.2.84

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ require_relative 'version'
2
+
3
+ def gem_version
4
+ format('%s.%s', BASE_VERSION, build_number)
5
+ end
6
+
7
+ def build_number
8
+ ENV['TRAVIS_BUILD_NUMBER'] || 0
9
+ end
@@ -0,0 +1,63 @@
1
+ require 'json'
2
+ require 'yaml'
3
+
4
+ # Everything needed for a meetup generator
5
+ #
6
+ class MeetupGenerator
7
+ attr_reader :words, :lib, :unused_templates
8
+
9
+ def initialize
10
+ grep, dict = find_unix_stuff
11
+ @words = `#{grep} "^[a-z]*$" #{dict}`.split("\n")
12
+ @lib = YAML.load_file(ROOT + 'lib' + 'all_the_things.yaml')
13
+ end
14
+
15
+ def find_unix_stuff
16
+ case RUBY_PLATFORM
17
+ when /solaris/
18
+ %w[/bin/grep /usr/share/lib/dict/words]
19
+ when /linux/
20
+ %w[/bin/grep /usr/share/dict/words]
21
+ when /darwin/
22
+ %w[/usr/bin/grep /usr/share/dict/words]
23
+ else
24
+ abort "unsupported platform: #{RUBY_PLATFORM}"
25
+ end
26
+ end
27
+
28
+ def title
29
+ @unused_templates ||= lib[:template].dup
30
+ t = unused_templates.sample
31
+ unused_templates.delete(t)
32
+ t.scan(/%\w+%/).each { |k| t = t.sub(k, lib[k[1..-2].to_sym].sample) }
33
+ t.scan(/RAND\d+/).each do |i|
34
+ t = t.sub(i, rand(2..(i.sub(/RAND/, '').to_i)).to_s)
35
+ end
36
+ t
37
+ end
38
+
39
+ def talks(count = 5)
40
+ @unused_templates = lib[:template].dup
41
+ count.times.with_object([]) { |_i, a| a.<< title }
42
+ end
43
+
44
+ def talker
45
+ lib[:first_name].sample + ' ' + lib[:last_name].sample
46
+ end
47
+
48
+ def role
49
+ lib[:job_role].sample + ' ' + lib[:job_title].sample
50
+ end
51
+
52
+ def company
53
+ words.sample.sub(/([^aeiou])er$/, '\\1r').downcase + '.io'
54
+ end
55
+
56
+ def refreshment
57
+ lib[:food_style].sample + ' ' + lib[:food].sample
58
+ end
59
+
60
+ def talk
61
+ { talk: talks(1)[0], talker: talker, role: role, company: company }
62
+ end
63
+ end
@@ -0,0 +1,4 @@
1
+ # We define the major and minor here. The patch version comes from
2
+ # the Travis build number
3
+ #
4
+ BASE_VERSION = '1.2'.freeze
@@ -0,0 +1,35 @@
1
+ require 'pathname'
2
+ require 'date'
3
+ require 'English'
4
+ require_relative 'lib/build_helpers'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'meetup-generator'
8
+ gem.version = gem_version
9
+ gem.date = Date.today.to_s
10
+
11
+ gem.summary = 'Stupid fatuous random string generatpr'
12
+ gem.description = 'Generates a website advertising a fictional ' \
13
+ 'DevOps meetup, using all the latest buzzwords, ' \
14
+ 'new-shiny, and clichés'
15
+ gem.authors = ['Robert Fisher']
16
+ gem.email = 'slackboy@gmail.com'
17
+ gem.homepage = 'https://github.com/snltd/meetup-generator'
18
+ gem.license = 'BSD-2-Clause'
19
+
20
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
21
+ gem.test_files = gem.files.grep(%r{^spec/})
22
+
23
+ gem.add_runtime_dependency 'sinatra', '~>2.0', '>= 2.0.1'
24
+ gem.add_runtime_dependency 'slim', '~> 3.0', '>= 3.0.0'
25
+ gem.add_runtime_dependency 'puma', '~> 3.11', '>= 3.11.0'
26
+
27
+ gem.add_development_dependency 'bundler', '~> 1.3'
28
+ gem.add_development_dependency 'minitest', '~> 5.11', '>= 5.11.0'
29
+ gem.add_development_dependency 'nokogiri', '~> 1.8', '>= 1.8.0'
30
+ gem.add_development_dependency 'rack-test', '~> 0.8', '>= 0.8.0'
31
+ gem.add_development_dependency 'rake', '~> 12.3', '>= 12.3.0'
32
+ gem.add_development_dependency 'rubocop', '~> 0.52', '>= 0.52.0'
33
+
34
+ gem.required_ruby_version = Gem::Requirement.new('>= 2.2.0')
35
+ end
@@ -0,0 +1,61 @@
1
+ @font-face {
2
+ font-family: 'ZX Spectrum';
3
+ src: url('/zxspectr.woff') format('woff');
4
+ }
5
+
6
+ body {
7
+ font-family: 'ZX Spectrum';
8
+ font-size: 0.9em;
9
+ background: #000;
10
+ color: #0f0;
11
+ line-height: 120%;
12
+ }
13
+
14
+ .tperson {
15
+ font-size: small;
16
+ margin-left: 12em;
17
+ }
18
+
19
+ ul {
20
+ list-style: none;
21
+ }
22
+
23
+ li {
24
+ padding-top: 1em;
25
+ text-indent: -9em;
26
+ margin-left: 9em;
27
+ }
28
+
29
+ .ttitle {
30
+ /*font-style: italic;*/
31
+ font-weight: bold;
32
+ background-color: #0ff;
33
+ color: #000;
34
+ }
35
+
36
+ h1 {
37
+ text-align: center;
38
+ padding-bottom: 0.5em;
39
+ margin-bottom: 1em;
40
+ color: #ff0;
41
+ line-height:100%;
42
+ border-bottom: 4px dotted #f0f;
43
+ }
44
+
45
+ #container {
46
+ padding-top: 3em;
47
+ width: 900px;
48
+ margin-left: auto;
49
+ margin-right: auto;
50
+ }
51
+
52
+ #footer {
53
+ margin-top: 20em;
54
+ font-size: x-small;
55
+ text-align: right;
56
+ }
57
+
58
+ a {
59
+ text-decoration: none;
60
+ color: #f0f;
61
+ }
Binary file
Binary file
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Acceptance tests for the meetup generator. Yeah, I know.
4
+ #
5
+ %w[minitest minitest/unit minitest/autorun rack/test pathname json
6
+ yaml cgi nokogiri].each { |f| require f }
7
+
8
+ MGROOT = Pathname.new(__FILE__).realpath.dirname.parent
9
+
10
+ OUTER_APP = Rack::Builder.parse_file((MGROOT + 'config.ru').to_s).first
11
+
12
+ class TestApp < MiniTest::Test
13
+ attr_reader :things
14
+ include Rack::Test::Methods
15
+
16
+ def initialize(args)
17
+ super(args)
18
+ @things = YAML.load_file(MGROOT + 'lib' + 'all_the_things.yaml')
19
+ end
20
+
21
+ def app
22
+ OUTER_APP
23
+ end
24
+
25
+ # Load the page 1000 times and make sure no talk titles occur
26
+ # twice
27
+ #
28
+ def test_no_repeats
29
+ 1000.times do
30
+ html = Nokogiri::HTML(get('/').body)
31
+ titles = html.css('span[class="ttitle"]').map(&:text)
32
+ assert_equal(titles, titles.uniq)
33
+ end
34
+ end
35
+
36
+ def test_default
37
+ #
38
+ # Get all of the templates used to generate talk titles, and re-run
39
+ # the test until we've seen them all. Then we know no template
40
+ # causes a crash. That's good enough.
41
+ #
42
+ templates = things[:template].map do |t|
43
+ escaped = Regexp.escape(CGI.escapeHTML(t))
44
+ matcher = escaped.gsub(/%\w+%/, '\w+').gsub(/RAND\d+/, '\d+')
45
+ Regexp.new('^.*ttitle">' + matcher + '</span>.*$')
46
+ end
47
+
48
+ until templates.empty?
49
+ get '/'
50
+ assert last_response.ok?
51
+ assert last_response.header['Content-Type'] == 'text/html;charset=utf-8'
52
+ x = last_response.body
53
+ assert_match(/The code./, x)
54
+ assert_match(/DevOps Meetup/, x)
55
+ templates.each { |t| templates.delete(t) if x.match(t) }
56
+ end
57
+ end
58
+
59
+ def test_api_talk
60
+ get '/api/talk'
61
+ assert last_response.ok?
62
+ assert last_response.header['Content-Type'] == 'application/json'
63
+ resp = last_response.body
64
+ refute_empty resp
65
+ j = JSON.parse(resp)
66
+ fields = %w[talk talker role company]
67
+ assert_equal(j.keys, fields)
68
+ fields.each { |f| refute_empty j[f] }
69
+ name = j['talker'].split
70
+ assert_includes(things[:first_name], name.first)
71
+ assert_includes(things[:last_name], name.last)
72
+ assert j['company'].end_with?('.io')
73
+ end
74
+
75
+ def test_api_misc
76
+ %w[title talker company role refreshment].each do |word|
77
+ get format('/api/%s', word)
78
+ assert last_response.ok?
79
+ assert last_response.header['Content-Type'] == 'application/json'
80
+ end
81
+ end
82
+
83
+ def test_api_404
84
+ get '/api/no_such_thing'
85
+ assert_equal(last_response.status, 404)
86
+ end
87
+ end
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'minitest/autorun'
4
+ require_relative '../lib/meetup-generator'
5
+
6
+ THINGS = { food_style: %w[artisan],
7
+ food: %w[flatbread],
8
+ first_name: %w[John],
9
+ last_name: %w[Smith],
10
+ job_role: %w[Neckbeard],
11
+ job_title: ['Without Portfolio'],
12
+ tech: %w[Ruby],
13
+ template: ['RAND20 %tech% things'] }.freeze
14
+
15
+ class Giblets < MeetupGenerator
16
+ def initialize; end
17
+ end
18
+
19
+ class GibletsTest < MiniTest::Test
20
+ attr_reader :m
21
+
22
+ def setup
23
+ @m = Giblets.new
24
+ m.instance_variable_set(:@lib, THINGS)
25
+ end
26
+
27
+ def test_title
28
+ x = m.title
29
+ assert_instance_of(String, x)
30
+ assert !x.empty?
31
+ refute_match(/%\w+%/, x)
32
+ refute_match(/RAND/, x)
33
+ end
34
+
35
+ def test_talk
36
+ x = m.talks(1)
37
+ assert_instance_of(Array, x)
38
+ assert_instance_of(String, x.first)
39
+ toks = x.first.split
40
+ number = toks.first.to_i
41
+ assert number > 0
42
+ assert number <= 20
43
+ assert_equal('Ruby', toks[1])
44
+ assert_equal('things', toks[2])
45
+ end
46
+
47
+ def test_talker
48
+ assert_equal(m.talker, 'John Smith')
49
+ end
50
+
51
+ def test_role
52
+ assert_equal(m.role, 'Neckbeard Without Portfolio')
53
+ end
54
+
55
+ def test_company_no_e
56
+ m.instance_variable_set(:@words, %w[leadswinger])
57
+ assert_equal(m.company, 'leadswingr.io')
58
+ end
59
+
60
+ def test_company
61
+ m.instance_variable_set(:@words, %w[Cabbage])
62
+ assert_equal(m.company, 'cabbage.io')
63
+ end
64
+
65
+ def test_refreshment
66
+ assert_equal(m.refreshment, 'artisan flatbread')
67
+ end
68
+ end
@@ -0,0 +1,48 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title #Devops Meetup
5
+ meta charset='utf-8'
6
+ link href='/css/main.css' rel='stylesheet'
7
+
8
+ body
9
+ #container
10
+ h1 #DevOps Meetup // Shoreditch, probably // #{(Date.today + 1).strftime("%d/%m/%Y")}
11
+
12
+ ul
13
+ li 18:00 // Introduction
14
+
15
+ li
16
+ ' 18:10 // Lightning talk //
17
+ span.ttitle=@talks.pop
18
+ .tperson=@jobs.pop
19
+
20
+ li
21
+ ' 18:20 //
22
+ span.ttitle=@talks.pop
23
+ .tperson=@jobs.pop
24
+
25
+ li 18:50 // break
26
+ .tperson=@food
27
+
28
+ li
29
+ ' 19:20 //
30
+ span.ttitle=@talks.pop
31
+ .tperson=@jobs.pop
32
+
33
+ li
34
+ ' 19:40 // Ignite //
35
+ span.ttitle=@talks.pop
36
+ .tperson=@jobs.pop
37
+
38
+ li
39
+ ' 20:00 //
40
+ span.ttitle=@talks.pop
41
+ .tperson=@jobs.pop
42
+
43
+ li
44
+ ' 20:30 // Close
45
+ .tperson Everyone is hiring, but no one's paying
46
+
47
+ #footer
48
+ a href='https://github.com/snltd/meetup-generator' The code.
@@ -0,0 +1,100 @@
1
+ <?xml version='1.0'?>
2
+
3
+ <!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
4
+
5
+ <service_bundle type='manifest' name='snltd:sinatra:meetup-generator'>
6
+
7
+ <service
8
+ name='application/sinatra/meetup-generator'
9
+ type='service'
10
+ version='1'>
11
+
12
+ <single_instance />
13
+
14
+ <property_group name='startd' type='framework'>
15
+
16
+ <stability value='Unstable' />
17
+
18
+ <propval
19
+ name='duration'
20
+ type='astring'
21
+ value='transient' />
22
+
23
+ </property_group>
24
+
25
+ <property_group name='options' type='applications'>
26
+
27
+ <propval
28
+ name='rackup'
29
+ type='astring'
30
+ value='/opt/local/bin/rackup' />
31
+
32
+ <propval
33
+ name='user'
34
+ type='astring'
35
+ value='sinatra' />
36
+
37
+ <propval
38
+ name='dir'
39
+ type='astring'
40
+ value='/www/meetup-generator' />
41
+
42
+ <propval
43
+ name='port'
44
+ type='astring'
45
+ value='8002' />
46
+
47
+ </property_group>
48
+
49
+ <instance name='default' enabled='true'>
50
+
51
+ <!-- Run in multi-user mode -->
52
+
53
+ <dependency
54
+ name='multi-user'
55
+ grouping='require_all'
56
+ restart_on='none'
57
+ type='service'>
58
+
59
+ <service_fmri value='svc:/milestone/multi-user-server:default' />
60
+
61
+ </dependency>
62
+
63
+ <exec_method
64
+ name='start'
65
+ type='method'
66
+ timeout_seconds='0'
67
+ exec='%{options/rackup} -D -p %{options/port} %{options/dir}/config.ru'>
68
+ <method_context>
69
+ <method_credential
70
+ user='%{options/user}'
71
+ group='nogroup'
72
+ privileges='basic,!proc_session,!proc_info,!file_link_any'/>
73
+ </method_context>
74
+ </exec_method>
75
+
76
+ <exec_method
77
+ name='stop'
78
+ type='method'
79
+ timeout_seconds='10'
80
+ exec='pkill -2 -f "%{options/rackup}.*-p %{options/port}"' />
81
+
82
+ </instance>
83
+
84
+ <template>
85
+
86
+ <common_name>
87
+ <loctext xml:lang='C'>
88
+ meetup-generator website
89
+ </loctext>
90
+ </common_name>
91
+
92
+ <documentation>
93
+ <doc_link name='meetup.rfisher.co.uk' uri='http://meetup.rdfisher.co.uk' />
94
+ </documentation>
95
+
96
+ </template>
97
+
98
+ </service>
99
+
100
+ </service_bundle>