meetup-generator 1.2.84

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,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>