tlaw 0.0.2 → 0.1.0.pre

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +18 -2
  4. data/README.md +10 -7
  5. data/examples/demo_base.rb +2 -2
  6. data/examples/experimental/README.md +3 -0
  7. data/examples/experimental/afterthedeadline.rb +22 -0
  8. data/examples/experimental/airvisual.rb +14 -0
  9. data/examples/experimental/apixu.rb +32 -0
  10. data/examples/experimental/bing_maps.rb +18 -0
  11. data/examples/experimental/currencylayer.rb +25 -0
  12. data/examples/experimental/earthquake.rb +29 -0
  13. data/examples/experimental/freegeoip.rb +16 -0
  14. data/examples/experimental/geonames.rb +98 -0
  15. data/examples/experimental/isfdb.rb +17 -0
  16. data/examples/experimental/musicbrainz.rb +27 -0
  17. data/examples/experimental/nominatim.rb +52 -0
  18. data/examples/experimental/omdb.rb +68 -0
  19. data/examples/experimental/open_exchange_rates.rb +36 -0
  20. data/examples/experimental/open_route.rb +27 -0
  21. data/examples/experimental/open_street_map.rb +16 -0
  22. data/examples/experimental/quandl.rb +50 -0
  23. data/examples/experimental/reddit.rb +25 -0
  24. data/examples/experimental/swapi.rb +27 -0
  25. data/examples/experimental/tmdb.rb +53 -0
  26. data/examples/experimental/world_bank.rb +85 -0
  27. data/examples/experimental/world_bank_climate.rb +77 -0
  28. data/examples/experimental/wunderground.rb +66 -0
  29. data/examples/experimental/wunderground_demo.rb +7 -0
  30. data/examples/forecast_io.rb +16 -16
  31. data/examples/giphy.rb +4 -4
  32. data/examples/giphy_demo.rb +1 -1
  33. data/examples/open_weather_map.rb +64 -60
  34. data/examples/open_weather_map_demo.rb +4 -4
  35. data/examples/tmdb_demo.rb +1 -1
  36. data/examples/urbandictionary_demo.rb +2 -2
  37. data/lib/tlaw.rb +14 -15
  38. data/lib/tlaw/api.rb +108 -26
  39. data/lib/tlaw/api_path.rb +86 -87
  40. data/lib/tlaw/data_table.rb +15 -10
  41. data/lib/tlaw/dsl.rb +126 -224
  42. data/lib/tlaw/dsl/api_builder.rb +47 -0
  43. data/lib/tlaw/dsl/base_builder.rb +108 -0
  44. data/lib/tlaw/dsl/endpoint_builder.rb +26 -0
  45. data/lib/tlaw/dsl/namespace_builder.rb +86 -0
  46. data/lib/tlaw/endpoint.rb +63 -85
  47. data/lib/tlaw/formatting.rb +55 -0
  48. data/lib/tlaw/formatting/describe.rb +86 -0
  49. data/lib/tlaw/formatting/inspect.rb +52 -0
  50. data/lib/tlaw/namespace.rb +141 -98
  51. data/lib/tlaw/param.rb +45 -141
  52. data/lib/tlaw/param/type.rb +36 -49
  53. data/lib/tlaw/response_processors.rb +81 -0
  54. data/lib/tlaw/util.rb +16 -33
  55. data/lib/tlaw/version.rb +6 -3
  56. data/tlaw.gemspec +9 -9
  57. metadata +63 -13
  58. data/lib/tlaw/param_set.rb +0 -111
  59. data/lib/tlaw/response_processor.rb +0 -126
@@ -0,0 +1,68 @@
1
+ require_relative '../demo_base'
2
+ #http://docs.themoviedb.apiary.io/#reference/movies/movielatest
3
+
4
+ class OMDB < TLAW::API
5
+ define do
6
+ base 'http://www.omdbapi.com'
7
+ param :api_key, field: :apikey, required: true
8
+
9
+ SPLIT = ->(v) { v.split(/\s*,\s*/) }
10
+
11
+ shared_def :imdb do
12
+ post_process('imdbRating', &:to_f)
13
+ post_process('imdbVotes') { |v| v.gsub(',', '').to_i }
14
+ end
15
+
16
+ post_process do |response|
17
+ response.delete('Response') == 'False' and fail(response['Error'])
18
+ end
19
+
20
+ endpoint :by_id, path: '/?i={imdb_id}' do
21
+ param :imdb_id, required: true
22
+
23
+ param :type, enum: %i[movie series episode]
24
+ param :year, :to_i, field: :y
25
+ param :plot, enum: %i[short full]
26
+ param :tomatoes, enum: [true, false]
27
+
28
+ post_process('Released', &Date.method(:parse))
29
+ post_process('totalSeasons', &:to_i)
30
+ use_def :imdb
31
+ end
32
+
33
+ endpoint :by_title, path: '/?t={title}' do
34
+ param :title, required: true
35
+
36
+ param :type, enum: %i[movie series episode]
37
+ param :year, :to_i, field: :y
38
+ param :plot, enum: %i[short full]
39
+ param :tomatoes, enum: [true, false]
40
+
41
+ post_process('Released', &Date.method(:parse))
42
+ use_def :imdb
43
+
44
+ post_process('Metascore', &:to_i)
45
+
46
+ post_process('totalSeasons', &:to_i)
47
+
48
+ post_process('Genre', &SPLIT)
49
+ post_process('Country', &SPLIT)
50
+ post_process('Writer', &SPLIT)
51
+ post_process('Actors', &SPLIT)
52
+ end
53
+
54
+ endpoint :search, path: '/?s={search}' do
55
+ param :search, required: true
56
+
57
+ param :type, enum: %i[movie series episode]
58
+ param :year, :to_i, field: :y
59
+ param :page, :to_i
60
+ end
61
+ end
62
+ end
63
+
64
+ o = OMDB.new(api_key: ENV.fetch('OMDB'))
65
+
66
+ #pp o.by_id("tt0944947")
67
+ pp o.by_title('Suicide Squad', tomatoes: true, plot: :full)
68
+ #pp o.search('Game of')['Search'].first
@@ -0,0 +1,36 @@
1
+ require_relative '../demo_base'
2
+
3
+ class OpenExchangeRate < TLAW::API
4
+ define do
5
+ base 'https://openexchangerates.org/api'
6
+
7
+ param :app_id, required: true
8
+
9
+ post_process { |h|
10
+ h['rates'] = h
11
+ .select { |k, v| k.start_with?('rates.') }
12
+ .map { |k, v| {'to' => k.sub('rates.', ''), 'rate' => v} }
13
+
14
+ h.reject! { |k, v| k.start_with?('rates.') }
15
+ }
16
+ post_process 'timestamp', &Time.method(:at)
17
+
18
+ endpoint :currencies, path: '/currencies.json'
19
+
20
+ endpoint :latest, path: '/latest.json'
21
+
22
+ endpoint :historical, path: '/historical/{date}.json' do
23
+ param :date, :to_date, format: ->(v) { v.strftime('%Y-%m-%d') }
24
+ end
25
+
26
+ endpoint :usage, path: '/usage.json'
27
+ end
28
+ end
29
+
30
+ api = OpenExchangeRate.new(app_id: ENV['OPEN_EXCHANGE_RATES'])
31
+
32
+ #pp api.latest['rates'].first(3)
33
+ #pp api.historical(Date.parse('2016-05-01'))['rates'].detect { |r| r['to'] == 'INR' } #, base: 'USD')
34
+ #pp api.convert(100, 'INR', 'USD')
35
+ #pp api.usage
36
+ pp api.latest['rates'].detect { |r| r['to'] == 'INR' }
@@ -0,0 +1,27 @@
1
+ require_relative '../demo_base'
2
+ require 'geo/coord'
3
+
4
+ class OpenRouteService < TLAW::API
5
+ define do
6
+ base 'https://api.openrouteservice.org'
7
+
8
+ param :api_key
9
+
10
+ endpoint :directions do
11
+ post_process { |res|
12
+ res['route'] = res['routes'].first
13
+ }
14
+ param :coordinates, :to_a, keyword: false,
15
+ format: ->(coords) { coords.map { |c| c.latlng.join(',') }.join('|') }
16
+ param :profile
17
+ param :geometry
18
+ param :geometry_format
19
+ end
20
+ end
21
+ end
22
+
23
+ osm = OpenRouteService.new(api_key: ENV['OPEN_ROUTE_SERVICE'])
24
+ kharkiv = Geo::Coord.new(50.004444,36.231389)
25
+ kyiv = Geo::Coord.new(50.450000,30.523333)
26
+
27
+ pp osm.directions([kharkiv, kyiv], profile: 'driving-car', geometry_format: 'geojson')['route.segments'].first['steps']
@@ -0,0 +1,16 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class OpenStreetMap < TLAW::API
7
+ define do
8
+ base 'http://api.openstreetmap.org/api/0.6'
9
+
10
+ endpoint :relation, '/relation/{id}', xml: true
11
+ end
12
+ end
13
+
14
+ osm = OpenStreetMap.new
15
+
16
+ pp osm.relation(1543125)["osm.relation.tag"].to_a
@@ -0,0 +1,50 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ # https://www.quandl.com/docs/api?json#get-data
7
+ class Quandl < TLAW::API
8
+ define do
9
+ base 'https://www.quandl.com/api/v3'
10
+
11
+ param :api_key, required: true
12
+
13
+ namespace :databases do
14
+ endpoint :list, path: '.json' do
15
+ param :per_page, :to_i
16
+ end
17
+
18
+ endpoint :search, '.json?query={query}' do
19
+ param :query, required: true
20
+ end
21
+
22
+ namespace :[], '/{code}' do
23
+ endpoint :meta, '.json'
24
+ endpoint :codes, '/codes.csv'
25
+
26
+ namespace :datasets, '/../../datasets/{code}' do
27
+ endpoint :[], '/{dataset_code}.json' do
28
+ param :code
29
+
30
+ post_process { |h|
31
+ columns = h['dataset.column_names']
32
+ h['dataset.data'] = h['dataset.data']
33
+ .map { |r| columns.zip(r).to_h }
34
+ }
35
+
36
+ post_process_items 'dataset.data' do
37
+ post_process 'Date', &Date.method(:parse)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ q = Quandl.new(api_key: ENV['QUANDL'])
47
+
48
+ #pp q.databases.search('ukraine')['databases'].first
49
+ pp q.databases['WIKI'].datasets['AAPL', code: 'WIKI']['dataset.data']['Date'].min
50
+ #pp q.databases['WIKI'].datasets.endpoint(:[]).construct_template
@@ -0,0 +1,25 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class Reddit < TLAW::API
7
+ define do
8
+ base 'https://www.reddit.com'
9
+
10
+ post_process_items 'data.children' do
11
+ post_process("data.permalink") { |v| "https://www.reddit.com#{v}" }
12
+ post_process("data.created", &Time.method(:at))
13
+ end
14
+
15
+ namespace :r, '/r/{subreddit}' do
16
+ endpoint :new, '/new.json' do
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ r = Reddit.new
23
+ res = r.r(:ruby).new
24
+ p res['data.children']['data.ups']
25
+ p res['data.children']['data.num_comments']
@@ -0,0 +1,27 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class SWAPI < TLAW::API
7
+ define do
8
+ base 'http://swapi.co/api'
9
+
10
+ namespace :people do
11
+ endpoint :all, ''
12
+ endpoint :[], '/{id}/'
13
+ endpoint :search, '/?search={query}'
14
+ end
15
+
16
+ namespace :species do
17
+ endpoint :all, ''
18
+ endpoint :[], '/{id}/'
19
+ endpoint :search, '/?search={query}'
20
+ end
21
+ end
22
+ end
23
+
24
+ s = SWAPI.new
25
+
26
+ pp s.people.search('r2')['results'].first
27
+ pp s.species[2]
@@ -0,0 +1,53 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ #http://docs.themoviedb.apiary.io/#reference/movies/movielatest
7
+
8
+ class TMDB < TLAW::API
9
+ define do
10
+ base 'http://api.themoviedb.org/3'
11
+ param :api_key, required: true
12
+ param :language, default: 'en'
13
+
14
+ namespace :movies, '/movie' do
15
+ namespace :[], '/{id}' do
16
+ param :id, required: true
17
+
18
+ endpoint :get, ''
19
+
20
+ endpoint :alt_titles
21
+
22
+ endpoint :images
23
+ end
24
+
25
+ endpoint :latest
26
+ endpoint :now_playing do
27
+ param :page, :to_i, default: 1 # TODO: validate: 1..1000
28
+ end
29
+
30
+ endpoint :upcoming
31
+ end
32
+
33
+ namespace :search do
34
+ endpoint :movie do
35
+ param :query, required: true, keyword: false
36
+
37
+ #post_process_items 'results', 'release_date', &Date.method(:parse)
38
+ # TODO: post-process image pathes!
39
+ end
40
+ end
41
+
42
+ # TODO: should work!
43
+ #post_process_items 'results', 'release_date', &Date.method(:parse)
44
+ end
45
+ end
46
+
47
+ tmdb = TMDB.new(api_key: ENV['TMDB'], language: 'uk')
48
+
49
+ #pp tmdb.movies.upcoming['results'].columns(:release_date, :title).to_a
50
+ #pp tmdb.movies[413898].images
51
+ #p tmdb.describe
52
+ #pp tmdb.search.movie('Terminator')['results'].first
53
+ p tmdb.movies[1187043].get
@@ -0,0 +1,85 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class WorldBank < TLAW::API
7
+ define do
8
+ base 'http://api.worldbank.org'
9
+
10
+ post_process_replace { |response|
11
+ if response.is_a?(Array) && response.size == 1 && response.first.is_a?(Hash)
12
+ response.first
13
+ elsif response.is_a?(Array) && response.size == 2
14
+ {'meta' => response.first, 'data' => response.last}
15
+ else
16
+ response
17
+ end
18
+ }
19
+
20
+ post_process_items('data') do
21
+ post_process 'longitude', &:to_f
22
+ post_process 'latitude', &:to_f
23
+ post_process 'value', &:to_f
24
+ # post_process 'date', &Date.method(:parse)
25
+ end
26
+
27
+ SINGULAR = ->(h) { h['data'].first }
28
+
29
+ namespace :countries, '/countries' do
30
+ endpoint :list, '?format=json' do
31
+ param :income_level, field: :incomeLevel
32
+ param :lending_type, field: :lendingType
33
+ end
34
+
35
+ namespace :[], '/{country}' do
36
+ #param :countries, :to_a, format: ->(c) { c.join(';') }
37
+ # TODO: splat
38
+
39
+ endpoint :get, '?format=json' do
40
+ #post_process_replace(&SINGULAR)
41
+ end
42
+
43
+ endpoint :indicator, '/indicators/{name}?format=json'
44
+ # TODO: filter indicator by date
45
+ end
46
+ end
47
+
48
+ namespace :dictionaries, '' do
49
+ endpoint :topics, '/topics?format=json'
50
+ #namespace :sources, '/sources?format=json' do
51
+
52
+ endpoint :income_levels, '/incomeLevels?format=json'
53
+ endpoint :lending_types, '/lendingTypes?format=json'
54
+
55
+ namespace :indicators do
56
+ endpoint :list, '?format=json'
57
+ endpoint :by_topic, '/../topic/{topic_id}/indicator?format=json'
58
+ endpoint :by_source, '/../source/{source_id}/indicators?format=json'
59
+
60
+ endpoint :[], '/{name}?format=json' do
61
+ post_process_replace(&SINGULAR)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ wb = WorldBank.new
69
+
70
+ #pp wb.dictionaries.indicators.list
71
+
72
+ #pp wb.sources['data']['name'].reject(&:empty?)
73
+ #pp wb.countries(income_level: 'LIC')['data']['name'].sort # ['message'].first
74
+ #pp wb.indicators['NY.GDP.MKTP.CD'] #['data'].first
75
+ #pp wb.sources[3].indicators #['data']['name']
76
+ #pp wb.countries['ua'].indicator('NY.GDP.MKTP.CD')['data'].first(5)
77
+ #pp wb.countries['ua'].get
78
+ #pp wb.dictionaries.indicators.by_topic(5)['data'].last
79
+
80
+ #pp wb.countries.list['data'].to_a
81
+ #pp wb.countries['us'].indicator("EG.EGY.PRIM.PP.KD")['data'].first(10)
82
+
83
+ #pp wb.countries['ukr'].get['data'].first
84
+ #pp wb.dictionaries.indicators.list
85
+ pp wb.countries['ukr'].indicator('SP.POP.TOTL')['data'].to_a.first(3)
@@ -0,0 +1,77 @@
1
+ require 'pp'
2
+
3
+ $:.unshift 'lib'
4
+ require 'tlaw'
5
+
6
+ class WorldBankClimate < TLAW::API
7
+ define do
8
+ base 'http://climatedataapi.worldbank.org/climateweb/rest/v1'
9
+
10
+ {
11
+ basin: :basinID,
12
+ country: :country_iso3
13
+ }.each do |namespace_name, param_name|
14
+ namespace namespace_name do
15
+ param param_name, keyword: false, required: true
16
+
17
+ {
18
+ :temperature => 'tas',
19
+ :precipation => 'pr'
20
+ }.each do |varname, var|
21
+ namespace varname, path: '' do
22
+ {
23
+ monthly: 'mavg',
24
+ annual: 'annualavg',
25
+ monthly_anomaly: 'manom',
26
+ annual_anomaly: 'annualanom'
27
+ }.each do |typename, type|
28
+ endpoint typename, path: "/#{type}/#{var}/{since}/{#{param_name}}.json" do
29
+ param :since, keyword: true, required: true,
30
+ enum: {
31
+ 1920 => '1920/1939',
32
+ 1940 => '1940/1959',
33
+ 1960 => '1960/1979',
34
+ 1980 => '1980/1999',
35
+ 2020 => '2020/2039',
36
+ 2040 => '2040/2059',
37
+ 2060 => '2060/2079',
38
+ 2080 => '2080/2099',
39
+ }
40
+
41
+ if typename.to_s.include?('monthly')
42
+ post_process_replace do |res|
43
+ {
44
+ 'variable' => res.first['variable'],
45
+ 'fromYear' => res.first['fromYear'],
46
+ 'toYear' => res.first['toYear'],
47
+ 'data' => TLAW::DataTable
48
+ .from_columns(
49
+ res.map { |r| r['gcm'] },
50
+ res.map { |r| r['monthVals'] }
51
+ )
52
+ }
53
+ end
54
+ else
55
+ post_process_replace do |res|
56
+ {
57
+ 'variable' => res.first['variable'],
58
+ 'fromYear' => res.first['fromYear'],
59
+ 'toYear' => res.first['toYear'],
60
+ 'gcm' => res.map { |res| [res['gcm'], res['annualData'].first] }.to_h
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ wbc = WorldBankClimate.new
74
+
75
+ pp wbc.country('ukr').temperature.annual(since: 1980)
76
+ pp wbc.country('ukr').precipation.monthly(since: 1980)['data']
77
+