bbc_redux 0.4.7.pre → 0.4.8.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +0 -2
- data/bbc_redux.gemspec +4 -0
- data/bin/bbc-redux +325 -0
- data/lib/bbc/redux/channel.rb +2 -0
- data/lib/bbc/redux/serializers.rb +5 -0
- data/lib/bbc/redux/version.rb +1 -1
- data/lib/bbc/redux.rb +1 -0
- metadata +22 -4
data/README.md
CHANGED
data/bbc_redux.gemspec
CHANGED
@@ -29,6 +29,8 @@ Gem::Specification.new do |gem|
|
|
29
29
|
|
30
30
|
# Files / paths
|
31
31
|
|
32
|
+
gem.executables << 'bbc-redux'
|
33
|
+
|
32
34
|
gem.files = FileList[
|
33
35
|
'AUTHORS',
|
34
36
|
'COPYING',
|
@@ -36,6 +38,7 @@ Gem::Specification.new do |gem|
|
|
36
38
|
'README.md',
|
37
39
|
'Rakefile',
|
38
40
|
'bbc_redux.gemspec',
|
41
|
+
'bin/*',
|
39
42
|
'lib/**/*'
|
40
43
|
]
|
41
44
|
|
@@ -54,6 +57,7 @@ Gem::Specification.new do |gem|
|
|
54
57
|
|
55
58
|
gem.add_dependency 'nokogiri'
|
56
59
|
gem.add_dependency 'representable'
|
60
|
+
gem.add_dependency 'terminal-table'
|
57
61
|
gem.add_dependency 'typhoeus', '>= 0.6.8'
|
58
62
|
gem.add_dependency 'virtus', '>= 0.5.0'
|
59
63
|
|
data/bin/bbc-redux
ADDED
@@ -0,0 +1,325 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# vim: set filetype=ruby:
|
4
|
+
|
5
|
+
$LOAD_PATH << File.join( File.dirname(__FILE__), '..', 'lib' )
|
6
|
+
|
7
|
+
require 'fileutils'
|
8
|
+
require 'logger'
|
9
|
+
require 'optparse'
|
10
|
+
|
11
|
+
require 'bbc/redux'
|
12
|
+
require 'terminal-table'
|
13
|
+
|
14
|
+
################################################################################
|
15
|
+
# OPTIONS PARSER
|
16
|
+
|
17
|
+
def parse_options( input )
|
18
|
+
|
19
|
+
options = { :command => :assets }
|
20
|
+
|
21
|
+
parser = OptionParser.new do |opts|
|
22
|
+
|
23
|
+
opts.banner = 'usage: ' + File.basename(__FILE__) + ' [options]'
|
24
|
+
|
25
|
+
opts.separator ''
|
26
|
+
opts.separator 'asset download options:'
|
27
|
+
|
28
|
+
opts.on( '-a', '--after DATE', 'Filter by after date' ) do |d|
|
29
|
+
options[:after] = DateTime.parse( d )
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on( '-b', '--before DATE', 'Filter by before date' ) do |d|
|
33
|
+
options[:before] = DateTime.parse( d )
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on( '-c', '--channels CHANNEL,...', 'Filter by channel name' ) do |c|
|
37
|
+
options[:channel] = c.split(',')
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on( '-i', '--id ID', 'Filter by asset id' ) do |i|
|
41
|
+
options[:id] = i
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on( '-m', '--metadata', 'Download json metadata' ) do |metadata|
|
45
|
+
options[:metadata] = metadata
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on( '-o', '--output-directory DIR', 'Save to directory' ) do |d|
|
49
|
+
options[:output_directory] = d
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on( '-p', '--profiles PROFILE,...', 'Fetch asset with profile' ) do |p|
|
53
|
+
options[:profiles] = p.split(',')
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.on( '-q', '--query QUERY', 'Filter by query' ) do |q|
|
57
|
+
options[:q] = q
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on( '--[no]-repeats', 'Include / exclude repeats' ) do |repeats|
|
61
|
+
options[:repeats] = repeats
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.separator ''
|
65
|
+
opts.separator 'channel info commands:'
|
66
|
+
|
67
|
+
opts.on( '--list-channels', 'List available channels' ) do
|
68
|
+
options[:command] = :list_channels
|
69
|
+
end
|
70
|
+
|
71
|
+
opts.on( '--list-categories', 'List available channel categories' ) do
|
72
|
+
options[:command] = :list_categories
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.separator ''
|
76
|
+
opts.separator 'common options:'
|
77
|
+
|
78
|
+
opts.on_tail( '-h', '--help', 'Show this message' ) do
|
79
|
+
puts opts
|
80
|
+
puts DATA.read
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on_tail( '-v', '--verbose', 'Enable verbose logging' ) do
|
85
|
+
options[:verbose] = true
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.on_tail( '-V', '--version', 'Show version' ) do
|
89
|
+
puts BBC::Redux::VERSION
|
90
|
+
exit
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
parser.parse!( input )
|
96
|
+
|
97
|
+
return options
|
98
|
+
|
99
|
+
rescue ArgumentError,
|
100
|
+
OptionParser::InvalidOption,
|
101
|
+
OptionParser::MissingArgument => e
|
102
|
+
$stderr.puts e.message
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
|
106
|
+
################################################################################
|
107
|
+
# APPLICATION
|
108
|
+
|
109
|
+
class BBC::Redux::CLI
|
110
|
+
|
111
|
+
attr_reader :options
|
112
|
+
|
113
|
+
def initialize( options )
|
114
|
+
@options = options
|
115
|
+
end
|
116
|
+
|
117
|
+
def run
|
118
|
+
|
119
|
+
valid_commands = [ :assets, :list_channels, :list_categories ]
|
120
|
+
|
121
|
+
if valid_commands.include? options[:command]
|
122
|
+
self.send( options[:command] )
|
123
|
+
else
|
124
|
+
fail "Unrecognized command #{options[:command]}, see --help"
|
125
|
+
end
|
126
|
+
|
127
|
+
if options[:token].nil?
|
128
|
+
logger.debug 'Logging out of redux'
|
129
|
+
redux_client.logout
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
def logger
|
135
|
+
if @logger.nil?
|
136
|
+
@logger = Logger.new( $stderr )
|
137
|
+
|
138
|
+
if options[:verbose]
|
139
|
+
@logger.level = Logger::DEBUG
|
140
|
+
else
|
141
|
+
@logger.level = Logger::INFO
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
@logger
|
146
|
+
end
|
147
|
+
|
148
|
+
def redux_client
|
149
|
+
if @redux_client.nil?
|
150
|
+
if options[:token]
|
151
|
+
credentials = { :token => options[:token] }
|
152
|
+
elsif options[:username] && options[:password]
|
153
|
+
credentials = {
|
154
|
+
:username => options[:username],
|
155
|
+
:password => options[:password],
|
156
|
+
}
|
157
|
+
else
|
158
|
+
$stderr.puts 'You need to set either the REDUX_TOKEN or REDUX_USERNAME'
|
159
|
+
$stderr.puts 'and REDUX_PASSWORD environment variables'
|
160
|
+
fail
|
161
|
+
end
|
162
|
+
|
163
|
+
@redux_client = BBC::Redux::Client.new( credentials )
|
164
|
+
end
|
165
|
+
|
166
|
+
@redux_client
|
167
|
+
end
|
168
|
+
|
169
|
+
def fail( message = '' )
|
170
|
+
$stderr.puts message
|
171
|
+
exit 1
|
172
|
+
end
|
173
|
+
|
174
|
+
def print_table( headings, rows )
|
175
|
+
puts Terminal::Table.new :headings => headings, :rows => rows
|
176
|
+
end
|
177
|
+
|
178
|
+
def assets
|
179
|
+
|
180
|
+
disk_references = [ ]
|
181
|
+
output_directory = options[:output_directory] || '.'
|
182
|
+
|
183
|
+
FileUtils.mkdir_p output_directory
|
184
|
+
|
185
|
+
if options[:id]
|
186
|
+
disk_references << options[:id]
|
187
|
+
else
|
188
|
+
|
189
|
+
search_params = options.select do |key,_|
|
190
|
+
[ :after, :before, :channel, :q ].include? key
|
191
|
+
end
|
192
|
+
|
193
|
+
unless options[:repeats] == false
|
194
|
+
search_params[:repeats] = true
|
195
|
+
end
|
196
|
+
|
197
|
+
search_params = search_params.merge({
|
198
|
+
:offset => 0,
|
199
|
+
:sort_by =>'time',
|
200
|
+
:sort_order => 'ascending'
|
201
|
+
})
|
202
|
+
|
203
|
+
logger.info 'Searching for references'
|
204
|
+
|
205
|
+
results = redux_client.search( search_params )
|
206
|
+
|
207
|
+
while true do
|
208
|
+
results.assets.each { |a| disk_references << a.disk_reference }
|
209
|
+
|
210
|
+
if results.has_more?
|
211
|
+
next_query = results.query.merge({
|
212
|
+
:offset => results.query[:offset] + 10
|
213
|
+
})
|
214
|
+
|
215
|
+
logger.debug "Searching for references, offset #{next_query[:offset]}"
|
216
|
+
|
217
|
+
results = redux_client.search(next_query)
|
218
|
+
else
|
219
|
+
break
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
disk_references.each do |disk_reference|
|
225
|
+
|
226
|
+
logger.info 'Fetching data for asset ' + disk_reference
|
227
|
+
|
228
|
+
asset = redux_client.asset( disk_reference )
|
229
|
+
|
230
|
+
if options[:metadata]
|
231
|
+
logger.debug 'Saving metadata for asset ' + disk_reference
|
232
|
+
|
233
|
+
serializer = BBC::Redux::Serializers::Asset.new( asset )
|
234
|
+
file_path = File.join( output_directory, disk_reference + '.json' )
|
235
|
+
|
236
|
+
File.open( file_path, 'w' ) { |f| f << serializer.to_json }
|
237
|
+
end
|
238
|
+
|
239
|
+
if options[:profiles]
|
240
|
+
options[:profiles].each do |profile|
|
241
|
+
|
242
|
+
logger.debug "Saving profile #{profile} for asset #{disk_reference}"
|
243
|
+
|
244
|
+
url = asset.send( profile + '_url' ).end_point
|
245
|
+
fname = File.basename( url )
|
246
|
+
file_path = File.join( output_directory, fname )
|
247
|
+
|
248
|
+
`wget --quiet -O "#{file_path}" "#{url}"`
|
249
|
+
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
def list_categories
|
258
|
+
logger.debug 'Listing categories'
|
259
|
+
|
260
|
+
headings = %w{ id description priority }
|
261
|
+
|
262
|
+
rows = redux_client.channel_categories.map do |category|
|
263
|
+
[ category.id, category.description, category.priority ]
|
264
|
+
end
|
265
|
+
|
266
|
+
print_table headings, rows
|
267
|
+
end
|
268
|
+
|
269
|
+
def list_channels
|
270
|
+
logger.debug 'Listing channels'
|
271
|
+
|
272
|
+
headings = %w{ category_id longname name sortorder }
|
273
|
+
|
274
|
+
rows = redux_client.channels.map do |channel|
|
275
|
+
[
|
276
|
+
channel.category_id,
|
277
|
+
channel.longname,
|
278
|
+
channel.name,
|
279
|
+
channel.sortorder
|
280
|
+
]
|
281
|
+
end
|
282
|
+
|
283
|
+
print_table headings, rows
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
################################################################################
|
289
|
+
# FIRE UP THE QUATTRO
|
290
|
+
|
291
|
+
options = parse_options( ARGV )
|
292
|
+
|
293
|
+
runner = BBC::Redux::CLI.new( options.merge({
|
294
|
+
:token => ENV['REDUX_TOKEN'],
|
295
|
+
:username => ENV['REDUX_USERNAME'],
|
296
|
+
:password => ENV['REDUX_PASSWORD'],
|
297
|
+
}))
|
298
|
+
|
299
|
+
runner.run
|
300
|
+
|
301
|
+
################################################################################
|
302
|
+
# EXTENDED USAGE INFO
|
303
|
+
|
304
|
+
__END__
|
305
|
+
|
306
|
+
examples:
|
307
|
+
|
308
|
+
To use the client you must have set one of these environment variables:
|
309
|
+
|
310
|
+
REDUX_TOKEN # A valid session token
|
311
|
+
REDUX_USERNAME & REDUX_PASSWORD # Your credentials
|
312
|
+
|
313
|
+
You may then us the client, some examples below:
|
314
|
+
|
315
|
+
# Listing channels
|
316
|
+
$: bbc-redux --list-channels
|
317
|
+
|
318
|
+
# Downloading json metadata for an asset
|
319
|
+
$: bbc-redux --metadata --id 6008591816398520492
|
320
|
+
|
321
|
+
# Downloading MP3 files for a week of The Archers
|
322
|
+
$: bbc-redux -p mp3 -q 'The Archers' -a 2014-W01 -b 2014-W02
|
323
|
+
|
324
|
+
# Downloading TS files for a day of BBC One
|
325
|
+
$: bbc-redux -p ts -c bbcone -a 2014-01-01 -b 2014-01-02
|
data/lib/bbc/redux/channel.rb
CHANGED
@@ -42,6 +42,11 @@ module BBC
|
|
42
42
|
|
43
43
|
end
|
44
44
|
|
45
|
+
class Assets < Representable::Decorator
|
46
|
+
include Representable::JSON::Collection
|
47
|
+
items extend: Asset, class: BBC::Redux::Asset
|
48
|
+
end
|
49
|
+
|
45
50
|
class Channel < Representable::Decorator
|
46
51
|
include Representable::JSON
|
47
52
|
property :category_id, :as => :category
|
data/lib/bbc/redux/version.rb
CHANGED
data/lib/bbc/redux.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bbc_redux
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.8.pre
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-03-
|
14
|
+
date: 2015-03-13 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rspec
|
@@ -109,6 +109,22 @@ dependencies:
|
|
109
109
|
- - ! '>='
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: terminal-table
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
type: :runtime
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
112
128
|
- !ruby/object:Gem::Dependency
|
113
129
|
name: typhoeus
|
114
130
|
requirement: !ruby/object:Gem::Requirement
|
@@ -145,7 +161,8 @@ description: A gem to help navigate the BBC Redux API
|
|
145
161
|
email:
|
146
162
|
- james.harrison@bbc.co.uk
|
147
163
|
- matt.haynes@bbc.co.uk
|
148
|
-
executables:
|
164
|
+
executables:
|
165
|
+
- bbc-redux
|
149
166
|
extensions: []
|
150
167
|
extra_rdoc_files: []
|
151
168
|
files:
|
@@ -155,6 +172,7 @@ files:
|
|
155
172
|
- README.md
|
156
173
|
- Rakefile
|
157
174
|
- bbc_redux.gemspec
|
175
|
+
- bin/bbc-redux
|
158
176
|
- lib/bbc/redux/asset.rb
|
159
177
|
- lib/bbc/redux/channel.rb
|
160
178
|
- lib/bbc/redux/channel_category.rb
|
@@ -200,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
200
218
|
version: '0'
|
201
219
|
segments:
|
202
220
|
- 0
|
203
|
-
hash:
|
221
|
+
hash: 2647790705023314369
|
204
222
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
205
223
|
none: false
|
206
224
|
requirements:
|