Merge branch 'develop' into feature/nocaptcha
This commit is contained in:
commit
6cfe5decbf
|
|
@ -11,6 +11,18 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
|
|||
form :partial => 'form'
|
||||
|
||||
index do
|
||||
|
||||
# default_actions # use this for all view/edit/delete links
|
||||
column "Actions" do |jam_track|
|
||||
links = ''.html_safe
|
||||
clz = "member_link view_link show_tracks"
|
||||
clz += ' expand' if params[:focus_track]==jam_track.id
|
||||
links << link_to("Show Tracks", '#', :class => clz)
|
||||
links << link_to("Update", edit_resource_path(jam_track), :class => "member_link edit_link")
|
||||
links
|
||||
end
|
||||
|
||||
|
||||
column :id
|
||||
column :name
|
||||
column :description
|
||||
|
|
@ -40,18 +52,35 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
|
|||
column :track_type
|
||||
column :instrument
|
||||
column :part
|
||||
column :track do |track|
|
||||
|
||||
column "" do |track|
|
||||
if track.position > 1
|
||||
link_to 'Move Up', "jam_tracks/#{track.id}/move_up"
|
||||
end
|
||||
end
|
||||
column "" do |track|
|
||||
if track.position < jam_track.jam_track_tracks.count
|
||||
link_to 'Move Down', "jam_tracks/#{track.id}/move_down"
|
||||
end
|
||||
end
|
||||
column "" do |track|
|
||||
link_to 'Play', '#'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# default_actions # use this for all view/edit/delete links
|
||||
column "Actions" do |jam_track|
|
||||
links = ''.html_safe
|
||||
links << link_to("Show Tracks", '#', :class => "member_link view_link show_tracks")
|
||||
links << link_to("Update", edit_resource_path(jam_track), :class => "member_link edit_link")
|
||||
links
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
member_action :move_up, :method => :get do
|
||||
track = JamTrackTrack.where("id=?",params[:id]).first
|
||||
track.move_up
|
||||
redirect_to("/admin/jam_tracks?focus_track=#{track.jam_track_id}", {:notice => "Moved Up."})
|
||||
end
|
||||
|
||||
member_action :move_down, :method => :get do
|
||||
track = JamTrackTrack.where("id=?",params[:id]).first
|
||||
track.move_down
|
||||
redirect_to("/admin/jam_tracks?focus_track=#{track.jam_track_id}", {:notice => "Moved Down."})
|
||||
end
|
||||
end
|
||||
|
|
@ -1,43 +1,48 @@
|
|||
function showTracks(rowJamTrack) {
|
||||
var $jamTrackTracks = rowJamTrack.find("td.jam_track_tracks");
|
||||
|
||||
var name=rowJamTrack.find("td.name").text()
|
||||
var count = $jamTrackTracks.find("table tbody tr").length;
|
||||
|
||||
if (rowJamTrack.next().attr('id') == "jam_track_tracks_detail") {
|
||||
$(this).html("Show Tracks");
|
||||
rowJamTrack.next().remove();
|
||||
} else {
|
||||
$(this).html('Hide Tracks');
|
||||
if (count == 0) {
|
||||
rowJamTrack.after(
|
||||
$("<tr id=\"jam_track_tracks_detail\"></tr>").html(
|
||||
$("<td colspan=\"1\"></td>")
|
||||
).append(
|
||||
$("<td colspan=\"4\"></td>").html(
|
||||
"No Tracks"
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
rowJamTrack.after(
|
||||
$("<tr id=\"jam_track_tracks_detail\"></tr>").html(
|
||||
$("<td/><td colspan=\"1\"><em><strong>Tracks in '" + name + "':</strong></em></td>")
|
||||
).append(
|
||||
$("<td colspan=\"4\"></td>").html(
|
||||
$jamTrackTracks.html()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("th.jam_track_tracks").css('display', 'none');
|
||||
$("td.jam_track_tracks").css('display', 'none');
|
||||
|
||||
showTracks($("a.expand").parents("tr"))
|
||||
|
||||
$(".show_tracks").click(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $rowJamTrack = $(this).parents('tr');
|
||||
var $jamTrackTracks = $($rowJamTrack).find("td.jam_track_tracks");
|
||||
|
||||
var count = $jamTrackTracks.find("table tbody tr").length;
|
||||
|
||||
if ($rowJamTrack.next().attr('id') == "jam_track_tracks_detail") {
|
||||
$(this).html("Show Tracks");
|
||||
$rowJamTrack.next().remove();
|
||||
}
|
||||
else {
|
||||
$(this).html('Hide Tracks');
|
||||
if (count == 0) {
|
||||
$rowJamTrack.after(
|
||||
$("<tr id=\"jam_track_tracks_detail\"></tr>").html(
|
||||
$("<td colspan=\"18\"></td>")
|
||||
).append(
|
||||
$("<td colspan=\"4\"></td>").html(
|
||||
"No Tracks"
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
$rowJamTrack.after(
|
||||
$("<tr id=\"jam_track_tracks_detail\"></tr>").html(
|
||||
$("<td colspan=\"18\"></td>")
|
||||
).append(
|
||||
$("<td colspan=\"4\"></td>").html(
|
||||
$jamTrackTracks.html()
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
showTracks($rowJamTrack)
|
||||
})
|
||||
});
|
||||
|
|
@ -2,25 +2,26 @@
|
|||
= f.semantic_errors *f.object.errors.keys
|
||||
= f.inputs name: 'JamTrack fields' do
|
||||
|
||||
= f.input :name
|
||||
= f.input :description
|
||||
= f.input :name, :input_html => { :rows=>1, :maxlength=>200 }
|
||||
= f.input :description, :input_html => { :rows=>5, :maxlength=>1000 }
|
||||
= f.input :bpm
|
||||
= f.input :time_signature, collection: JamRuby::JamTrack::TIME_SIGNATURES
|
||||
= f.input :status, collection: JamRuby::JamTrack::STATUS
|
||||
= f.input :recording_type, collection: JamRuby::JamTrack::RECORDING_TYPE
|
||||
= f.input :original_artist
|
||||
= f.input :songwriter
|
||||
= f.input :publisher
|
||||
= f.input :licensor, collection: JamRuby::JamTrackLicensor.all
|
||||
= f.input :pro, collection: JamRuby::JamTrack::PRO
|
||||
= f.input :genre, collection: JamRuby::Genre.all
|
||||
= f.input :sales_region, collection: JamRuby::JamTrack::SALES_REGION
|
||||
= f.input :price
|
||||
= f.input :time_signature, collection: JamRuby::JamTrack::TIME_SIGNATURES, include_blank: false
|
||||
= f.input :status, collection: JamRuby::JamTrack::STATUS, include_blank: false
|
||||
= f.input :recording_type, collection: JamRuby::JamTrack::RECORDING_TYPE, include_blank: false
|
||||
= f.input :original_artist, :input_html => { :rows=>2, :maxlength=>200 }
|
||||
= f.input :songwriter, :input_html => { :rows=>5, :maxlength=>1000 }
|
||||
= f.input :publisher, :input_html => { :rows=>5, :maxlength=>1000 }
|
||||
= f.input :licensor, collection: JamRuby::JamTrackLicensor.all, include_blank: false
|
||||
= f.input :pro, collection: JamRuby::JamTrack::PRO, include_blank: false
|
||||
= f.input :genre, collection: JamRuby::Genre.all, include_blank: false
|
||||
= f.input :sales_region, collection: JamRuby::JamTrack::SALES_REGION, include_blank: false
|
||||
= f.input :price, :required=>true, :input_html=>{type:'numeric'}
|
||||
= f.input :reproduction_royalty, :label => 'Reproduction Royalty'
|
||||
= f.input :public_performance_royalty, :label => 'Public Performance Royalty'
|
||||
= f.input :reproduction_royalty_amount
|
||||
= f.input :licensor_royalty_amount
|
||||
= f.input :pro_royalty_amount
|
||||
= f.input :reproduction_royalty_amount, :required=>true, :input_html=>{type:'numeric'}
|
||||
= f.input :licensor_royalty_amount, :required=>true, :input_html=>{type:'numeric'}
|
||||
= f.input :pro_royalty_amount, :required=>true, :input_html=>{type:'numeric'}
|
||||
= f.input :plan_code, :label=>'Recurly Plan Code', :required=>true
|
||||
= f.input :url, :as => :file, :label => 'Audio File'
|
||||
|
||||
= f.semantic_fields_for :jam_track_tracks do |track|
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
= f.inputs name: 'Track fields' do
|
||||
|
||||
%ol.nested-fields
|
||||
= f.input :track_type, :as => :select, collection: JamRuby::JamTrackTrack::TRACK_TYPE
|
||||
= f.input :instrument, collection: Instrument.all
|
||||
= f.input :part
|
||||
= f.input :track_type, :as => :select, collection: JamRuby::JamTrackTrack::TRACK_TYPE, include_blank: false
|
||||
= f.input :instrument, collection: Instrument.all, include_blank: false
|
||||
= f.input :part, :required=>true, :input_html => { :rows=>1, :maxlength=>20, :type=>'numeric' }
|
||||
|
||||
= f.input :position
|
||||
|
||||
- if f.object.new_record?
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ JamAdmin::Application.configure do
|
|||
|
||||
# Generate digests for assets URLs
|
||||
config.assets.digest = true
|
||||
|
||||
|
||||
# Defaults to nil and saved in location specified by config.assets.prefix
|
||||
# config.assets.manifest = YOUR_PATH
|
||||
|
||||
|
|
@ -73,4 +73,5 @@ JamAdmin::Application.configure do
|
|||
|
||||
config.aws_bucket_public = 'jamkazam-public'
|
||||
config.aws_bucket = 'jamkazam'
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -233,4 +233,6 @@ add_track_resource_id.sql
|
|||
user_genres.sql
|
||||
user_online.sql
|
||||
icecast_source_changes.sql
|
||||
diagnostics_user_id_index.sql
|
||||
diagnostics_user_id_index.sql
|
||||
jam_track_updates.sql
|
||||
private_key_in_jam_track_rights.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
-- Drop Jam Track Tracks constraints:
|
||||
ALTER TABLE jam_track_tracks
|
||||
DROP CONSTRAINT jam_track_tracks_jam_track_id_fkey;
|
||||
|
||||
-- Drop Jam Track Tracks constraints:
|
||||
ALTER TABLE jam_track_rights
|
||||
DROP CONSTRAINT jam_track_rights_user_id_fkey,
|
||||
DROP CONSTRAINT jam_track_rights_jam_track_id_fkey;
|
||||
|
||||
-- Change Jam Tracks ID type to BIGINT so it can work like the other downloadable items:
|
||||
CREATE SEQUENCE jam_tracks_next_seq;
|
||||
ALTER TABLE jam_tracks
|
||||
ALTER COLUMN id DROP DEFAULT,
|
||||
ALTER COLUMN id TYPE BIGINT USING nextval('jam_tracks_next_seq'),
|
||||
ALTER COLUMN id SET DEFAULT nextval('jam_tracks_next_seq');
|
||||
|
||||
-- Change referencing ID type and re-add constraints:
|
||||
ALTER TABLE jam_track_tracks
|
||||
ALTER COLUMN jam_track_id TYPE BIGINT USING 0,
|
||||
ALTER COLUMN jam_track_id SET NOT NULL,
|
||||
ADD CONSTRAINT jam_track_tracks_jam_track_id_fkey FOREIGN KEY(jam_track_id) REFERENCES jam_tracks(id) ON DELETE CASCADE;
|
||||
|
||||
-- Change referencing ID type and re-add constraints. Also
|
||||
-- add S3 URL for user-specific downloads:
|
||||
ALTER TABLE jam_track_rights
|
||||
ALTER COLUMN id DROP DEFAULT,
|
||||
ALTER COLUMN id TYPE BIGINT USING nextval('tracks_next_tracker_seq'),
|
||||
ALTER COLUMN id SET DEFAULT nextval('tracks_next_tracker_seq'),
|
||||
ADD COLUMN url VARCHAR(2048),
|
||||
ADD COLUMN md5 VARCHAR,
|
||||
ADD COLUMN length INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN download_count INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN signed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
ADD COLUMN downloaded_since_sign BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
ADD COLUMN last_signed_at timestamp without time zone NULL,
|
||||
ADD COLUMN last_downloaded_at timestamp without time zone NULL,
|
||||
ADD COLUMN created_at timestamp without time zone NOT NULL,
|
||||
ADD COLUMN updated_at timestamp without time zone NOT NULL,
|
||||
ALTER COLUMN jam_track_id TYPE BIGINT USING 0,
|
||||
ALTER COLUMN jam_track_id SET NOT NULL,
|
||||
ADD CONSTRAINT jam_track_rights_user_id_fkey FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT jam_track_rights_jam_track_id_fkey FOREIGN KEY(jam_track_id) REFERENCES jam_tracks(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE notifications ADD COLUMN jam_track_right_id BIGINT REFERENCES jam_track_rights(id);
|
||||
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE jam_track_rights ADD COLUMN private_key VARCHAR;
|
||||
|
|
@ -78,6 +78,9 @@ message ClientMessage {
|
|||
SOURCE_UP = 252;
|
||||
SOURCE_DOWN = 253;
|
||||
|
||||
// jamtracks notifications
|
||||
JAM_TRACK_SIGN_COMPLETE = 260;
|
||||
|
||||
TEST_SESSION_MESSAGE = 295;
|
||||
|
||||
PING_REQUEST = 300;
|
||||
|
|
@ -180,6 +183,9 @@ message ClientMessage {
|
|||
optional SourceUp source_up = 252;
|
||||
optional SourceDown source_down = 253;
|
||||
|
||||
// jamtracks notification
|
||||
optional JamTrackSignComplete jam_track_sign_complete=260;
|
||||
|
||||
// Client-Session messages (to/from)
|
||||
optional TestSessionMessage test_session_message = 295;
|
||||
|
||||
|
|
@ -594,6 +600,11 @@ message SourceDown {
|
|||
optional string music_session = 1; // music session id
|
||||
}
|
||||
|
||||
|
||||
message JamTrackSignComplete {
|
||||
required int32 jam_track_right_id = 1; // jam track right id
|
||||
}
|
||||
|
||||
message SubscriptionMessage {
|
||||
optional string type = 1; // the type of the subscription
|
||||
optional string id = 2; // data about what to subscribe to, specifically
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ require "jam_ruby/resque/scheduled/active_music_session_cleaner"
|
|||
require "jam_ruby/resque/scheduled/score_history_sweeper"
|
||||
require "jam_ruby/resque/scheduled/scheduled_music_session_cleaner"
|
||||
require "jam_ruby/resque/scheduled/recordings_cleaner"
|
||||
require "jam_ruby/resque/scheduled/jam_tracks_cleaner"
|
||||
require "jam_ruby/resque/jam_tracks_builder"
|
||||
require "jam_ruby/resque/scheduled/stats_maker"
|
||||
require "jam_ruby/resque/google_analytics_event"
|
||||
require "jam_ruby/resque/batch_email_job"
|
||||
|
|
@ -75,6 +77,7 @@ require "jam_ruby/app/uploaders/mix_uploader"
|
|||
require "jam_ruby/app/uploaders/music_notation_uploader"
|
||||
require "jam_ruby/app/uploaders/jam_track_uploader"
|
||||
require "jam_ruby/app/uploaders/jam_track_track_uploader"
|
||||
require "jam_ruby/app/uploaders/jam_track_right_uploader"
|
||||
require "jam_ruby/app/uploaders/max_mind_release_uploader"
|
||||
require "jam_ruby/lib/desk_multipass"
|
||||
require "jam_ruby/lib/ip"
|
||||
|
|
@ -193,6 +196,7 @@ require "jam_ruby/models/jam_company"
|
|||
require "jam_ruby/models/user_sync"
|
||||
require "jam_ruby/models/video_source"
|
||||
require "jam_ruby/models/recorded_video"
|
||||
require "jam_ruby/jam_tracks_manager"
|
||||
|
||||
include Jampb
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
class JamTrackRightUploader < CarrierWave::Uploader::Base
|
||||
# include CarrierWaveDirect::Uploader
|
||||
include CarrierWave::MimeTypes
|
||||
|
||||
process :set_content_type
|
||||
|
||||
def initialize(*)
|
||||
super
|
||||
JamRuby::UploaderConfiguration.set_aws_private_configuration(self)
|
||||
end
|
||||
|
||||
# Add a white list of extensions which are allowed to be uploaded.
|
||||
def extension_white_list
|
||||
%w(jkz)
|
||||
end
|
||||
|
||||
def store_dir
|
||||
nil
|
||||
end
|
||||
|
||||
def md5
|
||||
@md5 ||= ::Digest::MD5.file(current_path).hexdigest
|
||||
end
|
||||
|
||||
def filename
|
||||
"#{model.store_dir}/#{model.filename}" if model.id
|
||||
end
|
||||
end
|
||||
|
|
@ -11,7 +11,7 @@ class JamTrackUploader < CarrierWave::Uploader::Base
|
|||
|
||||
# Add a white list of extensions which are allowed to be uploaded.
|
||||
def extension_white_list
|
||||
%w(jka)
|
||||
%w(jkz)
|
||||
end
|
||||
|
||||
def store_dir
|
||||
|
|
|
|||
|
|
@ -45,5 +45,7 @@ module NotificationTypes
|
|||
# general purpose text message
|
||||
TEXT_MESSAGE = "TEXT_MESSAGE"
|
||||
|
||||
# Jam Tracks:
|
||||
JAM_TRACK_SIGN_COMPLETE = "JAM_TRACK_SIGN_COMPLETE"
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
require 'json'
|
||||
require 'tempfile'
|
||||
require 'open3'
|
||||
require 'fileutils'
|
||||
require 'open-uri'
|
||||
|
||||
module JamRuby
|
||||
|
||||
# Interact with external python tools to create the JKZ
|
||||
class JamTracksManager
|
||||
class << self
|
||||
def save_jam_track_jkz(user, jam_track)
|
||||
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
|
||||
|
||||
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"))
|
||||
py_root = APP_CONFIG.jamtracks_dir
|
||||
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)
|
||||
copy_url_to_file(track_url, File.join(".", nm))
|
||||
jam_file_opts << " -i '#{track_filename}+#{jam_track_track.part}'"
|
||||
end
|
||||
#puts "LS + " + `ls -la '#{tmp_dir}'`
|
||||
|
||||
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: #{err}" if err.present?
|
||||
raise ArgumentError, "Error calling python script: #{out}" if out && (out.index("No track files specified") || out.index("Cannot find file"))
|
||||
jam_track_right[:url]
|
||||
|
||||
#raise ArgumentError, "output_jkz is empty #{output_jkz}" unless File.exists?(output_jkz)
|
||||
|
||||
jam_track_right.url.store!(File.open(output_jkz, "rb"))
|
||||
jam_track_right.signed=true
|
||||
jam_track_right.downloaded_since_sign=false
|
||||
jam_track_right.private_key=File.read("#{tmp_dir}/skey.pem")
|
||||
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, 'w+b') 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
|
||||
puts "Response from server was #{response_code} / #{response.message}"
|
||||
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
|
||||
|
|
@ -13,11 +13,15 @@ module JamWebEventMachine
|
|||
|
||||
@@log = Logging.logger[JamWebEventMachine]
|
||||
|
||||
|
||||
# THIS WAS USED BY resque jobs needing EventMachine/AMQP, but it's no longer needed. It's useful code though
|
||||
|
||||
# starts amqp & eventmachine up first.
|
||||
# and then calls your block.
|
||||
# After the supplied block is done,
|
||||
# waits until all EM tasks scheduled in the supplied block are done, or timeout
|
||||
def self.run_wait_stop(timeout = 30, &blk)
|
||||
|
||||
JamWebEventMachine.run
|
||||
|
||||
thread = Thread.current
|
||||
|
|
|
|||
|
|
@ -1,5 +1,41 @@
|
|||
|
||||
require 'influxdb'
|
||||
|
||||
# monkey patch InfluxDB client to clear the queue when asked to stop
|
||||
module InfluxDB
|
||||
class Client
|
||||
def stop!
|
||||
@queue.clear if @queue
|
||||
@stopped = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module InfluxDB
|
||||
class Worker
|
||||
def spawn_threads!
|
||||
NUM_WORKER_THREADS.times do |thread_num|
|
||||
log :debug, "Spawning background worker thread #{thread_num}."
|
||||
|
||||
Thread.new do
|
||||
Thread.current[:influxdb] = self.object_id
|
||||
|
||||
at_exit do
|
||||
log :debug, "Thread exiting, bailing out (not flushing queue)"
|
||||
end
|
||||
|
||||
while !client.stopped?
|
||||
self.check_background_queue(thread_num)
|
||||
sleep rand(SLEEP_INTERVAL)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
module JamRuby
|
||||
class Stats
|
||||
|
||||
|
|
@ -10,6 +46,7 @@ module JamRuby
|
|||
|
||||
def self.destroy!
|
||||
if @client
|
||||
@client.queue.clear if @client.queue
|
||||
@client.stop!
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -712,6 +712,19 @@ module JamRuby
|
|||
)
|
||||
end
|
||||
|
||||
def jam_track_sign_complete(receiver_id, jam_track_right_id)
|
||||
signed = Jampb::JamTrackSignComplete.new(
|
||||
:jam_track_right_id => jam_track_right_id
|
||||
)
|
||||
|
||||
Jampb::ClientMessage.new(
|
||||
:type => ClientMessage::Type::JAM_TRACK_SIGN_COMPLETE,
|
||||
:route_to => USER_TARGET_PREFIX + receiver_id, #:route_to => CLIENT_TARGET,
|
||||
:jam_track_sign_complete => signed
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
def recording_master_mix_complete(receiver_id, recording_id, claimed_recording_id, band_id, msg, notification_id, created_at)
|
||||
recording_master_mix_complete = Jampb::RecordingMasterMixComplete.new(
|
||||
:recording_id => recording_id,
|
||||
|
|
|
|||
|
|
@ -229,11 +229,12 @@ module JamRuby
|
|||
CLIENT_TYPES.each do |type|
|
||||
stats[type] = 0
|
||||
end
|
||||
Connection.select('count(client_type) AS client_type_count, client_type') do |result|
|
||||
stats[result['client_type']] = result['client_type_count']
|
||||
|
||||
Connection.select('count(client_type) AS client_type_count, client_type').group('client_type').all.each do |result|
|
||||
stats[result['client_type']] = result['client_type_count'].to_i
|
||||
end
|
||||
|
||||
result = Connection.select('count(id) AS total, count(scoring_timeout) AS scoring_timeout_count, count(music_session_id) AS in_session, count(as_musician) AS musicians, count(udp_reachable) AS udp_reachable_count, count(is_network_testing) AS is_network_testing_count').first
|
||||
result = Connection.select('count(id) AS total, count(CASE WHEN scoring_timeout > NOW() THEN 1 ELSE null END) AS scoring_timeout_count, count(music_session_id) AS in_session, count(as_musician) AS musicians, count(CASE WHEN udp_reachable THEN 1 ELSE null END) AS udp_reachable_count, count(CASE WHEN is_network_testing THEN 1 ELSE null END) AS is_network_testing_count').first
|
||||
|
||||
stats['count'] = result['total'].to_i
|
||||
stats['scoring_timeout'] = result['scoring_timeout_count'].to_i
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module JamRuby
|
|||
attr_accessible :name, :description, :bpm, :time_signature, :status, :recording_type,
|
||||
:original_artist, :songwriter, :publisher, :licensor, :licensor_id, :pro, :genre, :genre_id, :sales_region, :price,
|
||||
:reproduction_royalty, :public_performance_royalty, :reproduction_royalty_amount,
|
||||
:licensor_royalty_amount, :pro_royalty_amount, :jam_track_tracks_attributes, as: :admin
|
||||
:licensor_royalty_amount, :pro_royalty_amount, :jam_track_tracks_attributes, :plan_code, as: :admin
|
||||
|
||||
validates :name, presence: true, uniqueness: true, length: {maximum: 200}
|
||||
validates :description, length: {maximum: 1000}
|
||||
|
|
@ -43,19 +43,47 @@ 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
|
||||
|
||||
class << self
|
||||
def index(options = {})
|
||||
limit = options[:limit]
|
||||
limit ||= 20
|
||||
limit = limit.to_i
|
||||
|
||||
start = options[:start].presence
|
||||
start = start.to_i || 0
|
||||
|
||||
query = JamTrack.joins(:jam_track_tracks)
|
||||
.offset(start)
|
||||
.limit(limit)
|
||||
|
||||
query = query.where("jam_tracks.genre_id = '#{options[:genre]}'") unless options[:genre].blank?
|
||||
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}'") unless options[:instrument].blank?
|
||||
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
|
||||
query = query.group("jam_tracks.id")
|
||||
|
||||
if query.length == 0
|
||||
[query, nil]
|
||||
elsif query.length < limit
|
||||
[query, nil]
|
||||
else
|
||||
[query, start + limit]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# create storage directory that will house this jam_track, as well as
|
||||
def store_dir
|
||||
"jam_tracks/#{created_at.strftime('%m-%d-%Y')}/#{id}"
|
||||
"jam_tracks/#{id}"
|
||||
end
|
||||
|
||||
# create name of the file
|
||||
def filename
|
||||
"#{name}.jka"
|
||||
"#{name}.jkz"
|
||||
end
|
||||
|
||||
# creates a short-lived URL that has access to the object.
|
||||
|
|
@ -63,40 +91,49 @@ module JamRuby
|
|||
# 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 => 'audio/jka', :secure => false})
|
||||
s3_manager.sign_url(self[:url], {:expires => expiration_time, :response_content_type => 'audio/jkz', :secure => false})
|
||||
end
|
||||
|
||||
|
||||
def can_download?(user)
|
||||
owners.include?(user)
|
||||
end
|
||||
|
||||
def self.index user, options = {}
|
||||
limit = options[:limit]
|
||||
limit ||= 20
|
||||
limit = limit.to_i
|
||||
def right_for_user(user)
|
||||
jam_track_rights.where("user_id=?", user).first
|
||||
end
|
||||
|
||||
start = options[:start].presence
|
||||
start = start.to_i || 0
|
||||
def self.list_downloads(user, limit = 100, since = 0)
|
||||
since = 0 unless since || since == '' # guard against nil
|
||||
downloads = []
|
||||
|
||||
query = JamTrack.joins(:jam_track_tracks)
|
||||
.offset(start)
|
||||
.limit(limit)
|
||||
|
||||
query = query.where("jam_tracks.genre_id = '#{options[:genre]}'") unless options[:genre].blank?
|
||||
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}'") unless options[:instrument].blank?
|
||||
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
|
||||
query = query.group("jam_tracks.id")
|
||||
|
||||
if query.length == 0
|
||||
[query, nil]
|
||||
elsif query.length < limit
|
||||
[query, nil]
|
||||
else
|
||||
[query, start + limit]
|
||||
user.jam_track_rights
|
||||
.limit(limit)
|
||||
.where('jam_track_rights.id > ?', since)
|
||||
.each do |jam_track_right|
|
||||
downloads << {
|
||||
:type => "jam_track",
|
||||
:id => jam_track_right.id.to_s,
|
||||
:jam_track_id => jam_track_right.jam_track_id,
|
||||
:length => jam_track_right.length,
|
||||
:md5 => jam_track_right.md5,
|
||||
:url => jam_track_right.url,
|
||||
:created_at => jam_track_right.created_at,
|
||||
:next => jam_track_right.id
|
||||
}
|
||||
end
|
||||
|
||||
next_id = downloads[-1][:next] if downloads.length > 0
|
||||
next_id = since if next_id.nil? # echo back to the client the same value they passed in, if there are no results
|
||||
|
||||
{
|
||||
'downloads' => downloads,
|
||||
'next' => next_id.to_s
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
private
|
||||
|
||||
def sanitize_active_admin
|
||||
self.genre_id = nil if self.genre_id == ''
|
||||
|
|
|
|||
|
|
@ -2,13 +2,94 @@ 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"
|
||||
|
||||
validates :user, presence:true
|
||||
validates :jam_track, presence:true
|
||||
validate :verify_download_count
|
||||
|
||||
validates_uniqueness_of :user_id, scope: :jam_track_id
|
||||
|
||||
# Uploads the JKZ:
|
||||
mount_uploader :url, JamTrackRightUploader
|
||||
before_destroy :delete_s3_files
|
||||
|
||||
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
|
||||
errors.add(:download_count, "must be less than or equal to #{MAX_JAM_TRACK_DOWNLOADS}")
|
||||
end
|
||||
end
|
||||
|
||||
def self.ready_to_clean
|
||||
JamTrackRight.where("downloaded_since_sign=? AND updated_at <= ?", true, 5.minutes.ago).limit(1000)
|
||||
end
|
||||
|
||||
def finish_sign(length, md5)
|
||||
self.last_signed_at = Time.now
|
||||
self.length = length
|
||||
self.md5 = md5
|
||||
self.signed = true
|
||||
if save
|
||||
Notification.send_jam_track_sign_complete(self)
|
||||
else
|
||||
raise "Error sending notification #{self.errors}"
|
||||
end
|
||||
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, :secure => false})
|
||||
end
|
||||
|
||||
def delete_s3_files
|
||||
remove_url!
|
||||
end
|
||||
|
||||
def enqueue
|
||||
begin
|
||||
Resque.enqueue(JamTracksBuilder, self.id)
|
||||
rescue Exception => e
|
||||
# implies redis is down. we don't update started_at by bailing out here
|
||||
false
|
||||
end
|
||||
|
||||
# avoid db validations
|
||||
JamTrackRight.where(:id => self.id).update_all(:last_downloaded_at => Time.now)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def update_download_count(count=1)
|
||||
self.download_count = self.download_count + count
|
||||
self.last_downloaded_at = Time.now
|
||||
end
|
||||
|
||||
def self.list_keys(user, jamtracks)
|
||||
if jamtracks.nil?
|
||||
return []
|
||||
end
|
||||
|
||||
JamTrack.select('jam_tracks.id, jam_track_rights.private_key AS private_key, jam_track_rights.id AS jam_track_right_id')
|
||||
.joins("LEFT OUTER JOIN jam_track_rights ON jam_tracks.id = jam_track_rights.jam_track_id AND jam_track_rights.user_id = '#{user.id}'")
|
||||
.where('jam_tracks.id IN (?)', jamtracks)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module JamRuby
|
|||
|
||||
mount_uploader :url, JamTrackTrackUploader
|
||||
|
||||
attr_accessible :track_type, :instrument, :instrument_id, :position, :part, :url, as: :admin
|
||||
attr_accessible :jam_track_id, :track_type, :instrument, :instrument_id, :position, :part, :url, as: :admin
|
||||
|
||||
validates :position, presence: true, numericality: {only_integer: true}, length: {in: 1..1000}
|
||||
validates :part, length: {maximum: 20}
|
||||
|
|
@ -43,5 +43,52 @@ module JamRuby
|
|||
# I think we have to make a special case for 'previews', but maybe that's just up to the controller to not check can_download?
|
||||
jam_track.owners.include?(user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def move_up
|
||||
#normalize_position
|
||||
if self.position > 1
|
||||
# Switch with previous
|
||||
previous_track = self.jam_track.jam_track_tracks.where("position=?", self.position-1).first
|
||||
if previous_track
|
||||
JamTrack.transaction do
|
||||
previous_track.position,self.position = self.position,previous_track.position
|
||||
previous_track.save(validate:false)
|
||||
self.save(validate:false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def move_down
|
||||
count=normalize_position
|
||||
if self.position < count
|
||||
# Switch with next:
|
||||
next_track = self.jam_track.jam_track_tracks.where("position=?", self.position+1).first
|
||||
if next_track
|
||||
next_track.position,self.position = self.position,next_track.position
|
||||
next_track.save(validate:false)
|
||||
self.save(validate:false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def normalize_position
|
||||
parent = self.jam_track
|
||||
position = 0
|
||||
if parent
|
||||
JamTrack.transaction do
|
||||
parent.jam_track_tracks.each do |jtt|
|
||||
position += 1
|
||||
if jtt.position != position
|
||||
jtt.position = position
|
||||
jtt.save(validate:false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
position
|
||||
end # normalize_position
|
||||
|
||||
end # class
|
||||
end # module
|
||||
|
|
|
|||
|
|
@ -286,12 +286,15 @@ module JamRuby
|
|||
# keep unstarted sessions around for 12 hours after scheduled_start
|
||||
session_not_started = "(music_sessions.scheduled_start > NOW() - '12 hour'::INTERVAL AND music_sessions.started_at IS NULL)"
|
||||
|
||||
# keep started sessions that are not finished yet
|
||||
session_started_not_finished = "(music_sessions.started_at IS NOT NULL AND music_sessions.session_removed_at IS NULL)"
|
||||
|
||||
# let session be restarted for up to 2 hours after finishing
|
||||
session_finished = "(music_sessions.session_removed_at > NOW() - '2 hour'::INTERVAL)"
|
||||
|
||||
query = MusicSession.where("music_sessions.canceled = FALSE")
|
||||
query = query.where("music_sessions.user_id = '#{user.id}'")
|
||||
query = query.where("music_sessions.scheduled_start IS NULL OR #{session_not_started} OR #{session_finished}")
|
||||
query = query.where("music_sessions.scheduled_start IS NULL OR #{session_not_started} OR #{session_finished} OR #{session_started_not_finished}")
|
||||
query = query.where("music_sessions.create_type IS NULL OR music_sessions.create_type != '#{CREATE_TYPE_QUICK_START}'")
|
||||
query = query.order("music_sessions.scheduled_start ASC")
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ module JamRuby
|
|||
belongs_to :band, :class_name => "JamRuby::Band", :foreign_key => "band_id"
|
||||
belongs_to :music_session, :class_name => "JamRuby::MusicSession", :foreign_key => "music_session_id"
|
||||
belongs_to :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id"
|
||||
belongs_to :jam_track_right, :class_name => "JamRuby::JamTrackRight", :foreign_key => "jam_track_right_id"
|
||||
|
||||
validates :target_user, :presence => true
|
||||
validates :message, length: {minimum: 1, maximum: 400}, no_profanity: true, if: :text_message?
|
||||
|
|
@ -203,6 +204,9 @@ module JamRuby
|
|||
when NotificationTypes::SCHEDULED_SESSION_COMMENT
|
||||
return "New message about session."
|
||||
|
||||
when NotificationTypes::JAM_TRACK_SIGN_COMPLETE
|
||||
return "Jam Track is ready for download."
|
||||
|
||||
# recording notifications
|
||||
when NotificationTypes::MUSICIAN_RECORDING_SAVED
|
||||
return "#{name} has made a new recording."
|
||||
|
|
@ -1186,6 +1190,19 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def send_jam_track_sign_complete(jam_track_right)
|
||||
|
||||
notification = Notification.new
|
||||
notification.jam_track_right_id = jam_track_right.id
|
||||
notification.description = NotificationTypes::JAM_TRACK_SIGN_COMPLETE
|
||||
notification.target_user_id = jam_track_right.user_id
|
||||
notification.save!
|
||||
|
||||
msg = @@message_factory.jam_track_sign_complete(jam_track_right.user_id, jam_track_right.id)
|
||||
@@mq_router.publish_to_user(jam_track_right.user_id, msg)
|
||||
#@@mq_router.publish_to_all_clients(msg)
|
||||
end
|
||||
|
||||
def send_client_update(product, version, uri, size)
|
||||
msg = @@message_factory.client_update( product, version, uri, size)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module JamRuby
|
|||
|
||||
def product_info
|
||||
product = self.cart_product
|
||||
{name: product.name, price: product.price} unless product.nil?
|
||||
{name: product.name, price: product.price, product_id: cart_id} unless product.nil?
|
||||
end
|
||||
|
||||
def cart_product
|
||||
|
|
|
|||
|
|
@ -1477,7 +1477,6 @@ module JamRuby
|
|||
def self.stats
|
||||
stats = {}
|
||||
result = User.select('count(CASE WHEN musician THEN 1 ELSE null END) as musician_count, count(CASE WHEN musician = FALSE THEN 1 ELSE null END) as fan_count, count(first_downloaded_client_at) first_downloaded_client_at_count, count(first_ran_client_at) first_ran_client_at_count, count(first_certified_gear_at) first_certified_gear_at_count, count(first_music_session_at) as first_music_session_at_count, count(first_invited_at) first_invited_at_count, count(first_friended_at) as first_friended_at_count, count(first_social_promoted_at) first_social_promoted_at_count, avg(last_jam_audio_latency) last_jam_audio_latency_avg').first
|
||||
puts "result #{result['musician_count']}"
|
||||
stats['musicians'] = result['musician_count'].to_i
|
||||
stats['fans'] = result['fan_count'].to_i
|
||||
stats['downloaded_client'] = result['first_downloaded_client_at_count'].to_i
|
||||
|
|
|
|||
|
|
@ -20,13 +20,11 @@ module JamRuby
|
|||
|
||||
def self.perform(mix_id, postback_ogg_url, postback_mp3_url)
|
||||
|
||||
JamWebEventMachine.run_wait_stop do
|
||||
audiomixer = AudioMixer.new()
|
||||
audiomixer.postback_ogg_url = postback_ogg_url
|
||||
audiomixer.postback_mp3_url = postback_mp3_url
|
||||
audiomixer.mix_id = mix_id
|
||||
audiomixer.run
|
||||
end
|
||||
audiomixer = AudioMixer.new()
|
||||
audiomixer.postback_ogg_url = postback_ogg_url
|
||||
audiomixer.postback_mp3_url = postback_mp3_url
|
||||
audiomixer.mix_id = mix_id
|
||||
audiomixer.run
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ require 'resque-lonely_job'
|
|||
|
||||
module JamRuby
|
||||
class BatchEmailJob
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@@log = Logging.logger[BatchEmailJob]
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ module JamRuby
|
|||
|
||||
# executes a mix of tracks, creating a final output mix
|
||||
class IcecastConfigWriter
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@@log = Logging.logger[IcecastConfigWriter]
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
require 'json'
|
||||
require 'resque'
|
||||
require 'resque-retry'
|
||||
require 'net/http'
|
||||
require 'digest/md5'
|
||||
|
||||
module JamRuby
|
||||
class JamTracksBuilder
|
||||
extend JamRuby::ResqueStats
|
||||
|
||||
@queue = :jam_tracks_builder
|
||||
|
||||
def log
|
||||
@log || Logging.logger[JamTracksBuilder]
|
||||
end
|
||||
|
||||
attr_accessor :jam_track_right_id
|
||||
|
||||
def self.perform(jam_track_right_id)
|
||||
jam_track_builder = JamTracksBuilder.new()
|
||||
jam_track_builder.jam_track_right_id = jam_track_right_id
|
||||
jam_track_builder.run
|
||||
end
|
||||
|
||||
def run
|
||||
log.info("jam_track_builder job starting. jam_track_right_id #{jam_track_right_id}")
|
||||
@jam_track_right = JamTrackRight.find(jam_track_right_id)
|
||||
JamRuby::JamTracksManager.save_jam_track_right_jkz(@jam_track_right)
|
||||
|
||||
length = @jam_track_right.url.size()
|
||||
md5 = Digest::MD5.new
|
||||
|
||||
@jam_track_right.finish_sign(length, md5.to_s)
|
||||
|
||||
log.info "Signed jamtrack to #{@jam_track_right[:url]}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -19,12 +19,10 @@ module JamRuby
|
|||
|
||||
def self.perform(quick_mix_id, postback_mp3_url)
|
||||
|
||||
JamWebEventMachine.run_wait_stop do
|
||||
audiomixer = QuickMixer.new
|
||||
audiomixer.postback_mp3_url = postback_mp3_url
|
||||
audiomixer.quick_mix_id = quick_mix_id
|
||||
audiomixer.run
|
||||
end
|
||||
audiomixer = QuickMixer.new
|
||||
audiomixer.postback_mp3_url = postback_mp3_url
|
||||
audiomixer.quick_mix_id = quick_mix_id
|
||||
audiomixer.run
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,52 @@
|
|||
require 'resque'
|
||||
|
||||
# https://devcenter.heroku.com/articles/forked-pg-connections
|
||||
Resque.before_fork do
|
||||
defined?(ActiveRecord::Base) and
|
||||
ActiveRecord::Base.connection.disconnect!
|
||||
ENV['FORK_PER_JOB'] = 'false'
|
||||
|
||||
JamRuby::Stats.destroy!
|
||||
def shutdown
|
||||
puts "Cleaning up resources..."
|
||||
Stats.destroy!
|
||||
EventMachine.stop_event_loop
|
||||
puts "Terminated!"
|
||||
exit!
|
||||
end
|
||||
|
||||
Resque.after_fork do
|
||||
defined?(ActiveRecord::Base) and
|
||||
ActiveRecord::Base.establish_connection
|
||||
Resque.before_first_fork do
|
||||
JamWebEventMachine.start
|
||||
|
||||
#ActiveRecord::Base.establish_connection
|
||||
config = {
|
||||
influxdb_database: APP_CONFIG.influxdb_database,
|
||||
influxdb_username: APP_CONFIG.influxdb_username,
|
||||
influxdb_password: APP_CONFIG.influxdb_password,
|
||||
influxdb_hosts: APP_CONFIG.influxdb_hosts,
|
||||
influxdb_port: APP_CONFIG.influxdb_port,
|
||||
influxdb_async: false # if we use async=true, the forked job will die before the stat is sent
|
||||
influxdb_async: true # if we use async=true, the forked job will die before the stat is sent
|
||||
}
|
||||
|
||||
# handle these events and force a shutdown. this is required I think due to influxdb-client.
|
||||
Signal.trap("TERM") do
|
||||
shutdown
|
||||
end
|
||||
Signal.trap("INT") do
|
||||
shutdown
|
||||
end
|
||||
|
||||
JamRuby::Stats.init(config)
|
||||
|
||||
end
|
||||
# https://devcenter.heroku.com/articles/forked-pg-connections
|
||||
Resque.before_fork do
|
||||
|
||||
#defined?(ActiveRecord::Base) and
|
||||
# ActiveRecord::Base.connection.disconnect!
|
||||
|
||||
#JamRuby::Stats.destroy!
|
||||
end
|
||||
|
||||
Resque.after_fork do
|
||||
#defined?(ActiveRecord::Base) and
|
||||
# ActiveRecord::Base.establish_connection
|
||||
|
||||
end
|
||||
|
||||
# for jobs that do not extend lonely job, just extend this module and get stats
|
||||
|
|
@ -36,19 +62,21 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
require 'resque-lonely_job'
|
||||
|
||||
# for jobs that extend lonely job, we override around_perform already implemented in LonelyJob, and call into it
|
||||
module Resque
|
||||
module Plugins
|
||||
module LonelyJob
|
||||
module JamLonelyJob
|
||||
def around_perform(*args)
|
||||
Stats.timer('job.stats') do
|
||||
begin
|
||||
yield
|
||||
ensure
|
||||
unlock_queue(*args)
|
||||
end
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Resque::Plugins::JamLonelyJob.module_eval { include Resque::Plugins::LonelyJob }
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ require 'digest/md5'
|
|||
module JamRuby
|
||||
|
||||
class ActiveMusicSessionCleaner
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
attr_accessor :interval
|
||||
|
||||
|
|
@ -22,11 +22,9 @@ module JamRuby
|
|||
def self.perform
|
||||
@@log.debug("ActiveMusicSessionCleaner waking up")
|
||||
|
||||
JamWebEventMachine.run_wait_stop do
|
||||
cleaner = ActiveMusicSessionCleaner.new
|
||||
cleaner.interval = "INTERVAL '1 minute'"
|
||||
cleaner.run
|
||||
end
|
||||
cleaner = ActiveMusicSessionCleaner.new
|
||||
cleaner.interval = "INTERVAL '1 minute'"
|
||||
cleaner.run
|
||||
|
||||
@@log.debug("ActiveMusicSessionCleaner done")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module JamRuby
|
|||
|
||||
# periodically scheduled to find jobs that need retrying, and cleanup activities
|
||||
class AudioMixerRetry
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :scheduled_audiomixer_retry
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@
|
|||
module JamRuby
|
||||
class CleanupFacebookSignup
|
||||
|
||||
|
||||
|
||||
|
||||
@queue = :scheduled_cleanup_facebook_signup
|
||||
|
||||
@@log = Logging.logger[CleanupFacebookSignup]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
module JamRuby
|
||||
class DailySessionEmailer
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :scheduled_daily_session_emailer
|
||||
@@log = Logging.logger[DailySessionEmailer]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module JamRuby
|
|||
|
||||
# periodically scheduled to find jobs that need retrying
|
||||
class IcecastConfigRetry
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :scheduled_icecast_config_retry
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ module JamRuby
|
|||
# http://blog.bignerdranch.com/1643-never-use-resque-for-serial-jobs/
|
||||
# periodically scheduled to find sources that need to be brought down, or alternatively, it seems the client failed to start sourcing
|
||||
class IcecastSourceCheck
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :scheduled_icecast_source_check
|
||||
|
||||
@@log = Logging.logger[IcecastSourceCheck]
|
||||
def log
|
||||
@log || Logging.logger[IcecastSourceCheck]
|
||||
end
|
||||
|
||||
def self.lock_timeout
|
||||
# this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job
|
||||
|
|
@ -21,13 +23,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.perform
|
||||
@@log.debug("waking up")
|
||||
|
||||
JamWebEventMachine.run_wait_stop do
|
||||
IcecastSourceCheck.new.run
|
||||
end
|
||||
|
||||
@@log.debug("done")
|
||||
IcecastSourceCheck.new.run
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -37,6 +33,8 @@ module JamRuby
|
|||
# ** listeners > 0 and sourced is DOWN (false)
|
||||
# ** listeners == 0 and sourced is UP (true)
|
||||
|
||||
log.debug("waking up")
|
||||
|
||||
IcecastMount.find_each(lock: true, :conditions => "( (listeners > 0 AND sourced = FALSE) OR (listeners = 0 AND sourced = TRUE) ) AND ( sourced_needs_changing_at IS NULL OR sourced_needs_changing_at < (NOW() - interval '#{APP_CONFIG.icecast_max_sourced_changed} second') ) ", :batch_size => 100) do |mount|
|
||||
if mount.music_session_id
|
||||
mount.with_lock do
|
||||
|
|
@ -44,18 +42,20 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
log.debug("done")
|
||||
end
|
||||
|
||||
def handle_notifications(mount)
|
||||
if mount.listeners == 0 && mount.sourced
|
||||
# if no listeners, but we are sourced, then ask it to stop sourcing
|
||||
@@log.debug("SOURCE_DOWN_REQUEST called on mount #{mount.name}")
|
||||
log.debug("SOURCE_DOWN_REQUEST called on mount #{mount.name}")
|
||||
|
||||
mount.notify_source_down_requested
|
||||
|
||||
elsif mount.listeners > 0 && !mount.sourced
|
||||
# if we have some listeners, and still are not sourced, then ask to start sourcing again
|
||||
@@log.debug("SOURCE_UP_REQUEST called on mount #{mount.name}")
|
||||
log.debug("SOURCE_UP_REQUEST called on mount #{mount.name}")
|
||||
|
||||
mount.notify_source_up_requested
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
require 'json'
|
||||
require 'resque'
|
||||
require 'resque-retry'
|
||||
require 'net/http'
|
||||
require 'digest/md5'
|
||||
|
||||
module JamRuby
|
||||
|
||||
# periodically scheduled to find jam_tracks to cleanup
|
||||
class JamTracksCleaner
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :jam_tracks_cleaner
|
||||
|
||||
class << self
|
||||
def log
|
||||
@log || Logging.logger[JamTracksCleaner]
|
||||
end
|
||||
|
||||
def lock_timeout
|
||||
# this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job
|
||||
1200
|
||||
end
|
||||
|
||||
def perform
|
||||
JamTrackRight.ready_to_clean.each do |jam_track_right|
|
||||
log.debug("deleting files for jam_track_right #{jam_track_right.id}")
|
||||
jam_track_right.delete_s3_files
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -6,7 +6,7 @@ require 'digest/md5'
|
|||
|
||||
module JamRuby
|
||||
class MusicSessionScheduler
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :music_session_scheduler
|
||||
|
||||
|
|
@ -19,9 +19,7 @@ module JamRuby
|
|||
def self.perform
|
||||
@@log.debug("MusicSessionScheduler waking up")
|
||||
|
||||
JamWebEventMachine.run_wait_stop do
|
||||
MusicSessionScheduler.new.run
|
||||
end
|
||||
MusicSessionScheduler.new.run
|
||||
|
||||
@@log.debug("MusicSessionScheduler done")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
module JamRuby
|
||||
class NewMusicianEmailer
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :scheduled_new_musician_emailer
|
||||
@@log = Logging.logger[NewMusicianEmailer]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module JamRuby
|
|||
|
||||
# periodically scheduled to find recordings to cleanup
|
||||
class RecordingsCleaner
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :recordings_cleaner
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
module JamRuby
|
||||
class ScheduledMusicSessionCleaner
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :scheduled_music_session_cleaner
|
||||
@@log = Logging.logger[ScheduledMusicSessionCleaner]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module JamRuby
|
|||
|
||||
# periodically scheduled to find jobs that need retrying
|
||||
class ScoreHistorySweeper
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :score_history_sweeper
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,25 @@ module JamRuby
|
|||
|
||||
# creates stats to send to influx periodically
|
||||
class StatsMaker
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :stats_maker
|
||||
@queue = :scheduled_db_metrics
|
||||
|
||||
def log
|
||||
@log || Logging.logger[StatsMaker]
|
||||
end
|
||||
|
||||
def self.lock_timeout
|
||||
120
|
||||
end
|
||||
|
||||
@@log = Logging.logger['StatsMaker']
|
||||
|
||||
def self.perform
|
||||
StatsMaker.new.run
|
||||
end
|
||||
|
||||
def run
|
||||
log.debug("starting...")
|
||||
Stats.write('connection', Connection.stats)
|
||||
Stats.write('users', User.stats)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ require 'digest/md5'
|
|||
|
||||
module JamRuby
|
||||
class UnusedMusicNotationCleaner
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :unused_music_notation_cleaner
|
||||
|
||||
|
|
@ -20,9 +20,7 @@ module JamRuby
|
|||
def self.perform
|
||||
@@log.debug("waking up")
|
||||
|
||||
JamWebEventMachine.run_wait_stop do
|
||||
UnusedMusicNotationCleaner.new.run
|
||||
end
|
||||
UnusedMusicNotationCleaner.new.run
|
||||
|
||||
@@log.debug("done")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
module JamRuby
|
||||
class UserProgressEmailer
|
||||
extend Resque::Plugins::LonelyJob
|
||||
extend Resque::Plugins::JamLonelyJob
|
||||
|
||||
@queue = :scheduled_user_progress_emailer
|
||||
@@log = Logging.logger[UserProgressEmailer]
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -193,5 +193,20 @@ describe JamRuby::Connection do
|
|||
stats['udp_reachable'].should eq(0)
|
||||
stats['networking_testing'].should eq(0)
|
||||
end
|
||||
|
||||
it "1 connection" do
|
||||
conn.touch
|
||||
|
||||
stats = Connection.stats
|
||||
stats[Connection::TYPE_CLIENT].should eq(1)
|
||||
stats[Connection::TYPE_BROWSER].should eq(0)
|
||||
stats[Connection::TYPE_LATENCY_TESTER].should eq(0)
|
||||
stats['count'].should eq(1)
|
||||
stats['scoring_timeout'].should eq(0)
|
||||
stats['in_session'].should eq(1)
|
||||
stats['musicians'].should eq(1)
|
||||
stats['udp_reachable'].should eq(1)
|
||||
stats['networking_testing'].should eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
@ -16,6 +17,14 @@ describe JamTrackRight do
|
|||
|
||||
end
|
||||
|
||||
it "lists" do
|
||||
jam_track_right = FactoryGirl.create(:jam_track_right)
|
||||
jam_tracks = JamTrack.list_downloads(jam_track_right.user)
|
||||
jam_tracks.should have_key('downloads')
|
||||
jam_tracks.should have_key('next')
|
||||
jam_tracks['downloads'].should have(1).items
|
||||
end
|
||||
|
||||
describe "validations" do
|
||||
it "one purchase per user/jam_track combo" do
|
||||
user = FactoryGirl.create(:user)
|
||||
|
|
@ -27,5 +36,92 @@ describe JamTrackRight do
|
|||
right_2.errors[:user_id].should == ['has already been taken']
|
||||
end
|
||||
end
|
||||
|
||||
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 raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "should create" do
|
||||
ogg_path = File.join('spec', 'files', 'on.ogg')
|
||||
user = FactoryGirl.create(:user)
|
||||
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, 'rb'))
|
||||
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
|
||||
url = jam_track_right[:url]
|
||||
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
s3.exists?(url).should be_true
|
||||
s3.length(url).should > File.size?(ogg_path)
|
||||
|
||||
JamTrackRight.ready_to_clean.count.should == 0
|
||||
jam_track_right.destroy
|
||||
s3.exists?(url).should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe "list_keys" do
|
||||
let(:user) {FactoryGirl.create(:user)}
|
||||
|
||||
it "empty" do
|
||||
JamTrackRight.list_keys(user, nil).should eq([])
|
||||
end
|
||||
|
||||
it "bogus key" do
|
||||
JamTrackRight.list_keys(user, ['a']).should eq([])
|
||||
end
|
||||
|
||||
it "valid track with no rights to it by querying user" do
|
||||
jam_track = FactoryGirl.create(:jam_track)
|
||||
keys = JamTrackRight.list_keys(user, [jam_track.id])
|
||||
keys.length.should == 0
|
||||
end
|
||||
|
||||
it "valid track with rights to it by querying user" do
|
||||
jam_track_right = FactoryGirl.create(:jam_track_right, private_key: 'keyabc')
|
||||
keys = JamTrackRight.list_keys(jam_track_right.user, [jam_track_right.jam_track.id])
|
||||
keys.length.should == 1
|
||||
keys[0].id.should == jam_track_right.jam_track.id
|
||||
keys[0]['private_key'].should eq('keyabc')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ describe JamTrack do
|
|||
end
|
||||
|
||||
describe "upload/download" do
|
||||
JKA_NAME = 'blah.jka'
|
||||
JKA_NAME = 'blah.jkz'
|
||||
|
||||
in_directory_with_file(JKA_NAME)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe JamTracksCleaner do
|
||||
include UsesTempFiles
|
||||
include CarrierWave::Test::Matchers
|
||||
RIGHT_NAME = 'abc.jkz'
|
||||
in_directory_with_file(RIGHT_NAME)
|
||||
|
||||
before (:all) do
|
||||
@user = FactoryGirl.create(:user)
|
||||
@jam_track = FactoryGirl.create(:jam_track)
|
||||
original_storage = JamTrackRightUploader.storage = :fog
|
||||
end
|
||||
|
||||
after(:all) do
|
||||
JamTrackRightUploader.storage = @original_storage
|
||||
end
|
||||
|
||||
|
||||
before(:each) do
|
||||
content_for_file('abc')
|
||||
end
|
||||
|
||||
it "should clean" do
|
||||
jam_track_right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track)
|
||||
jam_track_right.signed=true
|
||||
jam_track_right
|
||||
|
||||
jam_track_right.url.store!(File.open(RIGHT_NAME))
|
||||
jam_track_right.downloaded_since_sign=true
|
||||
jam_track_right.save!
|
||||
|
||||
jam_track_right[:url].should == jam_track_right.store_dir + '/' + jam_track_right.filename
|
||||
jam_track_right.reload
|
||||
|
||||
# Should exist after uploading:
|
||||
url = jam_track_right[:url]
|
||||
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
|
||||
url.should_not be_nil
|
||||
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
|
||||
|
||||
JamRuby::JamTracksCleaner.perform
|
||||
s3.exists?(url).should be_true
|
||||
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
jam_track_right.update_attribute("updated_at", 6.minutes.ago)
|
||||
|
||||
# But not after running cleaner job:
|
||||
JamRuby::JamTracksCleaner.perform
|
||||
s3.exists?(url).should be_false
|
||||
end
|
||||
end
|
||||
|
|
@ -12,6 +12,10 @@ require 'uses_temp_files'
|
|||
require 'resque_spec'
|
||||
require 'resque_failed_job_mailer'
|
||||
|
||||
# to prevent embedded resque code from forking
|
||||
ENV['FORK_PER_JOB'] = 'false'
|
||||
|
||||
|
||||
# recreate test database and migrate it
|
||||
SpecDb::recreate_database
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ def app_config
|
|||
0 # 0 seconds
|
||||
end
|
||||
|
||||
def jamtracks_dir
|
||||
ENV['JAMTRACKS_DIR'] || File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "jamtracks"))
|
||||
end
|
||||
|
||||
def rabbitmq_host
|
||||
"localhost"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
* TODO
|
||||
== TODO:
|
||||
|
||||
Jasmine Javascript Unit Tests
|
||||
=============================
|
||||
|
|
@ -11,3 +11,4 @@ $ rake jasmine
|
|||
|
||||
Open browser to localhost:8888
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -321,23 +321,15 @@
|
|||
lastDisconnectedReason = 'WEBSOCKET_CLOSED_LOCALLY'
|
||||
}
|
||||
|
||||
rest.createDiagnostic({
|
||||
type: lastDisconnectedReason,
|
||||
data: {logs: logger.logCache, client_type: clientType, client_id: server.clientID, channel_id: channelId}
|
||||
})
|
||||
.always(function() {
|
||||
if ($currentDisplay.is('.no-websocket-connection')) {
|
||||
// this path is the 'not in session path'; so there is nothing else to do
|
||||
$currentDisplay.removeClass('active');
|
||||
|
||||
// TODO: tell certain elements that we've reconnected
|
||||
}
|
||||
else {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
if ($currentDisplay.is('.no-websocket-connection')) {
|
||||
// this path is the 'not in session path'; so there is nothing else to do
|
||||
$currentDisplay.removeClass('active');
|
||||
|
||||
// TODO: tell certain elements that we've reconnected
|
||||
}
|
||||
else {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
function buildOptions() {
|
||||
|
|
|
|||
|
|
@ -1344,6 +1344,15 @@
|
|||
})
|
||||
}
|
||||
|
||||
function clearShoppingCart(options) {
|
||||
return $.ajax({
|
||||
type: "DELETE",
|
||||
url: '/api/shopping_carts/clear_all',
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
})
|
||||
}
|
||||
|
||||
function getRecurlyAccount() {
|
||||
return $.ajax({
|
||||
type: "GET",
|
||||
|
|
@ -1374,15 +1383,16 @@
|
|||
function updateBillingInfo(options) {
|
||||
return $.ajax({
|
||||
type: "PUT",
|
||||
url: '/api/recurly/update_billing_info?' + $.param(options),
|
||||
url: '/api/recurly/update_billing_info?' + $.param({billing_info: options}),
|
||||
dataType: "json",
|
||||
//data: JSON.stringify({"billing_info": $.param(options)}),
|
||||
contentType: 'application/json'
|
||||
});
|
||||
}
|
||||
|
||||
function placeOrder(options) {
|
||||
return $.ajax({
|
||||
type: "PUT",
|
||||
type: "POST",
|
||||
url: '/api/recurly/place_order?' + $.param(options),
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
|
|
@ -1534,6 +1544,7 @@
|
|||
this.addJamtrackToShoppingCart = addJamtrackToShoppingCart;
|
||||
this.getShoppingCarts = getShoppingCarts;
|
||||
this.removeShoppingCart = removeShoppingCart;
|
||||
this.clearShoppingCart = clearShoppingCart;
|
||||
this.getRecurlyAccount = getRecurlyAccount;
|
||||
this.createRecurlyAccount = createRecurlyAccount;
|
||||
this.getBillingInfo = getBillingInfo;
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@
|
|||
e.preventDefault();
|
||||
|
||||
var params = {id: $(e.target).attr("data-jamtrack-id")};
|
||||
|
||||
rest.addJamtrackToShoppingCart(params)
|
||||
.done(function(response) {
|
||||
context.location = "/client#/shoppingCart";
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
context.JK.ListenBroadcast = function($parentElement, options){
|
||||
|
||||
var WAIT_FOR_BUFFER_TIMEOUT = 5000;
|
||||
var WAIT_FOR_PLAYING_TIMEOUT = 7000;
|
||||
var RETRY_ATTEMPTS = 5; // we try 4 times, so the user will wait up until RETRY_ATTEMPTS * WAIT_FOR_BUFFER_TIMEOUTS
|
||||
|
||||
var logger = context.JK.logger;
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
var audioDomElement = null;
|
||||
var musicSessionId = null;
|
||||
var waitForBufferingTimeout = null;
|
||||
var waitForPlayingTimeout = null;
|
||||
var fanAccess = null;
|
||||
var audioSrc = null;
|
||||
var audioType = null;
|
||||
|
|
@ -49,6 +51,7 @@
|
|||
var self = this;
|
||||
var mountInfo = null;
|
||||
var $mountState = null;
|
||||
var sessionInfo = null; // stored so we can access .mount, mostly
|
||||
var lazyAudioInit = options && options.lazyAudioInit;
|
||||
var hoverOptions = (options && options.hoverOptions) ? options.hoverOptions : {}
|
||||
var $detailHelper = options && options.detailHelper;
|
||||
|
|
@ -77,21 +80,7 @@
|
|||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if(lazyAudioInit) {
|
||||
if($audio.length == 0) {
|
||||
$audio =
|
||||
$('<audio preload="none">' +
|
||||
'<source src="' + audioSrc + '" type="' + audioType + '" />' +
|
||||
'</audio>')
|
||||
$parent.append($audio)
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
}
|
||||
}
|
||||
|
||||
if(destroyed) return;
|
||||
|
||||
if(!audioDomElement) throw "no audio element supplied; the user should not be able to attempt a play"
|
||||
//if(destroyed) return;
|
||||
|
||||
if(context.JK.ListenBroadcastCurrentlyPlaying) {
|
||||
context.JK.ListenBroadcastCurrentlyPlaying.forcedPause();
|
||||
|
|
@ -102,20 +91,33 @@
|
|||
checkServer()
|
||||
.done(function(response) {
|
||||
|
||||
if(!response.mount) {
|
||||
if(!sessionInfo.mount) {
|
||||
transition(PlayStateSessionOver);
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
else {
|
||||
audioDomElement.play();
|
||||
recreateAudioElement();
|
||||
|
||||
retryAttempts = 0;
|
||||
audioDomElement.load();
|
||||
|
||||
transition(PlayStateInitializing);
|
||||
retryAttempts = 0;
|
||||
|
||||
transition(PlayStateInitializing);
|
||||
|
||||
// keep this after transition, because any transition clears this timer
|
||||
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
|
||||
logger.debug("setting buffering timeout");
|
||||
rest.addPlayablePlay(musicSessionId, 'JamRuby::MusicSession', null, context.JK.currentUserId);
|
||||
|
||||
if(needsCanPlayGuard()) {
|
||||
$audio.bind('canplay', function() {
|
||||
audioDomElement.play();
|
||||
})
|
||||
}
|
||||
else {
|
||||
audioDomElement.play();
|
||||
}
|
||||
|
||||
// keep this after transition, because any transition clears this timer
|
||||
waitForBufferingTimeout = setTimeout(noBuffer, WAIT_FOR_BUFFER_TIMEOUT);
|
||||
rest.addPlayablePlay(musicSessionId, 'JamRuby::MusicSession', null, context.JK.currentUserId);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -131,9 +133,7 @@
|
|||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if(destroyed) return;
|
||||
|
||||
if(!lazyAudioInit && !audioDomElement) throw "no audio element supplied; the user should not be able to attempt a pause"
|
||||
//if(destroyed) return;
|
||||
|
||||
transition(PlayStateNone);
|
||||
|
||||
|
|
@ -141,12 +141,13 @@
|
|||
}
|
||||
|
||||
function destroy() {
|
||||
if(!destroyed) {
|
||||
$audio.remove();
|
||||
$audio = null;
|
||||
audioDomElement = null;
|
||||
destroyed = true;
|
||||
}
|
||||
// if(!destroyed) {
|
||||
//$audio.remove();
|
||||
//$audio = null;
|
||||
//audioDomElement = null;
|
||||
recreateAudioElement()
|
||||
// destroyed = true;
|
||||
//}
|
||||
}
|
||||
|
||||
function onScreenChanged(e, data) {
|
||||
|
|
@ -155,30 +156,49 @@
|
|||
}
|
||||
}
|
||||
|
||||
function createAudioElementHtml() {
|
||||
if (sessionInfo == null) throw "no session info";
|
||||
if (sessionInfo.mount == null) throw "no session mount info";
|
||||
|
||||
$audio =
|
||||
$('<audio preload="none">' +
|
||||
'<source src="' + cacheBustedSrc(sessionInfo.mount.url) + '" type="' + sessionInfo.mount.mime_type + '"/>' +
|
||||
'</audio>')
|
||||
$parent.append($audio)
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
|
||||
}
|
||||
|
||||
// this is the only way to make audio stop buffering after the user hits pause
|
||||
function recreateAudioElement() {
|
||||
// jeez: http://stackoverflow.com/questions/4071872/html5-video-force-abort-of-buffering/13302599#13302599
|
||||
var originalSource = $audio.html()
|
||||
audioDomElement.pause();
|
||||
audioDomElement.src = '';
|
||||
audioDomElement.load();
|
||||
var $parent = $audio.parent();
|
||||
if(audioDomElement) {
|
||||
audioDomElement.pause();
|
||||
audioDomElement.src = '';
|
||||
audioDomElement.load();
|
||||
}
|
||||
$audio.remove();
|
||||
$parent.append('<audio preload="none"></audio>');
|
||||
$audio = $('audio', $parent);
|
||||
$audio.append(originalSource);
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
createAudioElementHtml();
|
||||
logger.log("recreated audio element ")
|
||||
}
|
||||
|
||||
function clearBufferTimeout() {
|
||||
if(waitForBufferingTimeout) {
|
||||
logger.debug("clearing buffering timeout");
|
||||
clearTimeout (waitForBufferingTimeout);
|
||||
waitForBufferingTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
function clearPlayingTimeout() {
|
||||
if(waitForPlayingTimeout) {
|
||||
logger.debug("clearing playing timeout");
|
||||
clearTimeout (waitForPlayingTimeout);
|
||||
waitForPlayingTimeout = null;
|
||||
}
|
||||
}
|
||||
|
||||
function transition(newState) {
|
||||
logger.log("transitioning from " + playState + " to " + newState);
|
||||
|
||||
|
|
@ -186,8 +206,15 @@
|
|||
|
||||
if(newState != PlayStateStalled) {
|
||||
clearBufferTimeout();
|
||||
clearPlayingTimeout();
|
||||
}
|
||||
|
||||
if(newState == PlayStateBuffering) {
|
||||
// give some time after buffering is seen to let play start
|
||||
waitForPlayingTimeout = setTimeout(noPlay, WAIT_FOR_PLAYING_TIMEOUT)
|
||||
}
|
||||
|
||||
|
||||
if( playState == PlayStateNone ||
|
||||
playState == PlayStateEnded ||
|
||||
playState == PlayStateFailedStart ||
|
||||
|
|
@ -202,6 +229,9 @@
|
|||
triggerStateChange();
|
||||
}
|
||||
|
||||
function noPlay() {
|
||||
noBuffer();
|
||||
}
|
||||
function noBuffer() {
|
||||
|
||||
waitForBufferingTimeout = null;
|
||||
|
|
@ -218,13 +248,16 @@
|
|||
checkServer()
|
||||
.done(function(response) {
|
||||
|
||||
if(!response.mount) {
|
||||
if(!sessionInfo.mount) {
|
||||
transition(PlayStateSessionOver);
|
||||
destroy();
|
||||
}
|
||||
else {
|
||||
// tell audio to stop/start, in attempt to retry
|
||||
//audioDomElement.pause();
|
||||
|
||||
recreateAudioElement();
|
||||
|
||||
audioDomElement.load();
|
||||
if(needsCanPlayGuard()) {
|
||||
$audio.bind('canplay', function() {
|
||||
|
|
@ -344,6 +377,10 @@
|
|||
|
||||
function checkServer() {
|
||||
return rest.getSession(musicSessionId)
|
||||
.done(function(response) {
|
||||
console.log("assigning sessionInfo")
|
||||
sessionInfo = response;
|
||||
})
|
||||
.fail(function(jqXHR) {
|
||||
if(jqXHR.status == 404 || jqXHR.status == 403) {
|
||||
transition(PlayStateSessionOver);
|
||||
|
|
@ -443,7 +480,12 @@
|
|||
|
||||
// we have cause to believe the session is done; check against the server
|
||||
if(refresh) {
|
||||
checkServer();
|
||||
checkServer()
|
||||
.done(function(response) {
|
||||
if(!sessionInfo.mount) {
|
||||
transition(PlayStateSessionOver);
|
||||
destroy();
|
||||
}})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -634,7 +676,8 @@
|
|||
|
||||
function openBubble() {
|
||||
checkServer().done(function(response) {
|
||||
var mountId = response.mount ? response.mount.id : null
|
||||
|
||||
var mountId = sessionInfo.mount ? sessionInfo.mount.id : null
|
||||
|
||||
if(mountId) {
|
||||
rest.getMount({id: mountId})
|
||||
|
|
@ -648,6 +691,10 @@
|
|||
}
|
||||
else {
|
||||
mountInfo = null;
|
||||
|
||||
transition(PlayStateSessionOver);
|
||||
destroy();
|
||||
|
||||
context.JK.app.layout.notify('This session can not currently broadcast')
|
||||
}
|
||||
})
|
||||
|
|
@ -679,8 +726,12 @@
|
|||
})
|
||||
}
|
||||
}
|
||||
function initialize() {
|
||||
|
||||
function cacheBustedSrc(src) {
|
||||
return src + '?cache-buster=' + new Date().getTime();
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
musicSessionId = $parent.attr('data-music-session');
|
||||
if(!musicSessionId) throw "data-music-session must be specified on $parentElement";
|
||||
|
|
@ -689,13 +740,6 @@
|
|||
if(fanAccess === null) throw 'fan-access must be specified in $parentElement';
|
||||
fanAccess = $parent.attr('fan-access') === 'true' // coerce to boolean
|
||||
|
||||
if(lazyAudioInit) {
|
||||
audioSrc = $parent.attr('data-audio-src');
|
||||
if(audioSrc === null) throw 'data-audio-src must be specified in $parentElement';
|
||||
audioType = $parent.attr('data-audio-type');
|
||||
if(audioType === null) throw 'data-audio-type must be specified in $parentElement';
|
||||
}
|
||||
|
||||
bindHoverDetail();
|
||||
|
||||
$audio = $('audio', $parent);
|
||||
|
|
@ -708,11 +752,6 @@
|
|||
throw "more than one <audio> element found";
|
||||
}
|
||||
|
||||
if(!lazyAudioInit) {
|
||||
audioDomElement = $audio.get(0);
|
||||
audioBind();
|
||||
}
|
||||
|
||||
$parent.bind('play.listenBroadcast', play);
|
||||
$parent.bind('pause.listenBroadcast', pause);
|
||||
$parent.bind('destroy.listenBroadcast', destroy);
|
||||
|
|
|
|||
|
|
@ -390,6 +390,12 @@
|
|||
context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.JAM_TRACK_SIGN_COMPLETE) {
|
||||
$notification.find('#div-actions').hide();
|
||||
logger.debug("context.jamClient.OnDownloadAvailable!")
|
||||
context.jamClient.OnDownloadAvailable(); // poke backend, letting it know a download is available
|
||||
}
|
||||
|
||||
else if (type === context.JK.MessageType.BAND_INVITATION) {
|
||||
var $action_btn = $notification.find($btnNotificationAction);
|
||||
$action_btn.text('ACCEPT');
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
var $shippingAsBilling = null;
|
||||
var $paymentInfoPanel = null;
|
||||
var $orderPanel = null;
|
||||
var $thanksPanel = null;
|
||||
var $orderContent = null;
|
||||
var userDetail = null;
|
||||
var step = null;
|
||||
|
|
@ -23,8 +24,7 @@
|
|||
var shipping_as_billing = null;
|
||||
|
||||
function beforeShow() {
|
||||
beforeShowPaymentInfo();
|
||||
// moveToOrder();
|
||||
beforeShowPaymentInfo();
|
||||
}
|
||||
|
||||
function beforeShowPaymentInfo() {
|
||||
|
|
@ -85,6 +85,7 @@
|
|||
|
||||
function next(e) {
|
||||
e.preventDefault();
|
||||
$("#order_error").addClass("hidden")
|
||||
|
||||
// validation
|
||||
var billing_first_name = $billingInfo.find("#billing-first-name").val();
|
||||
|
|
@ -267,7 +268,7 @@
|
|||
|
||||
var card_name = $paymentMethod.find("#card-name").val();
|
||||
var card_number = $paymentMethod.find("#card-number").val();
|
||||
var card_year = $paymentMethod.find("#card_expire-date_3i").val();
|
||||
var card_year = $paymentMethod.find("#card_expire-date_1i").val();
|
||||
var card_month = $paymentMethod.find("#card_expire-date_2i").val();
|
||||
var card_verify = $paymentMethod.find("#card-verify").val();
|
||||
|
||||
|
|
@ -317,16 +318,15 @@
|
|||
billing_info.number = card_number;
|
||||
billing_info.month = card_month;
|
||||
billing_info.year = card_year;
|
||||
billing_info.verification_value = card_verify;
|
||||
|
||||
billing_info.verification_value = card_verify;
|
||||
|
||||
if (shipping_as_billing) {
|
||||
shipping_info = billing_info;
|
||||
shipping_info = $.extend({},billing_info);
|
||||
delete shipping_info.number;
|
||||
delete shipping_info.month;
|
||||
delete shipping_info.year;
|
||||
delete shipping_info.verification_value;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
shipping_info.first_name = shipping_first_name;
|
||||
shipping_info.last_name = shipping_last_name;
|
||||
shipping_info.address1 = shipping_address1;
|
||||
|
|
@ -340,18 +340,13 @@
|
|||
$paymentInfoPanel.find("#payment-info-next").addClass("disabled");
|
||||
$paymentInfoPanel.find("#payment-info-next").off("click");
|
||||
|
||||
if (userDetail.has_recurly_account) {
|
||||
rest.updateBillingInfo(billing_info)
|
||||
.done(function() {
|
||||
})
|
||||
.fail(errorHandling);
|
||||
}
|
||||
else {
|
||||
rest.createRecurlyAccount({billing_info: billing_info})
|
||||
.done(function() {
|
||||
})
|
||||
.fail(errorHandling);
|
||||
}
|
||||
rest.createRecurlyAccount({billing_info: billing_info})
|
||||
.done(function() {
|
||||
moveToOrder();
|
||||
$paymentInfoPanel.find("#payment-info-next").removeClass("disabled");
|
||||
$paymentInfoPanel.find("#payment-info-next").on("click", next);
|
||||
})
|
||||
.fail(errorHandling);
|
||||
}
|
||||
|
||||
function errorHandling(xhr, ajaxOptions, thrownError) {
|
||||
|
|
@ -368,9 +363,18 @@
|
|||
}
|
||||
});
|
||||
|
||||
$paymentInfoPanel.find("#payment-info-next").removeClass("disabled");
|
||||
$paymentInfoPanel.find("#payment-info-next").on("click", next);
|
||||
// moveToOrder();
|
||||
$paymentInfoPanel.find("#payment-info-next").addClass("disabled");
|
||||
$paymentInfoPanel.find("#payment-info-next").on('click', next);
|
||||
}
|
||||
|
||||
function orderErrorHandling(xhr, ajaxOptions, thrownError) {
|
||||
var message = "Error submitting payment: "
|
||||
$.each(xhr.responseJSON.errors, function(key, error) {
|
||||
message += key + ": " + error
|
||||
})
|
||||
$("#order_error").text(message)
|
||||
$("#order_error").removeClass("hidden")
|
||||
$orderContent.find(".place-order").on('click', placeOrder)
|
||||
}
|
||||
|
||||
function beforeShowOrder() {
|
||||
|
|
@ -392,31 +396,32 @@
|
|||
}
|
||||
|
||||
function renderOrderPage(carts) {
|
||||
var data = {};
|
||||
var data = {}
|
||||
|
||||
var sub_total = 0;
|
||||
var sub_total = 0.0
|
||||
var taxes = 0.0
|
||||
$.each(carts, function(index, cart) {
|
||||
sub_total += parseFloat(cart.product_info.price) * parseFloat(cart.quantity);
|
||||
sub_total += parseFloat(cart.product_info.price) * parseFloat(cart.quantity)
|
||||
});
|
||||
data.sub_total = sub_total.toFixed(2);
|
||||
data.taxes = 12.01;
|
||||
|
||||
data.carts = carts;
|
||||
data.billing_info = billing_info;
|
||||
data.shipping_info = shipping_info;
|
||||
data.shipping_as_billing = shipping_as_billing;
|
||||
data.grand_total = (sub_total + taxes).toFixed(2)
|
||||
data.sub_total = sub_total.toFixed(2)
|
||||
data.taxes = taxes.toFixed(2)
|
||||
data.carts = carts
|
||||
data.billing_info = billing_info
|
||||
data.shipping_info = shipping_info
|
||||
data.shipping_as_billing = shipping_as_billing
|
||||
var orderContentHtml = $(
|
||||
context._.template(
|
||||
$('#template-order-content').html(),
|
||||
data,
|
||||
{variable: 'data'}
|
||||
)
|
||||
);
|
||||
)
|
||||
|
||||
$orderContent.append(orderContentHtml);
|
||||
$orderContent.append(orderContentHtml)
|
||||
|
||||
$orderPanel.find(".change-payment-info").on('click', moveToPaymentInfo);
|
||||
$orderContent.find(".place-order").on('click', placeOrder);
|
||||
$orderPanel.find(".change-payment-info").on('click', moveToPaymentInfo)
|
||||
$orderContent.find(".place-order").on('click', placeOrder)
|
||||
}
|
||||
|
||||
function moveToOrder() {
|
||||
|
|
@ -425,6 +430,15 @@
|
|||
beforeShowOrder();
|
||||
}
|
||||
|
||||
function moveToThanks() {
|
||||
$("#order_error").addClass("hidden")
|
||||
$paymentInfoPanel.addClass("hidden")
|
||||
$orderPanel.addClass("hidden")
|
||||
$thanksPanel.removeClass("hidden")
|
||||
rest.clearShoppingCart()
|
||||
beforeShowOrder()
|
||||
}
|
||||
|
||||
function moveToPaymentInfo(e) {
|
||||
e.preventDefault();
|
||||
$paymentInfoPanel.removeClass("hidden");
|
||||
|
|
@ -447,6 +461,17 @@
|
|||
|
||||
function placeOrder(e) {
|
||||
e.preventDefault();
|
||||
$orderContent.find(".place-order").off('click')
|
||||
rest.getShoppingCarts()
|
||||
.done(function(carts) {
|
||||
var jam_track_ids = _.map(carts, function(cart){
|
||||
return cart.product_info.product_id
|
||||
})
|
||||
rest.placeOrder({jam_tracks: jam_track_ids})
|
||||
.done(moveToThanks)
|
||||
.fail(orderErrorHandling);
|
||||
}
|
||||
).fail(app.ajaxError);
|
||||
}
|
||||
|
||||
function events() {
|
||||
|
|
@ -488,6 +513,7 @@
|
|||
$screen = $("#orderScreen");
|
||||
$paymentInfoPanel = $screen.find(".checkout-payment-info");
|
||||
$orderPanel = $screen.find(".order-panel");
|
||||
$thanksPanel = $screen.find(".thanks-panel");
|
||||
$navigation = $screen.find(".checkout-navigation-bar");
|
||||
$billingInfo = $paymentInfoPanel.find(".billing-address");
|
||||
$shippingInfo = $paymentInfoPanel.find(".shipping-address");
|
||||
|
|
|
|||
|
|
@ -23,9 +23,11 @@
|
|||
|
||||
// related to listen
|
||||
function stateChange(e, data) {
|
||||
var $listenLink = e.element;
|
||||
var $listenText = $('.listen-link-text', $listenLink);
|
||||
var $listenDetails = $('.listen-link-details', $listenLink);
|
||||
var $listenLink = data.element;
|
||||
var $parent = $listenLink.closest('.action-links')
|
||||
//console.log(e,$(this))
|
||||
var $listenText = $('.listen-link-text', $parent);
|
||||
var $listenDetails = $('.listen-link-details', $parent);
|
||||
|
||||
if(data.displayText)
|
||||
{
|
||||
|
|
@ -39,8 +41,9 @@
|
|||
}
|
||||
|
||||
if(data.isEnd) {
|
||||
$listenText.text('Listen').removeClass('statusing')
|
||||
stopPlay();
|
||||
//$listenDetails.removeClass('statusing')
|
||||
//$listenText.text('Listen')
|
||||
stopPlay($listenLink);
|
||||
}
|
||||
|
||||
if(data.isSessionOver) {
|
||||
|
|
@ -60,8 +63,9 @@
|
|||
|
||||
function togglePlay() {
|
||||
var $listenLink = $(this)
|
||||
var $listenText = $('.listen-link-text', $listenLink);
|
||||
var $listenDetails = $('.listen-link-details', $listenLink);
|
||||
var $parent = $listenLink.closest('.action-links');
|
||||
var $listenText = $('.listen-link-text', $parent);
|
||||
var $listenDetails = $('.listen-link-details', $parent);
|
||||
if($listenLink.data('listenbroadcast-playstate') == 'playing') {
|
||||
$listenText.text('Listen')
|
||||
$listenDetails.removeClass('statusing')
|
||||
|
|
|
|||
|
|
@ -73,14 +73,17 @@
|
|||
}
|
||||
|
||||
function startPlay() {
|
||||
var img = $('.play-icon');
|
||||
logger.debug("user initiated play")
|
||||
var img = $('.play-icon', $playButton);
|
||||
img.attr('src', '/assets/content/icon_pausebutton.png');
|
||||
$controls.trigger('play.listenBroadcast');
|
||||
playing = true;
|
||||
}
|
||||
|
||||
function stopPlay() {
|
||||
var img = $('.play-icon');
|
||||
logger.debug("user initiated pause")
|
||||
var img = $('.play-icon', $playButton);
|
||||
$status.text('LIVE SESSION IN PROGRESS')
|
||||
img.attr('src', '/assets/content/icon_playbutton.png');
|
||||
$controls.trigger('pause.listenBroadcast');
|
||||
playing = false;
|
||||
|
|
@ -98,7 +101,7 @@
|
|||
}
|
||||
|
||||
function initialize(musicSessionId) {
|
||||
$controls = $('.sessions-page .recording-controls');
|
||||
$controls = $('.sessions-page .session-controls');
|
||||
$status = $('.sessions-page .session-status')
|
||||
|
||||
$('.timeago').timeago();
|
||||
|
|
@ -130,7 +133,7 @@
|
|||
|
||||
$("#btnLike").click(like);
|
||||
|
||||
$playButton.trigger('click');
|
||||
startPlay();
|
||||
pollForUpdates(musicSessionId);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,6 +166,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.thanks-panel {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.order-panel {
|
||||
padding: 30px;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
.content-body {
|
||||
padding: 50px 20px 20px 20px;
|
||||
overflow: scroll;
|
||||
.shopping-cart-content {
|
||||
//padding-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.checkout-image {
|
||||
width: 10%;
|
||||
|
|
@ -52,8 +58,8 @@
|
|||
|
||||
.cart-items {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
overflow: auto;
|
||||
min-height: 200px;
|
||||
// overflow: auto;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +79,9 @@
|
|||
.no-cart-items {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
@import "client/common.css.scss";
|
||||
|
||||
.feed-entry .recording-controls, .feed-entry .session-controls, .landing-details .recording-controls {
|
||||
.feed-entry .recording-controls, .feed-entry .session-controls, .landing-details .recording-controls, .landing-details .session-controls {
|
||||
margin-top:0px;
|
||||
margin-bottom:5px;
|
||||
padding:8px 5px 8px 10px;
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
position:relative;
|
||||
}
|
||||
|
||||
.landing-details .recording-controls, .landing-details .recording-controls {
|
||||
.landing-details .recording-controls, .landing-details .session-controls {
|
||||
|
||||
background-color:#242323;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
class ApiController < ApplicationController
|
||||
|
||||
@@log = Logging.logger[ApiController]
|
||||
def log
|
||||
@log || Logging.logger[ApiController]
|
||||
end
|
||||
|
||||
@@html_encoder = HTMLEntities.new
|
||||
|
||||
# define common error handlers
|
||||
|
|
@ -21,11 +24,11 @@ class ApiController < ApplicationController
|
|||
render "errors/conflict_error", :status => 409
|
||||
end
|
||||
rescue_from 'ActiveRecord::RecordNotFound' do |exception|
|
||||
@@log.debug(exception)
|
||||
log.debug(exception)
|
||||
render :json => { :errors => { :resource => ["record not found"] } }, :status => 404
|
||||
end
|
||||
rescue_from 'PG::Error' do |exception|
|
||||
@@log.debug(exception)
|
||||
log.debug(exception)
|
||||
if exception.to_s.include? "duplicate key value violates unique constraint"
|
||||
render :json => { :errors => { :resource => ["resource already exists"] } }, :status => 409 # 409 = conflict
|
||||
else
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
class ApiJamTracksController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :api_signed_in_user
|
||||
before_filter :lookup_jam_track_right, :only => :download
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
data = JamTrack.index(params)
|
||||
@jam_tracks, @next = data[0], data[1]
|
||||
|
||||
render "api_jam_tracks/index", :layout => nil
|
||||
end
|
||||
|
||||
def downloads
|
||||
begin
|
||||
render :json => JamTrack.list_downloads(current_user, params[:limit], params[:since]), :status => 200
|
||||
rescue
|
||||
render :json => { :message => "could not produce list of files" }, :status => 403
|
||||
end
|
||||
end
|
||||
|
||||
def download
|
||||
if @jam_track_right.valid?
|
||||
if (@jam_track_right && @jam_track_right.signed && @jam_track_right.url.present? &&@jam_track_right.url.file.exists?)
|
||||
@jam_track_right.update_download_count
|
||||
@jam_track_right.save!
|
||||
redirect_to @jam_track_right.sign_url
|
||||
else
|
||||
@jam_track_right.enqueue
|
||||
render :json => { :message => "not available, digitally signing Jam Track offline." }, :status => 202
|
||||
end
|
||||
else
|
||||
render :json => { :message => "download limit surpassed", :errors=>@jam_track_right.errors }, :status => 403
|
||||
end
|
||||
end
|
||||
|
||||
def keys
|
||||
jamtrack_ids = params[:jamtracks]
|
||||
|
||||
unless jamtrack_ids.kind_of?(Array)
|
||||
render :json => {message: 'jamtracks parameter must be an array'}, :status => 200
|
||||
return
|
||||
end
|
||||
|
||||
@jam_tracks = JamTrackRight.list_keys(current_user, params[:jamtracks])
|
||||
|
||||
render "api_jam_tracks/list_keys", :layout => nil
|
||||
end
|
||||
|
||||
private
|
||||
def lookup_jam_track_right
|
||||
@jam_track_right = JamTrackRight.where("jam_track_id=? AND user_id=?", params[:id], current_user.id).first
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @jam_track_right
|
||||
end
|
||||
|
||||
end # class ApiJamTracksController
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
class ApiJamtracksController < ApiController
|
||||
|
||||
# have to be signed in currently to see this screen
|
||||
before_filter :api_signed_in_user
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
data = JamTrack.index current_user, params
|
||||
|
||||
@jamtracks = data[0]
|
||||
@next = data[1]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -8,7 +8,9 @@ class ApiRecordingsController < ApiController
|
|||
|
||||
respond_to :json
|
||||
|
||||
@@log = Logging.logger[ApiRecordingsController]
|
||||
def log
|
||||
@log || Logging.logger[ApiRecordingsController]
|
||||
end
|
||||
|
||||
def index
|
||||
# lists recordings created by for the current user
|
||||
|
|
|
|||
|
|
@ -1,155 +1,98 @@
|
|||
require 'recurly_client'
|
||||
class ApiRecurlyController < ApiController
|
||||
|
||||
before_filter :api_signed_in_user
|
||||
before_filter :create_client
|
||||
respond_to :json
|
||||
|
||||
# create Recurly account
|
||||
def create_account
|
||||
logger.debug(params[:billing_info])
|
||||
if current_user.recurly_code.nil?
|
||||
@account = Recurly::Account.create(
|
||||
account_code: current_user.id,
|
||||
email: current_user.email,
|
||||
first_name: current_user.first_name,
|
||||
last_name: current_user.last_name,
|
||||
address: {
|
||||
city: current_user.city,
|
||||
state: current_user.state,
|
||||
country: current_user.country
|
||||
}
|
||||
)
|
||||
else
|
||||
@account = Recurly::Account.find(current_user.recurly_code)
|
||||
end
|
||||
@account = @client.find_or_create_account(current_user, params[:billing_info])
|
||||
render :json=>account_json(@account)
|
||||
rescue RecurlyClientError => x
|
||||
render json: { :message => x.inspect, errors: x.errors }, :status => 404
|
||||
end
|
||||
|
||||
if @account.errors.any?
|
||||
response.status = 404
|
||||
else
|
||||
current_user.recurly_code = @account.account_code
|
||||
current_user.save
|
||||
|
||||
@account.billing_info = params[:billing_info]
|
||||
@account.billing_info.save
|
||||
|
||||
logger.debug @account
|
||||
end
|
||||
respond_with @account
|
||||
|
||||
rescue Recurly::Error, NoMethodError => e
|
||||
render :json => { :message => e.inspect }, :status => 404
|
||||
def delete_account
|
||||
@client.delete_account(current_user)
|
||||
render json: {}, status: 200
|
||||
rescue RecurlyClientError => x
|
||||
render json: { :message => x.inspect, errors: x.errors}, :status => 404
|
||||
end
|
||||
|
||||
# get Recurly account
|
||||
def get_account
|
||||
@account = Recurly::Account.find(current_user.reculry_code)
|
||||
respond_with @account
|
||||
rescue Recurly::Error, NoMethodError => e
|
||||
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||
@account=@client.get_account(current_user)
|
||||
|
||||
render :json=>account_json(@account)
|
||||
rescue RecurlyClientError => e
|
||||
render json: { message: x.inspect, errors: x.errors}, :status => 404
|
||||
end
|
||||
|
||||
# update Recurly account
|
||||
def update_account
|
||||
if current_user.recurly_code.nil?
|
||||
@account = Recurly::Account.create(
|
||||
account_code: current_user.id,
|
||||
email: current_user.email,
|
||||
first_name: current_user.first_name,
|
||||
last_name: current_user.last_name,
|
||||
address: {
|
||||
city: current_user.city,
|
||||
state: current_user.state,
|
||||
country: current_user.country
|
||||
}
|
||||
)
|
||||
else
|
||||
@account = Recurly::Account.get(current_user.recurly_code)
|
||||
end
|
||||
|
||||
@account.first_name = current_user.first_name
|
||||
@account.last_name = current_user.last_name
|
||||
@account.email = current_user.email
|
||||
@account.update
|
||||
|
||||
if @account.errors.any?
|
||||
response.status = 404
|
||||
else
|
||||
current_user.recurly_code = @account.account_code
|
||||
current_user.save
|
||||
end
|
||||
respond_with @account
|
||||
|
||||
rescue Recurly::Error, NoMethodError => e
|
||||
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||
end
|
||||
|
||||
# get subscription
|
||||
def get_subscription
|
||||
@account = Recurly::Acount.find(current_user.reculry_code)
|
||||
respond_with @account.subscriptions.last
|
||||
rescue Recurly::Error, NoMethodError => e
|
||||
render :json => { message: ValidationMessages::RECURLY_GET_ACCOUNT_ERROR}, :status => 404
|
||||
end
|
||||
|
||||
# create subscription
|
||||
def create_subscription
|
||||
@account=@client.update_account(current_user, params[:billing_info])
|
||||
render :json=>account_json(@account)
|
||||
rescue RecurlyClientError => x
|
||||
render json: { message: x.inspect, errors: x.errors}, :status => 404
|
||||
end
|
||||
|
||||
# get Billing Information
|
||||
def billing_info
|
||||
if current_user.recurly_code.nil?
|
||||
render :json => { message: ValidationMessages::RECURLY_ACCOUNT_ERROR }, :status => 404 and return
|
||||
else
|
||||
@account = Recurly::Account.find(current_user.recurly_code)
|
||||
logger.debug @account
|
||||
respond_with @account.billing_info
|
||||
end
|
||||
rescue Recurly::Error, NoMethodError => e
|
||||
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||
@account = @client.get_account(current_user)
|
||||
# @billing = @account.billing_info
|
||||
# @billing ||= @account
|
||||
render :json=> account_json(@account)
|
||||
rescue RecurlyClientError => x
|
||||
render json: { message: x.inspect, errors: x.errors}, :status => 404
|
||||
end
|
||||
|
||||
# update Billing Information
|
||||
def update_billing_info
|
||||
if current_user.recurly_code.nil?
|
||||
render :json => { message: ValidationMessages::RECURLY_ACCOUNT_ERROR }, :status => 404 and return
|
||||
else
|
||||
if params[:first_name].blank? or params[:last_name].blank? or params[:number].blank? or params[:year].blank? or params[:month].blank? or params[:verification_value].blank?
|
||||
render :json => { message: ValidationMessages::RECURLY_PARAMETER_ERROR }, :status => 404 and return
|
||||
end
|
||||
@account = Recurly::Acount.find(current_user.reculry_code)
|
||||
@account.billing_info = params
|
||||
@account.billing_info.save
|
||||
|
||||
if @account.erros.any?
|
||||
response.status = :unprocessable_entity
|
||||
end
|
||||
|
||||
respond_with @account
|
||||
end
|
||||
rescue Recurly::Error, NoMethodError => e
|
||||
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||
@account=@client.update_billing_info(current_user, params[:billing_info])
|
||||
render :json=> account_json(@account)
|
||||
rescue RecurlyClientError => x
|
||||
render json: { message: x.inspect, errors: x.errors}, :status => 404
|
||||
end
|
||||
|
||||
def place_order
|
||||
if current_user.recurly_code.nil?
|
||||
render :json => { message: ValidationMessages::RECURLY_ACCOUNT_ERROR }, :status => 404 and return
|
||||
else
|
||||
if params[:first_name].blank? or params[:last_name].blank? or params[:number].blank? or params[:year].blank? or params[:month].blank? or params[:verification_value].blank?
|
||||
render :json => { message: ValidationMessages::RECURLY_PARAMETER_ERROR }, :status => 404 and return
|
||||
error=nil
|
||||
puts "PLACING ORDER #{params.inspect}"
|
||||
params[:jam_tracks].each do |jam_track_id|
|
||||
jam_track = JamTrack.where("id=?", jam_track_id).first
|
||||
if jam_track
|
||||
@client.place_order(current_user, jam_track)
|
||||
else
|
||||
error="JamTrack not found for '#{jam_track_id}'"
|
||||
break
|
||||
end
|
||||
@account = Recurly::Account.find(current_user.recurly_code)
|
||||
@account.billing_info = params
|
||||
@account.billing_info.save
|
||||
|
||||
# create subscription.
|
||||
|
||||
if @account.erros.any?
|
||||
response.status = :unprocessable_entity
|
||||
end
|
||||
|
||||
respond_with @account
|
||||
end
|
||||
rescue Recurly::Error, NoMethodError => e
|
||||
render :json => { message: ValidationMessages::RECURLY_ERROR}, :status => 404
|
||||
|
||||
if error
|
||||
render json: { errors: {message:error}}, :status => 404
|
||||
else
|
||||
render :json=>{}, :status=>200
|
||||
end
|
||||
rescue RecurlyClientError => x
|
||||
render json: { message: x.inspect, errors: x.errors}, :status => 404
|
||||
end
|
||||
|
||||
end
|
||||
private
|
||||
def create_client
|
||||
@client = RecurlyClient.new
|
||||
end
|
||||
|
||||
def account_json(account)
|
||||
{
|
||||
:first_name => account.first_name,
|
||||
:last_name => account.last_name,
|
||||
:email => account.email,
|
||||
:address1 => account.billing_info ? account.billing_info.address1 : nil,
|
||||
:address2 => account.billing_info ? account.billing_info.address2 : nil,
|
||||
:city => account.billing_info ? account.billing_info.city : nil,
|
||||
:state => account.billing_info ? account.billing_info.state : nil,
|
||||
:zip => account.billing_info ? account.billing_info.zip : nil,
|
||||
:country => account.billing_info ? account.billing_info.country : nil
|
||||
}
|
||||
end
|
||||
|
||||
end # class
|
||||
|
|
@ -50,4 +50,9 @@ class ApiShoppingCartsController < ApiController
|
|||
respond_with responder: ApiResponder, :status => 204
|
||||
end
|
||||
|
||||
def clear_all
|
||||
ShoppingCart.where("user_id=?", current_user).destroy_all
|
||||
render :json=>{}, :status=>200
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ class ApiUserSyncsController < ApiController
|
|||
|
||||
respond_to :json
|
||||
|
||||
@@log = Logging.logger[ApiUserSyncsController]
|
||||
|
||||
def log
|
||||
@log || Logging.logger[ApiUserSyncsController]
|
||||
end
|
||||
|
||||
def show
|
||||
@user_sync = UserSync.show(params[:user_sync_id], current_user.id)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ require 'js_connect'
|
|||
|
||||
class VanillaForumsController < ApplicationController
|
||||
|
||||
@@log = Logging.logger[VanillaForumsController]
|
||||
|
||||
def log
|
||||
@log || Logging.logger[VanillaForumsController ]
|
||||
end
|
||||
|
||||
# displays the embedded forum
|
||||
# see http://vanillaforums.com/blog/jsconnect-technical-documentation-for-embedded-sso/
|
||||
|
|
@ -43,9 +46,9 @@ class VanillaForumsController < ApplicationController
|
|||
'photourl' => current_user.resolved_photo_url,
|
||||
'uniqueid' => current_user.id}
|
||||
|
||||
@@log.debug("user is logged in: #{user}")
|
||||
log.debug("user is logged in: #{user}")
|
||||
else
|
||||
@@log.debug("user is not logged in")
|
||||
log.debug("user is not logged in")
|
||||
end
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ node :next do |page|
|
|||
end
|
||||
|
||||
node :jamtracks do |page|
|
||||
partial "api_jamtracks/show", object: @jamtracks
|
||||
partial "api_jam_tracks/show", object: @jam_tracks
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
object @jam_tracks
|
||||
|
||||
node do |jam_track|
|
||||
{
|
||||
id: jam_track['id'],
|
||||
private: jam_track['private_key'],
|
||||
error: jam_track['private_key'] ? nil : ( jam_track['jam_track_right_id'] ? 'no_key' : 'not_purchased' )
|
||||
}
|
||||
end
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
object @jamtrack
|
||||
object @jam_track
|
||||
|
||||
attributes :id, :name, :description, :recording_type, :original_artist, :songwriter, :publisher, :sales_region, :price
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ node :genres do |item|
|
|||
end
|
||||
|
||||
node :added_cart do |item|
|
||||
current_user.shopping_carts.map(&:cart_id).include? item.id
|
||||
current_user.shopping_carts.where("cart_id='?'",item.id).count != 0
|
||||
end
|
||||
|
||||
child(:jam_track_tracks => :tracks) {
|
||||
|
|
@ -5,6 +5,7 @@ div layout="screen" layout-id="order" id="orderScreen" class="screen secondary"
|
|||
h1 check out
|
||||
= render "screen_navigation"
|
||||
.content-body
|
||||
#order_error.error.hidden
|
||||
.content-body-scroller
|
||||
.content-wrapper
|
||||
.checkout-navigation-bar
|
||||
|
|
@ -172,6 +173,15 @@ div layout="screen" layout-id="order" id="orderScreen" class="screen secondary"
|
|||
.clearall
|
||||
|
||||
.order-content
|
||||
.thanks-panel.hidden
|
||||
h2 Thank you for your order!
|
||||
br
|
||||
.thanks-detail We'll send you an email confirming your order shortly.
|
||||
br
|
||||
.thanks-detail If you purchased any JamTracks, the next time you run the JamKazam application, your JamTracks will automatically be downloaded to the app, and you will receive a notification when the download is complete.
|
||||
|
||||
|
||||
|
||||
|
||||
script type='text/template' id='template-order-content'
|
||||
.order-left-page
|
||||
|
|
@ -206,7 +216,8 @@ script type='text/template' id='template-order-content'
|
|||
.clearall
|
||||
|
||||
/= image_tag ''
|
||||
| ending in 1234
|
||||
="Ending in: {{data.billing_info.number.slice(-4)}}"
|
||||
|
||||
.clearall
|
||||
.order-items-page
|
||||
.cart-items
|
||||
|
|
@ -254,7 +265,7 @@ script type='text/template' id='template-order-content'
|
|||
hr
|
||||
b.order-total
|
||||
.left Order Total:
|
||||
.right= "${{data.sub_total + data.taxes}}}"
|
||||
.right= "${{data.grand_total}}"
|
||||
.clearall
|
||||
br
|
||||
div style="text-align: left;"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
%span{style: "text-decoration: underline;"} Quantity
|
||||
.clearall
|
||||
= "{% if (data.carts.length == 0) { %}"
|
||||
.no-cart-items You have no carts now.
|
||||
.no-cart-items Nothing in cart
|
||||
= "{% } %}"
|
||||
= "{% _.each(data.carts, function(cart) { %}"
|
||||
.cart-item{"cart-id" => "{{cart.id}}"}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@
|
|||
/ @end score filter
|
||||
-elsif :jamtrack==filter_label
|
||||
/ @begin availability filter
|
||||
%h3 hey
|
||||
=content_tag(:div, 'Availability:', :class => 'filter-element desc')
|
||||
=select_tag("#{filter_label}_availability", options_for_select([['Any', '']].concat(JamRuby::JamTrack::SALES_REGION), 'United States'), {:class => "easydropdown"})
|
||||
/ @end availability filter
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
<% end %>
|
||||
<br clear="all" />
|
||||
<div class="w100">
|
||||
<div class="recording-controls <%= @music_session.is_over? ? 'ended' : 'inprogress' %>" data-music-session="<%=@music_session.id %>">
|
||||
<div class="session-controls <%= @music_session.is_over? ? 'ended' : 'inprogress' %>" data-music-session="<%=@music_session.id %>">
|
||||
<a class="left play-button" href="#">
|
||||
<%= image_tag 'content/icon_pausebutton.png', width:20, height:20, class:'play-icon' %>
|
||||
<% if @music_session.active_music_session && @music_session.active_music_session.mount %>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
.latest
|
||||
.home-session-list
|
||||
%h2.latest-head Latest Sessions & Recordings
|
||||
.latest-body
|
||||
.session-list-wrapper.content-scroller
|
||||
= render :partial => "feed_item", :collection => @promo_latest
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
.latest
|
||||
.home-session-list
|
||||
- if Rails.application.config.use_promos_on_homepage
|
||||
h2.latest-head
|
||||
| Selected Sessions & Recordings
|
||||
- else
|
||||
h2.latest-head
|
||||
| Latest Sessions & Recordings
|
||||
.latest-body
|
||||
.session-list-wrapper.content-scroller
|
||||
= render :partial => "feed_item", :collection => @promo_latest
|
||||
|
|
@ -207,6 +207,9 @@ if defined?(Bundler)
|
|||
config.icecast_wait_after_reload = 0 # 0 seconds. a hack needed until VRFS-1043... maybe
|
||||
config.source_changes_missing_secs = 2 # amount of time before we think it's odd that there are no source_change notifications
|
||||
|
||||
# Location of jamtracks python tool:
|
||||
config.jamtracks_dir = ENV['JAMTRACKS_DIR'] || File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "jamtracks"))
|
||||
|
||||
config.email_alerts_alias = 'nobody@jamkazam.com' # should be used for 'oh no' server down/service down sorts of emails
|
||||
config.email_generic_from = 'nobody@jamkazam.com'
|
||||
config.email_smtp_address = 'smtp.sendgrid.net'
|
||||
|
|
|
|||
|
|
@ -3,10 +3,14 @@ require File.expand_path('../application', __FILE__)
|
|||
|
||||
Mime::Type.register "audio/ogg", :audio_ogg
|
||||
|
||||
# to prevent embedded resque code from forking
|
||||
ENV['FORK_PER_JOB'] = 'false'
|
||||
|
||||
# assign globals
|
||||
APP_CONFIG = Rails.application.config
|
||||
Stats.client = InfluxDB::Rails.client
|
||||
|
||||
|
||||
# Initialize the rails application
|
||||
SampleApp::Application.initialize!
|
||||
|
||||
|
|
|
|||
|
|
@ -89,4 +89,5 @@ SampleApp::Application.configure do
|
|||
# For product = JamKazamDev
|
||||
config.youtube_developer_key = "AI39si5bPqiNc5GQHscWJh9Wl1WTAr9aZqr_YncUvaR7Kz0rgPdBVWVubHZ94xZ3KLIBqtE9mu3VZe-UpMU80QxXoC66kBNp7A"
|
||||
config.youtube_app_name = "JamKazamDev"
|
||||
config.jam_tracks_available=true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -101,7 +101,8 @@ SampleApp::Application.configure do
|
|||
config.recurly_private_api_key = '4631527f203b41848523125b3ae51341'
|
||||
# Use Public Keys to identify your site when using Recurly.js. See https://docs.recurly.com/js/#include to learn more.
|
||||
config.recurly_public_api_key = 'sc-s6G2OA80Rwyvsb1RmS3mAE'
|
||||
config.recurly_subdomain = 'jamkazam-test'
|
||||
config.recurly_subdomain = 'jamkazam-test'
|
||||
config.log_level = :debug
|
||||
config.jam_tracks_available = true
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@
|
|||
# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
|
||||
|
||||
# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
|
||||
# Rails.backtrace_cleaner.remove_silencers!
|
||||
#Rails.backtrace_cleaner.remove_silencers!
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
@@log = Logging.logger['EmailInitializer']
|
||||
|
||||
ActionMailer::Base.raise_delivery_errors = true
|
||||
ActionMailer::Base.delivery_method = GenericState.allow_emails? ? :smtp : :test
|
||||
ActionMailer::Base.smtp_settings = {
|
||||
|
|
@ -12,4 +10,4 @@ ActionMailer::Base.smtp_settings = {
|
|||
:enable_starttls_auto => Rails.application.config.email_smtp_starttls_auto
|
||||
}
|
||||
|
||||
@@log.debug("ActionMailer.delivery_method = #{ActionMailer::Base.delivery_method}")
|
||||
Rails.logger.debug("ActionMailer.delivery_method = #{ActionMailer::Base.delivery_method}")
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ Rabl.configure do |config|
|
|||
# config.cache_engine = Rabl::CacheEngine.new # Defaults to Rails cache
|
||||
# config.escape_all_output = false
|
||||
# config.json_engine = nil # Any multi_json engines or a Class with #encode method
|
||||
config.json_engine = PrettyJson if Rails.env.development?
|
||||
# config.json_engine = PrettyJson if Rails.env.development?
|
||||
# config.msgpack_engine = nil # Defaults to ::MessagePack
|
||||
# config.bson_engine = nil # Defaults to ::BSON
|
||||
# config.plist_engine = nil # Defaults to ::Plist::Emit
|
||||
|
|
@ -24,4 +24,4 @@ Rabl.configure do |config|
|
|||
# config.enable_json_callbacks = false
|
||||
# config.xml_options = { :dasherize => true, :skip_types => false }
|
||||
config.view_paths << Rails.root.join('app/views')
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
Recurly.api_key = Rails.configuration.recurly_private_api_key
|
||||
Recurly.subdomain = Rails.configuration.recurly_subdomain
|
||||
Recurly.default_currency = 'USD'
|
||||
Recurly.logger = Rails.logger
|
||||
|
|
|
|||
|
|
@ -191,13 +191,17 @@ SampleApp::Application.routes.draw do
|
|||
match '/music_notations/:id' => 'api_music_notations#download', :via => :get, :as => :download_music_notation
|
||||
|
||||
# Jamtracks
|
||||
match '/jamtracks' => 'api_jamtracks#index', :via => :get
|
||||
match '/jamtracks' => 'api_jam_tracks#index', :via => :get, :as => 'api_jam_tracks_list'
|
||||
match '/jamtracks/downloads' => 'api_jam_tracks#downloads', :via => :get, :as => 'api_jam_tracks_downloads'
|
||||
match '/jamtracks/download/:id' => 'api_jam_tracks#download', :via => :get, :as => 'api_jam_tracks_download'
|
||||
match '/jamtracks/keys' => 'api_jam_tracks#keys', :via => :post, :as => 'api_jam_tracks_keys'
|
||||
|
||||
# Shopping carts
|
||||
match '/shopping_carts/add_jamtrack' => 'api_shopping_carts#add_jamtrack', :via => :post
|
||||
match '/shopping_carts' => 'api_shopping_carts#index', :via => :get
|
||||
match '/shopping_carts' => 'api_shopping_carts#remove_cart', :via => :delete
|
||||
|
||||
match '/shopping_carts/clear_all' => 'api_shopping_carts#clear_all', :via => :delete
|
||||
|
||||
# RSVP requests
|
||||
match '/rsvp_requests' => 'api_rsvp_requests#index', :via => :get
|
||||
match '/rsvp_requests' => 'api_rsvp_requests#create', :via => :post
|
||||
|
|
@ -233,11 +237,14 @@ SampleApp::Application.routes.draw do
|
|||
match '/users/:id/set_password' => 'api_users#set_password', :via => :post
|
||||
|
||||
# recurly
|
||||
match '/recurly/create_account' => 'api_recurly#create_account', :via => :post
|
||||
match '/recurly/create_account' => 'api_recurly#create_account', :via => :post
|
||||
match '/recurly/delete_account' => 'api_recurly#delete_account', :via => :delete
|
||||
match '/recurly/get_account' => 'api_recurly#get_account', :via => :get
|
||||
#match '/recurly/get_subscription' => 'api_recurly#get_subscription', :via => :get
|
||||
match '/recurly/update_account' => 'api_recurly#update_account', :via => :put
|
||||
match '/recurly/billing_info' => 'api_recurly#billing_info', :via => :get
|
||||
match '/recurly/update_billing_info' => 'api_recurly#update_billing_info', :via => :put
|
||||
match '/recurly/place_order' => 'api_recurly#place_order', :via => :put
|
||||
match '/recurly/place_order' => 'api_recurly#place_order', :via => :post
|
||||
|
||||
# login/logout
|
||||
match '/auth_session' => 'api_users#auth_session_create', :via => :post
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ IcecastSourceCheck:
|
|||
class: "JamRuby::IcecastSourceCheck"
|
||||
description: "Finds icecast mounts that need their 'sourced' state to change, but haven't in some time"
|
||||
|
||||
JamTracksCleaner:
|
||||
cron: "0 5 * * *"
|
||||
class: "JamRuby::UnusedMusicNotationCleaner"
|
||||
description: "Remove unused music notations"
|
||||
|
||||
CleanupFacebookSignup:
|
||||
cron: "30 2 * * *"
|
||||
class: "JamRuby::CleanupFacebookSignup"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
module Middlewares
|
||||
class ClearDuplicatedSession
|
||||
|
||||
@@log = Logging.logger[ClearDuplicatedSession]
|
||||
def log
|
||||
@log || Logging.logger[ClearDuplicatedSession]
|
||||
end
|
||||
|
||||
def initialize(app)
|
||||
@app = app
|
||||
|
|
@ -53,7 +55,7 @@ module Middlewares
|
|||
# Sets expiration date = 1970-01-01 to the cookie, this way browser will
|
||||
# note the cookie is expired and will delete it
|
||||
def delete_session_cookie_for_current_domain(env, headers)
|
||||
@@log.debug "deleting default domain session cookie"
|
||||
log.debug "deleting default domain session cookie"
|
||||
::Rack::Utils.set_cookie_header!(
|
||||
headers, # contains response headers
|
||||
get_session_key(env), # gets the cookie session name, '_session_cookie' - for this example
|
||||
|
|
|
|||
|
|
@ -0,0 +1,149 @@
|
|||
require 'recurly'
|
||||
module JamRuby
|
||||
class RecurlyClient
|
||||
def initialize()
|
||||
end
|
||||
|
||||
def create_account(current_user, billing_info=nil)
|
||||
options = account_hash(current_user, billing_info)
|
||||
account = nil
|
||||
begin
|
||||
account = Recurly::Account.create(options)
|
||||
raise RecurlyClientError.new(account.errors) if account.errors.any?
|
||||
rescue Recurly::Error, NoMethodError => x
|
||||
raise RecurlyClientError, x.to_s
|
||||
else
|
||||
if account
|
||||
current_user.update_attribute(:recurly_code, account.account_code)
|
||||
end
|
||||
end
|
||||
account
|
||||
end
|
||||
|
||||
def delete_account(current_user)
|
||||
account = get_account(current_user)
|
||||
if (account)
|
||||
begin
|
||||
account.destroy
|
||||
rescue Recurly::Error, NoMethodError => x
|
||||
raise RecurlyClientError, x.to_s
|
||||
end
|
||||
else
|
||||
raise RecurlyClientError, "Could not find account to delete."
|
||||
end
|
||||
account
|
||||
end
|
||||
|
||||
def get_account(current_user)
|
||||
(current_user && current_user.recurly_code) ? Recurly::Account.find(current_user.recurly_code) : nil
|
||||
end
|
||||
|
||||
def update_account(current_user, billing_info=nil)
|
||||
account = get_account(current_user)
|
||||
if(account.present?)
|
||||
options = account_hash(current_user, billing_info)
|
||||
begin
|
||||
account.update_attributes(options)
|
||||
rescue Recurly::Error, NoMethodError => x
|
||||
raise RecurlyClientError, x.to_s
|
||||
end
|
||||
end
|
||||
account
|
||||
end
|
||||
|
||||
def update_billing_info(current_user, billing_info=nil)
|
||||
account = get_account(current_user)
|
||||
if (account.present?)
|
||||
begin
|
||||
account.billing_info=billing_info
|
||||
account.billing_info.save
|
||||
rescue Recurly::Error, NoMethodError => x
|
||||
raise RecurlyClientError, x.to_s
|
||||
end
|
||||
|
||||
raise RecurlyClientError.new(account.errors) if account.errors.any?
|
||||
else
|
||||
raise RecurlyClientError, "Could not find account to update billing info."
|
||||
end
|
||||
account
|
||||
end
|
||||
|
||||
def place_order(current_user, jam_track)
|
||||
account = get_account(current_user)
|
||||
if (account.present?)
|
||||
begin
|
||||
subscription = Recurly::Subscription.create(:account=>account, :plan_code=>jam_track.plan_code)
|
||||
raise RecurlyClientError.new(subscription.errors) if subscription.errors.any?
|
||||
|
||||
# Reload and make sure it went through:
|
||||
account = get_account(current_user)
|
||||
|
||||
|
||||
paid_subscription = account.subscriptions.last
|
||||
raise RecurlyClientError, "Subscription not found" if paid_subscription.nil?
|
||||
raise RecurlyClientError, "Plan code '#{paid_subscription.plan_code}' doesn't match jam track: '#{jam_track.plan_code}'" if paid_subscription.plan_code != jam_track.plan_code
|
||||
|
||||
jam_track_right=JamRuby::JamTrackRight.find_or_create_by_user_id_and_jam_track_id(current_user.id, jam_track.id)
|
||||
raise RecurlyClientError.new("Error creating jam_track_right for jam_track: #{jam_track.id}") if jam_track_right.nil?
|
||||
raise RecurlyClientError.new(jam_track_right.errors) if jam_track_right.errors.any?
|
||||
rescue Recurly::Error, NoMethodError => x
|
||||
raise RecurlyClientError, x.to_s
|
||||
end
|
||||
|
||||
raise RecurlyClientError.new(account.errors) if account.errors.any?
|
||||
else
|
||||
raise RecurlyClientError, "Could not find account to place order."
|
||||
end
|
||||
account
|
||||
end
|
||||
|
||||
def find_or_create_account(current_user, billing_info=nil)
|
||||
account = get_account(current_user)
|
||||
|
||||
if(account.nil?)
|
||||
account = create_account(current_user, billing_info)
|
||||
else
|
||||
update_billing_info(current_user, billing_info)
|
||||
end
|
||||
account
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def account_hash(current_user, billing_info)
|
||||
options = {
|
||||
account_code: current_user.id,
|
||||
email: current_user.email,
|
||||
first_name: current_user.first_name,
|
||||
last_name: current_user.last_name,
|
||||
address: {
|
||||
city: current_user.city,
|
||||
state: current_user.state,
|
||||
country: current_user.country
|
||||
}
|
||||
}
|
||||
|
||||
options[:billing_info] = billing_info if billing_info
|
||||
options
|
||||
end
|
||||
end # class
|
||||
|
||||
class RecurlyClientError < Exception
|
||||
attr_accessor :errors
|
||||
def initialize(data)
|
||||
if data.respond_to?('has_key?')
|
||||
self.errors = data
|
||||
else
|
||||
self.errors = {:message=>data.to_s}
|
||||
end
|
||||
end # initialize
|
||||
|
||||
def to_s
|
||||
s=super
|
||||
s << ", errors: #{errors.inspect}" if self.errors.any?
|
||||
s
|
||||
end
|
||||
|
||||
end # RecurlyClientError
|
||||
end # module
|
||||
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
task :all_jobs do
|
||||
Rake::Task['environment'].invoke
|
||||
|
||||
ENV['FORK_PER_JOB'] = 'false'
|
||||
ENV['QUEUE'] = ENV['QUEUE'] || '*'
|
||||
Rake::Task['resque:work'].invoke
|
||||
end
|
||||
|
|
@ -12,6 +13,7 @@ end
|
|||
task :audiomixer do
|
||||
Rake::Task['environment'].invoke
|
||||
|
||||
ENV['FORK_PER_JOB'] = 'false'
|
||||
ENV['QUEUE'] = 'audiomixer'
|
||||
Rake::Task['resque:work'].invoke
|
||||
end
|
||||
|
|
@ -20,6 +22,7 @@ end
|
|||
task :icecast do
|
||||
Rake::Task['environment'].invoke
|
||||
|
||||
ENV['FORK_PER_JOB'] = 'false'
|
||||
ENV['QUEUE'] = 'icecast'
|
||||
Rake::Task['resque:work'].invoke
|
||||
end
|
||||
|
|
@ -29,6 +32,7 @@ end
|
|||
task :odd_jobs do
|
||||
Rake::Task['environment'].invoke
|
||||
|
||||
ENV['FORK_PER_JOB'] = 'false'
|
||||
ENV['QUEUE'] = '*,!icecast,!audiomixer'
|
||||
Rake::Task['resque:work'].invoke
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
require 'faraday'
|
||||
#require 'thin'
|
||||
require 'launchy'
|
||||
require 'cgi'
|
||||
require 'json'
|
||||
require 'google/api_client'
|
||||
require 'google/api_client/client_secrets'
|
||||
require 'google/api_client/auth/installed_app'
|
||||
require 'socket' # Provides TCPServer and TCPSocket classes
|
||||
# require 'youtube_client'; c = YouTubeClient.new
|
||||
# Youtube API functionality:
|
||||
require 'socket'
|
||||
|
||||
# Youtube OAuth and API functionality:
|
||||
module JamRuby
|
||||
class YouTubeClient
|
||||
attr_accessor :client
|
||||
|
|
@ -28,13 +27,7 @@ module JamRuby
|
|||
:application_version => '1.0.0'
|
||||
)
|
||||
|
||||
youtube = client.discovered_api('youtube', 'v3')
|
||||
# client.authorization = nil
|
||||
# result = client.execute
|
||||
# :key => config.youtube_developer_key,
|
||||
# :api_method => youtube.videos.list,
|
||||
# :parameters => {:id => '<YOUR_VIDEO_ID>', :part => 'snippet'}
|
||||
# result = JSON.parse(result.data.to_json)
|
||||
youtube = client.discovered_api('youtube', 'v3')
|
||||
end
|
||||
|
||||
# Return a login URL that will show a web page with
|
||||
|
|
@ -42,7 +35,6 @@ module JamRuby
|
|||
uri = "https://accounts.google.com/o/oauth2/auth"
|
||||
uri << "?scope=#{CGI.escape('https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload https://gdata.youtube.com email profile ')}" # # https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload
|
||||
uri << "&client_id=#{CGI.escape(self.config.google_email)}"
|
||||
#uri << "&client_secret=#{CGI.escape(self.config.google_secret)}"
|
||||
uri << "&response_type=code"
|
||||
uri << "&access_type=online"
|
||||
uri << "&prompt=consent"
|
||||
|
|
@ -62,6 +54,7 @@ module JamRuby
|
|||
# https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol
|
||||
def upload_sign(user, filename, length)
|
||||
raise ArgumentError, "Length is required and should be > 0" if length.to_i.zero?
|
||||
|
||||
# Something like this:
|
||||
# POST /upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails HTTP/1.1
|
||||
# Host: www.googleapis.com
|
||||
|
|
@ -104,38 +97,24 @@ module JamRuby
|
|||
}
|
||||
|
||||
conn = Faraday.new(:url =>"https://www.googleapis.com",:ssl => {:verify => false}) do |faraday|
|
||||
faraday.request :url_encoded
|
||||
faraday.response :logger
|
||||
faraday.adapter Faraday.default_adapter
|
||||
faraday.request :url_encoded
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
video_json=video_data.to_json
|
||||
# result = conn.post do |req|
|
||||
# req.url('/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status')
|
||||
# req.headers['authorization']="bearer #{(auth.token)}"
|
||||
# req.headers['content-type']='application/json;charset=utf-8'
|
||||
# req.headers['x-Upload-Content-Length']="#{length}"
|
||||
# req.headers['x-upload-content-type']="video/*"
|
||||
# req.body = video_json
|
||||
# end
|
||||
# access_token=#{CGI.escape(auth.token)}
|
||||
result = conn.post("/upload/youtube/v3/videos?access_token=#{CGI.escape(auth.token)}&uploadType=resumable&part=snippet,status,contentDetails",
|
||||
video_json,
|
||||
{
|
||||
# 'client_id'=>"#{(self.config.google_email)}",
|
||||
# 'client_secret'=>config.google_secret,
|
||||
#'Authorization'=>"bearer #{(auth.token)}",
|
||||
'content-type'=>'application/json;charset=utf-8',
|
||||
'x-Upload-Content-Length'=>"#{length}",
|
||||
'x-upload-content-type'=>"video/*"
|
||||
}
|
||||
)
|
||||
|
||||
#puts result.inspect
|
||||
|
||||
# Response should something look like:
|
||||
# HTTP/1.1 200 OK
|
||||
# Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails
|
||||
# Content-Length: 0
|
||||
# HTTP/1.1 200 OK
|
||||
# Location: https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&upload_id=xa298sd_f&part=snippet,status,contentDetails
|
||||
# Content-Length: 0
|
||||
|
||||
if (result.nil? || result.status!=200 || result.headers['location'].blank?)
|
||||
msg = "Failed signing with status=#{result.status} #{result.inspect}: "
|
||||
|
|
@ -158,8 +137,6 @@ module JamRuby
|
|||
"Content-Type" => "video/*"
|
||||
}
|
||||
end
|
||||
|
||||
# This has everything one needs to start the upload to youtube:
|
||||
end
|
||||
|
||||
# https://developers.google.com/youtube/v3/guides/using_resumable_upload_protocol#Check_Upload_Status
|
||||
|
|
@ -178,7 +155,6 @@ module JamRuby
|
|||
'Content-Length'=> "0",
|
||||
'Content-Range' => "bytes */#{length}"
|
||||
}) do |response, request, result|
|
||||
# puts "response: #{response.class}: #{response.code} / #{response.headers} / #{response.body}"
|
||||
# Result looks like this:
|
||||
# 308 Resume Incomplete
|
||||
# Content-Length: 0
|
||||
|
|
@ -216,6 +192,8 @@ module JamRuby
|
|||
(status_hash['status']>=200 && status_hash['status']<300)
|
||||
end
|
||||
|
||||
# Set fully_uploaded if the upload can be verified.
|
||||
# @return true if verified; false otherwise:
|
||||
def complete_upload(recorded_video)
|
||||
if (verify_upload(recorded_video.user, recorded_video.url, recorded_video.length))
|
||||
recorded_video.update_attribute(:fully_uploaded, true)
|
||||
|
|
@ -245,12 +223,10 @@ module JamRuby
|
|||
end
|
||||
|
||||
# Must manually confirm to obtain refresh token:
|
||||
# 4/ZwtU8nNgiEiu2JlJMrmnnw.Qo7Zys7XjRoZPm8kb2vw2M2j2ZEskgI
|
||||
def get_refresh_token
|
||||
config = Rails.application.config
|
||||
conn = Faraday.new(:url => 'https://accounts.google.com',:ssl => {:verify => false}) do |faraday|
|
||||
faraday.request :url_encoded
|
||||
faraday.response :logger
|
||||
faraday.request :url_encoded
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
|
|
@ -258,7 +234,6 @@ module JamRuby
|
|||
Rails.logger.info("The refresh_token is #{refresh_token}")
|
||||
end
|
||||
|
||||
|
||||
result = conn.get '/o/oauth2/auth', {
|
||||
'scope'=>'email profile',
|
||||
'client_id'=>config.google_client_id,
|
||||
|
|
@ -270,17 +245,15 @@ module JamRuby
|
|||
|
||||
def get_access_token(refresh_token)
|
||||
refresh_token = "4/g9uZ8S4lq2Bj1J8PPIkgOFKhTKmCHSmRe68iHA75hRg.gj8Nt5bpVYQdPm8kb2vw2M23tnRnkgI"
|
||||
#refresh_token = "4/ZwtU8nNgiEiu2JlJMrmnnw.Qo7Zys7XjRoZPm8kb2vw2M2j2ZEskgI"
|
||||
|
||||
config = Rails.application.config
|
||||
conn = Faraday.new(:url => 'https://accounts.google.com',:ssl => {:verify => false}) do |faraday|
|
||||
faraday.request :url_encoded
|
||||
faraday.response :logger
|
||||
faraday.request :url_encoded
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
wait_for_callback do |access_token|
|
||||
Rails.logger.info("The access_token is #{access_token}")
|
||||
#self.server.stop()
|
||||
Rails.logger.info("The access_token is #{access_token}")
|
||||
end
|
||||
|
||||
result = conn.post '/o/oauth2/token', nil, {
|
||||
|
|
@ -288,9 +261,7 @@ module JamRuby
|
|||
'client_id'=>config.google_client_id,
|
||||
'client_secret'=>config.google_secret,
|
||||
'refresh_token'=>refresh_token,
|
||||
#'response_type'=>"code",
|
||||
'grant_type'=>"refresh_token",
|
||||
#'access_type'=>"offline",
|
||||
'redirect_uri'=>redirect_uri
|
||||
}
|
||||
|
||||
|
|
@ -334,19 +305,16 @@ module JamRuby
|
|||
|
||||
|
||||
def exchange_for_token(access_code)
|
||||
#puts "EXCHANGING token for code: [#{access_code}] #{access_code.class}"
|
||||
|
||||
Rails.logger.info("Exchanging token for code: [#{access_code}]")
|
||||
conn = Faraday.new(:url =>"https://accounts.google.com",:ssl => {:verify => false}) do |faraday|
|
||||
faraday.request :url_encoded
|
||||
# faraday.request :multipart
|
||||
faraday.response :logger
|
||||
faraday.adapter Faraday.default_adapter
|
||||
end
|
||||
|
||||
exchange_parms={
|
||||
'grant_type'=>'authorization_code',
|
||||
'code'=>(access_code),
|
||||
'client_id'=>(config.google_email),#CGI.escape(config.google_client_id),
|
||||
'client_id'=>(config.google_email),
|
||||
'client_secret'=>(config.google_secret),
|
||||
'redirect_uri'=>(redirect_uri),
|
||||
}
|
||||
|
|
@ -357,16 +325,12 @@ module JamRuby
|
|||
end
|
||||
|
||||
body_hash = JSON.parse(result.body)
|
||||
|
||||
#puts "RESULT #{result.body.class}: #{result.body}"
|
||||
#puts "EXCHANGING for token: [#{body_hash['access_token']}]"
|
||||
body_hash['access_token']
|
||||
end
|
||||
|
||||
# shutdown
|
||||
def shutdown()
|
||||
Rails.logger.info("Stopping oauth server...")
|
||||
#Thread.kill(self.server)
|
||||
if (self.socket)
|
||||
begin
|
||||
self.socket.close
|
||||
|
|
@ -376,11 +340,6 @@ module JamRuby
|
|||
end
|
||||
self.socket = nil
|
||||
end
|
||||
|
||||
# if (self.server)
|
||||
# Thread.kill(self.server)
|
||||
# self.server = nil
|
||||
# end
|
||||
end
|
||||
end # class
|
||||
end # module
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
require 'spec_helper'
|
||||
describe ApiJamTracksController do
|
||||
render_views
|
||||
include CarrierWave::Test::Matchers
|
||||
|
||||
before(:all) do
|
||||
@original_storage = JamTrackTrackUploader.storage = :fog
|
||||
@original_storage_right = JamTrackRightUploader.storage = :fog
|
||||
end
|
||||
|
||||
after(:all) do
|
||||
JamTrackTrackUploader.storage = @original_storage
|
||||
JamTrackRightUploader.storage = @original_storage_right
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
@user = FactoryGirl.create(:user)
|
||||
@jam_track = FactoryGirl.create(:jam_track)
|
||||
controller.current_user = @user
|
||||
end
|
||||
|
||||
describe "download functionality" do
|
||||
it "lists available tracks" do
|
||||
get :index
|
||||
response.should be_success
|
||||
json = JSON.parse(response.body)#, :symbolize_names => true)
|
||||
json["next"].should be_nil
|
||||
json["jamtracks"].length.should == 1
|
||||
|
||||
jam_track2 = FactoryGirl.create(:jam_track)
|
||||
get :index
|
||||
response.should be_success
|
||||
json = JSON.parse(response.body)#, :symbolize_names => true)
|
||||
json["next"].should be_nil
|
||||
json["jamtracks"].length.should == 2
|
||||
end
|
||||
|
||||
it "lists owned tracks" do
|
||||
get :downloads
|
||||
response.should be_success
|
||||
json = JSON.parse(response.body)
|
||||
json['downloads'].should have(0).items
|
||||
|
||||
right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track)
|
||||
get :downloads
|
||||
response.should be_success
|
||||
json = JSON.parse(response.body)
|
||||
json['downloads'].should have(1).items
|
||||
end
|
||||
|
||||
it "finds a download" do
|
||||
#get "/download/#{right.id}/"
|
||||
right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track)
|
||||
get :download, { :format => 'json', :id => @jam_track.id }
|
||||
|
||||
response.should be_success
|
||||
response.status.should == 202
|
||||
response.body.should =~ /not available.*/
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
describe "with a JamTrack" do
|
||||
before(:each) do
|
||||
JamTrackRight.destroy_all
|
||||
# Create a working JamTrack for these tests. The integrity
|
||||
# of this process is checked in other tests:
|
||||
@ogg_path = File.join('spec', 'files', 'on.ogg')
|
||||
@jam_track = FactoryGirl.create(:jam_track) #jam_track_track.jam_track
|
||||
jam_track_track = @jam_track.jam_track_tracks.first
|
||||
|
||||
uploader = JamTrackTrackUploader.new(jam_track_track, :url)
|
||||
uploader.store!(File.open(@ogg_path, 'rb'))
|
||||
#jam_track_track.url.store!(File.open(ogg_path, "rb"))
|
||||
jam_track_track.save!
|
||||
jam_track_track.reload
|
||||
ResqueSpec.reset!
|
||||
end
|
||||
|
||||
it "download depends on rights" do
|
||||
s3 = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
||||
get :download, :id => @jam_track.id
|
||||
response.status.should == 403
|
||||
|
||||
right = JamTrackRight.create(:user=>@user, :jam_track=>@jam_track)
|
||||
get :download, :id => @jam_track.id
|
||||
response.status.should == 202
|
||||
right.download_count.should eq(0)
|
||||
right.private_key.should be_nil
|
||||
|
||||
JamTracksBuilder.should have_queued(right.id).in(:jam_tracks_builder)
|
||||
|
||||
qname = "#{ResqueSpec.queue_name(JamRuby::JamTracksBuilder)}"
|
||||
expect(ResqueSpec.peek(qname).present?).to eq(true)
|
||||
ResqueSpec.perform_next(qname)
|
||||
|
||||
JamTracksBuilder.should_not have_queued(right.id).in(:jam_tracks_builder)
|
||||
right.reload
|
||||
right.private_key.should_not be_nil
|
||||
right.download_count.should eq(0)
|
||||
|
||||
get :download, :id => @jam_track.id
|
||||
response.status.should == 302
|
||||
response.location.should =~ /.*#{Regexp.escape(right.filename)}.*/
|
||||
right.reload
|
||||
right.download_count.should eq(1)
|
||||
|
||||
notifications = Notification.where(:jam_track_right_id => right.id)
|
||||
notifications.count.should == 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "keys" do
|
||||
it "empty" do
|
||||
get :keys, jamtracks: []
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json.length == 0
|
||||
end
|
||||
|
||||
it "track with no rights" do
|
||||
get :keys, jamtracks: [@jam_track.id]
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json.length.should == 1
|
||||
puts json.inspect
|
||||
json[0]['id'].should == @jam_track.id
|
||||
json[0]['private'].should be_nil
|
||||
json[0]['error'].should == 'not_purchased'
|
||||
end
|
||||
|
||||
it "track with no key" do
|
||||
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, private_key: nil, jam_track: @jam_track)
|
||||
|
||||
get :keys, jamtracks: [@jam_track.id]
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json.length.should == 1
|
||||
json[0]['id'].should == @jam_track.id
|
||||
json[0]['private'].should be_nil
|
||||
json[0]['error'].should == 'no_key'
|
||||
end
|
||||
|
||||
it "track with key" do
|
||||
right = FactoryGirl.create(:jam_track_right, user: @user, private_key: 'abc', jam_track: @jam_track)
|
||||
get :keys, jamtracks: [@jam_track.id]
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json.length.should == 1
|
||||
json[0]['id'].should == @jam_track.id
|
||||
json[0]['private'].should eq('abc')
|
||||
json[0]['error'].should be_nil
|
||||
end
|
||||
|
||||
it "non-owning user asking for a real track" do
|
||||
right = FactoryGirl.create(:jam_track_right, user: FactoryGirl.create(:user), private_key: 'abc', jam_track: @jam_track)
|
||||
get :keys, jamtracks: [@jam_track.id]
|
||||
response.status.should == 200
|
||||
json = JSON.parse(response.body)
|
||||
json[0]['id'].should == @jam_track.id
|
||||
json[0]['private'].should be_nil
|
||||
json[0]['error'].should == 'not_purchased'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,34 +1,118 @@
|
|||
# require 'spec_helper'
|
||||
#
|
||||
# describe ApiRecurlyController do
|
||||
# render_views
|
||||
#
|
||||
# let(:user) { FactoryGirl.create(:user) }
|
||||
# let(:jamtrack) { FactoryGirl.create(:jam_track) }
|
||||
#
|
||||
# before(:each) do
|
||||
# @billing_info = {}
|
||||
# @billing_info[:first_name] = user.first_name
|
||||
# @billing_info[:last_name] = user.last_name
|
||||
# @billing_info[:address1] = 'Test Address 1'
|
||||
# @billing_info[:address2] = 'Test Address 2'
|
||||
# @billing_info[:city] = user.city
|
||||
# @billing_info[:state] = user.state
|
||||
# @billing_info[:country] = user.country
|
||||
# @billing_info[:zip] = '12345'
|
||||
# @billing_info[:number] = '4111-1111-1111-1111'
|
||||
# @billing_info[:month] = '08'
|
||||
# @billing_info[:year] = '2017'
|
||||
# @billing_info[:verification_value] = '1111'
|
||||
# controller.current_user = user
|
||||
# end
|
||||
#
|
||||
# describe "start" do
|
||||
# it "should create recurly account" do
|
||||
# post :create_account, { :format => 'json', :billing_info => @billing_info}
|
||||
# response_body = JSON.parse(response.body)
|
||||
# puts response_body
|
||||
# response.should be_success
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
require 'spec_helper'
|
||||
require 'recurly_client'
|
||||
#require 'recurly/account'
|
||||
|
||||
describe ApiRecurlyController, :type=>:controller do
|
||||
render_views
|
||||
|
||||
# let(:user) { FactoryGirl.create(:user) }
|
||||
# let(:jamtrack) { FactoryGirl.create(:jam_track) }
|
||||
|
||||
before(:each) do
|
||||
@user = FactoryGirl.create(:user)
|
||||
#@jamtrack = FactoryGirl.create(:jam_track)
|
||||
@billing_info = {}
|
||||
@billing_info[:first_name] = @user.first_name
|
||||
@billing_info[:last_name] = @user.last_name
|
||||
@billing_info[:address1] = 'Test Address 1'
|
||||
@billing_info[:address2] = 'Test Address 2'
|
||||
@billing_info[:city] = @user.city
|
||||
@billing_info[:state] = @user.state
|
||||
@billing_info[:country] = @user.country
|
||||
@billing_info[:zip] = '12345'
|
||||
@billing_info[:number] = '4111-1111-1111-1111'
|
||||
@billing_info[:month] = '08'
|
||||
@billing_info[:year] = '2017'
|
||||
@billing_info[:verification_value] = '111'
|
||||
@billing_info[:vat_number] = ''
|
||||
controller.current_user = @user
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
if (@user.recurly_code)
|
||||
@account = Recurly::Account.find(@user.recurly_code)
|
||||
if @account.present?
|
||||
@account.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "should send correct error" do
|
||||
@billing_info[:number]='121'
|
||||
post :create_account, {:format => 'json', :billing_info=>@billing_info}
|
||||
response.status.should == 404
|
||||
body = JSON.parse(response.body)
|
||||
body['errors'].should have(1).items
|
||||
body['errors']['number'].should_not be_nil
|
||||
end
|
||||
|
||||
it "should create account" do
|
||||
post :create_account, {:format => 'json'}
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it "should retrieve account" do
|
||||
post :create_account, {:format => 'json'}
|
||||
response.should be_success
|
||||
|
||||
get :get_account
|
||||
body = JSON.parse(response.body)
|
||||
response.should be_success
|
||||
body['email'].should eq(@user.email)
|
||||
end
|
||||
|
||||
it "should update account" do
|
||||
post :create_account
|
||||
response.should be_success
|
||||
body = JSON.parse(response.body)
|
||||
body['first_name'].should eq("Person")
|
||||
|
||||
@user.update_attribute(:first_name, "Thing")
|
||||
controller.current_user = @user
|
||||
put :update_account
|
||||
body = JSON.parse(response.body)
|
||||
body['first_name'].should eq("Thing")
|
||||
|
||||
get :get_account, { :format => 'json'}
|
||||
response.should be_success
|
||||
body = JSON.parse(response.body)
|
||||
body['first_name'].should eq("Thing")
|
||||
end
|
||||
|
||||
# Note: We don't have any subscriptions yet:
|
||||
it "should get subscription" do
|
||||
pending "We don't have any subscriptions yet -- uncomment in routes"
|
||||
get :get_subscription, { :format => 'json'}
|
||||
response.should be_success
|
||||
body = JSON.parse(response.body)
|
||||
end
|
||||
|
||||
it "should update billing info" do
|
||||
# $enable_tracing = false
|
||||
# $trace_out = open('trace.txt', 'w')
|
||||
|
||||
# set_trace_func proc { |event, file, line, id, binding, classname|
|
||||
# if $enable_tracing && event == 'call' && !file.start_with?("/Users/tangledpath/.ddrvm/")
|
||||
# $trace_out.puts "#{file}:#{line} #{classname}##{id}"
|
||||
# end
|
||||
# }
|
||||
|
||||
# $enable_tracing = true
|
||||
|
||||
post :create_account
|
||||
response.should be_success
|
||||
body = JSON.parse(response.body)
|
||||
body['first_name'].should eq("Person")
|
||||
@billing_info[:state] = "NE"
|
||||
|
||||
put :update_billing_info, {:format => 'json', :billing_info=>@billing_info}
|
||||
|
||||
response.should be_success
|
||||
body = JSON.parse(response.body)
|
||||
|
||||
get :billing_info
|
||||
response.should be_success
|
||||
body = JSON.parse(response.body)
|
||||
end
|
||||
|
||||
end # spec
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ FactoryGirl.define do
|
|||
before(:create) do |user, evaluator|
|
||||
if evaluator.specific_instruments
|
||||
evaluator.specific_instruments.each do |instrument|
|
||||
puts "burp: "
|
||||
user.musician_instruments << FactoryGirl.build(:musician_instrument, user: user, instrument: instrument)
|
||||
end
|
||||
else
|
||||
|
|
@ -709,7 +708,7 @@ FactoryGirl.define do
|
|||
reproduction_royalty_amount 0.999
|
||||
licensor_royalty_amount 0.999
|
||||
pro_royalty_amount 0.999
|
||||
|
||||
plan_code 'jamtrack-acdc-backinblack'
|
||||
ignore do
|
||||
make_track true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ describe "Create Session", :js => true, :type => :feature, :capybara_feature =>
|
|||
|
||||
btn = first('#btn-alert-ok')# accept the 'If you start this session now, the scheduled start time...'
|
||||
btn.trigger(:click) if btn
|
||||
|
||||
|
||||
expect(page).to have_selector('h2', text: 'my tracks')
|
||||
find('#session-screen .session-mytracks .session-track')
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue