rev-api 2.2.0 → 2.4.0

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 (63) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +22 -21
  3. data/.ruby-gemset +1 -1
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +8 -8
  6. data/Gemfile +3 -3
  7. data/LICENSE +191 -191
  8. data/README.md +131 -132
  9. data/Rakefile +13 -13
  10. data/examples/cli.rb +270 -270
  11. data/lib/rev-api.rb +26 -26
  12. data/lib/rev-api/api.rb +326 -326
  13. data/lib/rev-api/api_serializable.rb +30 -30
  14. data/lib/rev-api/exceptions.rb +97 -100
  15. data/lib/rev-api/http_client.rb +97 -97
  16. data/lib/rev-api/models/order.rb +129 -138
  17. data/lib/rev-api/models/order_request.rb +273 -222
  18. data/lib/rev-api/version.rb +3 -3
  19. data/rev-api.gemspec +33 -34
  20. data/spec/fixtures/api_cassettes/cancel_order.yml +38 -38
  21. data/spec/fixtures/api_cassettes/cancel_order_not_allowed.yml +40 -40
  22. data/spec/fixtures/api_cassettes/get_attachment_content.yml +399 -399
  23. data/spec/fixtures/api_cassettes/get_attachment_content_as_pdf.yml +399 -399
  24. data/spec/fixtures/api_cassettes/get_attachment_content_as_text.yml +65 -65
  25. data/spec/fixtures/api_cassettes/get_attachment_content_as_youtube_transcript.yml +66 -66
  26. data/spec/fixtures/api_cassettes/get_attachment_content_unacceptable_representation.yml +42 -42
  27. data/spec/fixtures/api_cassettes/get_attachment_content_with_invalid_id.yml +42 -42
  28. data/spec/fixtures/api_cassettes/get_attachment_metadata.yml +42 -42
  29. data/spec/fixtures/api_cassettes/get_attachment_with_invalid_id.yml +40 -40
  30. data/spec/fixtures/api_cassettes/get_orders.yml +122 -122
  31. data/spec/fixtures/api_cassettes/get_orders_with_clientRef.yml +41 -41
  32. data/spec/fixtures/api_cassettes/get_tc_order.yml +44 -44
  33. data/spec/fixtures/api_cassettes/get_third_page_of_orders.yml +52 -58
  34. data/spec/fixtures/api_cassettes/link_input.yml +44 -44
  35. data/spec/fixtures/api_cassettes/link_input_with_all_attributes.yml +44 -44
  36. data/spec/fixtures/api_cassettes/link_input_with_spaces_in_filename.yml +45 -45
  37. data/spec/fixtures/api_cassettes/not_found_order.yml +42 -42
  38. data/spec/fixtures/api_cassettes/submit_cp_order.yml +44 -45
  39. data/spec/fixtures/api_cassettes/submit_su_order.yml +44 -45
  40. data/spec/fixtures/api_cassettes/submit_tc_order_with_account_balance.yml +44 -45
  41. data/spec/fixtures/api_cassettes/submit_tc_order_with_invalid_request.yml +45 -45
  42. data/spec/fixtures/api_cassettes/submit_tc_order_without_specifying_payment.yml +44 -45
  43. data/spec/fixtures/api_cassettes/unauthorized.yml +42 -42
  44. data/spec/fixtures/api_cassettes/upload_input.yml +90 -90
  45. data/spec/fixtures/api_cassettes/upload_input_with_invalid_content_type.yml +91 -91
  46. data/spec/lib/rev/api_spec.rb +30 -24
  47. data/spec/lib/rev/cancel_order_spec.rb +24 -24
  48. data/spec/lib/rev/exceptions_spec.rb +8 -8
  49. data/spec/lib/rev/get_attachment_content_spec.rb +79 -79
  50. data/spec/lib/rev/get_attachment_metadata_spec.rb +33 -33
  51. data/spec/lib/rev/get_order_spec.rb +52 -68
  52. data/spec/lib/rev/get_orders_spec.rb +62 -62
  53. data/spec/lib/rev/http_client_spec.rb +32 -32
  54. data/spec/lib/rev/models/order_request_spec.rb +79 -10
  55. data/spec/lib/rev/models/order_spec.rb +58 -58
  56. data/spec/lib/rev/post_inputs_spec.rb +94 -94
  57. data/spec/lib/rev/post_order_spec.rb +163 -195
  58. data/spec/spec_helper.rb +47 -49
  59. data/spec/test_helpers.rb +5 -0
  60. metadata +10 -28
  61. data/.coveralls.yml +0 -2
  62. data/spec/fixtures/api_cassettes/get_tr_order.yml +0 -44
  63. data/spec/fixtures/api_cassettes/submit_tr_order.yml +0 -44
@@ -1,138 +1,129 @@
1
- require 'rev-api/api_serializable'
2
-
3
- module Rev
4
- # Represents Translation, Caption, or Transcription order.
5
- # Should have TranslationInfo, CaptionInfo, or TranscriptionInfo, list
6
- # of comments and attachments. Attributes names reflect
7
- # API exposed names, but occasional hyphens are replaced
8
- # with underscores
9
- class Order < ApiSerializable
10
- attr_reader :order_number, :price, :status, :attachments, :comments,
11
- :translation, :transcription, :caption, :client_ref
12
-
13
- # @param fields [Hash] hash of order fields parsed from JSON API response
14
- def initialize(fields)
15
- super fields
16
- @attachments = fields['attachments'].map { |attachment_fields| Attachment.new(attachment_fields) }
17
- @comments = fields['comments'].map { |comment_fields| Comment.new(comment_fields) }
18
- @translation = TranslationInfo.new(fields['translation']) if fields['translation']
19
- @transcription = TranscriptionInfo.new(fields['transcription']) if fields['transcription']
20
- @caption = CaptionInfo.new(fields['caption']) if fields['caption']
21
- end
22
-
23
- # @return [Array of Attachment] with the kind of "transcript"
24
- def transcripts
25
- @attachments.select { |a| a.kind == Attachment::KINDS[:transcript]}
26
- end
27
-
28
- # @return [Array of Attachment] with the kind of "translation"
29
- def translations
30
- @attachments.select { |a| a.kind == Attachment::KINDS[:translation]}
31
- end
32
-
33
- # @return [Array of Attachment] with the kind of "caption"
34
- def captions
35
- @attachments.select { |a| a.kind == Attachment::KINDS[:caption] }
36
- end
37
-
38
- # @return [Array of Attachment] with the kind of "sources"
39
- def sources
40
- @attachments.select { |a| a.kind == Attachment::KINDS[:media]}
41
- end
42
- end
43
-
44
- # Order comment, containing author, creation timestamp and text
45
- class Comment < ApiSerializable
46
- require 'date'
47
-
48
- attr_reader :by, :timestamp, :text
49
-
50
- # @param fields [Hash] hash of comment fields parsed from JSON API response
51
- def initialize(fields)
52
- super fields
53
- @timestamp = Date.iso8601(fields['timestamp'])
54
- @text = fields['text'] ? fields['text'] : String.new # right now API gives no 'text' field if text is empty
55
- end
56
- end
57
-
58
- # Additional information specific to translation orders,
59
- # such as word count, languages
60
- class TranslationInfo < ApiSerializable
61
- attr_reader :total_word_count, :source_language_code,
62
- :destination_language_code
63
- end
64
-
65
- # Additional information specific to transcription orders,
66
- # such as total length in minutes, verbatim and timestamps flags
67
- class TranscriptionInfo < ApiSerializable
68
- attr_reader :total_length_seconds, :verbatim, :timestamps
69
-
70
- # @deprecated use :total_length_seconds instead
71
- attr_reader :total_length
72
- end
73
-
74
- # Additional information specific to caption orders
75
- class CaptionInfo < ApiSerializable
76
- attr_reader :total_length_seconds
77
-
78
- # @deprecated use :total_length_seconds instead
79
- attr_reader :total_length
80
- end
81
-
82
- # Represents order attachment - logical document associated with order
83
- class Attachment < ApiSerializable
84
- attr_reader :kind, :name, :id, :audio_length_seconds, :word_count, :links, :video_length_seconds
85
-
86
- KINDS = {
87
- :transcript => 'transcript',
88
- :translation => 'translation',
89
- :caption => 'caption',
90
- :media => 'media'
91
- }
92
-
93
- # List of supported mime-types used to request attachment's content
94
- # within 'Accept' header
95
- REPRESENTATIONS = {
96
- # Supported by :transcript and :translation
97
- :docx => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
98
- :doc => 'application/msword',
99
- :pdf => 'application/pdf',
100
- :txt => 'text/plain',
101
- :youtube => 'text/plain; format=youtube-transcript',
102
-
103
- # Supported by :caption
104
- :srt => 'application/x-subrip',
105
- :scc => 'text/x-scc',
106
- :ttml => 'application/ttml+xml',
107
- :qt => 'application/x-quicktime-timedtext'
108
- }
109
-
110
- # @param fields [Hash] fields of attachment fields parsed from JSON API response
111
- def initialize(fields)
112
- super fields
113
- @links = fields['links'].map { |link_fields| Link.new(link_fields) }
114
- end
115
-
116
- # @param ext [Symbol] extension
117
- # @return [String] mime-type for requested extension
118
- def self.representation_mime(ext)
119
- REPRESENTATIONS[ext]
120
- end
121
- end
122
-
123
- # Link to actual file represented by attachment
124
- class Link < ApiSerializable
125
- attr_reader :rel, :href, :content_type
126
- end
127
-
128
- # Represents a paginated list of orders, including padination info.
129
- class OrdersListPage < ApiSerializable
130
- attr_reader :total_count, :results_per_page, :page, :orders
131
-
132
- # @param fields [Hash] hash of OrdersListPage fields parsed from JSON API response
133
- def initialize(fields)
134
- super fields
135
- @orders = fields['orders'].map { |order_fields| Order.new(order_fields) }
136
- end
137
- end
138
- end
1
+ require 'rev-api/api_serializable'
2
+
3
+ module Rev
4
+ # Represents a Caption or Transcription order.
5
+ # Should have CaptionInfo or TranscriptionInfo, list
6
+ # of comments and attachments. Attributes names reflect
7
+ # API exposed names, but occasional hyphens are replaced
8
+ # with underscores
9
+ class Order < ApiSerializable
10
+ attr_reader :order_number, :price, :status, :attachments, :comments,
11
+ :transcription, :caption, :client_ref
12
+
13
+ # @param fields [Hash] hash of order fields parsed from JSON API response
14
+ def initialize(fields)
15
+ super fields
16
+ @attachments = fields['attachments'].map { |attachment_fields| Attachment.new(attachment_fields) }
17
+ @comments = fields['comments'].map { |comment_fields| Comment.new(comment_fields) }
18
+ @transcription = TranscriptionInfo.new(fields['transcription']) if fields['transcription']
19
+ @caption = CaptionInfo.new(fields['caption']) if fields['caption']
20
+ end
21
+
22
+ # @return [Array of Attachment] with the kind of "transcript"
23
+ def transcripts
24
+ @attachments.select { |a| a.kind == Attachment::KINDS[:transcript]}
25
+ end
26
+
27
+ # @return [Array of Attachment] with the kind of "caption"
28
+ def captions
29
+ @attachments.select { |a| a.kind == Attachment::KINDS[:caption] }
30
+ end
31
+
32
+ # @return [Array of Attachment] with the kind of "sources"
33
+ def sources
34
+ @attachments.select { |a| a.kind == Attachment::KINDS[:media]}
35
+ end
36
+ end
37
+
38
+ # Order comment, containing author, creation timestamp and text
39
+ class Comment < ApiSerializable
40
+ require 'date'
41
+
42
+ attr_reader :by, :timestamp, :text
43
+
44
+ # @param fields [Hash] hash of comment fields parsed from JSON API response
45
+ def initialize(fields)
46
+ super fields
47
+ @timestamp = Date.iso8601(fields['timestamp'])
48
+ @text = fields['text'] ? fields['text'] : String.new # right now API gives no 'text' field if text is empty
49
+ end
50
+ end
51
+
52
+ # Additional information specific to transcription orders,
53
+ # such as total length in minutes, verbatim and timestamps flags
54
+ class TranscriptionInfo < ApiSerializable
55
+ attr_reader :total_length_seconds, :verbatim, :timestamps
56
+
57
+ # @deprecated use :total_length_seconds instead
58
+ attr_reader :total_length
59
+ end
60
+
61
+ # Additional information specific to caption orders
62
+ class CaptionInfo < ApiSerializable
63
+ attr_reader :total_length_seconds
64
+
65
+ # @deprecated use :total_length_seconds instead
66
+ attr_reader :total_length
67
+ end
68
+
69
+ # Represents order attachment - logical document associated with order
70
+ class Attachment < ApiSerializable
71
+ attr_reader :kind, :name, :id, :audio_length_seconds, :links, :video_length_seconds
72
+
73
+ KINDS = {
74
+ :transcript => 'transcript',
75
+ :caption => 'caption',
76
+ :media => 'media'
77
+ }
78
+
79
+ # List of supported mime-types used to request attachment's content
80
+ # within 'Accept' header
81
+ REPRESENTATIONS = {
82
+ # Supported by :transcript
83
+ :docx => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
84
+ :pdf => 'application/pdf',
85
+ :txt => 'text/plain',
86
+ :youtube => 'text/plain; format=youtube-transcript',
87
+
88
+ # Supported by :caption
89
+ :srt => 'application/x-subrip',
90
+ :scc => 'text/x-scc',
91
+ :mcc => 'text/x-mcc',
92
+ :ttml => 'application/ttml+xml',
93
+ :qt => 'application/x-quicktime-timedtext',
94
+ :vtt => 'text/vtt',
95
+ :dfxp => 'application/ttaf+xml',
96
+ :cap => 'application/x-cheetah-cap',
97
+ :stl => 'text/x-stl',
98
+ :avidds => 'text/vnd.avid-ds'
99
+ }
100
+
101
+ # @param fields [Hash] fields of attachment fields parsed from JSON API response
102
+ def initialize(fields)
103
+ super fields
104
+ @links = fields['links'].map { |link_fields| Link.new(link_fields) }
105
+ end
106
+
107
+ # @param ext [Symbol] extension
108
+ # @return [String] mime-type for requested extension
109
+ def self.representation_mime(ext)
110
+ REPRESENTATIONS[ext]
111
+ end
112
+ end
113
+
114
+ # Link to actual file represented by attachment
115
+ class Link < ApiSerializable
116
+ attr_reader :rel, :href, :content_type
117
+ end
118
+
119
+ # Represents a paginated list of orders, including padination info.
120
+ class OrdersListPage < ApiSerializable
121
+ attr_reader :total_count, :results_per_page, :page, :orders
122
+
123
+ # @param fields [Hash] hash of OrdersListPage fields parsed from JSON API response
124
+ def initialize(fields)
125
+ super fields
126
+ @orders = fields['orders'].map { |order_fields| Order.new(order_fields) }
127
+ end
128
+ end
129
+ end
@@ -1,222 +1,273 @@
1
- require 'rev-api/api_serializable'
2
-
3
- module Rev
4
- # OrderRequest is used for constructing order 'spec' in consumer code and passing it into.
5
- # It consists of three main elements: :payment, :transcription_options and :notification.
6
- # You can also supply reference number, customer comment, and whether standard turnaround time is not required
7
- #
8
- # @note https://www.rev.com/api/ordersposttranscription, https://www.rev.com/api/ordersposttranslation, https://www.rev.com/api/orderspostcaption
9
- class OrderRequest < ApiSerializable
10
- # see {Rev::Payment}
11
- attr_reader :payment
12
-
13
- # see {Rev::TranscriptionOptions}
14
- attr_reader :transcription_options
15
-
16
- # see {Rev::TranslationOptions}
17
- attr_reader :translation_options
18
-
19
- # see {Rev::CaptionOptions}
20
- attr_reader :caption_options
21
-
22
- # see {Rev::Notification}
23
- attr_reader :notification
24
-
25
- # a reference number for the order meaningful for the client (optional)
26
- attr_reader :client_ref
27
-
28
- # a comment with any special messages about the order (optional)
29
- attr_reader :comment
30
-
31
- # a boolean flag specifying whether normal turnaround time is not required, defaults to false (optional)
32
- attr_reader :non_standard_tat_guarantee
33
-
34
- # @param payment [Payment] payment info
35
- # @param fields [Hash] of fields to initialize instance. See instance attributes for available fields.
36
- # @deprecated payment always defaults to :account_balance
37
- def self.new_with_payment(payment, fields = {})
38
- fields = { :non_standard_tat_guarantee => false }.merge(fields)
39
- super fields
40
- @payment = payment
41
- end
42
-
43
- # @param fields [Hash] of fields to initialize instance. See instance attributes for available fields.
44
- def initialize(fields = {})
45
- fields = { :non_standard_tat_guarantee => false }.merge(fields)
46
- @payment = Rev::Payment.with_account_balance
47
- super fields
48
- end
49
- end
50
-
51
- # Payment Info. Payment can only be done by debiting the user's account balance.
52
- # @deprecated setting the payment is no longer necessary. All orders now default to :account_balance
53
- class Payment < ApiSerializable
54
- attr_accessor :type
55
-
56
- # use to correctly set payment type
57
- TYPES = {
58
- :account_balance => 'AccountBalance'
59
- }
60
-
61
- CC_ON_FILE_ID = 1
62
-
63
- # @param type [String] payment method
64
- def initialize(type)
65
- @type = type
66
- end
67
-
68
- class << self
69
- def with_account_balance()
70
- Payment::new(TYPES[:account_balance])
71
- end
72
- end
73
- end
74
-
75
- # Billing address
76
- class BillingAddress < ApiSerializable
77
- attr_reader :street, :street2, :city, :state, :zip, :country_alpha2
78
- end
79
-
80
- # Superclass for the business-line options that handles capture and common validation of inputs.
81
- class InputOptions < ApiSerializable
82
- # Mandatory, contains list of inputs. Must have at least one element.
83
- attr_reader :inputs
84
-
85
- # @param inputs [Array] list of inputs
86
- # @param info [Hash] of fields to initialize instance.
87
- def initialize(inputs, info = {})
88
- super info
89
- raise(ArgumentError, "inputs must have at least one element") unless validate_inputs(inputs)
90
- @inputs = inputs
91
- end
92
-
93
- private
94
-
95
- def validate_inputs(inputs)
96
- !inputs.nil? && inputs.length > 0
97
- end
98
- end
99
-
100
- # Transcription options. This section contains the input media that must be transferred to our servers
101
- # using a POST to /inputs, and are referenced using the URIs returned by that call. We also support external links.
102
- # @see https://www.rev.com/api/ordersposttranscription
103
- class TranscriptionOptions < InputOptions
104
- # Optional, should we transcribe the provided files verbatim? If true,
105
- # all filler words (i.e. umm, huh) will be included.
106
- attr_reader :verbatim
107
-
108
- # Optional, should we include timestamps?
109
- attr_reader :timestamps
110
-
111
- # @param inputs [Array] list of inputs
112
- # @param info [Hash] of fields to initialize instance. May contain:
113
- # - :verbatim => true/false
114
- # - :timestamps => true/false
115
- def initialize(inputs, info = {})
116
- super inputs, info
117
- end
118
- end
119
-
120
- # Translation options. This section contains the input media that must be transferred to our
121
- # servers using a POST to /inputs, and are referenced using the URIs returned by that call.
122
- # For each media, word count must be specified. The language code for the source and desitination
123
- # languages must also be specified.
124
- # @see https://www.rev.com/api/ordersposttranslation
125
- class TranslationOptions < InputOptions
126
- # Mandatory, source language code
127
- attr_reader :source_language_code
128
-
129
- # Mandatory, destination language code
130
- attr_reader :destination_language_code
131
-
132
- # @param inputs [Array] list of inputs
133
- # @param info [Hash] of fields to initialize instance. May contain:
134
- # - :source_language_code
135
- # - :destination_language_code
136
- # @note For language codes refer to http://www.loc.gov/standards/iso639-2/php/code_list.php
137
- def initialize(inputs, info = {})
138
- super inputs, info
139
- end
140
- end
141
-
142
- # Caption options. This section contains the input media that must be transferred to our servers
143
- # using a POST to /inputs, and are referenced using the URIs returned by that call. We also support external links.
144
- # @see https://www.rev.com/api/orderspostcaption
145
- class CaptionOptions < InputOptions
146
- # Array of file formats the captions should be delivered as. (Optional, default is SubRip)
147
- attr_reader :output_file_formats
148
-
149
- # Optional, Array of language codes to request foreign language subtitles
150
- attr_reader :subtitle_languages
151
-
152
- # All supported output file formats
153
- OUTPUT_FILE_FORMATS = {
154
- :subrip => 'SubRip',
155
- :scc => 'Scc',
156
- :mcc => 'Mcc',
157
- :ttml => 'Ttml',
158
- :qttext => 'QTtext',
159
- :transcript => 'Transcript',
160
- :webvtt => 'WebVtt',
161
- :dfxp => 'Dfxp',
162
- :cheetahcap => 'CheetahCap'
163
- }
164
-
165
- # @param inputs [Array] list of inputs
166
- # @param info [Hash] of fields to initialize instance. May contain:
167
- # - :subtitle_languages
168
- # @see TranslationOptions for a list of language codes.
169
- def initialize(inputs, info = {})
170
- super(inputs, info)
171
- raise(ArgumentError, "invalid format(s)") unless validate_output_formats(info[:output_file_formats])
172
- end
173
-
174
- private
175
-
176
- def validate_output_formats(formats)
177
- formats.nil? || formats.select{|f| !OUTPUT_FILE_FORMATS.has_value?(f) }.empty?
178
- end
179
- end
180
-
181
- # Input for order (aka source file)
182
- class Input < ApiSerializable
183
- # Mandatory when used with {Rev::OrderRequest::TranslationInfo}, length of document, in words
184
- attr_reader :word_length
185
-
186
- # Length of audio in seconds (mandatory in case of inability to determine it automatically).
187
- # Used within {Rev::OrderRequest::TranscriptionInfo}
188
- attr_reader :audio_length_seconds
189
-
190
- # Length of video in seconds (mandatory in case of inability to determine it automatically).
191
- # Used within {Rev::OrderRequest::CaptionInfo}
192
- attr_reader :video_length_seconds
193
-
194
- # Mandatory, URI of the media, as returned from the call to POST /inputs.
195
- # :external_link might substitute :uri for Transcription or Caption.
196
- attr_reader :uri
197
-
198
- # External URL, if sources wasn't POSTed as input (YouTube, Vimeo, Dropbox, etc)
199
- attr_reader :external_link
200
- end
201
-
202
- # Notification Info. Optionally you may request that an HTTP post be made to a url of your choice when the order enters
203
- # a new status (eg being transcribed or reviewed) and when it is complete.
204
- class Notification < ApiSerializable
205
- attr_reader :url, :level
206
-
207
- # Notification levels
208
- LEVELS = {
209
- :detailed => 'Detailed',
210
- :final_only => 'FinalOnly'
211
- }
212
-
213
- # @param url [String] The url for notifications. Mandatory if the notifications element is used. Updates will be posted to this URL
214
- # @param level [String] Optional, specifies which notifications are sent:
215
- # - :detailed - a notification is sent whenever the order is in a new status or has a new comment
216
- # - :final_only - (the default), notification is sent only when the order is complete
217
- def initialize(url, level = nil)
218
- @url = url
219
- @level = level ? level : LEVELS[:final_only]
220
- end
221
- end
222
- end
1
+ require 'rev-api/api_serializable'
2
+
3
+ module Rev
4
+ # OrderRequest is used for constructing order 'spec' in consumer code and passing it into.
5
+ # It consists of three main elements: :payment, :transcription_options and :notification.
6
+ # You can also supply reference number and whether standard turnaround time is not required
7
+ #
8
+ # @note https://www.rev.com/api/ordersposttranscription, https://www.rev.com/api/orderspostcaption
9
+
10
+ GLOSSARY_ENTRIES_LIMIT = 1000
11
+ GLOSSARY_ENTRY_LENGTH_LIMIT = 255
12
+ SPEAKER_ENTRIES_LIMIT = 100
13
+ SPEAKER_ENTRY_LENGTH_LIMIT = 15
14
+
15
+ class OrderRequest < ApiSerializable
16
+ # see {Rev::Payment}
17
+ attr_reader :payment
18
+
19
+ # see {Rev::TranscriptionOptions}
20
+ attr_reader :transcription_options
21
+
22
+ # see {Rev::CaptionOptions}
23
+ attr_reader :caption_options
24
+
25
+ # see {Rev::Notification}
26
+ attr_reader :notification
27
+
28
+ # a reference number for the order meaningful for the client (optional)
29
+ attr_reader :client_ref
30
+
31
+ # a boolean flag specifying whether normal turnaround time is not required, defaults to false (optional)
32
+ attr_reader :non_standard_tat_guarantee
33
+
34
+ # @param payment [Payment] payment info
35
+ # @param fields [Hash] of fields to initialize instance. See instance attributes for available fields.
36
+ # @deprecated payment always defaults to :account_balance
37
+ def self.new_with_payment(payment, fields = {})
38
+ fields = { :non_standard_tat_guarantee => false }.merge(fields)
39
+ super fields
40
+ @payment = payment
41
+ end
42
+
43
+ # @param fields [Hash] of fields to initialize instance. See instance attributes for available fields.
44
+ def initialize(fields = {})
45
+ fields = { :non_standard_tat_guarantee => false }.merge(fields)
46
+ @payment = Rev::Payment.with_account_balance
47
+ super fields
48
+ end
49
+ end
50
+
51
+ # Payment Info. Payment can only be done by debiting the user's account balance.
52
+ # @deprecated setting the payment is no longer necessary. All orders now default to :account_balance
53
+ class Payment < ApiSerializable
54
+ attr_accessor :type
55
+
56
+ # use to correctly set payment type
57
+ TYPES = {
58
+ :account_balance => 'AccountBalance'
59
+ }
60
+
61
+ CC_ON_FILE_ID = 1
62
+
63
+ # @param type [String] payment method
64
+ def initialize(type)
65
+ @type = type
66
+ end
67
+
68
+ class << self
69
+ def with_account_balance()
70
+ Payment::new(TYPES[:account_balance])
71
+ end
72
+ end
73
+ end
74
+
75
+ # Billing address
76
+ class BillingAddress < ApiSerializable
77
+ attr_reader :street, :street2, :city, :state, :zip, :country_alpha2
78
+ end
79
+
80
+ # Superclass for the business-line options that handles capture and common validation of inputs.
81
+ class InputOptions < ApiSerializable
82
+ # Mandatory, contains list of inputs. Must have at least one element.
83
+ attr_reader :inputs
84
+
85
+ # @param inputs [Array] list of inputs
86
+ # @param info [Hash] of fields to initialize instance.
87
+ def initialize(inputs, info = {})
88
+ super info
89
+ raise(ArgumentError, "inputs must have at least one element") unless validate_inputs(inputs)
90
+ @inputs = inputs
91
+ end
92
+
93
+ private
94
+
95
+ def validate_inputs(inputs)
96
+ !inputs.nil? && inputs.length > 0
97
+ end
98
+ end
99
+
100
+ # Transcription options. This section contains the input media that must be transferred to our servers
101
+ # using a POST to /inputs, and are referenced using the URIs returned by that call. We also support external links.
102
+ # @see https://www.rev.com/api/ordersposttranscription
103
+ class TranscriptionOptions < InputOptions
104
+ # Optional, should we transcribe the provided files verbatim? If true,
105
+ # all filler words (i.e. umm, huh) will be included.
106
+ attr_reader :verbatim
107
+
108
+ # Optional, should we include timestamps?
109
+ attr_reader :timestamps
110
+
111
+ # @param inputs [Array] list of inputs
112
+ # @param info [Hash] of fields to initialize instance. May contain:
113
+ # - :verbatim => true/false
114
+ # - :timestamps => true/false
115
+ def initialize(inputs, info = {})
116
+ super inputs, info
117
+ options_validation(inputs)
118
+ end
119
+
120
+ private
121
+
122
+ def options_validation(inputs)
123
+ inputs.each { |input|
124
+ input.validate_glossary
125
+ input.validate_speakers
126
+ input.validate_accents
127
+ }
128
+ end
129
+ end
130
+
131
+ # Caption options. This section contains the input media that must be transferred to our servers
132
+ # using a POST to /inputs, and are referenced using the URIs returned by that call. We also support external links.
133
+ # @see https://www.rev.com/api/orderspostcaption
134
+ class CaptionOptions < InputOptions
135
+ # Array of file formats the captions should be delivered as. (Optional, default is SubRip)
136
+ attr_reader :output_file_formats
137
+
138
+ # Optional, Array of language codes to request foreign language subtitles
139
+ attr_reader :subtitle_languages
140
+
141
+ # All supported output file formats
142
+ OUTPUT_FILE_FORMATS = {
143
+ :subrip => 'SubRip',
144
+ :scc => 'Scc',
145
+ :mcc => 'Mcc',
146
+ :ttml => 'Ttml',
147
+ :qttext => 'QTtext',
148
+ :transcript => 'Transcript',
149
+ :webvtt => 'WebVtt',
150
+ :dfxp => 'Dfxp',
151
+ :cheetahcap => 'CheetahCap'
152
+ }
153
+
154
+ # @param inputs [Array] list of inputs
155
+ # @param info [Hash] of fields to initialize instance. May contain:
156
+ # - :subtitle_languages
157
+ # @see For language codes refer to http://www.loc.gov/standards/iso639-2/php/code_list.php
158
+ def initialize(inputs, info = {})
159
+ super(inputs, info)
160
+ raise(ArgumentError, "invalid format(s)") unless validate_output_formats(info[:output_file_formats])
161
+ options_validation(inputs)
162
+ end
163
+
164
+ private
165
+
166
+ def validate_output_formats(formats)
167
+ formats.nil? || formats.select{|f| !OUTPUT_FILE_FORMATS.has_value?(f) }.empty?
168
+ end
169
+
170
+ def options_validation(inputs)
171
+ inputs.each { |input|
172
+ input.validate_glossary
173
+ input.validate_speakers
174
+ }
175
+ end
176
+ end
177
+
178
+ # Input for order (aka source file)
179
+ class Input < ApiSerializable
180
+ # Length of audio in seconds (mandatory in case of inability to determine it automatically).
181
+ # Used within {Rev::OrderRequest::TranscriptionInfo}
182
+ attr_reader :audio_length_seconds
183
+
184
+ # Length of video in seconds (mandatory in case of inability to determine it automatically).
185
+ # Used within {Rev::OrderRequest::CaptionInfo}
186
+ attr_reader :video_length_seconds
187
+
188
+ # Mandatory, URI of the media, as returned from the call to POST /inputs.
189
+ # :external_link might substitute :uri for Transcription or Caption.
190
+ attr_reader :uri
191
+
192
+ # External URL, if sources wasn't POSTed as input (YouTube, Vimeo, Dropbox, etc)
193
+ attr_reader :external_link
194
+
195
+ # Optional, list of glossary entries.
196
+ attr_reader :glossary
197
+
198
+ # Optional, list of speaker names.
199
+ attr_reader :speakers
200
+
201
+ # Optional, list of accents.
202
+ attr_reader :accents
203
+
204
+ SUPPORTED_ACCENTS = {
205
+ :american_neutral => 'AmericanNeutral',
206
+ :american_southern => 'AmericanSouthern',
207
+ :asian => 'Asian',
208
+ :australian => 'Australian',
209
+ :british => 'British',
210
+ :indian => 'Indian',
211
+ :other => 'Other',
212
+ :unknown => 'Unknown'
213
+ }
214
+
215
+ def validate_glossary
216
+ if glossary
217
+ if glossary.length > GLOSSARY_ENTRIES_LIMIT
218
+ raise(ArgumentError, "Glossary must not exceed #{GLOSSARY_ENTRIES_LIMIT} entries")
219
+ end
220
+ glossary.each { |term|
221
+ if term.length > GLOSSARY_ENTRY_LENGTH_LIMIT
222
+ raise(ArgumentError, "Glossary entries cannot exceed #{GLOSSARY_ENTRY_LENGTH_LIMIT} characters")
223
+ end
224
+ }
225
+ end
226
+ end
227
+
228
+ def validate_speakers
229
+ if speakers
230
+ if speakers.length > SPEAKER_ENTRIES_LIMIT
231
+ raise(ArgumentError, "Speaker list must not exceed #{SPEAKER_ENTRIES_LIMIT} entries")
232
+ end
233
+ speakers.each { |speaker|
234
+ if speaker.length > SPEAKER_ENTRY_LENGTH_LIMIT
235
+ raise(ArgumentError, "Speaker name cannot exceed #{SPEAKER_ENTRY_LENGTH_LIMIT} characters")
236
+ end
237
+ }
238
+ end
239
+ end
240
+
241
+ def validate_accents
242
+ if accents
243
+ if accents.length > SUPPORTED_ACCENTS.length
244
+ raise(ArgumentError, "Length of accents list cannot exceed number of supported accents.")
245
+ end
246
+ if accents.any?{ |accent| !Rev::Input::SUPPORTED_ACCENTS.has_value?(accent) }
247
+ raise(ArgumentError, 'Unsupported accent provided')
248
+ end
249
+ end
250
+ end
251
+ end
252
+
253
+ # Notification Info. Optionally you may request that an HTTP post be made to a url of your choice when the order enters
254
+ # a new status (eg being transcribed or reviewed) and when it is complete.
255
+ class Notification < ApiSerializable
256
+ attr_reader :url, :level
257
+
258
+ # Notification levels
259
+ LEVELS = {
260
+ :detailed => 'Detailed',
261
+ :final_only => 'FinalOnly'
262
+ }
263
+
264
+ # @param url [String] The url for notifications. Mandatory if the notifications element is used. Updates will be posted to this URL
265
+ # @param level [String] Optional, specifies which notifications are sent:
266
+ # - :detailed - a notification is sent whenever the order is in a new status or has a new comment
267
+ # - :final_only - (the default), notification is sent only when the order is complete
268
+ def initialize(url, level = nil)
269
+ @url = url
270
+ @level = level ? level : LEVELS[:final_only]
271
+ end
272
+ end
273
+ end