├── eventdb ├── .gitignore ├── CHANGELOG.md ├── test │ ├── helper.rb │ ├── data │ │ ├── test.txt │ │ ├── conferences_ii.yml │ │ ├── conferences.csv │ │ ├── conferences.yml │ │ └── RUBY.md │ ├── test_version.rb │ ├── test_database.rb │ ├── templates │ │ └── RUBY.md.erb │ ├── test_calendar.rb │ ├── test_reader.rb │ └── test_parser.rb ├── script │ ├── test_read_outline.rb │ ├── test_read_2023.rb │ ├── test_re.rb │ ├── test_memory.rb │ ├── test_read.rb │ └── conferences2023.yml ├── NOTES.md ├── lib │ ├── eventdb │ │ ├── version.rb │ │ ├── schema.rb │ │ ├── database.rb │ │ ├── outline_reader.rb │ │ ├── calendar.rb │ │ ├── models.rb │ │ └── reader.rb │ └── eventdb.rb ├── Manifest.txt ├── Rakefile └── README.md ├── whatson ├── .gitignore ├── CHANGELOG.md ├── test │ ├── helper.rb │ ├── test_rubyconf.rb │ ├── test_kickoff.rb │ └── test_beerfest.rb ├── bin │ ├── pycon │ ├── beerfest │ ├── kickoff │ ├── rubyconf │ └── whatson ├── Manifest.txt ├── lib │ ├── whatson │ │ ├── beerfest.rb │ │ ├── pycon.rb │ │ ├── rubyconf.rb │ │ ├── version.rb │ │ ├── football.rb │ │ ├── whatson.rb │ │ └── tool.rb │ └── whatson.rb ├── Rakefile ├── sandbox │ ├── test_read.rb │ └── conferences2023.yml ├── NEWS.md └── README.md ├── README.md └── LICENSE.md /eventdb/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore ruby rake generated folders 2 | 3 | pkg/ 4 | doc/ 5 | 6 | 7 | -------------------------------------------------------------------------------- /eventdb/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 0.0.1 / 2015-06-21 2 | 3 | * Everything is new. First release 4 | -------------------------------------------------------------------------------- /whatson/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore ruby rake generated folders 2 | 3 | pkg/ 4 | doc/ 5 | 6 | 7 | -------------------------------------------------------------------------------- /whatson/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 0.0.1 / 2015-06-23 2 | 3 | * Everything is new. First release 4 | -------------------------------------------------------------------------------- /eventdb/test/helper.rb: -------------------------------------------------------------------------------- 1 | 2 | ## minitest setup 3 | require 'minitest/autorun' 4 | 5 | ## our own code 6 | require 'eventdb' 7 | 8 | -------------------------------------------------------------------------------- /eventdb/test/data/test.txt: -------------------------------------------------------------------------------- 1 | ##################################### 2 | # Test List of Event Datafiles / Dataset Sources 3 | 4 | test/data/conferences.yml 5 | test/data/conferences.csv 6 | -------------------------------------------------------------------------------- /whatson/test/helper.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## minitest setup 4 | require 'minitest/autorun' 5 | 6 | ## our own code 7 | $LOAD_PATH.unshift( "../eventdb/lib" ) 8 | 9 | require 'whatson' 10 | 11 | -------------------------------------------------------------------------------- /eventdb/script/test_read_outline.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib script/test_read_outline.rb 4 | 5 | 6 | ## our own code 7 | require 'eventdb' 8 | 9 | puts EventDb::VERSION 10 | 11 | nodes = EventDb::OutlineReader.read( "#{EventDb.root}/test/data/RUBY.md" ) 12 | pp nodes 13 | -------------------------------------------------------------------------------- /eventdb/script/test_read_2023.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib script/test_read_2023.rb 4 | 5 | 6 | ## our own code 7 | require 'eventdb' 8 | 9 | puts EventDb::VERSION 10 | 11 | events = EventDb::EventReader.read( "./script/conferences2023.yml" ) 12 | pp events 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /whatson/bin/pycon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ################### 4 | # == DEV TIPS: 5 | # 6 | # For local testing run like: 7 | # 8 | # ruby -Ilib bin/pycon 9 | # 10 | # Set the executable bit in Linux. Example: 11 | # 12 | # % chmod a+x bin/pycon 13 | # 14 | 15 | require 'whatson' 16 | 17 | WhatsOn::PyCon.main 18 | -------------------------------------------------------------------------------- /whatson/bin/beerfest: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ################### 4 | # == DEV TIPS: 5 | # 6 | # For local testing run like: 7 | # 8 | # ruby -Ilib bin/beerfest 9 | # 10 | # Set the executable bit in Linux. Example: 11 | # 12 | # % chmod a+x bin/beerfest 13 | # 14 | 15 | require 'whatson' 16 | 17 | WhatsOn::BeerFest.main 18 | -------------------------------------------------------------------------------- /whatson/bin/kickoff: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ################### 4 | # == DEV TIPS: 5 | # 6 | # For local testing run like: 7 | # 8 | # ruby -Ilib bin/kickoff 9 | # 10 | # Set the executable bit in Linux. Example: 11 | # 12 | # % chmod a+x bin/kickoff 13 | # 14 | 15 | require 'whatson' 16 | 17 | WhatsOn::Football.main 18 | -------------------------------------------------------------------------------- /whatson/bin/rubyconf: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ################### 4 | # == DEV TIPS: 5 | # 6 | # For local testing run like: 7 | # 8 | # ruby -Ilib bin/rubyconf 9 | # 10 | # Set the executable bit in Linux. Example: 11 | # 12 | # % chmod a+x bin/rubyconf 13 | # 14 | 15 | require 'whatson' 16 | 17 | WhatsOn::RubyConf.main 18 | -------------------------------------------------------------------------------- /whatson/bin/whatson: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ################### 4 | # == DEV TIPS: 5 | # 6 | # For local testing run like: 7 | # 8 | # ruby -Ilib bin/whatson 9 | # 10 | # Set the executable bit in Linux. Example: 11 | # 12 | # % chmod a+x bin/whatson 13 | # 14 | 15 | require 'whatson' 16 | 17 | WhatsOn::WhatsOn.main 18 | -------------------------------------------------------------------------------- /eventdb/test/test_version.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib -I ./test test/test_version.rb 4 | 5 | 6 | require 'helper' 7 | 8 | class TestVersion < MiniTest::Test 9 | 10 | def test_version 11 | assert_equal EventDb::VERSION, EventDb.version 12 | assert true # if we get here - test success 13 | end 14 | 15 | 16 | end # class TestVersion 17 | -------------------------------------------------------------------------------- /whatson/test/test_rubyconf.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib -I ./test test/test_rubyconf.rb 4 | 5 | 6 | require 'helper' 7 | 8 | class TestRubyConf < MiniTest::Test 9 | 10 | def test_list 11 | 12 | whatson = WhatsOn::RubyConf.new 13 | whatson.list 14 | whatson.list 15 | 16 | assert true # assume ok if we get here 17 | end 18 | 19 | end # class TestRubyConf 20 | -------------------------------------------------------------------------------- /whatson/test/test_kickoff.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | ### 4 | # to run use 5 | # ruby -I ./lib -I ./test test/test_kickoff.rb 6 | 7 | 8 | require 'helper' 9 | 10 | class TestKickOff < MiniTest::Test 11 | 12 | def test_list 13 | 14 | whatson = WhatsOn::Football.new 15 | whatson.list 16 | whatson.list 17 | 18 | assert true # assume ok if we get here 19 | end 20 | 21 | end # class TestKickOff 22 | -------------------------------------------------------------------------------- /whatson/test/test_beerfest.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | ### 4 | # to run use 5 | # ruby -I ./lib -I ./test test/test_beerfest.rb 6 | 7 | 8 | require 'helper' 9 | 10 | class TestBeerFest < MiniTest::Test 11 | 12 | def test_list 13 | 14 | whatson = WhatsOn::BeerFest.new 15 | whatson.list 16 | whatson.list 17 | 18 | assert true # assume ok if we get here 19 | end 20 | 21 | end # class TestBeerFest 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # events - tools, libraries & scripts, schemas & formats 2 | 3 | Gems: 4 | 5 | - [**whatson**](whatson) - what's on now command line tool (using the event.db machinery) incl. rubyconf, pyconf, beerfest, etc. 6 | - [eventdb](eventdb) - event.db schema 'n' models for easy (re)use 7 | 8 | 9 | 10 | ## License 11 | 12 | The scripts are dedicated to the public domain. 13 | Use it as you please with no restrictions whatsoever. 14 | 15 | -------------------------------------------------------------------------------- /eventdb/NOTES.md: -------------------------------------------------------------------------------- 1 | # Notes 2 | 3 | 4 | # ToDos 5 | 6 | - add to schema tags - why? why not? 7 | - add an (optional) country and city field to schema - why? why not? 8 | - lets you search/filter by country 9 | - lets you add geocoords (via nominatum/openstreetmap?) for adding maps? 10 | - save database - optional? why? why not? 11 | - use default as :memory: or something? 12 | - add a config/ini file for (easy) database setup/reuse - why? why not? 13 | -------------------------------------------------------------------------------- /whatson/Manifest.txt: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | Manifest.txt 3 | README.md 4 | Rakefile 5 | bin/beerfest 6 | bin/kickoff 7 | bin/pycon 8 | bin/rubyconf 9 | bin/whatson 10 | lib/whatson.rb 11 | lib/whatson/beerfest.rb 12 | lib/whatson/football.rb 13 | lib/whatson/pycon.rb 14 | lib/whatson/rubyconf.rb 15 | lib/whatson/tool.rb 16 | lib/whatson/version.rb 17 | lib/whatson/whatson.rb 18 | test/helper.rb 19 | test/test_beerfest.rb 20 | test/test_kickoff.rb 21 | test/test_rubyconf.rb 22 | -------------------------------------------------------------------------------- /whatson/lib/whatson/beerfest.rb: -------------------------------------------------------------------------------- 1 | 2 | module WhatsOn 3 | 4 | class BeerFest < Tool 5 | 6 | def self.main() new( ARGV ).list; end 7 | 8 | 9 | def initialize( args=ARGV ) 10 | args = ['https://github.com/beerbook/calendar/raw/master/README.md'] if args.empty? 11 | 12 | super( args, 13 | title: 'Upcoming Beerfests', 14 | more_link: 'github.com/beerbook/calendar' 15 | ) 16 | end 17 | end # class BeerFest 18 | 19 | end # module WhatsOn 20 | -------------------------------------------------------------------------------- /whatson/lib/whatson/pycon.rb: -------------------------------------------------------------------------------- 1 | 2 | module WhatsOn 3 | 4 | class PyCon < Tool 5 | 6 | def self.main() new( ARGV ).list; end 7 | 8 | 9 | def initialize( args=ARGV ) 10 | args = ['https://github.com/python-organizers/conferences/raw/main/2023.csv'] if args.empty? 11 | 12 | super( args, 13 | title: 'Upcoming Python Conferences', 14 | more_link: 'github.com/python-organizers/conferences' 15 | ) 16 | end 17 | end # class PyCon 18 | 19 | end # module WhatsOn 20 | -------------------------------------------------------------------------------- /whatson/lib/whatson/rubyconf.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | module WhatsOn 4 | 5 | class RubyConf < Tool 6 | 7 | def self.main() new( ARGV ).list; end 8 | 9 | 10 | def initialize( args=ARGV ) 11 | args = ['https://github.com/planetruby/conferences/raw/master/_data/conferences2023.yml'] if args.empty? 12 | 13 | super( args, 14 | title: 'Upcoming Ruby Conferences', 15 | more_link: 'github.com/planetruby/calendar' 16 | ) 17 | end 18 | end # class RubyConf 19 | 20 | end # module WhatsOn 21 | -------------------------------------------------------------------------------- /whatson/lib/whatson/version.rb: -------------------------------------------------------------------------------- 1 | 2 | module WhatsOn 3 | 4 | MAJOR = 2023 ## todo: namespace inside version or something - why? why not?? 5 | MINOR = 0 6 | PATCH = 0 7 | VERSION = [MAJOR,MINOR,PATCH].join('.') 8 | 9 | def self.version 10 | VERSION 11 | end 12 | 13 | def self.banner 14 | "whatson/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})" 15 | end 16 | 17 | def self.root 18 | File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) ) 19 | end 20 | 21 | end # module WhatsOn 22 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb/version.rb: -------------------------------------------------------------------------------- 1 | 2 | module EventDb 3 | 4 | MAJOR = 1 ## todo: namespace inside version or something - why? why not?? 5 | MINOR = 1 6 | PATCH = 2 7 | VERSION = [MAJOR,MINOR,PATCH].join('.') 8 | 9 | def self.version 10 | VERSION 11 | end 12 | 13 | def self.banner 14 | "eventdb/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in root (#{root})" 15 | end 16 | 17 | def self.root 18 | File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) ) 19 | end 20 | 21 | end # module EventDb 22 | -------------------------------------------------------------------------------- /whatson/lib/whatson/football.rb: -------------------------------------------------------------------------------- 1 | 2 | module WhatsOn 3 | 4 | class Football < Tool 5 | 6 | def self.main() new( ARGV ).list; end 7 | 8 | 9 | def initialize( args=ARGV ) 10 | args = ['https://github.com/footballbook/calendar/raw/master/README.md'] if args.empty? 11 | 12 | super( args, 13 | title: 'Upcoming Football Tournaments', 14 | more_link: 'github.com/footballbook/calendar', 15 | show_year: true ## e.g. World Cup 2020 etc. 16 | ) 17 | end 18 | end # class Football 19 | 20 | end # module WhatsOn 21 | -------------------------------------------------------------------------------- /eventdb/script/test_re.rb: -------------------------------------------------------------------------------- 1 | require 'pp' 2 | 3 | 4 | HEADING_RE = /^(\#{1,}) ## leading #### 5 | ([^#]+?) ## text 6 | \#* ## (optional) trailing ## 7 | $/x 8 | 9 | pp HEADING_RE 10 | 11 | 12 | lines = ["# Heading 1", 13 | "# Heading 1 ##", 14 | "## Heading 2", 15 | "### Heading 3", 16 | ] 17 | 18 | lines.each do |line| 19 | if m=HEADING_RE.match( line ) 20 | puts "bingo!! matching >#{line}<" 21 | pp m 22 | else 23 | puts "no match found >#{line}<" 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /whatson/lib/whatson/whatson.rb: -------------------------------------------------------------------------------- 1 | 2 | module WhatsOn 3 | 4 | class WhatsOn < Tool 5 | 6 | def self.main() new( ARGV ).list; end 7 | 8 | 9 | def initialize( args=ARGV ) 10 | args = ['https://github.com/planetruby/conferences/raw/master/_data/conferences2023.yml', 11 | 'https://github.com/python-organizers/conferences/raw/main/2023.csv', 12 | ] if args.empty? 13 | 14 | super( args, 15 | title: 'Upcoming Events', 16 | more_link: 'github.com/rubycocos/events/tree/master/whatson#public-event-datasets' 17 | ) 18 | end 19 | end # class WhatsOn 20 | end # module WhatsOn 21 | -------------------------------------------------------------------------------- /eventdb/Manifest.txt: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | Manifest.txt 3 | NOTES.md 4 | README.md 5 | Rakefile 6 | lib/eventdb.rb 7 | lib/eventdb/calendar.rb 8 | lib/eventdb/database.rb 9 | lib/eventdb/models.rb 10 | lib/eventdb/outline_reader.rb 11 | lib/eventdb/reader.rb 12 | lib/eventdb/schema.rb 13 | lib/eventdb/version.rb 14 | test/data/RUBY.md 15 | test/data/conferences.csv 16 | test/data/conferences.yml 17 | test/data/conferences_ii.yml 18 | test/data/test.txt 19 | test/helper.rb 20 | test/templates/RUBY.md.erb 21 | test/test_calendar.rb 22 | test/test_database.rb 23 | test/test_parser.rb 24 | test/test_reader.rb 25 | test/test_version.rb 26 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb/schema.rb: -------------------------------------------------------------------------------- 1 | 2 | module EventDb 3 | 4 | class CreateDb 5 | 6 | def up 7 | ActiveRecord::Schema.define do 8 | 9 | create_table :events do |t| 10 | t.string :title, null: false ## title (just the first link text) 11 | t.string :link ## for now optional - why? why not?? 12 | t.string :place, null: false 13 | t.date :start_date, null: false ## use (rename) to start_at - why? why not? 14 | t.date :end_date, null: false ## use (rename) to end_at - why? why not? 15 | t.integer :days, null: false 16 | 17 | t.timestamps 18 | end 19 | 20 | end # Schema.define 21 | end # method up 22 | 23 | end # class CreateDb 24 | 25 | end # module EventDb 26 | -------------------------------------------------------------------------------- /eventdb/script/test_memory.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib script/test_memory.rb 4 | 5 | 6 | ## our own code 7 | require 'eventdb' 8 | 9 | db = EventDb::Memory.new 10 | db.read( "#{EventDb.root}/test/data/conferences.yml" ) 11 | 12 | today = Date.today 13 | 14 | puts 'Upcoming Ruby Conferences:' 15 | puts '' 16 | 17 | on = EventDb::Model::Event.live( today ) 18 | on.each do |e| 19 | puts " NOW ON #{e.current_day(today)}d #{e.title}, #{e.date_fmt} (#{e.days}d) @ #{e.place}" 20 | end 21 | 22 | puts '' if on.any? 23 | 24 | up = EventDb::Model::Event.limit( 17 ).upcoming( today ) 25 | up.each do |e| 26 | puts " in #{e.diff_days(today)}d #{e.title}, #{e.date_fmt} (#{e.days}d) @ #{e.place}" 27 | end 28 | -------------------------------------------------------------------------------- /whatson/lib/whatson.rb: -------------------------------------------------------------------------------- 1 | # 3rd party libs (gems) 2 | require 'eventdb' 3 | require 'fetcher' 4 | 5 | 6 | # our own code 7 | 8 | require_relative 'whatson/version' ## let version always go first 9 | 10 | 11 | require_relative 'whatson/tool' 12 | require_relative 'whatson/beerfest' ## used by beerfest bin(ary) tool 13 | require_relative 'whatson/pycon' ## used by pyocn bin(ary) tool 14 | require_relative 'whatson/rubyconf' ## used by rubyconf bin(ary) tool 15 | require_relative 'whatson/football' ## used by kickoff bin(ary) tool 16 | require_relative 'whatson/whatson' ## used by whatson bin(ary) tool 17 | 18 | 19 | 20 | 21 | # say hello 22 | puts WhatsOn.banner if defined?($RUBYCOCOS_DEBUG) && $RUBYCOCOS_DEBUG 23 | -------------------------------------------------------------------------------- /eventdb/test/test_database.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib -I ./test test/test_database.rb 4 | 5 | 6 | require 'helper' 7 | 8 | class TestDatabase < MiniTest::Test 9 | 10 | def test_ruby 11 | db = EventDb::Memory.new 12 | db.read( "#{EventDb.root}/test/data/RUBY.md" ) 13 | 14 | ## get next 17 events 15 | today = Date.new( 2015, 1, 1 ) 16 | up = EventDb::Model::Event.limit( 17 ).upcoming( today ) 17 | pp up.to_sql 18 | pp up 19 | 20 | puts "Upcoming Ruby Conferences:" 21 | up.each do |e| 22 | puts " #{e.date_fmt('short')} | #{e.date_fmt} - #{e.title} @ #{e.place}" 23 | end 24 | 25 | assert true # assume ok if we get here 26 | end 27 | 28 | end # class TestDatabase 29 | -------------------------------------------------------------------------------- /eventdb/test/templates/RUBY.md.erb: -------------------------------------------------------------------------------- 1 | # Ruby Conference Calendar 2 | 3 | NOTE: This page gets auto-generated from the [awesome-events](README.md) page @ Planet Ruby. 4 | (Last update on <%= Date.today %>.) Do NOT edit this page, please update or edit conferences, camps, meetups etc. 5 | on the [awesome-events](README.md) page. Anything missing? Contributions welcome. Thanks! 6 | 7 | 8 | [2016](#2016) • [2015](#2015) • [2014](#2014) • [2013](#2013) 9 | 10 | <% events.each do |ev,q| %> 11 | <% if q.new_year? %> 12 | 13 | ## <%= ev.start_date.year %> 14 | 15 | <% end %> 16 | <% if q.new_month? %> 17 | 18 | **<%= Date::MONTHNAMES[ev.start_date.month] %>** 19 | 20 | <% end %> 21 | 22 | <%= ev.date_fmt( 'short' ) %> • [**<%= ev.title %>**](<%= ev.link %>) @ <%= ev.place %> 23 | 24 | <% end %> 25 | -------------------------------------------------------------------------------- /eventdb/script/test_read.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib script/test_read.rb 4 | 5 | 6 | ## our own code 7 | require 'eventdb' 8 | 9 | puts EventDb::VERSION 10 | 11 | events = EventDb::EventReader.read( "#{EventDb.root}/test/data/RUBY.md" ) 12 | # events = EventDb::EventReader.read( "#{EventDb.root}/test/data/conferences.yml" ) 13 | pp events 14 | 15 | 16 | 17 | __END__ 18 | 19 | [#, 25 | #, 31 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb.rb: -------------------------------------------------------------------------------- 1 | 2 | # stdlibs 3 | require 'pp' 4 | require 'date' 5 | require 'strscan' ## StringScanner lib 6 | require 'yaml' 7 | require 'erb' 8 | 9 | # 3rd party libs (gems) 10 | require 'props' 11 | require 'logutils' 12 | require 'csvreader' 13 | 14 | require 'props/activerecord' 15 | require 'logutils/activerecord' 16 | 17 | 18 | # our own code 19 | 20 | require_relative 'eventdb/version' ## let version always go first 21 | 22 | require_relative 'eventdb/schema' 23 | require_relative 'eventdb/models' 24 | 25 | require_relative 'eventdb/outline_reader' 26 | require_relative 'eventdb/reader' 27 | require_relative 'eventdb/calendar' # note: depends (requires) models (first) 28 | require_relative 'eventdb/database' 29 | 30 | 31 | 32 | # say hello 33 | puts EventDb.banner if defined?($RUBYCOCOS_DEBUG) && $RUBYCOCOS_DEBUG 34 | -------------------------------------------------------------------------------- /whatson/Rakefile: -------------------------------------------------------------------------------- 1 | require 'hoe' 2 | require './lib/whatson/version.rb' 3 | 4 | 5 | ### 6 | # hack/ quick fix for broken intuit_values - overwrite with dummy 7 | class Hoe 8 | def intuit_values( input ); end 9 | end 10 | 11 | 12 | 13 | Hoe.spec 'whatson' do 14 | 15 | self.version = WhatsOn::VERSION 16 | 17 | self.summary = "whatson - what's on now command line tool (using the event.db machinery)" 18 | self.description = summary 19 | 20 | self.urls = { home: 'https://github.com/rubycocos/events' } 21 | 22 | self.author = 'Gerald Bauer' 23 | self.email = 'ruby-talk@ruby-lang.org' 24 | 25 | # switch extension to .markdown for gihub formatting 26 | self.readme_file = 'README.md' 27 | self.history_file = 'CHANGELOG.md' 28 | 29 | self.extra_deps = [ 30 | ['eventdb', '>= 1.1.1'], 31 | ## 3rd party 32 | ['fetcher', '>= 0.4.5'], 33 | ['sqlite3'] 34 | ] 35 | 36 | self.licenses = ['Public Domain'] 37 | 38 | self.spec_extras = { 39 | required_ruby_version: '>= 2.2.2' 40 | } 41 | end 42 | -------------------------------------------------------------------------------- /whatson/sandbox/test_read.rb: -------------------------------------------------------------------------------- 1 | 2 | require 'yaml' 3 | require 'date' 4 | require 'time' 5 | 6 | ## see https://github.com/ruby/psych/issues/262 and 7 | ## http://sundivenetworks.com/archive/2021/tried-to-load-unspecified-class-time-psych-disallowedclass.html 8 | ## https://makandracards.com/makandra/465149-ruby-the-yaml-safe_load-method-hides-some-pitfalls 9 | ## about the issues with parsing dates in yml 10 | ## workaround 1) - use quotes for dates as string 11 | ## 12 | 13 | ## 14 | ## Psych#safe_load only whitelists the following classes: 15 | ## TrueClass, FalseClass, NilClass, Numeric, String, Array and Hash. 16 | ## All other classes will raise an exception unless you whitelist them. Maybe it is a good idea to add Symbol, Date and Time to that list, but other classes could also make sense. 17 | 18 | 19 | txt = File.open( './sandbox/conferences2023.yml'){ |f| f.read } 20 | pp txt 21 | puts 22 | 23 | data = Psych.safe_load( txt, permitted_classes: [Date] ) 24 | pp data 25 | 26 | 27 | puts "Psych.libyaml_version:" 28 | pp Psych.libyaml_version 29 | 30 | 31 | puts "bye" -------------------------------------------------------------------------------- /eventdb/test/test_calendar.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib -I ./test test/test_calendar.rb 4 | 5 | 6 | require 'helper' 7 | 8 | 9 | class TestCalendar < MiniTest::Test 10 | 11 | def test_ruby 12 | db = EventDb::Memory.new 13 | db.read( "#{EventDb.root}/test/data/RUBY.md" ) 14 | 15 | cal = EventDb::EventCalendar.new 16 | buf = cal.render( template: "#{EventDb.root}/test/templates/RUBY.md.erb" ) 17 | puts buf 18 | 19 | start_buf =<= 1.2.0'], # settings / prop(ertie)s / env / INI 22 | ['logutils', '>= 0.6.1'], # logging 23 | ['csvreader', '>= 1.2.4'], # read tabular (csv) data 24 | 25 | ## 3rd party 26 | ['activerecord'], # NB: will include activesupport,etc. 27 | 28 | ## more activerecord utils/addons 29 | ## ['tagutils', '>= 0.3.0'], # tags n categories for activerecord 30 | ## ['activerecord-utils', '>= 0.4.0'], 31 | ['props-activerecord', '>= 0.2.0'], 32 | ['logutils-activerecord', '>= 0.2.1'], 33 | ] 34 | 35 | self.licenses = ['Public Domain'] 36 | 37 | self.spec_extras = { 38 | required_ruby_version: '>= 2.2.2' 39 | } 40 | 41 | end 42 | -------------------------------------------------------------------------------- /eventdb/script/conferences2023.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # ruby event news in 2023 3 | # 4 | # published at the Calendar @ Planet Ruby 5 | # see https://planetruby.github.io/calendar/2023 6 | 7 | 8 | - name: RubyConf Australia 9 | location: Melbourne, Australia 10 | start: 2023-02-20 11 | end: 2023-02-21 12 | days: 2 13 | month: 2 14 | url: https://www.rubyconf.org.au 15 | twitter: rubyconf_au 16 | updated: 2023-01-05 ## note: used for feed.xml|json 17 | 18 | 19 | - name: RailsConf (United States) 20 | location: Atlanta, Georgia, United States 21 | start: 2023-04-24 22 | end: 2023-04-26 23 | days: 3 24 | month: 4 25 | url: https://railsconf.org 26 | twitter: railsconf 27 | updated: 2023-01-05 ## note: used for feed.xml|json 28 | 29 | - name: RubyKaigi 30 | location: Nagano, Japan 31 | start: 2023-05-11 32 | end: 2023-05-13 33 | days: 3 34 | month: 5 35 | url: https://rubykaigi.org/2023 36 | twitter: rubykaigi 37 | updated: 2023-01-05 ## note: used for feed.xml|json 38 | 39 | 40 | - name: Punk's Not Dead Conf - Ruby (Pixel) Art Programming 41 | location: Vienna, Austria, Central Europe 42 | start: 2023-06-29 43 | end: 2023-06-30 44 | days: 2 45 | month: 6 46 | url: https://viennacrypto.github.io/punksnotdead2023/ 47 | updated: 2023-01-05 ## note: used for feed.xml|json 48 | 49 | 50 | -------------------------------------------------------------------------------- /whatson/sandbox/conferences2023.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # ruby event news in 2023 3 | # 4 | # published at the Calendar @ Planet Ruby 5 | # see https://planetruby.github.io/calendar/2023 6 | 7 | 8 | - name: RubyConf Australia 9 | location: Melbourne, Australia 10 | start: 2023-02-20 11 | end: 2023-02-21 12 | days: 2 13 | month: 2 14 | url: https://www.rubyconf.org.au 15 | twitter: rubyconf_au 16 | updated: 2023-01-05 ## note: used for feed.xml|json 17 | 18 | 19 | - name: RailsConf (United States) 20 | location: Atlanta, Georgia, United States 21 | start: 2023-04-24 22 | end: 2023-04-26 23 | days: 3 24 | month: 4 25 | url: https://railsconf.org 26 | twitter: railsconf 27 | updated: 2023-01-05 ## note: used for feed.xml|json 28 | 29 | - name: RubyKaigi 30 | location: Nagano, Japan 31 | start: 2023-05-11 32 | end: 2023-05-13 33 | days: 3 34 | month: 5 35 | url: https://rubykaigi.org/2023 36 | twitter: rubykaigi 37 | updated: 2023-01-05 ## note: used for feed.xml|json 38 | 39 | 40 | - name: Punk's Not Dead Conf - Ruby (Pixel) Art Programming 41 | location: Vienna, Austria, Central Europe 42 | start: 2023-06-29 43 | end: 2023-06-30 44 | days: 2 45 | month: 6 46 | url: https://viennacrypto.github.io/punksnotdead2023/ 47 | updated: 2023-01-05 ## note: used for feed.xml|json 48 | 49 | 50 | -------------------------------------------------------------------------------- /eventdb/test/data/conferences_ii.yml: -------------------------------------------------------------------------------- 1 | ## source: https://github.com/ruby-conferences/ruby-conferences.github.io/blob/master/_data/conferences.yml 2 | 3 | - name: Rubyfuza 4 | location: Cape Town, South Africa 5 | start_date: 2020-02-06 6 | end_date: 2020-02-08 7 | url: http://www.rubyfuza.org 8 | twitter: rubyfuza 9 | 10 | - name: ParisRB Conf 11 | location: Paris, France 12 | url: https://2020.rubyparis.org/ 13 | start_date: 2020-02-18 14 | end_date: 2020-02-19 15 | twitter: parisrb 16 | 17 | - name: RubyConf AU 18 | location: Melbourne, Australia 19 | url: https://www.rubyconf.org.au/2020 20 | start_date: 2020-02-20 21 | end_date: 2020-02-21 22 | twitter: rubyconf_au 23 | 24 | 25 | - name: RubyDay 26 | location: Verona, Italy 27 | start_date: 2020-04-02 28 | end_date: 2020-04-02 29 | url: https://2020.rubyday.it 30 | twitter: rubydayit 31 | 32 | - name: RubyKaigi 33 | location: Nagano, Japan 34 | start_date: 2020-04-09 35 | end_date: 2020-04-11 36 | url: https://rubykaigi.org/2020 37 | twitter: rubykaigi 38 | 39 | 40 | - name: RailsConf 41 | location: Portland, OR 42 | start_date: 2020-05-05 43 | end_date: 2020-05-07 44 | url: https://railsconf.com/ 45 | twitter: railsconf 46 | 47 | - name: Balkan Ruby 48 | location: Sofia, Bulgaria 49 | start_date: 2020-05-15 50 | end_date: 2020-05-16 51 | url: https://balkanruby.com 52 | twitter: balkanruby 53 | 54 | 55 | - name: Brighton Ruby Conf 56 | location: Brighton, UK 57 | start_date: 2020-07-03 58 | end_date: 2020-07-03 59 | url: https://brightonruby.com 60 | twitter: brightonruby 61 | 62 | 63 | - name: RubyConf 64 | location: Houston, TX 65 | start_date: 2020-11-17 66 | end_date: 2020-11-19 67 | url: https://rubyconf.org 68 | twitter: rubyconf 69 | -------------------------------------------------------------------------------- /eventdb/test/data/conferences.csv: -------------------------------------------------------------------------------- 1 | ## source: https://github.com/python-organizers/conferences/blob/master/2020.csv 2 | 3 | Subject,Start Date,End Date,Location,Country,Venue,Tutorial Deadline,Talk Deadline,Website URL,Proposal URL,Sponsorship URL 4 | PyCascades,2020-02-08,2020-02-09,"Portland, Oregon, United States of America",USA,Revolution Hall,,2019-10-01,https://2020.pycascades.com,https://www.papercall.io/pycascades-2020,https://2020.pycascades.com/become-a-sponsor/ 5 | PyCon Namibia,2020-02-18,2020-02-20,"Windhoek, Namibia",NAM,,,2019-12-27,https://na.pycon.org/,https://na.pycon.org/call-proposals/, 6 | PyTennessee,2020-03-07,2020-03-08,"Nashville, Tennessee, United States of America",USA,Nashville School of Law,,,https://www.pytennessee.org/,https://www.pytennessee.org/prospectus, 7 | PyCon US,2020-04-15,2020-04-23,"Pittsburgh, Pennsylvania, United States of America",USA,David L. Lawrence Convention Center,2019-11-22,2019-12-20,https://us.pycon.org/,https://us.pycon.org/2020/speaking/talks/,https://us.pycon.org/2020/sponsors/ 8 | PyTexas,2020-05-16,2020-05-17,"Austin, Texas, United States of America",USA,,,,https://www.pytexas.org/2020/,, 9 | PyCon Italy,2020-04-02,2020-04-05,"Florence, Italy",ITA,"Grand Hotel Mediterraneo",,,https://www.pycon.it/en/,,https://www.pycon.it/en/sponsor/ 10 | EuroPython,2020-07-20,2020-07-26,"Dublin, Ireland",IRL,,,,,, 11 | PyOhio,2020-07-25,2020-07-26,"Columbus, Ohio, United States of America",USA,"The Ohio Union",,,https://www.pyohio.org/2020/,, 12 | EuroSciPy,2020-07-27,2020-07-31,"Bilbao, Spain",ESP,"Bizkaia Aretoa",,,https://www.euroscipy.org/,, 13 | GeoPython,2020-07-27,2020-07-31,"Bilbao, Spain",ESP,"Bizkaia Aretoa",,,http://2020.geopython.net,, 14 | "PyConDE & PyData Berlin 2020",2020-10-14,2020-10-16,"Berlin, Germany",DEU,,,,https://de.pycon.org,,https://de.pycon.org/sponsors/ 15 | "Moscow Python Conf ++ 2020",2020-03-27,2020-03-27,"Moscow, Russia",RUS,"Infospace",,2020-01-13,https://conf.python.ru/en/2020,https://onticoconferences.typeform.com/to/OySCUQ, 16 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb/database.rb: -------------------------------------------------------------------------------- 1 | 2 | module EventDb 3 | 4 | 5 | class Database 6 | def initialize( config={} ) 7 | @config = config 8 | end 9 | 10 | def connect 11 | ActiveRecord::Base.establish_connection( @config ) 12 | end 13 | 14 | def create 15 | CreateDb.new.up 16 | ConfDb::Model::Prop.create!( key: 'db.schema.event.version', value: VERSION ) 17 | end 18 | 19 | def create_all 20 | LogDb.create # add logs table 21 | ConfDb.create 22 | create 23 | end 24 | 25 | 26 | def read( path ) ## path_or_url 27 | events = EventReader.read( path ) 28 | add( events ) 29 | end 30 | 31 | def add( events ) 32 | ## todo/fix: add check if Array and also allow single event 33 | ## change arg to event_or_events - why? why not? 34 | 35 | ## todo/fix: use attributes or to_hash or somehting that works with ActiveRecord and Struct objects - why? why not? 36 | 37 | events.each do |ev| 38 | Model::Event.create!( 39 | title: ev.title, 40 | link: ev.link, 41 | place: ev.place, 42 | start_date: ev.start_date, 43 | end_date: ev.end_date, 44 | ## note: (pre)calculate duration in days 45 | ## -- mjd == Modified Julian Day Number 46 | ## -- note: 0 = same day (end==start), thus always add plus one (for one day event) 47 | days: ev.end_date.mjd - ev.start_date.mjd + 1 48 | ) 49 | end 50 | end 51 | 52 | end ## class DatabaseBase 53 | 54 | 55 | ## convenience class for in-memory (SQLite3) database 56 | class MemoryDatabase < Database 57 | 58 | def initialize 59 | ## -- default to sqlite3 in-memory database 60 | super( adapter: 'sqlite3', 61 | database: ':memory:' ) 62 | 63 | ## step 1) (auto-)connect 64 | connect 65 | ## step 2) (auto-)migrate, that is, create tables, etc. 66 | create_all # -- incl. props, logs tables etc. 67 | end 68 | 69 | end # class Database 70 | 71 | MemDatabase = MemoryDatabase 72 | Memory = MemoryDatabase 73 | 74 | end # module EventDb 75 | -------------------------------------------------------------------------------- /eventdb/test/test_reader.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib -I ./test test/test_reader.rb 4 | 5 | 6 | require 'helper' 7 | 8 | class TestReader < MiniTest::Test 9 | 10 | def test_datafiles 11 | events = EventDb::EventReader.read( "#{EventDb.root}/test/data/test.txt" ) 12 | pp events 13 | end 14 | 15 | def test_markdown 16 | events = EventDb::EventReader.read( "#{EventDb.root}/test/data/RUBY.md" ) 17 | 18 | ## pp events 19 | ev = events[0] 20 | 21 | assert_equal 'Rails Rumble', ev.title 22 | assert_equal 'https://railsrumble.com', ev.link 23 | assert_equal 'Intertubes, Online', ev.place 24 | assert_equal Date.new(2014,10,18), ev.start_date 25 | assert_equal Date.new(2014,10,19), ev.end_date 26 | 27 | 28 | ev = events[1] 29 | 30 | assert_equal 'JekyllConf', ev.title 31 | assert_equal 'http://jekyllconf.com', ev.link 32 | assert_equal 'Intertubes, Online', ev.place 33 | assert_equal Date.new(2015,5,2), ev.start_date 34 | end 35 | 36 | def test_csv 37 | rows = CsvHash.read( "#{EventDb.root}/test/data/conferences.csv", :header_converters => :symbol ) 38 | pp rows 39 | 40 | events = EventDb::EventReader.read( "#{EventDb.root}/test/data/conferences.csv" ) 41 | 42 | ## pp events 43 | ev = events[0] 44 | 45 | assert_equal 'PyCascades', ev.title 46 | assert_equal 'https://2020.pycascades.com', ev.link 47 | assert_equal 'Portland, Oregon, United States of America', ev.place 48 | assert_equal Date.new(2020, 2, 8), ev.start_date 49 | assert_equal Date.new(2020, 2, 9), ev.end_date 50 | 51 | ev = events[1] 52 | 53 | assert_equal 'PyCon Namibia', ev.title 54 | assert_equal 'https://na.pycon.org/', ev.link 55 | assert_equal 'Windhoek, Namibia', ev.place 56 | assert_equal Date.new(2020, 2, 18), ev.start_date 57 | assert_equal Date.new(2020, 2, 20), ev.end_date 58 | end 59 | 60 | end # class TestReader 61 | -------------------------------------------------------------------------------- /whatson/NEWS.md: -------------------------------------------------------------------------------- 1 | # News Posting Templates 2 | 3 | 4 | ## rubyflow & reddit (markdown) 5 | 6 | Upcoming Ruby Conferences - November 2015 Edition - Live Version Try $ rubyconf 7 | 8 | Hello, For you convenience the upcoming Ruby Conferences as listed with the [whatson gem](https://github.com/textkit/whatson) 9 | and the included rubyconf command line tool (for a live version try $ rubyconf): 10 | 11 | - in 10d RubyWorld Conference, Wed+Thu Nov/11+12 (2d) @ Matsue › Japan (jp) › Asia 12 | - in 12d RubyDay, Fri Nov/13 (1d) @ Turin › Italy (it) › Southern Europe › Europe 13 | - in 14d RubyConf, Sun-Tue Nov/15-17 (3d) @ San Antonio, Texas › United States (us) › North Ameria 14 | - in 40d RubyKaigi, Fri-Sun Dec/11-13 (3d) @ Tokyo › Japan (jp) › Asia 15 | - in 101d RubyConf Australia, Wed-Sat Feb/10-13 (4d) @ Gold Coast › Australia (au) › Pacific / Oceania 16 | 17 | Any conference or camps missing? 18 | Add it to the [Awesome Ruby Events](https://github.com/planetruby/awesome-events) page. 19 | For more updates follow [@rubycalendar](https://twitter.com/rubycalendar) on twitter. Cheers. 20 | 21 | 22 | ## ruby-talk (plain "vanilla" text) 23 | 24 | Upcoming Ruby Conferences - November 2015 Edition - Live Version Try $ rubyconf 25 | 26 | Hello, 27 | For you convenience the upcoming Ruby Conferences as listed with the whatson gem [1] 28 | and the included rubyconf command line tool (for a live version try $ rubyconf): 29 | 30 | - in 10d RubyWorld Conference, Wed+Thu Nov/11+12 (2d) @ Matsue › Japan (jp) › Asia 31 | - in 12d RubyDay, Fri Nov/13 (1d) @ Turin › Italy (it) › Southern Europe › Europe 32 | - in 14d RubyConf, Sun-Tue Nov/15-17 (3d) @ San Antonio, Texas › United States (us) › North Ameria 33 | - in 40d RubyKaigi, Fri-Sun Dec/11-13 (3d) @ Tokyo › Japan (jp) › Asia 34 | - in 101d RubyConf Australia, Wed-Sat Feb/10-13 (4d) @ Gold Coast › Australia (au) › Pacific / Oceania 35 | 36 | Any conference or camps missing? Add it to the Awesome Ruby Events [2] page. 37 | For more updates follow @rubycalendar [3] on twitter. Cheers. 38 | 39 | [1] https://github.com/textkit/whatson 40 | [2] https://github.com/planetruby/awesome-events 41 | [3] https://twitter.com/rubycalendar 42 | 43 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb/outline_reader.rb: -------------------------------------------------------------------------------- 1 | 2 | module EventDb 3 | 4 | class OutlineReader 5 | 6 | def self.read( path ) ## use - rename to read_file or from_file etc. - why? why not? 7 | txt = File.open( path, 'r:utf-8' ).read 8 | parse( txt ) 9 | end 10 | 11 | 12 | HEADING_RE = /^(\#{1,}) ## leading #### 13 | ([^#]+?) ## text - note: use non-greedy e.g. +? 14 | \#* ## (optional) trailing ## 15 | $/x 16 | 17 | LISTITEM_RE = /^ \s* 18 | -\s+ ## space required after dash (-) 19 | (.+) ## text 20 | $/x 21 | 22 | 23 | 24 | def self.parse( txt ) 25 | outline=[] ## outline structure 26 | 27 | # note: cut out; remove all html comments e.g. 28 | # supports multi-line comments too (e.g. uses /m - make dot match newlines) 29 | txt = txt.gsub( //xm, '' ) ## todo/fix: track/log cut out comments!!! 32 | 33 | 34 | txt.each_line do |line| 35 | line = line.strip ## todo/fix: keep leading and trailing spaces - why? why not? 36 | 37 | next if line.empty? ## todo/fix: keep blank line nodes e.g. just remove comments and process headings?! - why? why not? 38 | break if line == '__END__' 39 | 40 | pp line 41 | 42 | ## note: all optional trailing ### too 43 | if HEADING_RE.match( line ) 44 | heading_marker = $1 45 | heading_level = $1.length ## count number of = for heading level 46 | heading = $2.strip 47 | 48 | puts "heading #{heading_level} >#{heading}<" 49 | outline << [:"h#{heading_level}", heading] 50 | elsif LISTITEM_RE.match( line ) 51 | item = $1.strip 52 | 53 | puts "list item >#{item}<" 54 | outline << [:li, item] 55 | else 56 | ## assume it's a (plain/regular) text line 57 | outline << [:l, line] 58 | end 59 | end 60 | outline 61 | end # method read 62 | end # class OutlineReader 63 | 64 | end # module EventDb 65 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb/calendar.rb: -------------------------------------------------------------------------------- 1 | 2 | module EventDb 3 | 4 | class EventCursor 5 | def initialize( events ) 6 | @events = events 7 | end 8 | 9 | def each 10 | state = State.new 11 | @events.each do |event| 12 | state.next( event ) 13 | yield( event, state ) 14 | end 15 | end 16 | 17 | class State 18 | def initialize 19 | @last_date = Date.new( 1971, 1, 1 ) 20 | @new_date = true 21 | @new_year = true 22 | @new_month = true 23 | end 24 | def new_date?() @new_date; end 25 | def new_year?() @new_year; end 26 | def new_month?() @new_month; end 27 | 28 | def next( event ) 29 | if @last_date.year == event.start_date.year && 30 | @last_date.month == event.start_date.month 31 | @new_date = false 32 | @new_year = false 33 | @new_month = false 34 | else 35 | @new_date = true 36 | ## new year? 37 | @new_year = @last_date.year != event.start_date.year ? true : false 38 | ## new_month ? 39 | @new_month = (@new_year == true || @last_date.month != event.start_date.month) ? true : false 40 | end 41 | @last_date = event.start_date 42 | end 43 | 44 | end # class State 45 | 46 | end # class EventCursor 47 | 48 | 49 | class EventCalendar 50 | 51 | include Models # e.g. lets you use Event instead of (EventDb::)Model::Event 52 | 53 | def initialize( opts={} ) 54 | @events = opts[:events] || Event.order('start_date DESC') ## sort events by date (newest first) 55 | end 56 | 57 | def events 58 | ## note: return new cursor -- use decorator (instead of extra loop arg, why? why not? 59 | EventCursor.new( @events ) 60 | end 61 | 62 | def render( opts={} ) 63 | tmpl_path = opts[:template] || './templates/CALENDAR.md.erb' 64 | tmpl = File.open( tmpl_path, 'r:utf-8' ).read 65 | 66 | ERB.new( tmpl, nil, '<>' ).result( binding ) # <> omit newline for lines starting with <% and ending in %> 67 | end 68 | 69 | # def save( path = './CALENDAR.md' ) ## use (rename to) save_as - why? why not?? 70 | # File.open( path, 'w' ) do |f| 71 | # f.write( render ) 72 | # end 73 | # end 74 | 75 | end # class EventCalendar 76 | 77 | end # module EventDb 78 | -------------------------------------------------------------------------------- /whatson/lib/whatson/tool.rb: -------------------------------------------------------------------------------- 1 | 2 | module WhatsOn 3 | 4 | 5 | ## base (shared) tool class 6 | class Tool 7 | 8 | ## todo/fix: use header, footer instead of title, more_link - why? why not? 9 | 10 | Config = Struct.new( :title, ## todo/change: find better names for config params - why? why not? 11 | :more_link, 12 | :show_year ) 13 | 14 | def initialize( args=ARGV, 15 | title: 'Upcoming Events', 16 | more_link: nil, 17 | show_year: false 18 | ) 19 | ## turn down logger (default :debug?) 20 | LogUtils::Logger.root.level = :info 21 | 22 | @config = Config.new( title, 23 | more_link, 24 | show_year ) 25 | 26 | @db = EventDb::Memory.new ## note: use in-memory SQLite database 27 | args.each do |arg| 28 | puts " reading >#{arg}<..." 29 | @db.read( arg ) 30 | end 31 | end 32 | 33 | 34 | def list ## note: use list and NOT print (otherwise built-in call to print is recursive and will crash!!!) 35 | today = Date.today 36 | 37 | puts '' 38 | puts '' 39 | puts "#{@config.title}:" 40 | puts '' 41 | 42 | on = EventDb::Model::Event.live( today ) 43 | on.each do |e| 44 | print " NOW ON #{e.current_day(today)}d " 45 | print "#{e.title}" 46 | print " #{e.start_date.year}" if @config.show_year 47 | print ", " 48 | print "#{e.date_fmt} (#{e.days}d) @ #{e.place}" 49 | print "\n" 50 | end 51 | 52 | puts '' if on.any? 53 | 54 | ## get next 17 events 55 | up = EventDb::Model::Event.limit( 17 ).upcoming( today ) 56 | ## pp up.to_sql 57 | ## pp up 58 | 59 | if up.count > 0 60 | up.each do |e| 61 | print " in #{e.diff_days(today)}d " 62 | print "#{e.title}" 63 | print " #{e.start_date.year}" if @config.show_year 64 | print ", " 65 | print "#{e.date_fmt} (#{e.days}d) @ #{e.place}" 66 | print "\n" 67 | end 68 | else 69 | puts " -- No upcoming events found. #{EventDb::Model::Event.count} past event(s) in database. --" 70 | end 71 | 72 | puts '' 73 | 74 | if @config.more_link 75 | puts " More @ #{@config.more_link}" 76 | puts '' 77 | end 78 | end 79 | 80 | end # class Tool 81 | 82 | end # module WhatsOn 83 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb/models.rb: -------------------------------------------------------------------------------- 1 | 2 | module EventDb 3 | module Model 4 | 5 | class Event < ActiveRecord::Base 6 | 7 | ## todo: auto-add today ?? - why, why not? 8 | ## move order('start_date') into its own scope ?? 9 | 10 | scope :upcoming, ->( today=Date.today ) { order('start_date').where( 'start_date > ?', today ) } 11 | 12 | ## rename to now_on/on_now/now_playing/running/etc. - why? why not?? 13 | scope :live, ->( today=Date.today ) { order('start_date').where( 'start_date <= ? AND end_date >= ?', today, today ) } 14 | 15 | 16 | def current_day( today=Date.today ) 17 | today.mjd - start_date.mjd + 1 # calculate current event day (1,2,3,etc.) 18 | end 19 | alias_method :cur_day, :current_day 20 | 21 | def diff_days( today=Date.today ) 22 | start_date.mjd - today.mjd # note: mjd == Modified Julian Day Number 23 | end 24 | 25 | 26 | 27 | def date_fmt( fmt='long' ) # date pretty printed (pre-formatted) as string (with weeknames) 28 | 29 | ## note: wday - (0-6, Sunday is zero). 30 | if days == 1 31 | buf = '' 32 | if fmt == 'long' 33 | buf << Date::ABBR_DAYNAMES[start_date.wday] 34 | buf << ' ' 35 | end 36 | buf << Date::ABBR_MONTHNAMES[start_date.month] 37 | buf << '/' 38 | buf << start_date.day.to_s 39 | elsif days == 2 40 | buf = '' 41 | if fmt == 'long' 42 | buf << Date::ABBR_DAYNAMES[start_date.wday] 43 | buf << '+' 44 | buf << Date::ABBR_DAYNAMES[end_date.wday] 45 | buf << ' ' 46 | end 47 | buf << Date::ABBR_MONTHNAMES[start_date.month] 48 | buf << '/' 49 | buf << start_date.day.to_s 50 | buf << '+' 51 | if start_date.month != end_date.month 52 | buf << Date::ABBR_MONTHNAMES[end_date.month] 53 | buf << '/' 54 | end 55 | buf << end_date.day.to_s 56 | else ## assume multi day 57 | buf = '' 58 | if fmt == 'long' 59 | buf << Date::ABBR_DAYNAMES[start_date.wday] 60 | buf << '-' 61 | buf << Date::ABBR_DAYNAMES[end_date.wday] 62 | buf << ' ' 63 | end 64 | buf << Date::ABBR_MONTHNAMES[start_date.month] 65 | buf << '/' 66 | buf << start_date.day.to_s 67 | buf << '-' 68 | if start_date.month != end_date.month 69 | buf << Date::ABBR_MONTHNAMES[end_date.month] 70 | buf << '/' 71 | end 72 | buf << end_date.day.to_s 73 | end 74 | 75 | buf 76 | end # method date_fmt 77 | end # class Event 78 | 79 | end # module Model 80 | 81 | Models = Model ## note: add conveniene shortcut for models 82 | end # module EventDb 83 | -------------------------------------------------------------------------------- /eventdb/test/data/conferences.yml: -------------------------------------------------------------------------------- 1 | ############################# 2 | # ruby event news in 2020 3 | # 4 | # source: https://github.com/planetruby/calendar/blob/master/_data/conferences2020.yml 5 | 6 | - name: Rubyfuza 7 | location: Cape Town, South Africa 8 | start: 2020-02-06 # February 6-8, 2020 9 | end: 2020-02-08 10 | url: http://www.rubyfuza.org 11 | twitter: rubyfuza 12 | 13 | - name: ParisRB Conf 14 | location: Paris, France 15 | start: 2020-02-18 # February 18-19, 2020 16 | end: 2020-02-19 17 | url: https://2020.rubyparis.org 18 | twitter: parisrb 19 | 20 | - name: RubyConf Australia 21 | location: Melbourne, Victoria, Australia 22 | start: 2020-02-20 23 | end: 2020-02-21 24 | url: https://www.rubyconf.org.au/2020 25 | twitter: rubyconf_au 26 | 27 | 28 | - name: Wrocław <3 Ruby (wroclove.rb) 29 | location: Wrocław, Poland 30 | start: 2020-03-20 # 20-22th March, 2020 31 | end: 2020-03-22 32 | url: https://wrocloverb.com 33 | twitter: wrocloverb 34 | 35 | 36 | - name: RubyDay Italy 37 | location: Verona, Veneto, Italy 38 | start: 2020-04-02 39 | end: 2020-04-02 40 | url: https://2020.rubyday.it 41 | twitter: rubydayit 42 | 43 | # RubyKaigi 2020: April 9th - 11th, 2020 @ Matsumoto, Nagano, Japan https://rubykaigi.org/2020 44 | - name: RubyKaigi 45 | location: Nagano, Japan 46 | start: 2020-04-09 47 | end: 2020-04-11 48 | url: https://rubykaigi.org/2020 49 | twitter: rubykaigi 50 | 51 | - name: RubyConf India 52 | location: Goa, India 53 | start: 2020-04-25 # April 25-26 2020 54 | end: 2020-04-26 55 | url: http://rubyconfindia.org 56 | twitter: rubyconfindia 57 | 58 | 59 | # RailsConf 2020 will be in Portland, OR from May 5-7 60 | - name: RailsConf (United States) 61 | location: Portland, Oregon, United States 62 | start: 2020-05-05 63 | end: 2020-05-07 64 | url: https://railsconf.com 65 | twitter: railsconf 66 | 67 | - name: Balkan Ruby 68 | location: Sofia, Bulgaria 69 | start: 2020-05-15 70 | end: 2020-05-16 71 | url: https://balkanruby.com 72 | twitter: balkanruby 73 | 74 | 75 | - name: Ruby Unconf Hamburg 76 | location: Hamburg, Germany 77 | start: 2020-06-06 ## June 6th & 7th 2020 78 | end: 2020-06-07 79 | url: http://2020.rubyunconf.eu 80 | twitter: rubyunconfeu 81 | 82 | 83 | - name: Brighton RubyConf 84 | location: Brighton, Sussex, England, United Kingdom 85 | start: 2020-07-03 86 | end: 2020-07-03 87 | url: https://brightonruby.com 88 | twitter: brightonruby 89 | 90 | - name: RubyConf Kenya 91 | location: Nairobi, Kenya 92 | start: 2020-07-23 93 | end: 2020-07-25 94 | url: http://rubyconf.nairuby.org/2020 95 | twitter: nairubyke 96 | 97 | 98 | - name: European Ruby Konference (EuRuKo) 99 | location: Helsinki, Finnland 100 | start: 2020-08-21 # 21–22.8.2020 101 | end: 2020-08-22 102 | url: https://euruko2020.org 103 | twitter: euruko 104 | 105 | 106 | - name: RubyConf (United States) 107 | location: Houston, Texas, United States 108 | start: 2020-11-17 109 | end: 2020-11-19 110 | url: https://rubyconf.org 111 | twitter: rubyconf 112 | -------------------------------------------------------------------------------- /eventdb/test/test_parser.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # to run use 3 | # ruby -I ./lib -I ./test test/test_parser.rb 4 | 5 | 6 | require 'helper' 7 | 8 | class TestParser < MiniTest::Test 9 | 10 | def test_ruby_markdown 11 | txt =< 17 | 18 | - [Rails Rumble](https://railsrumble.com) 19 | - 2014 @ Intertubes; Oct/18+19 20 | 21 | 22 | 23 | - **JekyllConf** (web: [jekyllconf.com](http://jekyllconf.com)) 24 | - 2015 @ Intertubes; May/2 25 | TXT 26 | 27 | events = EventDb::EventReader::MarkdownParser.parse( txt ) 28 | 29 | ## pp events 30 | ev = events[0] 31 | 32 | assert_equal 'Rails Rumble', ev.title 33 | assert_equal 'https://railsrumble.com', ev.link 34 | assert_equal 'Intertubes, Online', ev.place 35 | assert_equal Date.new(2014,10,18), ev.start_date 36 | assert_equal Date.new(2014,10,19), ev.end_date 37 | 38 | ev = events[1] 39 | 40 | assert_equal 'JekyllConf', ev.title 41 | assert_equal 'http://jekyllconf.com', ev.link 42 | assert_equal 'Intertubes, Online', ev.place 43 | assert_equal Date.new(2015,5,2), ev.start_date 44 | end 45 | 46 | def test_ruby_yaml 47 | txt =< 12 | 13 | - [Rails Rumble](https://railsrumble.com) 14 | - 2014 @ Intertubes; Oct/18+19 15 | 16 | 17 | 18 | - **JekyllConf** (web: [jekyllconf.com](http://jekyllconf.com)) 19 | - 2015 @ Intertubes; May/2 20 | 21 | ## Europe 22 | 23 | - [European Ruby Konference - EuRuKo](http://euruko.org) 24 | - 2015 @ Salzburg, Austria; Oct/17+18 25 | - 2014 @ Kyiv, Ukraine; Jun/20+21 26 | - 2013 @ Athens, Greece; Jun/28+29 27 | - [European Ruby Camp - eurucamp](http://eurucamp.org) 28 | - 2015 @ Berlin (Potsdam), Germany; Jul/31-Aug/2 29 | - [Ruby Open Source Software (ROSS) Conference - ROSSConf](http://rossconf.io) - [:octocat:](https://github.com/rossconf) 30 | - 2015 @ Berlin, Germany; Sept/26 31 | - 2015 @ Vienna, Austria; Apr/25 32 | - [JRuby Conference Europe - JRubyConf EU](http://jrubyconf.eu) 33 | - 2015 @ Berlin (Potsdam), Germany; Jul/31 34 | - [RubyMotion Conference - #inspect](http://conference.rubymotion.com) 35 | - 2015 @ Paris, France; Jul/1+2 36 | 37 | ### Central Europe 38 | 39 | #### Poland 40 | 41 | - [wroc_love.rb](http://www.wrocloverb.com) 42 | - 2015 @ Wrocław; Mar/13-15 43 | 44 | 45 | ### Western Europe 46 | 47 | #### England 48 | 49 | - [Brighton Ruby Conference](http://brightonruby.com) 50 | - 2015 @ Brighton, East Sussex; Jul/20 51 | - [Bath Ruby Conference](http://bathruby.org) 52 | - 2015 @ Bath, Somerset; Mar/13 53 | 54 | #### Belgium / België / Belgique 55 | 56 | - [ArrrCamp](http://arrrrcamp.be) 57 | - 2015 @ Ghent, Oost-Vlaanderen; Oct/1+2 58 | - 2014 @ Ghent, Oost-Vlaanderen; Oct/2+3 59 | 60 | ### Southern Europe 61 | 62 | #### Portugal 63 | 64 | - [RubyConf Portugal](http://rubyconf.pt) 65 | - 2015 @ Braga; Sep/14+15 66 | - 2014 @ Braga; Oct/13+14 67 | 68 | #### Italy 69 | 70 | - [RubyDay](http://www.rubyday.it) 71 | - 2015 @ Turin; Nov/13 72 | - 2014 @ Roncade, Treviso; Sept/26 73 | 74 | 75 | ### Northern Europe 76 | 77 | #### Lithuania / Lietuva 78 | 79 | - [RubyConfLT - Lithuanian Ruby Conference](http://rubyconf.lt) 80 | - 2015 @ Vilnius; Mar/21 81 | 82 | 83 | ### Eastern Europe 84 | 85 | #### Russia / Россия 86 | 87 | - [Rails Club](http://railsclub.ru) 88 | - 2015 @ Moscow; May/21+22 89 | 90 | #### Ukraine / Україна / Украина 91 | 92 | - [RubyC](http://rubyc.eu) 93 | - 2015 @ Kyiv; May/30+31 94 | 95 | 96 | 97 | ## America 98 | 99 | ### North America 100 | 101 | #### United States 102 | 103 | - [RubyConf](http://rubyconf.org) 104 | - 2015 @ San Antonio, Texas; Nov/15-17 105 | - 2014 @ San Diego, California; Nov/17-19 106 | - [RailsConf](http://railsconf.com) 107 | - 2016 @ Kansas City, Missouri; May/4-6 108 | - 2015 @ Atlanta, Georgia; Apr/21-23 109 | - 2014 @ Chicago, Illinois; Apr/22-25 110 | 111 | ##### New England 112 | 113 | - [Burlington Ruby Conference](http://www.burlingtonrubyconference.com) 114 | - 2015 @ Burlington, Vermont; Aug/1+2 115 | 116 | ##### Mid Atlantic 117 | 118 | - [Gotham Ruby Conference (GORUCO)](http://goruco.com) 119 | - 2015 @ New York, New York; Jun/20 120 | 121 | ##### Great Lakes 122 | 123 | - [Madison+ Ruby](http://madisonpl.us/ruby) 124 | - 2015 @ Madison, Wisconsin; Aug/21+22 125 | 126 | ##### Rocky Mountains 127 | 128 | - [Rocky Mountain Ruby Conference](http://rockymtnruby.com) 129 | - 2015 @ Boulder, Colorado; Sept/23-25 130 | 131 | 132 | 133 | #### Mexico / México 134 | 135 | - [MagmaConf](http://magmaconf.com) 136 | - 2015 @ Manzanillo, Colima; Jun/18-20 137 | - 2014 @ Manzanillo, Colima; Jun/4-6 138 | 139 | 140 | 141 | ### South America 142 | 143 | #### Brazil / Brasil 144 | 145 | - [RubyConf Brasil](http://www.rubyconf.com.br) 146 | - 2015 @ São Paulo; Sept/18+19 147 | - 2014 @ São Paulo; Aug/28+29 148 | - [RuPy Campinas](http://campinas.rupy.com.br), [RuPy](http://rupy.com.br) 149 | - 2015 @ Campinas, São Paulo; Jun/20 150 | - 2014 @ São José dos Campos, São Paulo; Nov/29 151 | - [Tropical Ruby](http://tropicalrb.com) 152 | - 2015 @ Porto de Galinhas, Pernambuco; Mar/5-8 153 | - 2014 @ Porto de Galinhas, Pernambuco; Apr/24-27 (formerly: Abril Pro Ruby) 154 | 155 | #### Colombia 156 | 157 | - [RubyConf Colombia](http://www.rubyconf.co) 158 | - 2015 @ Medellin; Oct/15+16 159 | 160 | 161 | ## Asia 162 | 163 | ### Japan 164 | 165 | - [RubyWorld Conference](http://www.rubyworld-conf.org/en) 166 | - 2015 @ Matsue; Nov/11+12 167 | - 2014 @ Matsue; Nov/13+14 168 | - [RubyKaigi](http://rubykaigi.org) 169 | - 2015 @ Tokyo; Dec/11-13 170 | - 2014 @ Tokyo; Sep/18-20 171 | 172 | ### Taiwan 173 | 174 | - [RubyConf Taiwan](http://rubyconf.tw) 175 | - 2015 @ Taipei; Sept/11+12 176 | - 2014 @ Taipei; Apr/25+26 177 | 178 | ### Singapore 179 | 180 | - [RedDotRubyConf](http://www.reddotrubyconf.com) 181 | - 2015 @ Singapore; Jun/4+5 182 | - 2014 @ Singapore; Jun/26+27 183 | 184 | ### Philippines / Pilipinas 185 | 186 | - [RubyConf Philippines](http://rubyconf.ph) 187 | - 2015 @ Boracy Island; Mar/27-28 188 | - 2014 @ Manila; Mar/28-29 189 | 190 | ### India 191 | 192 | - [RubyConf India](http://rubyconfindia.org) 193 | - 2015 @ Goa; Apr/3-5 194 | - [Garden City Ruby Conference](http://www.gardencityruby.org) 195 | - 2015 @ Bangalore; Jan/10 196 | 197 | 198 | ## Africa 199 | 200 | ### Kenya 201 | 202 | - [RubyConf Kenya](http://ruby-conf-ke.nairuby.org) 203 | - 2015 @ Nairobi; May/8+9 204 | 205 | ### South Africa 206 | 207 | - [RubyFuza](http://www.rubyfuza.org) 208 | - 2015 @ Cape Town; Feb/5+6 209 | 210 | 211 | ## Pacific / Oceania 212 | 213 | ### Australia 214 | 215 | - [RubyConf Australia](http://www.rubyconf.org.au) 216 | - 2015 @ Melbourne; Feb/4-7 217 | 218 | 219 | 220 | ## Meta 221 | 222 | **License** 223 | 224 | The awesome list is dedicated to the public domain. Use it as you please with no restrictions whatsoever. 225 | 226 | **Questions? Comments?** 227 | 228 | Send them along to the ruby-talk mailing list. Thanks! 229 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /eventdb/README.md: -------------------------------------------------------------------------------- 1 | # event.db 2 | 3 | event.db schema 'n' models for easy (re)use 4 | 5 | * home :: [github.com/rubycocos/events](https://github.com/rubycocos/events) 6 | * bugs :: [github.com/rubycocos/events/issues](https://github.com/rubycocos/events/issues) 7 | * gem :: [rubygems.org/gems/eventdb](https://rubygems.org/gems/eventdb) 8 | * rdoc :: [rubydoc.info/gems/eventdb](http://rubydoc.info/gems/eventdb) 9 | 10 | 11 | 12 | --- 13 | 14 | NOTE: Command Line Tools - `rubyconf`, `kickoff`, `beerfest` - Now in `whatson` Package 15 | 16 | The "out-of-the-box" ready-to-use command line tools (that is, `rubyconf`, `kickoff`, `beerfest`, etc.) 17 | for listing upcoming events (ruby conferences, football tournaments, beer festivals, etc.) 18 | moved to its own package / library, that is, `whatson`. 19 | See the [whatson project for more »](../whatson) 20 | 21 | --- 22 | 23 | 24 | 25 | ## Usage 26 | 27 | ``` ruby 28 | require 'eventdb' 29 | 30 | ## Step 1 - Setup (In-Memory) Database and Read-in / Fetch Events 31 | 32 | url = "https://github.com/planetruby/calendar/raw/master/_data/conferences2023.yml" 33 | 34 | db = EventDb::Memory.new # note: use in-memory SQLite database 35 | db.read( url ) 36 | 37 | 38 | ## Step 2 - Print Out Ongoing and Upcoming Events 39 | 40 | today = Date.today 41 | 42 | puts 'Upcoming Ruby Conferences:' 43 | puts '' 44 | 45 | on = EventDb::Model::Event.live( today ) 46 | on.each do |e| 47 | puts " NOW ON #{cur_day(today)}d #{e.title}, #{e.date_fmt} (#{e.days}d) @ #{e.place}" 48 | end 49 | 50 | puts '' if on.any? 51 | 52 | up = EventDb::Model::Event.limit( 17 ).upcoming( today ) 53 | up.each do |e| 54 | puts " in #{diff_days(today)}d #{e.title}, #{e.date_fmt} (#{e.days}d) @ #{e.place}" 55 | end 56 | ``` 57 | 58 | will print in 2023: 59 | 60 | ``` 61 | Upcoming Ruby Conferences: 62 | 63 | in 33d RubyConf Australia, Mon+Tue Feb/20+21 (2d) @ Melbourne, Australia 64 | in 96d RailsConf (United States), Mon-Wed Apr/24-26 (3d) @ Atlanta, Georgia, United States 65 | in 113d RubyKaigi, Thu-Sat May/11-13 (3d) @ Nagano, Japan 66 | in 162d Punk's Not Dead Conf - Ruby (Pixel) Art Programming, Thu+Fri Jun/29+30 (2d) @ Vienna, Austria 67 | ... 68 | ``` 69 | 70 | 71 | and back in 2020: 72 | 73 | ``` 74 | Upcoming Ruby Conferences: 75 | 76 | in 62d Rubyfuza, Thu-Sat Feb/6-8 (3d) @ Cape Town, South Africa 77 | in 74d ParisRB Conf, Tue+Wed Feb/18+19 (2d) @ Paris, France 78 | in 76d RubyConf Australia, Thu+Fri Feb/20+21 (2d) @ Melbourne, Victoria, Australia 79 | in 105d Wrocław <3 Ruby (wroclove.rb), Fri-Sun Mar/20-22 (3d) @ Wrocław, Poland 80 | in 118d RubyDay Italy, Thu Apr/2 (1d) @ Verona, Veneto, Italy 81 | in 125d RubyKaigi, Thu-Sat Apr/9-11 (3d) @ Nagano, Japan 82 | in 141d RubyConf India, Sat+Sun Apr/25+26 (2d) @ Goa, India 83 | in 151d RailsConf (United States), Tue-Thu May/5-7 (3d) @ Portland, Oregon, United States 84 | in 161d Balkan Ruby, Fri+Sat May/15+16 (2d) @ Sofia, Bulgaria 85 | in 183d Ruby Unconf Hamburg, Sat+Sun Jun/6+7 (2d) @ Hamburg, Germany 86 | in 210d Brighton RubyConf, Fri Jul/3 (1d) @ Brighton, Sussex, England, United Kingdom 87 | in 230d RubyConf Kenya, Thu-Sat Jul/23-25 (3d) @ Nairobi, Kenya 88 | in 259d European Ruby Konference (EuRuKo), Fri+Sat Aug/21+22 (2d) @ Helsinki, Finnland 89 | in 347d RubyConf (United States), Tue-Thu Nov/17-19 (3d) @ Houston, Texas, United States 90 | ``` 91 | 92 | and back in 2015 93 | 94 | ``` 95 | Upcoming Ruby Conferences: 96 | 97 | NOW ON 2d RubyMotion Conference - #inspect, Wed+Thu Jul/1+2 (2d) @ Paris, France 98 | 99 | in 18d Brighton Ruby Conference, Mon Jul/20 (1d) @ Brighton, East Sussex, England 100 | in 27d European Ruby Camp - eurucamp, Fri-Sun Jul/31-Aug/2 (3d) @ Berlin (Potsdam), Germany 101 | in 27d JRuby Conference Europe - JRubyConf EU, Fri Jul/31 (1d) @ Berlin (Potsdam), Germany 102 | in 28d Burlington Ruby Conference, Sat+Sun Aug/1+2 (2d) @ Burlington, Vermont, New England, United States 103 | in 50d Madison+ Ruby, Fri+Sat Aug/21+22 (2d) @ Madison, Wisconsin, Great Lakes, United States 104 | in 71d RubyConf Taiwan, Fri+Sat Sep/11+12 (2d) @ Taipei, Taiwan 105 | in 72d RubyConf Portugal, Mon+Tue Sep/14+15 (2d) @ Braga, Portugal 106 | in 78d RubyConf Brasil, Fri+Sat Sep/18+19 (2d) @ São Paulo, Brazil 107 | in 83d Rocky Mountain RubyConf, Wed-Fri Sep/23-25 (3d) @ Boulder, Colorado, Rocky Mountains, United States 108 | in 85d Ruby Open Source Software (ROSS) Conference - ROSSConf, Sat Sep/26 (1d) @ Berlin, Germany 109 | in 93d ArrrCamp, Thu+Fri Oct/1+2 (2d) @ Ghent, Oost-Vlaanderen, Belgium 110 | in 105d RubyConf Colombia, Thu+Fri Oct/15+16 (2d) @ Medellin, Colombia 111 | in 107d European Ruby Konference - EuRuKo, Sat+Sun Oct/17+18 (2d) @ Salzburg, Austria 112 | in 132d RubyWorld Conference, Wed+Thu Nov/11+12 (2d) @ Matsue, Japan 113 | ... 114 | ``` 115 | 116 | 117 | 118 | ## Format 119 | 120 | **Markdown** 121 | 122 | Option 1a) Classic Style 123 | 124 | ``` markdown 125 | - [European Ruby Konference - EuRuKo](http://euruko.org) 126 | - 2020 @ Helsinki, Finnland; Aug/21+22 127 | ``` 128 | 129 | Option 1b) Modern Style 130 | 131 | ``` markdown 132 | - **European Ruby Konference - EuRuKo** (web: [euruko.org](http://euruko.org)) 133 | - 2020 @ Helsinki, Finnland; Aug/21+22 134 | ``` 135 | 136 | **YAML** 137 | 138 | Option 2a) Style A 139 | 140 | ``` yaml 141 | - title: European Ruby Konference - EuRuKo 142 | link: http://euruko.org 143 | place: Helsinki, Finnland 144 | start_date: 2020-08-21 145 | end_date: 2020-08-22 146 | ``` 147 | 148 | Option 2b) Style B 149 | 150 | ``` yaml 151 | - name: European Ruby Konference - EuRuKo 152 | url: http://euruko.org 153 | location: Helsinki, Finnland 154 | start: 2020-08-21 155 | end: 2020-08-22 156 | ``` 157 | 158 | **CSV** 159 | 160 | Option 3a) Style A 161 | 162 | ``` csv 163 | title, link, place, start_date, end_date 164 | European Ruby Konference - EuRuKo, http://euruko.org, "Helsinki, Finnland", 2020-08-21, 2020-08-22 165 | ``` 166 | 167 | Option 3b) Style B 168 | 169 | ``` csv 170 | name, url, location, start, end 171 | European Ruby Konference - EuRuKo, http://euruko.org, "Helsinki, Finnland", 2020-08-21, 2020-08-22 172 | ``` 173 | 174 | Option 3c) Style C 175 | 176 | ``` csv 177 | subject, website_url, location, start_date, end_date 178 | European Ruby Konference - EuRuKo, http://euruko.org, "Helsinki, Finnland", 2020-08-21, 2020-08-22 179 | ``` 180 | 181 | 182 | resulting in: 183 | 184 | ``` 185 | # 191 | ``` 192 | 193 | Note: The headings hierarchy (starting w/ heading level 2) gets added to the place as a 194 | geo tree. Example: 195 | 196 | ``` markdown 197 | ## Europe 198 | 199 | ### Central Europe 200 | 201 | #### Germany 202 | 203 | ##### Bavaria 204 | 205 | ###### Upper Franconia 206 | 207 | - [**Sandwerka (Sandkirchweih)**](http://www.sandkerwa.de) 208 | - 2020 @ Bamberg, Aug/20-24 209 | ``` 210 | 211 | resulting in: 212 | 213 | ``` 214 | # 219 | ``` 220 | 221 | 222 | 223 | ## Public Event Datasets 224 | 225 | - [Calendar @ Planet Ruby](https://github.com/planetruby/calendar) - a collection of awesome Ruby events (meetups, conferences, camps, etc.) from around the world 226 | - [Calendar @ World Football Book](https://github.com/footballbook/calendar) - a collection of awesome football tournaments, cups, etc. from around the world 227 | - [Calendar @ World Beer Book](https://github.com/beerbook/calendar) - a collection of awesome beer events (oktoberfest, starkbierfest, etc.) from around the world 228 | 229 | 230 | 231 | ## Install 232 | 233 | Just install the gem: 234 | 235 | $ gem install eventdb 236 | 237 | 238 | ## License 239 | 240 | The `eventdb` scripts are dedicated to the public domain. 241 | Use it as you please with no restrictions whatsoever. 242 | 243 | 244 | ## Questions? Comments? 245 | 246 | Send them along to the ruby-talk mailing list. 247 | Thanks! 248 | -------------------------------------------------------------------------------- /whatson/README.md: -------------------------------------------------------------------------------- 1 | # whatson 2 | 3 | what's on now command line tool (using the event.db machinery) 4 | 5 | * home :: [github.com/rubycocos/events](https://github.com/rubycocos/events) 6 | * bugs :: [github.com/rubycocos/events/issues](https://github.com/rubycocos/events/issues) 7 | * gem :: [rubygems.org/gems/whatson](https://rubygems.org/gems/whatson) 8 | * rdoc :: [rubydoc.info/gems/whatson](http://rubydoc.info/gems/whatson) 9 | 10 | 11 | 12 | ## Command Line Tools - `rubyconf`, `pycon`, `kickoff`, `beerfest` 13 | 14 | The whatson package includes command line tools 15 | to list upcoming events (ruby conferences, python conferences, 16 | football tournaments, beer festivals. etc.). 17 | 18 | 19 | ### Upcoming Ruby Conferences 20 | 21 | Use 22 | 23 | ``` 24 | $ rubyconf 25 | ``` 26 | 27 | to list upcoming Ruby (un)conferences from around the world. Will print in 2023: 28 | 29 | ``` 30 | Upcoming Ruby Conferences: 31 | 32 | in 33d RubyConf Australia, Mon+Tue Feb/20+21 (2d) @ Melbourne, Australia 33 | in 96d RailsConf (United States), Mon-Wed Apr/24-26 (3d) @ Atlanta, Georgia, United States 34 | in 113d RubyKaigi, Thu-Sat May/11-13 (3d) @ Nagano, Japan 35 | in 162d Punk's Not Dead Conf - Ruby (Pixel) Art Programming, Thu+Fri Jun/29+30 (2d) @ Vienna, Austria 36 | ... 37 | ``` 38 | 39 | 40 | and back in 2020: 41 | 42 | ``` 43 | Upcoming Ruby Conferences: 44 | 45 | in 62d Rubyfuza, Thu-Sat Feb/6-8 (3d) @ Cape Town, South Africa 46 | in 74d ParisRB Conf, Tue+Wed Feb/18+19 (2d) @ Paris, France 47 | in 76d RubyConf Australia, Thu+Fri Feb/20+21 (2d) @ Melbourne, Victoria, Australia 48 | in 105d Wrocław <3 Ruby (wroclove.rb), Fri-Sun Mar/20-22 (3d) @ Wrocław, Poland 49 | in 118d RubyDay Italy, Thu Apr/2 (1d) @ Verona, Veneto, Italy 50 | in 125d RubyKaigi, Thu-Sat Apr/9-11 (3d) @ Nagano, Japan 51 | in 141d RubyConf India, Sat+Sun Apr/25+26 (2d) @ Goa, India 52 | in 151d RailsConf (United States), Tue-Thu May/5-7 (3d) @ Portland, Oregon, United States 53 | in 161d Balkan Ruby, Fri+Sat May/15+16 (2d) @ Sofia, Bulgaria 54 | in 183d Ruby Unconf Hamburg, Sat+Sun Jun/6+7 (2d) @ Hamburg, Germany 55 | in 210d Brighton RubyConf, Fri Jul/3 (1d) @ Brighton, Sussex, England, United Kingdom 56 | in 230d RubyConf Kenya, Thu-Sat Jul/23-25 (3d) @ Nairobi, Kenya 57 | in 259d European Ruby Konference (EuRuKo), Fri+Sat Aug/21+22 (2d) @ Helsinki, Finnland 58 | in 347d RubyConf (United States), Tue-Thu Nov/17-19 (3d) @ Houston, Texas, United States 59 | ``` 60 | 61 | and back in 2015 62 | 63 | ``` 64 | Upcoming Ruby Conferences: 65 | 66 | NOW ON 2d RubyMotion Conference - #inspect, Wed+Thu Jul/1+2 (2d) @ Paris, France 67 | 68 | in 18d Brighton Ruby Conference, Mon Jul/20 (1d) @ Brighton, East Sussex, England 69 | in 27d European Ruby Camp - eurucamp, Fri-Sun Jul/31-Aug/2 (3d) @ Berlin (Potsdam), Germany 70 | in 27d JRuby Conference Europe - JRubyConf EU, Fri Jul/31 (1d) @ Berlin (Potsdam), Germany 71 | in 28d Burlington Ruby Conference, Sat+Sun Aug/1+2 (2d) @ Burlington, Vermont, New England, United States 72 | in 50d Madison+ Ruby, Fri+Sat Aug/21+22 (2d) @ Madison, Wisconsin, Great Lakes, United States 73 | in 71d RubyConf Taiwan, Fri+Sat Sep/11+12 (2d) @ Taipei, Taiwan 74 | in 72d RubyConf Portugal, Mon+Tue Sep/14+15 (2d) @ Braga, Portugal 75 | in 78d RubyConf Brasil, Fri+Sat Sep/18+19 (2d) @ São Paulo, Brazil 76 | in 83d Rocky Mountain RubyConf, Wed-Fri Sep/23-25 (3d) @ Boulder, Colorado, Rocky Mountains, United States 77 | in 85d Ruby Open Source Software (ROSS) Conference - ROSSConf, Sat Sep/26 (1d) @ Berlin, Germany 78 | in 93d ArrrCamp, Thu+Fri Oct/1+2 (2d) @ Ghent, Oost-Vlaanderen, Belgium 79 | in 105d RubyConf Colombia, Thu+Fri Oct/15+16 (2d) @ Medellin, Colombia 80 | in 107d European Ruby Konference - EuRuKo, Sat+Sun Oct/17+18 (2d) @ Salzburg, Austria 81 | in 132d RubyWorld Conference, Wed+Thu Nov/11+12 (2d) @ Matsue, Japan 82 | ... 83 | ``` 84 | 85 | 86 | 87 | ### Upcoming Python Conferences 88 | 89 | Use 90 | 91 | ``` 92 | $ pycon 93 | ``` 94 | 95 | to list upcoming Python (un)conferences from around the world. Will print in 2020: 96 | 97 | ``` 98 | Upcoming Python Conferences: 99 | 100 | in 62d PyCascades, Sat+Sun Feb/8+9 (2d) @ Portland, Oregon, United States 101 | in 72d PyCon Namibia, Tue-Thu Feb/18-20 (3d) @ Windhoek, Namibia 102 | in 90d PyTennessee, Sat+Sun Mar/7+8 (2d) @ Nashville, Tennessee, United States 103 | in 110d Moscow Python Conf, Fri Mar/27 (1d) @ Moscow, Russia 104 | in 116d PyCon Italy, Thu-Sun Apr/2-5 (4d) @ Florence, Italy 105 | in 129d PyCon US, Wed-Thu Apr/15-23 (9d) @ Pittsburgh, Pennsylvania, United States 106 | in 160d PyTexas, Sat+Sun May/16+17 (2d) @ Austin, Texas, United States 107 | in 225d EuroPython, Mon-Sun Jul/20-26 (7d) @ Dublin, Ireland 108 | in 230d PyOhio, Sat+Sun Jul/25+26 (2d) @ Columbus, Ohio, United States 109 | in 232d EuroSciPy, Mon-Fri Jul/27-31 (5d) @ Bilbao, Spain 110 | in 232d GeoPython, Mon-Fri Jul/27-31 (5d) @ Bilbao, Spain 111 | in 311d PyConDE & PyData Berlin, Wed-Fri Oct/14-16 (3d) @ Berlin, Germany 112 | ``` 113 | 114 | 115 | ### Upcoming Football Tournaments 116 | 117 | Use 118 | 119 | ``` 120 | $ kickoff 121 | ``` 122 | 123 | to list upcoming football tournaments from around the world. Will print: 124 | 125 | ``` 126 | Upcoming Football Tournaments: 127 | 128 | NOW ON 18d Women's World Cup 2015, Sat-Sun Jun/6-Jul/5 (30d) @ Canada › World (FIFA) 129 | NOW ON 13d Copa América 2015, Thu-Sat Jun/11-Jul/4 (24d) @ Chile › South America (CONMEBOL) 130 | 131 | in 14d Gold Cup / Copa de Oro 2015, Tue-Sun Jul/7-26 (20d) @ United States+Canada › North America (CONCACAF) 132 | in 346d Copa América 2016, Fri-Sun Jun/3-26 (24d) @ United States › South America (CONMEBOL) 133 | in 353d European Championship (Euro) 2016, Fri-Sun Jun/10-Jul/10 (31d) @ France › Europe (UEFA) 134 | in 1087d World Cup 2018, Thu-Sun Jun/14-Jul/15 (32d) @ Russia › World (FIFA) 135 | ... 136 | ``` 137 | 138 | 139 | ### Upcoming Beerfests 140 | 141 | Use 142 | 143 | ``` 144 | $ beerfest 145 | ``` 146 | 147 | to list upcoming beer festivals from around the world. Will print: 148 | 149 | ``` 150 | Upcoming Beerfests: 151 | 152 | in 9d Ottakringer Braukultur Wochen (9 Brauereien in 9 Wochen), Thu-Wed Jul/2-Sep/2 (63d) @ 16., Ottakring › Vienna / Wien › Austria / Österreich (at) › Central Europe › Europe 153 | in 31d Annafest ("Auf den Kellern"), Fri-Mon Jul/24-Aug/3 (11d) @ Forchheim › Upper Franconia / Oberfranken › Bavaria / Bayern › Germany / Deutschland (de) › Central Europe › Europe 154 | in 32d Kulmbacher Bierwoche, Sat-Sun Jul/25-Aug/2 (9d) @ Kulmbach › Upper Franconia / Oberfranken › Bavaria / Bayern › Germany / Deutschland (de) › Central Europe › Europe 155 | in 58d Sandwerka (Sandkirchweih), Thu-Mon Aug/20-24 (5d) @ Bamberg › Upper Franconia / Oberfranken › Bavaria / Bayern › Germany / Deutschland (de) › Central Europe › Europe 156 | in 88d Oktoberfest ("Die Wiesn"), Sat-Sun Sep/19-Oct/4 (16d) @ Munich / München › Upper Bavaria / Oberbayern › Bavaria / Bayern › Germany / Deutschland (de) › Central Europe › Europe 157 | in 123d Biermesse Ried (Festival der Biervielfalt), Sat+Sun Oct/24+25 (2d) @ Ried i. Innkreis › Upper Austria / Oberösterreich › Austria / Österreich (at) › Central Europe › Europe 158 | ... 159 | ``` 160 | 161 | 162 | 163 | ## Do-It-Yourself (DIY) - Use Your Own Event Datasets 164 | 165 | Note: You can pass in local or remote datafiles in the markdown, yaml or csv formats 166 | instead of using the built-in / pre-configured datafiles. 167 | Example: 168 | 169 | ``` 170 | $ rubyconf https://github.com/planetruby/calendar/raw/master/_data/conferences2023.yml 171 | # - or - 172 | $ rubyconf conferences2023.yml # note: assumes a saved (local) copy in the working dir (./) 173 | 174 | $ pycon https://github.com/python-organizers/conferences/raw/master/2023.csv 175 | # - or 176 | $ pycon 2023.csv # note: assumes a saved (local) copy in the working dir (./) 177 | 178 | $ kickoff https://github.com/footballbook/calendar/raw/master/README.md 179 | # - or - 180 | $ kickoff README.md # note: assumes a saved (local) copy in the working dir (./) 181 | ``` 182 | 183 | 184 | 185 | ## `whatson` Command Line Tool 186 | 187 | Use the `whatson` command line tool as a "generic catch-all" to print any type of event. 188 | Example: 189 | 190 | ``` 191 | $ whatson https://github.com/planetruby/calendar/raw/master/_data/conferences2023.yml \ 192 | https://github.com/python-organizers/conferences/raw/master/2023.csv 193 | ``` 194 | 195 | Note: `whatson` is pre-configured (that is, if you do not pass along any datafiles) 196 | to print ongoing and upcoming ruby and python conferences. 197 | 198 | For easy (re)use you can write all datafiles in a text file and pass along the 199 | text file. Example - `conf.txt`: 200 | 201 | ``` 202 | ######################################## 203 | # conf.txt - What's On Datafiles 204 | 205 | https://github.com/planetruby/calendar/raw/master/_data/conferences2023.yml 206 | https://github.com/python-organizers/conferences/raw/master/2023.csv 207 | ``` 208 | 209 | And pass along to `whatson`. Example: 210 | 211 | ``` 212 | $ whatson conf.txt 213 | ``` 214 | 215 | 216 | Resulting back in 2020: 217 | 218 | ``` 219 | reading >conf.txt<... 220 | reading >https://github.com/planetruby/calendar/raw/master/_data/conferences2020.yml<... 221 | reading >https://github.com/python-organizers/conferences/raw/master/2020.csv<... 222 | 223 | 224 | Upcoming Events: 225 | 226 | in 60d Rubyfuza, Thu-Sat Feb/6-8 (3d) @ Cape Town, South Africa 227 | in 62d PyCascades, Sat+Sun Feb/8+9 (2d) @ Portland, Oregon, United States 228 | in 72d ParisRB Conf, Tue+Wed Feb/18+19 (2d) @ Paris, France 229 | in 72d PyCon Namibia, Tue-Thu Feb/18-20 (3d) @ Windhoek, Namibia 230 | ... 231 | ``` 232 | 233 | 234 | 235 | 236 | ## Public Event Datasets 237 | 238 | - [Calendar @ Planet Ruby](https://github.com/planetruby/calendar) - a collection of awesome Ruby events (meetups, conferences, camps, etc.) from around the world 239 | - [Calendar @ World Football Book](https://github.com/footballbook/calendar) - a collection of awesome football tournaments, cups, etc. from around the world 240 | - [Calendar @ World Beer Book](https://github.com/beerbook/calendar) - a collection of awesome beer events (oktoberfest, starkbierfest, etc.) from around the world 241 | 242 | 243 | 244 | 245 | ## Install 246 | 247 | Just install the gem: 248 | 249 | $ gem install whatson 250 | 251 | 252 | ## License 253 | 254 | The `whatson` scripts are dedicated to the public domain. 255 | Use it as you please with no restrictions whatsoever. 256 | 257 | 258 | ## Questions? Comments? 259 | 260 | Send them along to the ruby-talk mailing list. 261 | Thanks! 262 | -------------------------------------------------------------------------------- /eventdb/lib/eventdb/reader.rb: -------------------------------------------------------------------------------- 1 | 2 | 3 | module EventDb 4 | 5 | 6 | class EventReader 7 | 8 | Event = Struct.new( :title, :link, 9 | :place, 10 | :start_date, :end_date ) 11 | 12 | 13 | def self.read( path ) 14 | txt = if path.start_with?( 'http://' ) || 15 | path.start_with?( 'https://' ) 16 | worker = Fetcher::Worker.new 17 | worker.read_utf8!( path ) 18 | else 19 | File.open( path, 'r:utf-8' ).read 20 | end 21 | 22 | parser = if path.end_with?( '.yml') || 23 | path.end_with?( '.yaml') 24 | YamlParser.new( txt ) 25 | elsif path.end_with?( '.csv') 26 | CsvParser.new( txt ) 27 | elsif path.end_with?( '.txt') 28 | DatafileParser.new( txt ) 29 | else 30 | MarkdownParser.new( txt ) 31 | end 32 | parser.parse 33 | end 34 | 35 | 36 | class DatafileParser 37 | def self.parse( text ) new( text ).parse; end 38 | 39 | include LogUtils::Logging 40 | 41 | def initialize( text ) 42 | @text = text 43 | end 44 | 45 | def parse 46 | events = [] 47 | 48 | @text.each_line do |line| 49 | line = line.strip 50 | next if line.empty? ## skip empty lines 51 | next if line.start_with?( '#') ## skip comment lines 52 | 53 | ## todo/check: add inline comments too - why? why not? 54 | 55 | puts " reading >#{line}<..." 56 | events += EventReader.read( line ) 57 | end 58 | 59 | events 60 | end 61 | end # class DatafileParser 62 | 63 | 64 | class CsvParser 65 | def self.parse( text ) new( text ).parse; end 66 | 67 | 68 | include LogUtils::Logging 69 | 70 | def initialize( text ) 71 | @text = text 72 | end 73 | 74 | def parse 75 | events = [] 76 | recs = CsvHash.parse( @text, :header_converters => :symbol ) 77 | 78 | ## note: 79 | ## support python's conferences.csv 80 | ## subject => name / title 81 | ## website_url => url / link 82 | 83 | recs.each do |rec| 84 | title = rec[:name] || rec[:title] || rec[:subject] 85 | link = rec[:url] || rec[:link] || rec[:website_url] 86 | place = rec[:location] || rec[:place] 87 | 88 | start_date = Date.strptime( rec[:start] || rec[:start_date], '%Y-%m-%d' ) 89 | end_date = Date.strptime( rec[:end] || rec[:end_date], '%Y-%m-%d' ) 90 | 91 | event = Event.new( title, link, 92 | place, 93 | start_date, end_date ) 94 | ## pp event 95 | 96 | events << event 97 | end 98 | 99 | events 100 | end 101 | end # class CsvParser 102 | 103 | 104 | class YamlParser 105 | def self.parse( text ) new( text ).parse; end 106 | 107 | 108 | include LogUtils::Logging 109 | 110 | def initialize( text ) 111 | @text = text 112 | end 113 | 114 | def parse 115 | events = [] 116 | ## fix: unquoted dates e.g. 2022-11-27 no longer supported!! 117 | ## with YAML.safe_load 118 | ## 119 | ## quick fix: assume Pysch yaml parser 120 | ## and allow Date!!! 121 | recs = YAML.load( @text, permitted_classes: [Date] ) 122 | 123 | recs.each do |rec| 124 | title = rec['name'] || rec['title'] 125 | link = rec['url'] || rec['link'] 126 | place = rec['location'] || rec['place'] 127 | 128 | # note: already parsed into a date (NOT string) by yaml parser!! 129 | start_date = rec['start'] || rec['start_date'] 130 | end_date = rec['end'] || rec['end_date'] 131 | 132 | event = Event.new( title, link, 133 | place, 134 | start_date, end_date ) 135 | ## pp event 136 | 137 | events << event 138 | end 139 | 140 | events 141 | end 142 | end # class YamlReader 143 | 144 | 145 | class MarkdownParser 146 | def self.parse( text ) new( text ).parse; end 147 | 148 | 149 | include LogUtils::Logging 150 | 151 | def initialize( text ) 152 | @text = text 153 | end 154 | 155 | MONTH_EN_TO_MM = { 156 | 'Jan' => '1', 157 | 'Feb' => '2', 158 | 'Mar' => '3', 'March' => '3', 159 | 'Apr' => '4', 'April' => '4', 160 | 'May' => '5', 161 | 'Jun' => '6', 'June' => '6', 162 | 'Jul' => '7', 'July' => '7', 163 | 'Aug' => '8', 164 | 'Sep' => '9', 'Sept' => '9', 165 | 'Oct' => '10', 166 | 'Nov' => '11', 167 | 'Dec' => '12' } 168 | 169 | MONTH_EN = MONTH_EN_TO_MM.keys.join('|') # e.g. 'Jan|Feb|March|Mar|...' 170 | 171 | ## examples: 172 | ## - 2015 @ Salzburg, Austria; Oct/17+18 173 | ## - 2015 @ Brussels / Brussel / Bruxelles; Jan/31+Feb/1 174 | ## - 2014 @ Porto de Galinhas, Pernambuco; Apr/24-27 (formerly: Abril Pro Ruby) 175 | 176 | DATE_ENTRY_RE = /(?20\d\d) ## year 177 | \s+ 178 | @ ## at location 179 | \s+ 180 | [^;]+ ## use ; as separator between place and date 181 | ; 182 | \s+ 183 | (?#{MONTH_EN}) 184 | \/ 185 | (?[0-9]{1,2}) ## start date 186 | (?: 187 | [+\-] ## use + for two days, - for more than two days 188 | (?: 189 | (?#{MONTH_EN}) 190 | \/ 191 | )? ## optional end_month 192 | (?[0-9]{1,2}) 193 | )? ## optional end_date 194 | /x 195 | 196 | 197 | ## example: 198 | ## - [RubyWorld Conference - rubyworldconf](http://www.rubyworld-conf.org/en) 199 | 200 | LINK_ENTRY_RE = /\[ 201 | [^\]]+ 202 | \] 203 | \( 204 | [^\)]+ 205 | \) 206 | /x 207 | 208 | 209 | 210 | def parse 211 | events = [] 212 | stack = [] ## header/heading stack; note: last_stack is stack.size; starts w/ 0 213 | 214 | last_link_entry = nil 215 | 216 | 217 | nodes = OutlineReader.parse( @text ) 218 | nodes.each do |node| 219 | 220 | if [:h1,:h2,:h3,:h4,:h5,:h6].include?( node[0] ) 221 | heading = node[1] 222 | # stop when hitting >## More< or or etc. section 223 | # note: must escape # e.g. #{2,} must be escaped to \#{2,} 224 | break if heading =~ /^(More|Calendar|Thanks|Meta)\b/ 225 | 226 | # skip "pseudo" headings (for contribs etc.) 227 | ## e.g. #### _Contributions welcome. Anything missing? Send in a pull request. Thanks._ 228 | next if heading =~ /Contributions welcome\.|Anything Missing\?/ 229 | 230 | 231 | level = node[0][1].to_i 232 | 233 | logger.debug " heading level: #{level}, title: >#{heading}<" 234 | 235 | level_diff = level - stack.size 236 | 237 | if level_diff > 0 238 | logger.debug "[EventReader] up +#{level_diff}" 239 | if level_diff > 1 240 | logger.error "fatal: level step must be one (+1) is +#{level_diff}" 241 | fail "[EventReader] level step must be one (+1) is +#{level_diff}" 242 | end 243 | elsif level_diff < 0 244 | logger.debug "[EventReader] down #{level_diff}" 245 | level_diff.abs.times { stack.pop } 246 | stack.pop 247 | else 248 | ## same level 249 | stack.pop 250 | end 251 | stack.push( [level, heading] ) 252 | logger.debug " stack: #{stack.inspect}" 253 | 254 | elsif [:li].include?( node[0] ) ## list item 255 | line = node[1] 256 | 257 | if LINK_ENTRY_RE.match( line ) 258 | logger.debug " link entry: #{line}" 259 | 260 | last_link_entry = line 261 | elsif m=DATE_ENTRY_RE.match( line ) 262 | year = m[:year] 263 | 264 | start_month_en = m[:start_month_en] 265 | start_day = m[:start_day] 266 | 267 | start_month = MONTH_EN_TO_MM[ start_month_en ] 268 | start_date = Date.new( year.to_i, start_month.to_i, start_day.to_i ) 269 | 270 | 271 | end_month_en = m[:end_month_en] 272 | end_month_en = start_month_en if end_month_en.nil? # no end month; use same as start 273 | 274 | end_day = m[:end_day] 275 | end_day = start_day if end_day.nil? # no end day; single day event (use start day) 276 | 277 | end_month = MONTH_EN_TO_MM[ end_month_en ] 278 | end_date = Date.new( year.to_i, end_month.to_i, end_day.to_i ) 279 | 280 | ## pp start_date 281 | 282 | logger.debug " date entry: #{line}" 283 | logger.debug " start_date: #{start_date}, year: #{year}, start_month_en: #{start_month_en}, start_month: #{start_month} start_day: #{start_day} => #{last_link_entry}" 284 | logger.debug " end_date: #{end_date}, end_month_en: #{end_month_en}, end_day_en: #{end_day}" 285 | 286 | 287 | s = StringScanner.new( line ) 288 | s.skip_until( /@/ ) 289 | 290 | place = s.scan( /[^;]+/ ) ## get place (everything until ; (separator)) 291 | place = place.strip 292 | logger.debug " place: #{place}, rest: >#{s.rest}<" 293 | 294 | ## todo/fix: make place uniform e.g. change 295 | ## Vienna, Austria => 296 | ## Vienna › Austria - why? why not? 297 | 298 | ## note: cut of heading 1 (e.g. page title) 299 | more_places = stack[1..-1].reverse.map {|it| it[1] }.join(', ') ## was: join(' › ') 300 | place = "#{place}, #{more_places}" 301 | logger.debug " place: #{place}" 302 | 303 | 304 | title, link = find_title_and_link( last_link_entry ) 305 | 306 | 307 | event = Event.new( title, link, 308 | place, 309 | start_date, end_date ) 310 | ## pp event 311 | 312 | events << event 313 | else 314 | logger.debug " *** skip list item line: #{line}" 315 | end 316 | else 317 | logger.debug " *** skip node:" 318 | pp node 319 | end 320 | end 321 | 322 | events 323 | end 324 | 325 | ### helper 326 | def find_title_and_link( line ) 327 | title = nil 328 | link = nil 329 | 330 | ## note: extract title and link from line 331 | 332 | ### 1) try "new" format first e.g. 333 | ## - **European Ruby Konference - EuRuKo** (web: [euruko.org](http://euruko.org), t: [euruko](https://twitter.com/euruko)) - _since 2003_ 334 | if m = (line =~ /^\*{2}([^*]+)\*{2}/) ## note: **title** must start line 335 | title = $1 336 | puts " adding (new/modern format) => #{title}" 337 | ## 2) try "old" classic format - get title from first (markdown) link e.g. 338 | ## - [Oktoberfest ("Die Wiesn")](http://www.muenchen.de/veranstaltungen/oktoberfest.html) 339 | elsif m = (line =~ /^\[([^\]]+)\]/) ## note: [title](link) must start line 340 | title = $1 341 | puts " adding (old/classic format) => #{title}" 342 | else 343 | puts "*** !! ERROR !!: cannot find event title in #{line}" 344 | exit 1 345 | end 346 | 347 | ## try extract link - use first (markdown) link 348 | ## todo/fix: use shared markdown link regex!!!!! 349 | if m = (line =~ /\[[^\]]+\]\(([^\)]+)\)/) 350 | link = $1 351 | puts " => @ #{link}" 352 | else 353 | link = nil 354 | puts "*** !! WARN !!: cannot find event link in #{line}" 355 | end 356 | 357 | [title,link] 358 | end # method find_title_and_link 359 | end # class MarkdownReader 360 | 361 | end # class EventReader 362 | end # module EventDb 363 | --------------------------------------------------------------------------------