poms 1.2.2 → 2.0.0.a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -0
  3. data/.rubocop.yml +24 -0
  4. data/.ruby-version +1 -0
  5. data/.todo.reek +50 -0
  6. data/CHANGELOG.md +1 -0
  7. data/Gemfile +4 -0
  8. data/README.md +54 -6
  9. data/bin/ci-run +57 -0
  10. data/bin/ci-setup +46 -0
  11. data/bin/reek +16 -0
  12. data/bin/rspec +16 -0
  13. data/bin/rubocop +16 -0
  14. data/examples/fetch.rb +16 -0
  15. data/examples/search.rb +17 -0
  16. data/lib/poms.rb +84 -156
  17. data/lib/poms/api/auth.rb +42 -22
  18. data/lib/poms/api/client.rb +58 -0
  19. data/lib/poms/api/drivers/net_http.rb +69 -0
  20. data/lib/poms/api/json_client.rb +35 -0
  21. data/lib/poms/api/pagination_client.rb +67 -0
  22. data/lib/poms/api/request.rb +29 -31
  23. data/lib/poms/api/response.rb +31 -0
  24. data/lib/poms/api/search.rb +38 -0
  25. data/lib/poms/api/uris.rb +10 -0
  26. data/lib/poms/api/uris/media.rb +41 -0
  27. data/lib/poms/api/uris/schedule.rb +28 -0
  28. data/lib/poms/configuration.rb +59 -0
  29. data/lib/poms/errors.rb +26 -0
  30. data/lib/poms/fields.rb +26 -3
  31. data/lib/poms/timestamp.rb +10 -3
  32. data/lib/poms/version.rb +1 -1
  33. data/poms.gemspec +10 -11
  34. metadata +59 -128
  35. data/Gemfile.lock +0 -120
  36. data/lib/poms/base.rb +0 -8
  37. data/lib/poms/broadcast.rb +0 -55
  38. data/lib/poms/builder.rb +0 -92
  39. data/lib/poms/builderless/broadcast.rb +0 -37
  40. data/lib/poms/builderless/clip.rb +0 -36
  41. data/lib/poms/connect.rb +0 -11
  42. data/lib/poms/has_ancestors.rb +0 -54
  43. data/lib/poms/has_base_attributes.rb +0 -29
  44. data/lib/poms/merged_series.rb +0 -28
  45. data/lib/poms/poms_error.rb +0 -5
  46. data/lib/poms/schedule_event.rb +0 -34
  47. data/lib/poms/season.rb +0 -13
  48. data/lib/poms/series.rb +0 -12
  49. data/lib/poms/views.rb +0 -52
  50. data/spec/fabricators/poms_fabricator.rb +0 -44
  51. data/spec/fixtures/poms_broadcast.json +0 -318
  52. data/spec/fixtures/poms_broadcast_multiple_schedule_events.json +0 -354
  53. data/spec/fixtures/poms_broadcast_pippi.json +0 -180
  54. data/spec/fixtures/poms_group.json +0 -1087
  55. data/spec/fixtures/poms_series.json +0 -49
  56. data/spec/fixtures/poms_single_broadcast_by_channel.json +0 -136
  57. data/spec/fixtures/poms_zapp.json +0 -47363
  58. data/spec/fixtures/vcr_cassettes/poms/builderless/broadcast_starts_at/returns_a_datetime.yml +0 -53
  59. data/spec/fixtures/vcr_cassettes/poms/builderless/clip/has_a_position.yml +0 -43
  60. data/spec/fixtures/vcr_cassettes/poms/builderless/clip/has_a_title.yml +0 -43
  61. data/spec/fixtures/vcr_cassettes/poms/builderless/clip/has_a_video_url.yml +0 -43
  62. data/spec/fixtures/vcr_cassettes/poms/builderless/clip/has_an_image_id.yml +0 -43
  63. data/spec/fixtures/vcr_cassettes/poms/fetch_broadcasts_fetch_current_broadcast_fetches_the_current_broadcast.yml +0 -60
  64. data/spec/fixtures/vcr_cassettes/poms/fetch_broadcasts_fetch_next_broadcast_and_key_fetches_the_current_broadcast.yml +0 -68
  65. data/spec/fixtures/vcr_cassettes/poms/fetch_broadcasts_fetch_next_broadcast_and_key_returns_the_key.yml +0 -68
  66. data/spec/fixtures/vcr_cassettes/poms/merged_series/turns_the_json_into_a_hash.yml +0 -46
  67. data/spec/fixtures/vcr_cassettes/poms_fetch/a_broadcast_has_scheduled_events_with_last_with_starts_at.yml +0 -43
  68. data/spec/fixtures/vcr_cassettes/poms_fetch/a_clip_has_a_title.yml +0 -43
  69. data/spec/fixtures/vcr_cassettes/poms_fetch/an_aankeiler_has_images.yml +0 -43
  70. data/spec/fixtures/vcr_cassettes/poms_fetch_broadcasts_for_serie/returns_nil_when_a_broadcast_does_not_exist.yml +0 -42
  71. data/spec/fixtures/vcr_cassettes/poms_fetch_current_broadcast/has_a_mid.yml +0 -51
  72. data/spec/fixtures/vcr_cassettes/poms_fetch_current_broadcast/has_a_title.yml +0 -51
  73. data/spec/fixtures/vcr_cassettes/poms_fetch_current_broadcast/has_scheduled_events_with_last_with_starts_at.yml +0 -51
  74. data/spec/fixtures/vcr_cassettes/poms_fetch_current_broadcast_and_key/has_a_broadcast_with_a_mid.yml +0 -51
  75. data/spec/fixtures/vcr_cassettes/poms_fetch_current_broadcast_and_key/has_a_key.yml +0 -51
  76. data/spec/fixtures/vcr_cassettes/poms_fetch_descendant_mids/returns_a_list_of_mids.yml +0 -42
  77. data/spec/fixtures/vcr_cassettes/poms_fetch_descendants_for_serie/builds_a_list_of_broadcasts.yml +0 -102755
  78. data/spec/fixtures/vcr_cassettes/poms_fetch_group/has_a_child_with_a_media_type.yml +0 -448
  79. data/spec/fixtures/vcr_cassettes/poms_fetch_group/has_a_child_with_a_title.yml +0 -448
  80. data/spec/fixtures/vcr_cassettes/poms_fetch_playlist_clips/creates_an_array_of_clips.yml +0 -1051
  81. data/spec/integration/poms_spec.rb +0 -87
  82. data/spec/lib/poms/api/auth_spec.rb +0 -34
  83. data/spec/lib/poms/api/request_spec.rb +0 -30
  84. data/spec/lib/poms/broadcast_spec.rb +0 -49
  85. data/spec/lib/poms/builder_spec.rb +0 -53
  86. data/spec/lib/poms/builderless/broadcast_spec.rb +0 -11
  87. data/spec/lib/poms/builderless/clip_spec.rb +0 -20
  88. data/spec/lib/poms/fields_spec.rb +0 -63
  89. data/spec/lib/poms/merged_series_spec.rb +0 -26
  90. data/spec/lib/poms/schedule_event_spec.rb +0 -15
  91. data/spec/lib/poms/timestamp_spec.rb +0 -13
  92. data/spec/lib/poms/views_spec.rb +0 -38
  93. data/spec/lib/poms_spec.rb +0 -137
  94. data/spec/spec_helper.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2cf1cb8d138dfb0cc64941c91166579039374f9f
4
- data.tar.gz: 211325fcdf33276731f6955fff221311b3678e50
3
+ metadata.gz: f7ebd9df85593c5327fcc07f65eb00d38a8639a0
4
+ data.tar.gz: 652743af2c085d204cbf078138e1a20e2e5ffbb9
5
5
  SHA512:
6
- metadata.gz: 943723499c03b7dfa58465c365d07787aede3b30d710332bbc6c046fce03f6050ece00da032c9416c41e09383668e69bf0ff9ea9c5b5be6bcae153765b75aab7
7
- data.tar.gz: e73de97e4ef76cfd6db078e671d2ced5c4582e5021ec5132041e76fdee3246d86625a72fe83981c5174079fd9509eaf46f17becc12b706c04f634256833fa44d
6
+ metadata.gz: abadd1025995b03d9aefba6dd42e773de7dfc53b4afd16992cfec2bdb9eb438de2c201436cffee1f76d10d0b732c86990a6686c6b7ca45f8ec611bdb8e1dd1d3
7
+ data.tar.gz: 6c5b371f5e6f9d2ff52b97f13bd0b75a8cbfe19aa936f6f36539ca228853bbfb508028afcb65f5df9b08e11cf7edea3e6f3e49299536227eba00f0c86620b976
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rubocop.yml ADDED
@@ -0,0 +1,24 @@
1
+ require: rubocop-rspec
2
+
3
+ AllCops:
4
+ Exclude:
5
+ - bin/*
6
+ - poms.gemspec
7
+
8
+ Style/Documentation:
9
+ Exclude:
10
+ - 'lib/poms/has_ancestors.rb'
11
+ - spec/**/*_spec.rb
12
+
13
+ Style/BlockDelimiters:
14
+ Exclude:
15
+ - 'spec/**/*.rb'
16
+
17
+ Style/AndOr:
18
+ Exclude:
19
+ - 'lib/poms.rb' # here we do rely on how `or` has lower precedence than `||`
20
+ - 'lib/poms/configuration.rb' # here we do rely on how `or` has lower precedence than `||`
21
+
22
+ ModuleLength:
23
+ Exclude:
24
+ - spec/**/*_spec.rb # specs are only in module for easier access to functions
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.0
data/.todo.reek ADDED
@@ -0,0 +1,50 @@
1
+ ---
2
+ UncommunicativeVariableName:
3
+ exclude:
4
+ - Poms::Fields#available_until
5
+ - Poms::Fields#odi_streams
6
+ - Poms::MergedSeries#serie_mids
7
+ - Poms
8
+ DuplicateMethodCall:
9
+ exclude:
10
+ - Poms::Api::Client#handle_response
11
+ - Poms::Api::RequestExecution#headers
12
+ - Poms::Builderless::Clip#position
13
+ - Poms::Builderless::Clip#video_url
14
+ - Poms::Field
15
+ UtilityFunction:
16
+ exclude:
17
+ - Poms::Api::RequestExecution#execute_ssl_request
18
+ - Poms::Fields
19
+ NilCheck:
20
+ exclude:
21
+ - Poms::Fields#odi_streams
22
+ TooManyStatements:
23
+ exclude:
24
+ - Poms::Fields#odi_streams
25
+ - Poms::Api::Auth#sign
26
+ - Poms::Api::Drivers::NetHttp#attempt_request
27
+ - Poms::Api::PaginationClient#execute
28
+ LongParameterList:
29
+ exclude:
30
+ - Poms::MergedSeries#serie_mids
31
+ - Poms::Api::Client#post
32
+ - Poms::Api::JsonClient#post
33
+ FeatureEnvy:
34
+ exclude:
35
+ - Poms#first
36
+ - Poms::Api::Client#handle_response
37
+ - Poms::Api::Drivers::NetHttp#attempt_request
38
+ - Poms::Api::Drivers::NetHttp#execute
39
+ - Poms::Api::Drivers::NetHttp#prepare_request
40
+ - Poms::Api::Drivers::NetHttp#request_to_net_http_request
41
+ - Poms::Api::PaginationClient#execute
42
+ NestedIterators:
43
+ exclude:
44
+ - Poms::Api::PaginationClient#execute
45
+ Attribute:
46
+ exclude:
47
+ - Poms::Configuration#base_uri
48
+ - Poms::Configuration#key
49
+ - Poms::Configuration#secret
50
+ - Poms::Configuration#origin
data/CHANGELOG.md CHANGED
@@ -3,6 +3,7 @@
3
3
  ## 1.2.2
4
4
 
5
5
  * Fix issue with description type that did not exist.
6
+ * Add some more specs to the field classes to catch values that are empty.
6
7
 
7
8
  ## 1.2.1
8
9
 
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in poms.gemspec
4
4
  gemspec
5
+
6
+ group :development, :test do
7
+ require 'pry'
8
+ end
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
+ [ ![Codeship Status for brightin/poms](https://codeship.com/projects/c2baf9b0-ea8d-0132-2258-628e55ad70cc/status?branch=master)](https://codeship.com/projects/83157)
2
+
1
3
  # Poms
2
4
 
3
5
  The Poms gem provides an interface to the Dutch public broadcaster API: POMS. It
4
- is a couchdb service that is publicly available.
6
+ reads from the Frontend API.
5
7
 
6
8
  ## Installation
7
9
 
@@ -17,17 +19,63 @@ Or install it yourself as:
17
19
 
18
20
  $ gem install poms
19
21
 
22
+ ## Configuration
23
+
24
+ The Poms API is only accessible to authenticated accounts. In order to make authenticated requests to the service, the module needs to be configured before making requests. This can be done in a Rails initializer for instance.
25
+
26
+ In order to configure the module:
27
+
28
+ Poms.configure do |config|
29
+ config.key = '**poms key**'
30
+ config.origin = '**poms origin**'
31
+ config.secret = '**poms secret**'
32
+ end
33
+
34
+ `configure` can also read environment variables. `ENV['POMS_KEY']`, `ENV['POMS_ORIGIN']`, `ENV['POMS_SECRET']` are used in this case.
35
+
36
+ The `configure` function can also be provided with the `base_url` in case you want to access the test environment for instance.
37
+
20
38
  ## Usage
21
39
 
22
- The `Poms` module contains various ways to query the Poms CouchDB service. The simplest way to get something is to use the `fetch` function, which takes a MID.
40
+ The `Poms` module contains various ways to interact with the Poms service based on the API it exposes. The simplest way to get something is to use the `first` of `first!` function, which takes a MID (Media ID) used internally to identify all objects.
41
+
42
+ Poms.first('mid')
43
+
44
+ This returns a Hash of the json of the response provided by the Poms service. In this case this is a single object from Poms.
45
+
46
+ In order to do more advanced querying you might want to get the members or descendants of an object. `members` simply returns all objects that are members of the object with the requested mid.
47
+
48
+ Poms.members('mid')
49
+
50
+ The result is a lazy enumerator (as the results are paginated on Poms) that contains all the members.
51
+
52
+ The `descendants` function allows query parameters to be entered that are taken in account by the Poms service.
53
+
54
+ Poms.descendants('mid', {})
55
+
56
+ The result is similar to the members function, but each item contains metadata from the search query and the actual result is in the `result` key of the item hash.
57
+
58
+ The `poms` module contains a number of other functions that may be useful when you want to get some specific info from Poms. Also take a look at the examples in the `examples` directory of this project.
59
+
60
+ ## Fields
61
+
62
+ The hashes that are returned from Poms can be nested to a high degree, making it harder to get some specific fields from them. The `Poms::Fields` module provides helper functions to access things like title, descriptions and images.
63
+
64
+ Poms::Fields.title(poms_item)
65
+
66
+ This will return the title with the `MAIN` type.
23
67
 
24
- Poms.fetch('mid')
68
+ ## Searching
25
69
 
26
- This returns an OpenStruct-like object that wraps the json of the Poms response.
70
+ For reference of possible search options, see the [POMS API wiki](http://wiki.publiekeomroep.nl/display/npoapi/Media-+en+gids-API).
27
71
 
28
- For some more advanced querying, you can use functions like `fetch_clip` which also takes a MID, but returns a `Clip` object, that is a little easier to work with.
72
+ For Ruby we try to adhere to conventional naming and we map this to the relevant Poms API fields.
29
73
 
30
- You can also query collections in a way to get back multiple episodes. This is tied to the views in the Poms CouchDB service and is documented on the wiki of the NPO.
74
+ Gem | API
75
+ ---|---
76
+ `starts_at` | `"sortDates": { "begin" } `
77
+ `ends_at` | `"sortDates": { "end" } `
78
+ `type` | `{ "facets": { "subsearch": { "types" } } }`
31
79
 
32
80
  ## Contributing
33
81
 
data/bin/ci-run ADDED
@@ -0,0 +1,57 @@
1
+ #!/bin/bash --login
2
+ #
3
+ # Usage: bin/ci-run [--help|--job N]
4
+ #
5
+ # Run all tasks required for a Continuous Integration job. Also see ci-setup.
6
+ #
7
+ # Options:
8
+ #
9
+ # --job N May be used for CI parallelisation. Use this number to do only part
10
+ # of the usual work, for example by invoking different test scripts.
11
+ # --help Display this message.
12
+ #
13
+ # Examples:
14
+ #
15
+ # Run all the tests for this project:
16
+ #
17
+ # bin/ci-run
18
+ #
19
+ # Run only part of the test suite:
20
+ #
21
+ # bin/ci-run --job 1
22
+
23
+ set -e
24
+
25
+ # Run the actual tests for this project. The exit code of this function is
26
+ # determines the outcome of the CI build.
27
+ #
28
+ # TODO adapt the Rake command invokation below into something that makes sense for
29
+ # your particular project.
30
+ run_tests() {
31
+ # RVM is not activated in non-login shells, so we do so manually.
32
+ RUBY_VERSION=$(cat .ruby-version)
33
+ echo "Using Ruby $RUBY_VERSION"
34
+ source $(rvm $RUBY_VERSION do rvm env --path)
35
+
36
+ set -x
37
+ bundle exec rubocop
38
+ bundle exec reek
39
+ bundle exec rspec
40
+ }
41
+
42
+ # Print help for this script by printing its top comment block (without the
43
+ # comment markers).
44
+ show_help() {
45
+ awk '/^# Usage/,/^$/' $0 | cut -c 3-
46
+ exit 1
47
+ }
48
+
49
+ if [[ $# -ge 1 ]]
50
+ then
51
+ case $1 in
52
+ "--job" ) run_tests $2;;
53
+ * ) show_help;;
54
+ esac
55
+ else
56
+ run_tests
57
+ fi
data/bin/ci-setup ADDED
@@ -0,0 +1,46 @@
1
+ #!/bin/bash --login
2
+ #
3
+ # Usage: bin/ci-setup [--help]
4
+ #
5
+ # Set up a Codeship CI VM for running a test suite. Also see ci-run.
6
+ #
7
+ # Options:
8
+ #
9
+ # --help Display this message.
10
+
11
+ set -e
12
+
13
+ # Perform the steps necessary to set up the CI environment for testing. This
14
+ # should include languages, services, package managers, environment, etc.
15
+ setup() {
16
+ set -x
17
+ # Read the required version of Ruby from the Gemfile and use RVM to install it
18
+ rvm use $(cat .ruby-version) --install
19
+
20
+ # To use Node.js as Javascript runtime, uncomment the following lines.
21
+ # nvm install 0.12
22
+ # nvm use 0.12
23
+
24
+ # If the project has a package.json file and javascript dependencies, you can
25
+ # install them here.
26
+ # npm install
27
+
28
+ # Install Ruby dependencies with Bundler.
29
+ bundle install
30
+
31
+ set +x
32
+ }
33
+
34
+ # Print help for this script by printing its top comment block (without the
35
+ # comment markers).
36
+ show_help() {
37
+ awk '/^# Usage/,/^$/' $0 | cut -c 3-
38
+ exit 1
39
+ }
40
+
41
+ if [[ $# -ge 1 ]]
42
+ then
43
+ show_help
44
+ else
45
+ setup
46
+ fi
data/bin/reek ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'reek' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("reek", "reek")
data/bin/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/rubocop ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rubocop' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require "pathname"
10
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require "rubygems"
14
+ require "bundler/setup"
15
+
16
+ load Gem.bin_path("rubocop", "rubocop")
data/examples/fetch.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'poms'
2
+
3
+ # Initialize poms with the correct credentials
4
+ Poms.configure do |config|
5
+ config.key = '**poms key**'
6
+ config.origin = '**poms origin**'
7
+ config.secret = '**poms secret**'
8
+ end
9
+
10
+ # Get a single entity from POMS by mid
11
+ Poms.first('POMS_S_NTR_2342303')
12
+ # => A hash representing the data corresponding to the given MID
13
+
14
+ # Fetch multiple entities
15
+ Poms.fetch(%w(WO_TELEAC_003061 POMS_EO_622912))
16
+ # => An array of hashes representing data corresponding to those MIDs
@@ -0,0 +1,17 @@
1
+ require 'poms'
2
+
3
+ # You can build a search params hash using Poms::Api::Search
4
+ query = Poms::Api::Search.build(starts_at: Time.now, ends_at: 2.weeks.from_now)
5
+
6
+ # And use it to query the poms API
7
+ Poms.descendants('VPWON_1251179', query)
8
+ # => Returns all media that is a descendant of the media by the given mid, and
9
+ # was broadcasted between now and next week
10
+
11
+ # This example will fetch all media that is of type "BROADCAST"
12
+ query = Poms::Api::Search.build(starts_at: Time.now, type: 'BROADCAST')
13
+
14
+ # Use it
15
+ Poms.descendants('VPWON_1251179', query)
16
+ # => Returns all media that is a descendant of the media by the given mid, has
17
+ # not aired yet and is a broadcast
data/lib/poms.rb CHANGED
@@ -1,184 +1,112 @@
1
- require 'active_support'
2
- require 'open-uri'
1
+ require 'active_support/all'
2
+ require 'poms/api/uris'
3
+ require 'poms/api/json_client'
4
+ require 'poms/api/pagination_client'
5
+ require 'poms/errors'
6
+ require 'poms/api/search'
7
+ require 'poms/configuration'
3
8
  require 'json'
4
- require 'poms/base'
5
- require 'poms/version'
6
- require 'poms/builder'
7
- require 'poms/schedule_event'
8
- require 'poms/broadcast'
9
- require 'poms/season'
10
- require 'poms/series'
11
- require 'poms/views'
12
- require 'poms/fields'
13
- require 'poms/timestamp'
14
- require 'poms/builderless/broadcast'
15
- require 'poms/builderless/clip'
16
- require 'poms/merged_series'
17
- require 'poms/poms_error'
18
9
 
19
- # Module that allows interfacing with the POMS CouchDB service.
20
- # rubocop:disable Metrics/ModuleLength
10
+ # Main interface for the POMS gem
11
+ #
12
+ # Strategy
13
+ # 1 -- Build a request object that can be executed
14
+ # (PostRequest || GetRequest object)
15
+ # 2 -- Execute the request. Retry on failures (max 10?)
16
+ # 3 -- Parse responded JSON. Extract fields if necessary
21
17
  module Poms
22
- extend self
18
+ module_function
23
19
 
24
- URL = 'http://docs.poms.omroep.nl'
25
- MEDIA_PATH = '/media/'
26
- BROADCASTS_VIEW_PATH =
27
- '/media/_design/media/_view/broadcasts-by-broadcaster-and-start'
28
- ANCESTOR_AND_TYPE_PATH = '/media/_design/media/_view/by-ancestor-and-type'
29
- ANCESTOR_AND_SORTDATE_PATH =
30
- '/media/_design/media/_view/by-ancestor-and-sortdate'
31
- CHANNEL_AND_START_PATH =
32
- '/media/_design/media/_view/broadcasts-by-channel-and-start'
33
- VALID_CHANNELS = /^NED(1|2|3)$/
34
-
35
- def fetch(mid)
36
- return nil if mid.nil?
37
- hash = fetch_raw_json mid
38
- Builder.process_hash hash
39
- end
40
-
41
- def fetch_clip(mid)
42
- clip_hash = fetch_raw_json(mid)
43
- Builderless::Clip.new(clip_hash)
44
- end
45
-
46
- def fetch_playlist_clips(mid)
47
- uri = Views.by_group(mid)
48
- playlist_hash = get_bare_json(uri)
49
- playlist_hash['rows'].map do |hash|
50
- Builderless::Clip.new(hash['doc'])
20
+ def configure
21
+ @config = Configuration.new do |config|
22
+ yield config if block_given?
51
23
  end
24
+ nil
52
25
  end
53
26
 
54
- def fetch_raw_json(mid)
55
- uri = [MEDIA_PATH, mid].join
56
- get_json(uri)
57
- end
58
-
59
- alias_method :fetch_broadcast, :fetch_raw_json
60
-
61
- def fetch_group(mid)
62
- uri = Views.by_group(mid)
63
- get_bare_json(uri)
64
- end
65
-
66
- def upcoming_broadcasts(zender, start_time = Time.now,
67
- end_time = Time.now + 7.days)
68
- view_params = broadcast_view_params(zender, start_time, end_time)
69
- uri = [BROADCASTS_VIEW_PATH, view_params].join
70
- hash = get_json(uri)
71
- hash['rows'].map { |item| Builder.process_hash item['doc'] }
72
- end
73
-
74
- def fetch_descendants_for_serie(mid, type = 'BROADCAST')
75
- uri = Views.descendants_by_type(mid, type)
76
- hash = get_bare_json(uri) || { 'rows' => [] }
77
- hash['rows'].map { |item| Builder.process_hash item['doc'] }
78
- end
79
-
80
- alias_method :fetch_broadcasts_for_serie, :fetch_descendants_for_serie
81
-
82
- def fetch_descendants_by_date_for_serie(mid, start_time = 1.week.ago)
83
- view_params = ancestor_sortdate_params(mid, start_time)
84
- uri = [ANCESTOR_AND_SORTDATE_PATH, view_params].join
85
- hash = get_json(uri) || { 'rows' => [] }
86
- hash['rows'].map { |item| Builder.process_hash item['doc'] }
87
- end
88
-
89
- def fetch_descendant_mids(mid, type = 'BROADCAST')
90
- uri = Views.descendants_by_type(mid, type, include_docs: false)
91
- hash = get_bare_json(uri) || { 'rows' => [] }
92
- hash['rows'].map { |item| item['id'] }
93
- end
94
-
95
- def fetch_broadcasts_by_channel_and_start(channel, start_time = 1.week.ago,
96
- end_time = Time.now)
97
- view_params = channel_params(channel, start_time, end_time)
98
- uri = [CHANNEL_AND_START_PATH, view_params].join
99
- hash = get_json(uri)
100
- hash['rows'].map { |item| Builder.process_hash item['doc'] }
101
- end
102
-
103
- def fetch_current_broadcast(channel)
104
- uri = Views.broadcasts_by_channel_and_start(channel)
105
- hash = get_bare_json(uri)
106
- row = hash['rows'].first
107
- Builderless::Broadcast.new(row['doc']) if row
108
- end
109
-
110
- def fetch_current_broadcast_and_key(channel)
111
- hash = get_json(channel_and_start_uri(
112
- channel, Time.now, 1.day.ago, limit: 1, descending: true)
113
- )
114
- { key: get_first_key(hash), broadcast: get_first_broadcast(hash) }
27
+ # Returns the first result for a mid if it is not an error.
28
+ #
29
+ # @param [String] mid MID to find in POMS
30
+ # @return [Hash, nil]
31
+ def first(mid)
32
+ first!(mid)
33
+ rescue Errors::HttpMissingError
34
+ nil
115
35
  end
116
36
 
117
- def fetch_next_broadcast(channel)
118
- hash = get_json(channel_and_start_uri(
119
- channel, Time.now, 1.day.from_now, limit: 1)
120
- )
121
- get_first_broadcast(hash)
37
+ # Like `first`, but raises `Api::Client::HttpMissingError` when the requested
38
+ # MID could not be found.
39
+ #
40
+ # @param [String] mid
41
+ # @raise Api::Client::HttpMissingError
42
+ def first!(mid)
43
+ Api::JsonClient.get(
44
+ Api::Uris::Media.single(config.base_uri, mid),
45
+ config.credentials
46
+ )
122
47
  end
123
48
 
124
- def fetch_next_broadcast_and_key(channel)
125
- hash = get_json(channel_and_start_uri(
126
- channel, Time.now, 1.day.from_now, limit: 1)
127
- )
128
- { key: get_first_key(hash), broadcast: get_first_broadcast(hash) }
49
+ def fetch(arg)
50
+ Api::JsonClient.post(
51
+ Api::Uris::Media.multiple(config.base_uri),
52
+ Array(arg),
53
+ config.credentials
54
+ )
129
55
  end
130
56
 
131
- def broadcast_view_params(zender, start_time, end_time)
132
- zender = zender.capitalize
133
- "?startkey=[\"#{zender}\",#{start_time.to_i * 1000}]" \
134
- "&endkey=[\"#{zender}\",#{end_time.to_i * 1000}]" \
135
- '&reduce=false&include_docs=true'
57
+ def descendants(mid, search_params = {})
58
+ Api::PaginationClient.post(
59
+ Api::Uris::Media.descendants(config.base_uri, mid),
60
+ Api::Search.build(search_params),
61
+ config.credentials
62
+ )
136
63
  end
137
64
 
138
- def ancestor_type_params(mid, type)
139
- "?reduce=false&key=[\"#{mid}\",\"#{type}\"]&include_docs=true"
65
+ def members(mid)
66
+ Api::PaginationClient.get(
67
+ Api::Uris::Media.members(config.base_uri, mid),
68
+ config.credentials
69
+ )
140
70
  end
141
71
 
142
- def ancestor_sortdate_params(mid, start_time = 1.month.ago)
143
- end_time_i = 1.week.from_now.to_i * 1000
144
- start_time_i = start_time.to_i * 1000
145
- "?reduce=false&startkey=[\"#{mid}\",#{start_time_i}]" \
146
- "&endkey=[\"#{mid}\",#{end_time_i}]&include_docs=true"
72
+ # Gets the merged serie mids as a hash. Expects a JSON response from
73
+ # the server with a `map` key.
74
+ #
75
+ # @return [Hash] a hash with old_mid => new_mid pairs
76
+ def merged_series
77
+ Api::JsonClient.get(
78
+ Api::Uris::Media.redirects(config.base_uri),
79
+ config
80
+ ).fetch('map')
147
81
  end
148
82
 
149
- def channel_params(channel, start_time, end_time)
150
- "?startkey=[\"#{channel}\",#{start_time.to_i * 1000}]" \
151
- "&endkey=[\"#{channel}\",#{end_time.to_i * 1000}]" \
152
- '&reduce=false&include_docs=true'
83
+ # Fetches the event for current broadcast on the given channel
84
+ #
85
+ # @param channel The channel name
86
+ def scheduled_now(channel)
87
+ Poms::Api::JsonClient.get(
88
+ Poms::Api::Uris::Schedule.now(config.base_uri, channel),
89
+ config.credentials
90
+ )
153
91
  end
154
92
 
155
- def get_json(uri)
156
- get_bare_json(URI.escape([URL, uri].join))
93
+ # Fetches the event for the next broadcast on a given channel
94
+ #
95
+ # @param channel The channel name
96
+ def scheduled_next(channel)
97
+ Poms::Api::JsonClient.get(
98
+ Poms::Api::Uris::Schedule.next(config.base_uri, channel),
99
+ config.credentials
100
+ )
157
101
  end
158
102
 
159
- private
160
-
161
- def get_bare_json(uri)
162
- JSON.parse(open(uri).read)
163
- rescue OpenURI::HTTPError => e
164
- raise e unless e.message.match(/404/)
165
- nil
103
+ def reset_config
104
+ @config = nil
166
105
  end
167
106
 
168
- def channel_and_start_uri(channel, start_time, end_time, options = {})
169
- query_options = options.blank? ? '' : "&#{options.to_query}"
170
- view_params = channel_params(channel, start_time, end_time)
171
- [CHANNEL_AND_START_PATH, view_params, query_options].join
107
+ def config
108
+ @config or raise Errors::NotConfigured
172
109
  end
173
110
 
174
- def get_first_broadcast(hash)
175
- rows = hash['rows']
176
- Builder.process_hash(rows.empty? ? {} : rows.first['doc'])
177
- end
178
-
179
- def get_first_key(hash)
180
- rows = hash['rows']
181
- rows.empty? ? [] : rows.first['key']
182
- end
111
+ private_class_method :config
183
112
  end
184
- # rubocop:enable Metrics/ModuleLength