VRFS-2481 : Use jam_tracks object hierarchy to create jkz file, and upload to AWS. Meshed out spec to verify creation and upload, including a real ogg file (required by the python tool).

This commit is contained in:
Steven Miers 2014-12-15 18:02:51 -06:00
parent 1a7420ffb1
commit 8ac9d19e73
5 changed files with 141 additions and 30 deletions

View File

@ -1,6 +1,8 @@
require 'json'
require 'tempfile'
require 'open3'
require 'fileutils'
require 'open-uri'
module JamRuby
@ -8,31 +10,69 @@ module JamRuby
class JamTracksManager
class << self
def save_jam_track_jkz(user, jam_track)
py_root = File.expand_path(File.join("..", "..", "jamtracks"))
tmp_dir = Dir::Tmpname.make_tmpname("/tmp/jamtrack", nil)
puts "Executing python in #{py_root}, outputting to #{tmp_dir}"
sku=jam_track.id
tracks_filename=tmp_dir + "/jamtrack.info"
output_jkz="tmp_dir/#{jam_track.name.tableize}.jkz"
title=jam_track.name
# From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819:
#Open3.popen3("ls") do |stdin, stdout, stderr, wait_thr|
Open3.popen3("python",
"#{py_root}/jkcreate.py",
"-D -k #{sku} -c art.png -p #{tmp_dir}/pkey.pem -s #{tmp_dir}/skey.pem -I #{tracks_filename} -o #{output_jkz} -t '#{title}'"
) do |stdin, stdout, stderr, wait_thr|
pid = wait_thr.pid
exit_status = wait_thr.value
err = stderr.read(1000)
raise ArgumentError, "Error calling python script: #{err}" if err.present?
end
tmp_dir
jam_track_right = jam_track.right_for_user(user)
raise ArgumentError if jam_track_right.nil?
save_jam_track_right_jkz(jam_track_right)
end
end
end
end
def save_jam_track_right_jkz(jam_track_right)
jam_track = jam_track_right.jam_track
py_root = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "jamtracks"))
Dir.mktmpdir do |tmp_dir|
jam_file_opts=""
jam_track.jam_track_tracks.each do |jam_track_track|
nm=jam_track_track.filename
nm.gsub!(" ", "_")
track_filename = File.join(tmp_dir, nm)
track_url = jam_track_track.sign_url
copy_url_to_file(track_url, track_filename)
jam_file_opts << " -i '#{track_filename}+#{jam_track_track.part}'"
end
sku=jam_track.id
title=jam_track.name
output_jkz=File.join(tmp_dir, "#{title.parameterize}.jkz")
py_file = File.join(py_root, "jkcreate.py")
puts "Executing python source in #{py_file}, outputting to #{tmp_dir} (#{output_jkz})"
# From http://stackoverflow.com/questions/690151/getting-output-of-system-calls-in-ruby/5970819#5970819:
cli = "python #{py_file} -D -k #{sku} -p #{tmp_dir}/pkey.pem -s #{tmp_dir}/skey.pem #{jam_file_opts} -o #{output_jkz} -t '#{title}'"
Open3.popen3(cli) do |stdin, stdout, stderr, wait_thr|
pid = wait_thr.pid
exit_status = wait_thr.value
err = stderr.read(1000)
out = stdout.read(1000)
#puts "stdout: #{out}, stderr: #{err}"
raise ArgumentError, "Error calling python script: #{out}" if out && (out.index("No track files specified") || out.index("Cannot find file"))
raise ArgumentError, "Error calling python script: #{err}" if err.present?
jam_track_right[:url]
jam_track_right.url.store!(File.open(output_jkz))
jam_track_right.save!
end
end # mktmpdir
jam_track_right
end # save_jam_track_jkz
def copy_url_to_file(url, filename)
uri = URI(url)
open(filename, 'wb') do |io|
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri
http.request request do |response|
response_code = response.code.to_i
unless response_code >= 200 && response_code <= 299
raise "bad status code: #{response_code}. body: #{response.body}"
end
response.read_body do |chunk|
io.write chunk
end
end
end
end
end # copy_url_to_file
end # self
end # class
end # module

View File

@ -43,7 +43,7 @@ module JamRuby
has_many :jam_track_tracks, :class_name => "JamRuby::JamTrackTrack", order: 'position ASC'
has_many :jam_track_rights, :class_name => "JamRuby::JamTrackRight", inverse_of: 'jam_track', :foreign_key => "jam_track_id"
has_many :jam_track_rights, :class_name => "JamRuby::JamTrackRight" #, inverse_of: 'jam_track', :foreign_key => "jam_track_id"
has_many :owners, :through => :jam_track_rights, :class_name => "JamRuby::User", :source => :user
accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true
@ -107,6 +107,10 @@ module JamRuby
#JamTrack.joins(:recording).joins(:recording => :claimed_recordings)
end
def right_for_user(user)
jam_track_rights.where("user_id=?", user).first
end
private

View File

@ -2,6 +2,7 @@ module JamRuby
# describes what users have rights to which tracks
class JamTrackRight < ActiveRecord::Base
include JamRuby::S3ManagerMixin
attr_accessible :user, :jam_track, :user_id, :jam_track_id, :url, :md5, :length, :download_count
belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
@ -16,6 +17,15 @@ module JamRuby
mount_uploader :url, JamTrackRightUploader
MAX_JAM_TRACK_DOWNLOADS = 1000
def store_dir
"#{jam_track.store_dir}/rights"
end
# create name of the file
def filename
"#{jam_track.name}.jkz"
end
def verify_download_count
if (self.download_count < 0 || self.download_count > MAX_JAM_TRACK_DOWNLOADS) && !@current_user.admin
@ -28,5 +38,14 @@ module JamRuby
end
# creates a short-lived URL that has access to the object.
# the idea is that this is used when a user who has the rights to this tries to download this JamTrack
# we would verify their rights (can_download?), and generates a URL in response to the click so that they can download
# but the url is short lived enough so that it wouldn't be easily shared
def sign_url(expiration_time = 120)
s3_manager.sign_url(self[:url], {:expires => expiration_time, :response_content_type => 'jkz', :secure => false})
end
end
end

BIN
ruby/spec/files/on.ogg Normal file

Binary file not shown.

View File

@ -1,7 +1,8 @@
require 'spec_helper'
describe JamTrackRight do
include UsesTempFiles
include CarrierWave::Test::Matchers
it "created" do
jam_track_right = FactoryGirl.create(:jam_track_right)
@ -28,13 +29,60 @@ describe JamTrackRight do
end
end
it "saves JKZ" do
describe "JKZ" do
before(:all) do
original_storage = JamTrackTrackUploader.storage = :fog
original_storage = JamTrackRightUploader.storage = :fog
end
after(:all) do
JamTrackTrackUploader.storage = @original_storage
JamTrackRightUploader.storage = @original_storage
end
before(:each) do
#content_for_file('abc')
end
it "should fail if no tracks" do
user = FactoryGirl.create(:user)
jam_track = FactoryGirl.create(:jam_track)
right = JamTrackRight.create(:user=>user, :jam_track=>jam_track)
expect {
JamRuby::JamTracksManager.save_jam_track_jkz(user, jam_track)
}.to_not raise_error
}.to raise_error(ArgumentError)
end
it "should create" do
ogg_path = File.join('spec', 'files', 'on.ogg')
user = FactoryGirl.create(:user)
#jam_track = FactoryGirl.create(:jam_track)
jam_track_track = FactoryGirl.create(:jam_track_track)
jam_track = jam_track_track.jam_track
uploader = JamTrackTrackUploader.new(jam_track_track, :url)
uploader.store!(File.open(ogg_path))
jam_track_track.save!
jam_track_track[:url].should == jam_track_track.store_dir + '/' + jam_track_track.filename
# verify it's on S3
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
s3.exists?(jam_track_track[:url]).should be_true
s3.length(jam_track_track[:url]).should == File.size?(ogg_path)
jam_track_right = JamTrackRight.create(:user=>user, :jam_track=>jam_track)
expect {
JamRuby::JamTracksManager.save_jam_track_jkz(user, jam_track)
}.to_not raise_error(ArgumentError)
jam_track_right.reload
jam_track_right[:url].should == jam_track_right.store_dir + '/' + jam_track_right.filename
# verify it's on S3
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
s3.exists?(jam_track_right[:url]).should be_true
s3.length(jam_track_right[:url]).should > File.size?(ogg_path)
end
end
end