tlaw 0.0.2 → 0.1.0.pre

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