footty 2024.8.28 → 2024.9.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2866ba25c1b7a6d08787aaff2bff8821bbc92dada92bcc85ad084b65ceace8b9
4
- data.tar.gz: bad3de36a89de81e96565aa3c5c245d5cc53b56ea2faddfae38a0e8810f565e2
3
+ metadata.gz: 2254b1fa1cf0832e403b6bc0e6509d1ffee06e0f552fec2b805b124c0a867c0d
4
+ data.tar.gz: 8c8182dabe0e72801b580e46bed8471baacd01080fedac360b2532b63673d9cb
5
5
  SHA512:
6
- metadata.gz: fabcae4fbe59527bfb4dc35555d0ffa87271240a8ee385a6ea26842d3d268d58b4d6109ebee9159c362b1327447e5d36fae63b2e51f07931d32e5578103d7a70
7
- data.tar.gz: df46117a0ab611d90315a17525308f71bd82aac6b00c2a07388e115d92381efdf2f8d339e98311278a80b8b68e3f83283b2eaef3d9ee7ab2c01f753a252d90c5
6
+ metadata.gz: 3e7421b9f2bf8ec572a55075970301343604a4dbaaabfeceec10827df9a712184fa9372a72c34e0f79811a4ae47b8a773115916e0e195d46def89a9e509b509d
7
+ data.tar.gz: 4ef82377e9caead4e3ec0048b8eac6120fe77c8de4018e69e74faec2842f33909626234a5bc2ccef137661f999c7825f9ef834c64cab292bcf4e9c357467d645
data/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- ### 2024.8.28
1
+ ### 2024.9.27
2
2
  ### 1.0.0 / 2018-06-09
3
3
 
4
4
  * Everything is new (again). First release.
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
- # footty - football.db command line client for european ("euro") championship 2024 and more
1
+ # footty - football.db command line tool for national & int'l football club leagues (& cups) from around the world (bonus - incl. world cup, euro and more)
2
+
2
3
 
3
4
  * home :: [github.com/sportdb/footty](https://github.com/sportdb/footty)
4
5
  * bugs :: [github.com/sportdb/footty/issues](https://github.com/sportdb/footty/issues)
@@ -11,15 +12,27 @@
11
12
 
12
13
  ## Usage - Who's playing today?
13
14
 
14
- The footty command line tool lets you query the online football.db HTTP JSON API services
15
+ The footty command line tool lets you query the online football.db via HTTP
15
16
  for upcoming or past matches. For example:
16
17
 
17
- $ footty # Defaults to today's euro 2024 matches
18
+ $ footty # Defaults to today's English Premier League 2024/25 matches
19
+
20
+ prints on Sep 27, 2024:
21
+
22
+ Upcoming matches:
23
+ Sat Sep/28 12:30 (in 1d) Newcastle United FC vs Manchester City FC Matchday 6
24
+ Sat Sep/28 15:00 (in 1d) Arsenal FC vs Leicester City FC Matchday 6
25
+ Sat Sep/28 15:00 (in 1d) Brentford FC vs West Ham United FC Matchday 6
26
+ Sat Sep/28 15:00 (in 1d) Chelsea FC vs Brighton & Hove Albion Matchday 6
27
+ Sat Sep/28 15:00 (in 1d) Everton FC vs Crystal Palace FC Matchday 6
28
+ Sat Sep/28 15:00 (in 1d) Nottingham Forest FC vs Fulham FC Matchday 6
29
+ Sat Sep/28 17:30 (in 1d) Wolverhampton Wanderers FC vs Liverpool FC Matchday 6
30
+ Sun Sep/29 14:00 (in 2d) Ipswich Town FC vs Aston Villa FC Matchday 6
31
+ Sun Sep/29 16:30 (in 2d) Manchester United FC vs Tottenham Hotspur FC Matchday 6
32
+ Mon Sep/30 20:00 (in 3d) AFC Bournemouth vs Southampton FC Matchday 6
33
+
18
34
 
19
- prints on Jun/14 2024:
20
35
 
21
- #1 Fri Jun/14 Germany (GER) vs Scotland (SCO) Group A / Matchday 1
22
-
23
36
  Use `tomorrow` or `t` or `+1` to print tomorrow's matches e.g.:
24
37
 
25
38
  $ footty tomorrow # -or-
@@ -41,9 +54,34 @@ Use `past` or `p` to print all past matches e.g.:
41
54
  $ footty p
42
55
 
43
56
 
57
+
44
58
  That's it. Enjoy the beautiful game.
45
59
 
46
60
 
61
+ ## Bonus - More Leagues & Cups - Bundesliga, Serie A, Ligue 1, La Liga & More
62
+
63
+ Pass in the league code to display the Germand Bundesliga, Spanish La Liga, etc:
64
+
65
+ $ footty de # who's playing in the bundesliga today?
66
+ $ footty es # who's playing in la liga today?
67
+ ...
68
+
69
+ League codes include:
70
+
71
+ - `de` => Bundesliga
72
+ - `es` => La Liga
73
+ - `it` => Serie A
74
+ - `fr` => Ligue 1
75
+ - ...
76
+
77
+ More
78
+
79
+ - `world` => World Cup
80
+ - `euro` => "Euro" - European Championship
81
+
82
+ See [footty/dataset](https://github.com/sportdb/footty/blob/master/lib/footty/dataset.rb) for the complete built-in list of data sources (and league keys).
83
+
84
+
47
85
 
48
86
 
49
87
  ## Trivia
@@ -66,7 +104,6 @@ Use it as you please with no restrictions whatsoever.
66
104
 
67
105
 
68
106
 
69
-
70
107
  ## Questions? Comments?
71
108
 
72
109
  Yes, you can. More than welcome.
data/Rakefile CHANGED
@@ -2,23 +2,23 @@ require 'hoe'
2
2
  require './lib/footty/version.rb'
3
3
 
4
4
  Hoe.spec 'footty' do
5
-
6
5
  self.version = Footty::VERSION
7
6
 
8
- self.summary = 'footty - football.db command line client for european "euro" championship 2024 and more - who is playing today?'
7
+ self.summary = "footty - football.db command line tool for national & int'l football club leagues (& cups) from around the world (bonus - incl. world cup, euro and more)"
9
8
  self.description = summary
10
9
 
11
10
  self.urls = { home: 'https://github.com/sportdb/footty' }
12
11
 
13
12
  self.author = 'Gerald Bauer'
14
- self.email = 'gerald.bauer@gmail.com'
13
+ self.email = 'gerald.bauer@gmail.com'
15
14
 
16
15
  # switch extension to .markdown for gihub formatting
17
16
  self.readme_file = 'README.md'
18
17
  self.history_file = 'CHANGELOG.md'
19
18
 
20
19
  self.extra_deps = [
21
- ['sportdb-quick']
20
+ ['sportdb-quick', '>= 0.2.0'],
21
+ ['webget'],
22
22
  ]
23
23
 
24
24
  self.licenses = ['Public Domain']
@@ -1,49 +1,106 @@
1
1
  module Footty
2
2
 
3
3
 
4
-
5
4
  class Dataset
5
+ SOURCES = {
6
+ 'world' => { '2022' => [ 'worldcup/2022--qatar/cup.txt',
7
+ 'worldcup/2022--qatar/cup_finals.txt'],
8
+ '2018' => [ 'worldcup/2018--russia/cup.txt',
9
+ 'worldcup/2018--russia/cup_finals.txt']
10
+ },
11
+ 'euro' => { '2024' => 'euro/2024--germany/euro.txt',
12
+ '2021' => 'euro/2021--europe/euro.txt'
13
+ },
14
+ 'de' => 'deutschland/$season$/1-bundesliga.txt',
15
+ 'de2' => 'deutschland/$season$/2-bundesliga2.txt',
16
+ 'en'=> 'england/$season$/1-premierleague.txt',
17
+ 'es'=> 'espana/$season$/1-liga.txt',
18
+ 'it'=> 'italy/$season$/1-seriea.txt',
19
+ 'at'=> 'austria/$season$/1-bundesliga.txt',
20
+ 'at2' => 'austria/$season$/2-liga2.txt',
21
+ 'at3o' => 'austria/$season$/3-regionalliga-ost.txt',
22
+ 'atcup' => 'austria/$season$/cup.txt',
23
+
24
+ 'fr'=> 'europe/france/$season$/1-ligue1.txt',
25
+ 'nl'=> 'europe/netherlands/$season$/1-eredivisie.txt',
26
+ 'be'=> 'europe/belgium/$season$/1-firstdivisiona.txt',
27
+
28
+ 'champs'=> 'champions-league/$season$/cl.txt',
29
+
30
+ 'br' => 'south-america/brazil/$year$/1-seriea.txt',
31
+ 'ar' => 'south-america/argentina/$year$/1-primeradivision.txt',
32
+ 'co' => 'south-america/colombia/$year$/1-primeraa.txt',
33
+ ## use a different code for copa libertadores? why? why not?
34
+ 'copa' => 'south-america/copa-libertadores/$year$/libertadores.txt',
35
+
36
+ 'mx' => 'mexico/$season$/1-ligamx.txt',
37
+
38
+ 'eg' => 'africa/egypt/$season$/1-premiership.txt',
39
+ 'ma' => 'africa/morocco/$season$/1-botolapro1.txt',
40
+ }
41
+
6
42
 
7
- def initialize( league:, year: )
43
+ ## return built-in league keys
44
+ def self.leagues() SOURCES.keys; end
45
+
46
+
47
+ def initialize( league:, year: nil )
8
48
  @league = league
9
- @year = year
10
- @season = Season( "#{year}/#{year+1}" )
49
+
50
+ spec = SOURCES[ @league.downcase ]
51
+ urls = if spec.is_a?( Hash ) ## assume lookup by year
52
+ if year.nil? ## lookup default first entry
53
+ year = spec.keys[0].to_i
54
+ spec.values[0]
55
+ else
56
+ spec[ year.to_s ]
57
+ end
58
+ else ## assume vanilla urls (no lookup by year)
59
+ ## default to 2024 for now
60
+ year = 2024 if year.nil?
61
+ spec
62
+ end
63
+ raise ArgumentError, "no dataset (source) for league #{league} found" if urls.nil?
64
+
65
+ ## wrap single sources (strings) in array
66
+ urls = urls.is_a?( Array ) ? urls : [urls]
67
+ ## expand shortened url and fill-in template vars
68
+ @urls = urls.map { |url| openfootball_url( url, year: year ) }
11
69
  end
12
70
 
13
71
 
14
- APIS = {
15
- world: 'https://raw.githubusercontent.com/openfootball/worldcup.json/master/$year$/worldcup.json',
16
- euro: 'https://raw.githubusercontent.com/openfootball/euro.json/master/$year$/euro.json',
17
- de: 'https://raw.githubusercontent.com/openfootball/deutschland/master/$season$/1-bundesliga.txt',
18
- en: 'https://raw.githubusercontent.com/openfootball/england/master/$season$/1-premierleague.txt',
19
- at: 'https://raw.githubusercontent.com/openfootball/austria/master/$season$/1-bundesliga-i.txt',
20
- }
72
+ def openfootball_url( path, year: )
73
+ repo, local_path = path.split( '/', 2)
74
+ url = "https://raw.githubusercontent.com/openfootball/#{repo}/master/#{local_path}"
75
+ ## check for template vars too
76
+ season = Season( "#{year}/#{year+1}" )
77
+ url = url.gsub( '$year$', year.to_s )
78
+ url = url.gsub( '$season$', season.to_path )
79
+ url
80
+ end
81
+
21
82
 
22
83
  ### note:
23
84
  ## cache ALL methods - only do one web request for match schedule & results
24
85
  def matches
25
86
  @data ||= begin
26
- url = APIS[ @league.downcase.to_sym ]
27
- url = url.gsub( '$year$', @year.to_s )
28
- url = url.gsub( '$season$', @season.to_path )
29
-
30
- res = get!( url ) ## use "memoized" / cached result
31
- if url.end_with?( '.json' )
32
- JSON.parse( res.text )
33
- else ## assume football.txt format
34
- matches = SportDb::QuickMatchReader.parse( res.text )
35
- data = matches.map {|match| match.as_json } # convert to json
36
- ## quick hack to get keys as strings not symbols!!
37
- ## fix upstream
38
- JSON.parse( JSON.generate( data ))
87
+ matches = []
88
+ @urls.each do |url|
89
+ txt = get!( url ) ## use "memoized" / cached result
90
+ matches += SportDb::QuickMatchReader.parse( txt )
39
91
  end
92
+ data = matches.map {|match| match.as_json } # convert to json
93
+ ## quick hack to get keys as strings not symbols!!
94
+ ## fix upstream
95
+ JSON.parse( JSON.generate( data ))
40
96
  end
41
97
  end
42
98
 
99
+
43
100
  def end_date
44
101
  @end_date ||= begin
45
102
  end_date = nil
46
- each do |match|
103
+ matches.each do |match|
47
104
  date = Date.strptime(match['date'], '%Y-%m-%d' )
48
105
  end_date = date if end_date.nil? ||
49
106
  date > end_date
@@ -55,7 +112,7 @@ module Footty
55
112
  def start_date
56
113
  @start_date ||= begin
57
114
  start_date = nil
58
- each do |match|
115
+ matches.each do |match|
59
116
  date = Date.strptime(match['date'], '%Y-%m-%d' )
60
117
  start_date = date if start_date.nil? ||
61
118
  date < start_date
@@ -89,54 +146,44 @@ module Footty
89
146
  def past_matches( date: Date.today )
90
147
  matches = select_matches { |match| date > Date.parse( match['date'] ) }
91
148
  ## note reveserve matches (chronological order/last first)
92
- matches.reverse
149
+ ## matches.reverse
150
+ matches
93
151
  end
94
152
 
95
153
 
96
154
  private
97
- def each
98
- data = matches
99
- if data.is_a?( Hash) && data.has_key?('rounds')
100
- data['rounds'].each do |round|
101
- round['matches'].each do |match|
102
- ## hack: add (outer) round to match
103
- match['round'] = round['name']
104
- yield( match )
105
- end
106
- end
107
- else ## assume flat matches in Array
108
- data.each do |match|
109
- yield( match )
110
- end
111
- end
112
- end
113
-
114
-
115
- def select_matches
116
- matches = []
117
- each do |match|
118
- matches << match if yield( match )
155
+ def select_matches( &blk)
156
+ selected = []
157
+ matches.each do |match|
158
+ selected << match if blk.call( match )
119
159
  end
120
160
 
121
161
  ## todo/fix:
122
162
  ## sort matches here; might not be chronologicial (by default)
123
- matches
163
+ selected
124
164
  end # method select_matches
125
165
 
126
166
 
127
- def get!( url )
128
- response = Webclient.get( url )
129
167
 
130
- if response.status.ok?
131
- response
132
- else
133
- puts "!! HTTP ERROR - #{response.status.code} #{response.status.message}"
134
- ## dump headers
135
- response.headers.each do |key,value|
136
- puts " #{key}: #{value}"
137
- end
138
- exit 1
139
- end
140
- end # method get!
141
- end # class Client
168
+ def get!( url )
169
+ ## use cached urls for 12h by default
170
+ ## if expired in cache (or not present) than get/fetch
171
+ if Webcache.expired_in_12h?( url )
172
+ response = Webget.text( url )
173
+
174
+ if response.status.ok?
175
+ response.text # note - return text (utf-8)
176
+ else
177
+ ## dump headers
178
+ response.headers.each do |key,value|
179
+ puts " #{key}: #{value}"
180
+ end
181
+ puts "!! HTTP ERROR - #{response.status.code} #{response.status.message}"
182
+ exit 1
183
+ end
184
+ else
185
+ Webcache.read( url )
186
+ end
187
+ end # method get_txt!
188
+ end # class Dataset
142
189
  end # module Footty
@@ -1,6 +1,6 @@
1
1
 
2
2
  module Footty
3
- VERSION = '2024.8.28'
3
+ VERSION = '2024.9.27'
4
4
 
5
5
  def self.banner
6
6
  "footty/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
data/lib/footty.rb CHANGED
@@ -1,29 +1,34 @@
1
1
  require 'sportdb/quick' ## note - pulls in cocos et al
2
-
2
+ require 'webget' ## add webcache support
3
3
 
4
4
  # our own code
5
5
  require_relative 'footty/version' # let it always go first
6
6
  require_relative 'footty/dataset'
7
7
 
8
8
 
9
- module Footty
10
9
 
11
- def self.main
10
+ ## set cache to local .cache dir for now - why? why not?
11
+ Webcache.root = './cache'
12
+ # pp Webcache.root
13
+ Webget.config.sleep = 1 ## set delay in secs (to 1 sec - default is/maybe 3)
14
+
15
+
16
+ module Footty
17
+ def self.main( args=ARGV )
12
18
  puts banner # say hello
13
19
 
14
20
  league = 'en'
15
- year = 2024
21
+ year = nil
22
+
23
+ leagues = Dataset.leagues ## e.g. ['world','euro',
24
+ ## 'de','en','at']
16
25
 
17
- ## filter ARGV for league or year
18
- args = ARGV.select do |arg|
26
+ ## filter args for league or year
27
+ args = args.select do |arg|
19
28
  if arg =~ /^\d{4}$/
20
29
  year = arg.to_i(10)
21
30
  false ## eat-up
22
- elsif ['world',
23
- 'euro',
24
- 'de',
25
- 'en',
26
- 'at'].include?( arg )
31
+ elsif leagues.include?( arg )
27
32
  league = arg
28
33
  false
29
34
  else
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: footty
3
3
  version: !ruby/object:Gem::Version
4
- version: 2024.8.28
4
+ version: 2024.9.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-28 00:00:00.000000000 Z
11
+ date: 2024-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sportdb-quick
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: webget
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - ">="
@@ -58,8 +72,8 @@ dependencies:
58
72
  - - "~>"
59
73
  - !ruby/object:Gem::Version
60
74
  version: '4.1'
61
- description: footty - football.db command line client for european "euro" championship
62
- 2024 and more - who is playing today?
75
+ description: footty - football.db command line tool for national & int'l football
76
+ club leagues (& cups) from around the world (bonus - incl. world cup, euro and more)
63
77
  email: gerald.bauer@gmail.com
64
78
  executables:
65
79
  - footty
@@ -103,6 +117,6 @@ requirements: []
103
117
  rubygems_version: 3.4.10
104
118
  signing_key:
105
119
  specification_version: 4
106
- summary: footty - football.db command line client for european "euro" championship
107
- 2024 and more - who is playing today?
120
+ summary: footty - football.db command line tool for national & int'l football club
121
+ leagues (& cups) from around the world (bonus - incl. world cup, euro and more)
108
122
  test_files: []