footty 2024.8.28 → 2024.9.27

Sign up to get free protection for your applications and to get access to all the features.
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: []