merging develop

This commit is contained in:
Jonathan Kolyer 2015-08-04 13:44:47 +00:00
commit aa36b2f215
371 changed files with 13873 additions and 2103 deletions

View File

@ -14,7 +14,7 @@ else
ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true" ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true"
end end
gem 'rails', '~> 3.2.11' gem 'rails', '~> 3.2.22'
gem 'bootstrap-sass', '2.0.4' gem 'bootstrap-sass', '2.0.4'
gem 'bcrypt-ruby', '3.0.1' gem 'bcrypt-ruby', '3.0.1'
@ -44,7 +44,7 @@ gem 'rails3-jquery-autocomplete'
gem 'activeadmin' #, github: 'activeadmin', branch: '0-6-stable' gem 'activeadmin' #, github: 'activeadmin', branch: '0-6-stable'
gem 'mime-types', '1.25' gem 'mime-types', '1.25'
gem 'meta_search' gem 'meta_search'
gem 'fog', "~> 1.18.0" gem 'fog', "~> 1.32.0"
gem 'unf', '0.1.3' #optional fog dependency gem 'unf', '0.1.3' #optional fog dependency
gem 'country-select' gem 'country-select'
gem 'aasm', '3.0.16' gem 'aasm', '3.0.16'
@ -58,7 +58,7 @@ gem 'resque'
gem 'resque-retry' gem 'resque-retry'
gem 'resque-failed-job-mailer' gem 'resque-failed-job-mailer'
gem 'resque-lonely_job', '~> 1.0.0' gem 'resque-lonely_job', '~> 1.0.0'
gem 'eventmachine', '1.0.3' gem 'eventmachine', '1.0.4'
gem 'amqp', '0.9.8' gem 'amqp', '0.9.8'
gem 'logging-rails', :require => 'logging/rails' gem 'logging-rails', :require => 'logging/rails'
gem 'pg_migrate' gem 'pg_migrate'
@ -77,7 +77,7 @@ gem 'influxdb-rails', '0.1.10'
gem 'recurly' gem 'recurly'
group :libv8 do group :libv8 do
gem 'libv8', "~> 3.11.8" gem 'libv8', "~> 4.5.95"
end end
@ -101,15 +101,16 @@ end
group :development, :test do group :development, :test do
gem 'capybara' gem 'capybara'
gem 'rspec-rails', '2.14.2' gem 'rspec-rails', '2.14.2'
gem 'guard-rspec', '0.5.5' gem 'guard-rspec'
gem 'jasmine', '1.3.1' gem 'jasmine', '1.3.1'
gem 'execjs', '1.4.0' gem 'execjs', '1.4.0'
gem 'therubyracer' #, '0.11.0beta8' #gem 'therubyracer' #, '0.11.0beta8'
gem 'factory_girl_rails', '4.1.0' gem 'factory_girl_rails', '4.1.0'
gem 'database_cleaner', '0.7.0' gem 'database_cleaner', '0.7.0'
gem 'launchy' gem 'launchy'
gem 'faker', '1.3.0' gem 'faker', '1.3.0'
gem 'puma' gem 'puma'
gem 'test-unit'
end end
group :test do group :test do

View File

@ -5,9 +5,14 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
config.sort_order = 'name_asc' config.sort_order = 'name_asc'
config.batch_actions = false config.batch_actions = false
filter :genre filter :genres
filter :status, :as => :select, collection: JamRuby::JamTrack::STATUS filter :status, :as => :select, collection: JamRuby::JamTrack::STATUS
scope("Default", default: true) { |scope| scope }
scope("Onboarding TODO") { |scope| scope.where('onboarding_exceptions is not null') }
scope("Tency Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tency Music'") }
scope("Onboarding TODO w/ Tency Only") { |scope| scope.joins('INNER JOIN jam_track_licensors as licensors ON jam_tracks.licensor_id = licensors.id').where("licensors.name = 'Tency Music'").where('onboarding_exceptions is not null') }
form :partial => 'form' form :partial => 'form'
index do index do
@ -24,11 +29,21 @@ ActiveAdmin.register JamRuby::JamTrack, :as => 'JamTracks' do
column :original_artist column :original_artist
column :name column :name
column :onboarding_flags do |jam_track| jam_track.onboard_warnings end column :onboarding_exceptions do |jam_track|
if jam_track.onboarding_exceptions
exceptions = JSON.parse(jam_track.onboarding_exceptions)
exceptions.keys.join(',')
else
''
end
end
column :status column :status
column :master_track do |jam_track| jam_track.master_track.nil? ? 'None' : (link_to "Download", jam_track.master_track.url_by_sample_rate(44)) end column :master_track do |jam_track| jam_track.master_track.nil? ? 'None' : (link_to "Download", jam_track.master_track.url_by_sample_rate(44)) end
column :licensor column :licensor
column :genre column :genres do |jam_track|
jam_track.genres.map(&:description).join(',')
end
column :price column :price
column :reproduction_royalty column :reproduction_royalty
column :public_performance_royalty column :public_performance_royalty

View File

@ -12,7 +12,7 @@
= f.input :songwriter, :input_html => { :rows=>1, :maxlength=>1000 } = f.input :songwriter, :input_html => { :rows=>1, :maxlength=>1000 }
= f.input :publisher, :input_html => { :rows=>1, :maxlength=>1000 } = f.input :publisher, :input_html => { :rows=>1, :maxlength=>1000 }
= f.input :licensor, collection: JamRuby::JamTrackLicensor.all, include_blank: true = f.input :licensor, collection: JamRuby::JamTrackLicensor.all, include_blank: true
= f.input :genre, collection: JamRuby::Genre.all, include_blank: false = f.input :genres
= f.input :duration, hint: 'this should rarely need editing because it comes from the import process' = f.input :duration, hint: 'this should rarely need editing because it comes from the import process'
= f.input :sales_region, collection: JamRuby::JamTrack::SALES_REGION, 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 :price, :required => true, :input_html => {type: 'numeric'}

View File

@ -1,2 +1,2 @@
<%- headers = ['email', 'name', 'unsubscribe_token'] -%> <%- headers = ['email', 'name', 'unsubscribe_token'] -%>
<%= CSV.generate_line headers %><%- @users.each do |user| -%><%= CSV.generate_line([user.email, user.name, user.unsubscribe_token]) %><%- end -%> <%= CSV.generate_line headers %><%- @users.each do |user| -%><%= CSV.generate_line([user.email, user.first_name, user.unsubscribe_token]) %><%- end -%>

View File

@ -1,5 +1,10 @@
ActionMailer::Base.raise_delivery_errors = true ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = Rails.env == "test" ? :test : :smtp begin
ActionMailer::Base.delivery_method = Rails.env == "test" ? :test : :smtp
rescue
# this can happen on the build server when it's compiling assets and doesn't have the 'jam' database
ActionMailer::Base.delivery_method = :test
end
ActionMailer::Base.smtp_settings = { ActionMailer::Base.smtp_settings = {
:address => Rails.application.config.email_smtp_address, :address => Rails.application.config.email_smtp_address,
:port => Rails.application.config.email_smtp_port, :port => Rails.application.config.email_smtp_port,

View File

@ -16,7 +16,6 @@ class JamRuby::JamTrack
end end
def jmep_json_generate def jmep_json_generate
self.genre_id = nil if self.genre_id == ''
self.licensor_id = nil if self.licensor_id == '' self.licensor_id = nil if self.licensor_id == ''
self.jmep_json = nil if self.jmep_json == '' self.jmep_json = nil if self.jmep_json == ''
self.time_signature = nil if self.time_signature == '' self.time_signature = nil if self.time_signature == ''

View File

@ -4,4 +4,4 @@
# If you change this key, all old signed cookies will become invalid! # If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random, # Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks. # no regular words or you'll be exposed to dictionary attacks.
JamAdmin::Application.config.secret_token = 'e27a8deff5bc124d1c74cb86ebf38ac4a246091b859bcccf4f8076454e0ff3e04ffc87c9a0f4ddc801c4753e20b2a3cf06e5efc815cfe8e6377f912b737c5f77' JamAdmin::Application.config.secret_token = 'ced345e01611593c1b783bae98e4e56dbaee787747e92a141565f7c61d0ab2c6f98f7396fb4b178258301e2713816e158461af58c14b695901692f91e72b6200'

7
build
View File

@ -61,9 +61,10 @@ popd > /dev/null
if [ ! -z "$PACKAGE" ]; then if [ ! -z "$PACKAGE" ]; then
DEB_SERVER=http://localhost:9010/apt-`uname -p` source /etc/lsb-release
GEM_SERVER=http://localhost:9000/gems DEB_SERVER=https://int.jamkazam.com:9010/apt-`uname -p`/$DISTRIB_CODENAME
GEM_SERVER=http://localhost:9000/gems
# if still going, then push all debs up # if still going, then push all debs up
if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* || "$GIT_BRANCH" == *release* || "$GIT_BRANCH" == *feature* || "$GIT_BRANCH" == *hotfix* ]]; then if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* || "$GIT_BRANCH" == *release* || "$GIT_BRANCH" == *feature* || "$GIT_BRANCH" == *hotfix* ]]; then

View File

@ -3,4 +3,4 @@ source 'http://rubygems.org'
# Assumes you have already cloned pg_migrate_ruby in your workspace # Assumes you have already cloned pg_migrate_ruby in your workspace
# $ cd [workspace] # $ cd [workspace]
# $ git clone https://github.com/sethcall/pg_migrate_ruby # $ git clone https://github.com/sethcall/pg_migrate_ruby
gem 'pg_migrate', '0.1.13' gem 'pg_migrate', '0.1.13', :source => 'http://rubygems.org/'

View File

@ -15,7 +15,7 @@ PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
pg_migrate (= 0.1.13) pg_migrate (= 0.1.13)!
BUNDLED WITH BUNDLED WITH
1.10.3 1.10.5

View File

@ -31,6 +31,7 @@ if [ ! -z "$PACKAGE" ]; then
bundle install --path target/vendor/bundle bundle install --path target/vendor/bundle
pushd target pushd target
fpm -s gem -t deb ruby_package/jam_db-$VERSION.gem fpm -s gem -t deb ruby_package/jam_db-$VERSION.gem
find vendor/bundle/ruby/2.2.0/cache -name '*.gem' | xargs -rn1 fpm -s gem -t deb
find vendor/bundle/ruby/2.0.0/cache -name '*.gem' | xargs -rn1 fpm -s gem -t deb find vendor/bundle/ruby/2.0.0/cache -name '*.gem' | xargs -rn1 fpm -s gem -t deb
popd popd
fi fi

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
GEM_SERVER=http://localhost:9000/gems GEM_SERVER=https://int.jamkazam.com:9000/gems
DEB_SERVER=http://localhost:9010/apt-`uname -p` DEB_SERVER=https://int.jamkazam.com:9010/apt-`uname -p`
echo "starting build..." echo "starting build..."
./build ./build

View File

@ -276,12 +276,6 @@ jam_track_duration.sql
sales.sql sales.sql
show_whats_next_count.sql show_whats_next_count.sql
recurly_adjustments.sql recurly_adjustments.sql
alter_type_columns.sql
user_presences_rename.sql
add_genre_type.sql
add_description_to_perf_samples.sql
alter_genre_player_unique_constraint.sql
musician_search.sql
signup_hints.sql signup_hints.sql
packaging_notices.sql packaging_notices.sql
first_played_jamtrack_at.sql first_played_jamtrack_at.sql
@ -292,6 +286,17 @@ signing.sql
optimized_redeemption.sql optimized_redeemption.sql
optimized_redemption_warn_mode.sql optimized_redemption_warn_mode.sql
affiliate_partners2.sql affiliate_partners2.sql
enhance_band_profile.sql
broadcast_notifications.sql broadcast_notifications.sql
broadcast_notifications_fk.sql broadcast_notifications_fk.sql
calendar.sql
alter_type_columns.sql
user_presences_rename.sql
add_genre_type.sql
add_description_to_perf_samples.sql
alter_genre_player_unique_constraint.sql
musician_search.sql
enhance_band_profile.sql
alter_band_profile_rate_defaults.sql
repair_band_profile.sql
jam_track_onboarding_enhancements.sql
jam_track_name_drop_unique.sql

View File

@ -0,0 +1,2 @@
ALTER TABLE bands ALTER COLUMN hourly_rate SET DEFAULT NULL;
ALTER TABLE bands ALTER COLUMN gig_minimum SET DEFAULT NULL;

13
db/up/calendar.sql Normal file
View File

@ -0,0 +1,13 @@
CREATE TABLE calendars (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
target_uid VARCHAR(64) NOT NULL,
name VARCHAR(128),
description VARCHAR(8000),
trigger_delete BOOLEAN DEFAULT FALSE,
start_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
end_at TIMESTAMP WITHOUT TIME ZONE NOT NULL,
recurring_mode VARCHAR(50) NOT NULL DEFAULT 'once',
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);

View File

@ -0,0 +1 @@
ALTER TABLE jam_tracks DROP CONSTRAINT jam_tracks_name_key;

View File

@ -0,0 +1,78 @@
-- "rsvp_slots_instrument_id_fkey" FOREIGN KEY (instrument_id) REFERENCES instruments(id)
-- "musicians_instruments_instrument_id_fkey" FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE
-- "saved_tracks_instrument_id_fkey" FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE
ALTER TABLE rsvp_slots DROP CONSTRAINT rsvp_slots_instrument_id_fkey;
ALTER TABLE musicians_instruments DROP CONSTRAINT musicians_instruments_instrument_id_fkey;
ALTER TABLE recorded_tracks DROP CONSTRAINT saved_tracks_instrument_id_fkey;
UPDATE instruments SET id = 'double bass', description = 'Double Bass' WHERE id = 'upright bass';
UPDATE rsvp_slots SET instrument_id = 'double bass' where instrument_id = 'upright bass';
UPDATE musicians_instruments SET instrument_id = 'double bass' where instrument_id = 'upright bass';
UPDATE recorded_tracks SET instrument_id = 'double bass' where instrument_id = 'upright bass';
ALTER TABLE rsvp_slots ADD CONSTRAINT rsvp_slots_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE SET NULL;
ALTER TABLE musicians_instruments ADD CONSTRAINT musicians_instruments_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE;
ALTER TABLE recorded_tracks ADD CONSTRAINT saved_tracks_instrument_id_fkey FOREIGN KEY (instrument_id) REFERENCES instruments(id) ON DELETE CASCADE;
INSERT INTO instruments (id, description, popularity) VALUES ('steel guitar', 'Steel Guitar', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('orchestra', 'Orchestra', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('glockenspiel', 'Glockenspiel', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('dobro', 'Dobro', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('harp', 'Harp', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('vocoder', 'Vocoder', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('flugelhorn', 'Flugelhorn', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('timpani', 'Timpani', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('bassoon', 'Bassoon', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('charango', 'Charango', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('theremin', 'Theremin', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('sitar', 'Sitar', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('piccolo', 'Piccolo', 1);
INSERT INTO instruments (id, description, popularity) VALUES ('bagpipes', 'Bagpipes', 1);
ALTER TABLE jam_tracks ADD COLUMN onboarding_exceptions JSON;
ALTER TABLE jam_track_tracks ADD COLUMN original_filename VARCHAR;
ALTER TABLE jam_tracks ADD COLUMN additional_info VARCHAR;
ALTER TABLE jam_tracks ADD COLUMN language VARCHAR NOT NULL DEFAULT 'eng';
ALTER TABLE jam_tracks ADD COLUMN year INTEGER;
ALTER TABLE jam_tracks ADD COLUMN vendor_id VARCHAR;
INSERT INTO jam_track_licensors (name, description) VALUES ('Tency Music', 'Tency Music is a music production company specialized in re-recordings.');
CREATE TABLE genres_jam_tracks (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
jam_track_id VARCHAR(64) NOT NULL REFERENCES jam_tracks(id) ON DELETE CASCADE,
genre_id VARCHAR(64) NOT NULL REFERENCES genres(id) ON DELETE CASCADE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO genres_jam_tracks (jam_track_id, genre_id) ((SELECT jam_tracks.id, jam_tracks.genre_id FROM jam_tracks));
ALTER TABLE jam_tracks DROP COLUMN genre_id;
-- holds precount, click.wav, click.txt
CREATE TABLE jam_track_files (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
jam_track_id VARCHAR(64) REFERENCES jam_tracks(id) ON DELETE CASCADE,
file_type VARCHAR NOT NULL,
original_filename VARCHAR NOT NULL,
precount_num INTEGER,
url VARCHAR,
md5 VARCHAR,
length bigint,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO genres (id, description) VALUES ('soft rock', 'Soft Rock');
INSERT INTO genres (id, description) VALUES ('rap', 'Rap');
INSERT INTO genres (id, description) VALUES ('tv & movie soundtrack', 'TV & Movie Soundtrack');
INSERT INTO genres (id, description) VALUES ('holiday', 'Holiday');
INSERT INTO genres (id, description) VALUES ('kids', 'Kids');
INSERT INTO genres (id, description) VALUES ('disco', 'Disco');
INSERT INTO genres (id, description) VALUES ('soul', 'Soul');
INSERT INTO genres (id, description) VALUES ('hard rock', 'Hard Rock');
INSERT INTO genres (id, description) VALUES ('funk', 'Funk');
INSERT INTO genres (id, description) VALUES ('dance', 'Dance');
INSERT INTO genres (id, description) VALUES ('creole', 'Creole');
INSERT INTO genres (id, description) VALUES ('traditional', 'Traditional');
INSERT INTO genres (id, description) VALUES ('oldies', 'Oldies');
INSERT INTO genres (id, description) VALUES ('world', 'World');
INSERT INTO genres (id, description) VALUES ('musical', 'Musical');
INSERT INTO genres (id, description) VALUES ('celtic', 'Celtic');

View File

@ -0,0 +1,3 @@
ALTER TABLE musicians_instruments ALTER COLUMN player_id SET NOT NULL;
ALTER TABLE performance_samples ALTER COLUMN player_id SET NOT NULL;
ALTER TABLE online_presences ALTER COLUMN player_id SET NOT NULL;

View File

@ -0,0 +1,2 @@
ALTER TABLE users ALTER paid_sessions_hourly_rate TYPE integer;
ALTER TABLE users ALTER paid_sessions_daily_rate TYPE integer;

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
GEM_SERVER=http://localhost:9000/gems GEM_SERVER=https://int.jamkazam.com:9000/gems
echo "starting build..." echo "starting build..."
./build ./build

1
ruby/.gitignore vendored
View File

@ -9,6 +9,7 @@ _yardoc
coverage coverage
doc/ doc/
lib/bundler/man lib/bundler/man
jt_metadata.json
pkg pkg
rdoc rdoc
spec/reports spec/reports

View File

@ -18,15 +18,15 @@ end
gem 'pg', '0.17.1', :platform => [:mri, :mswin, :mingw] gem 'pg', '0.17.1', :platform => [:mri, :mswin, :mingw]
gem 'jdbc_postgres', :platform => [:jruby] gem 'jdbc_postgres', :platform => [:jruby]
gem 'activerecord', '3.2.13' gem 'activerecord', '3.2.22'
gem "activerecord-import", "~> 0.4.1" gem "activerecord-import", "~> 0.4.1"
gem 'uuidtools', '2.1.2' gem 'uuidtools', '2.1.2'
gem 'bcrypt-ruby', '3.0.1' gem 'bcrypt-ruby', '3.0.1'
gem 'ruby-protocol-buffers', '1.2.2' gem 'ruby-protocol-buffers', '1.2.2'
gem 'eventmachine', '1.0.3' gem 'eventmachine', '1.0.4'
gem 'amqp', '1.0.2' gem 'amqp', '1.0.2'
gem 'will_paginate' gem 'will_paginate'
gem 'actionmailer', '3.2.13' gem 'actionmailer', '3.2.22'
gem 'sendgrid', '1.2.0' gem 'sendgrid', '1.2.0'
gem 'aws-sdk', '~> 1' gem 'aws-sdk', '~> 1'
gem 'carrierwave', '0.9.0' gem 'carrierwave', '0.9.0'
@ -64,6 +64,7 @@ group :test do
gem 'rspec-prof' gem 'rspec-prof'
gem 'time_difference' gem 'time_difference'
gem 'byebug' gem 'byebug'
gem 'icalendar'
end end
# Specify your gem's dependencies in jam_ruby.gemspec # Specify your gem's dependencies in jam_ruby.gemspec

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
GEM_SERVER=http://localhost:9000/gems GEM_SERVER=https://int.jamkazam.com:9000/gems
echo "starting build..." echo "starting build..."
./build ./build

View File

@ -1 +0,0 @@
{"container_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150519-97259-1h1tbhj/jam-track-35.jkz", "version": "0", "coverart": null, "rsa_priv_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150519-97259-1h1tbhj/skey.pem", "tracks": [{"name": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150519-97259-1h1tbhj/7452fa4a-0c55-4cb2-948e-221475d7299c.ogg", "trackName": "track_00"}], "rsa_pub_file": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/d20150519-97259-1h1tbhj/pkey.pem", "jamktrack_info": "/var/folders/fk/0ckzmddd4tq28kxbb09vckbr0000gn/T/tmpGdncJS"}

View File

@ -51,8 +51,10 @@ require "jam_ruby/resque/scheduled/icecast_source_check"
require "jam_ruby/resque/scheduled/cleanup_facebook_signup" require "jam_ruby/resque/scheduled/cleanup_facebook_signup"
require "jam_ruby/resque/scheduled/unused_music_notation_cleaner" require "jam_ruby/resque/scheduled/unused_music_notation_cleaner"
require "jam_ruby/resque/scheduled/user_progress_emailer" require "jam_ruby/resque/scheduled/user_progress_emailer"
require "jam_ruby/resque/scheduled/daily_job"
require "jam_ruby/resque/scheduled/daily_session_emailer" require "jam_ruby/resque/scheduled/daily_session_emailer"
require "jam_ruby/resque/scheduled/new_musician_emailer" require "jam_ruby/resque/scheduled/new_musician_emailer"
require "jam_ruby/resque/scheduled/music_session_reminder"
require "jam_ruby/resque/scheduled/music_session_scheduler" require "jam_ruby/resque/scheduled/music_session_scheduler"
require "jam_ruby/resque/scheduled/active_music_session_cleaner" require "jam_ruby/resque/scheduled/active_music_session_cleaner"
require "jam_ruby/resque/scheduled/score_history_sweeper" require "jam_ruby/resque/scheduled/score_history_sweeper"
@ -94,6 +96,7 @@ require "jam_ruby/amqp/amqp_connection_manager"
require "jam_ruby/database" require "jam_ruby/database"
require "jam_ruby/message_factory" require "jam_ruby/message_factory"
require "jam_ruby/models/backing_track" require "jam_ruby/models/backing_track"
require "jam_ruby/models/calendar"
require "jam_ruby/models/feedback" require "jam_ruby/models/feedback"
require "jam_ruby/models/feedback_observer" require "jam_ruby/models/feedback_observer"
#require "jam_ruby/models/max_mind_geo" #require "jam_ruby/models/max_mind_geo"
@ -203,6 +206,8 @@ require "jam_ruby/models/jam_track"
require "jam_ruby/models/jam_track_track" require "jam_ruby/models/jam_track_track"
require "jam_ruby/models/jam_track_right" require "jam_ruby/models/jam_track_right"
require "jam_ruby/models/jam_track_tap_in" require "jam_ruby/models/jam_track_tap_in"
require "jam_ruby/models/jam_track_file"
require "jam_ruby/models/genre_jam_track"
require "jam_ruby/app/mailers/async_mailer" require "jam_ruby/app/mailers/async_mailer"
require "jam_ruby/app/mailers/batch_mailer" require "jam_ruby/app/mailers/batch_mailer"
require "jam_ruby/app/mailers/progress_mailer" require "jam_ruby/app/mailers/progress_mailer"
@ -227,6 +232,7 @@ require "jam_ruby/models/sale_line_item"
require "jam_ruby/models/recurly_transaction_web_hook" require "jam_ruby/models/recurly_transaction_web_hook"
require "jam_ruby/models/broadcast_notification" require "jam_ruby/models/broadcast_notification"
require "jam_ruby/models/broadcast_notification_view" require "jam_ruby/models/broadcast_notification_view"
require "jam_ruby/calendar_manager"
require "jam_ruby/jam_tracks_manager" require "jam_ruby/jam_tracks_manager"
require "jam_ruby/jam_track_importer" require "jam_ruby/jam_track_importer"
require "jam_ruby/jmep_manager" require "jam_ruby/jmep_manager"
@ -236,6 +242,7 @@ require "jam_ruby/models/json_store"
require "jam_ruby/models/base_search" require "jam_ruby/models/base_search"
require "jam_ruby/models/musician_search" require "jam_ruby/models/musician_search"
require "jam_ruby/models/band_search" require "jam_ruby/models/band_search"
require "jam_ruby/import/tency_stem_mapping"
include Jampb include Jampb

View File

@ -182,7 +182,7 @@
email = user.email email = user.email
subject = "Your band has a new follower on JamKazam" subject = "Your band has a new follower on JamKazam"
unique_args = {:type => "new_band_follower"} unique_args = {:type => "new_band_follower"}
@body = msg @body = msg
sendgrid_category "Notification" sendgrid_category "Notification"
sendgrid_unique_args :type => unique_args[:type] sendgrid_unique_args :type => unique_args[:type]
@ -390,13 +390,23 @@
end end
end end
def scheduled_session_reminder(user, msg, session) def scheduled_session_reminder_upcoming(user, session)
subject = "Your JamKazam session starts in 1 hour!"
unique_args = {:type => "scheduled_session_reminder_upcoming"}
send_scheduled_session_reminder(user, session, subject, unique_args)
end
def scheduled_session_reminder_day(user, session)
subject = "JamKazam Session Reminder"
unique_args = {:type => "scheduled_session_reminder_day"}
send_scheduled_session_reminder(user, session, subject, unique_args)
end
def send_scheduled_session_reminder(user, session, subject, unique_args)
return if !user.subscribe_email return if !user.subscribe_email
email = user.email email = user.email
subject = "Session Rescheduled" @user = user
unique_args = {:type => "scheduled_session_reminder"}
@body = msg
@session_name = session.name @session_name = session.name
@session_date = session.pretty_scheduled_start(true) @session_date = session.pretty_scheduled_start(true)
@session_url = "#{APP_CONFIG.external_root_url}/sessions/#{session.id}/details" @session_url = "#{APP_CONFIG.external_root_url}/sessions/#{session.id}/details"
@ -448,7 +458,7 @@
@sessions_and_latency = sessions_and_latency @sessions_and_latency = sessions_and_latency
@title = 'New Scheduled Sessions Matched to You' @title = 'New Scheduled Sessions Matched to You'
mail(:to => receiver.email, mail(:to => receiver.email,
:subject => EmailBatchScheduledSessions.subject) do |format| :subject => EmailBatchScheduledSessions.subject) do |format|
format.text format.text
format.html format.html
@ -461,7 +471,7 @@
email = user.email email = user.email
subject = "A band that you follow has joined a session" subject = "A band that you follow has joined a session"
unique_args = {:type => "band_session_join"} unique_args = {:type => "band_session_join"}
@body = msg @body = msg
@session_url = "#{APP_CONFIG.external_root_url}/sessions/#{session_id}" @session_url = "#{APP_CONFIG.external_root_url}/sessions/#{session_id}"
sendgrid_category "Notification" sendgrid_category "Notification"
@ -482,7 +492,7 @@
email = user.email email = user.email
subject = "A musician has saved a new recording on JamKazam" subject = "A musician has saved a new recording on JamKazam"
unique_args = {:type => "musician_recording_saved"} unique_args = {:type => "musician_recording_saved"}
@body = msg @body = msg
sendgrid_category "Notification" sendgrid_category "Notification"
sendgrid_unique_args :type => unique_args[:type] sendgrid_unique_args :type => unique_args[:type]
@ -502,7 +512,7 @@
email = user.email email = user.email
subject = "A band has saved a new recording on JamKazam" subject = "A band has saved a new recording on JamKazam"
unique_args = {:type => "band_recording_saved"} unique_args = {:type => "band_recording_saved"}
@body = msg @body = msg
sendgrid_category "Notification" sendgrid_category "Notification"
sendgrid_unique_args :type => unique_args[:type] sendgrid_unique_args :type => unique_args[:type]
@ -522,7 +532,7 @@
email = user.email email = user.email
subject = "You have been invited to join a band on JamKazam" subject = "You have been invited to join a band on JamKazam"
unique_args = {:type => "band_invitation"} unique_args = {:type => "band_invitation"}
@body = msg @body = msg
sendgrid_category "Notification" sendgrid_category "Notification"
sendgrid_unique_args :type => unique_args[:type] sendgrid_unique_args :type => unique_args[:type]

View File

@ -1,10 +0,0 @@
<% provide(:title, 'Scheduled Session Reminder') %>
<p><%= @body %></p>
<p>
<%= @session_name %><br/>
<%= @session_date %>
</p>
<p><a style="color: #ffcc00;" href="<%= @session_url %>">View Session Details</a></p>

View File

@ -1,6 +0,0 @@
<%= @body %>
<%= @session_name %>
<%= @session_date %>
See session details at <%= @session_url %>.

View File

@ -0,0 +1,18 @@
<% provide(:title, 'JamKazam Session Reminder') %>
<div>
Hi <%= @user.first_name %>,
</div>
<br/>
<div>
<span>This is a reminder that your JamKazam session</span>
<a href='<%=@session_url%>'><%= @session_name %></a>
<span>is scheduled for tomorrow. We hope you have fun!</span>
</div>
<br/>
<div>
Best Regards,
<br/>
Team JamKazam
</div>

View File

@ -0,0 +1,8 @@
Hi <%= @user.first_name %>,
This is a reminder that your JamKazam session <%=@session_name%> is scheduled for tomorrow. We hope you have fun!
Best Regards,
Team JamKazam
See session details at <%= @session_url %>.

View File

@ -0,0 +1,17 @@
<% provide(:title, 'Your JamKazam session starts in 1 hour!') %>
<div>
Hi <%= @user.first_name %>,
</div>
<br/>
<div>
<span>This is a reminder that your JamKazam session</span>
<a href='<%=@session_url%>'><%= @session_name %></a>
<span>starts in 1 hour. We hope you have fun!</span>
</div>
<br/>
<div>
Best Regards,
<br/>
Team JamKazam
</div>

View File

@ -0,0 +1,10 @@
Hi <%= @user.first_name %>,
This is a reminder that your JamKazam session
<%=@session_name%>
starts in 1 hour. We hope you have fun!
Best Regards,
Team JamKazam
See session details at <%= @session_url %>.

View File

@ -0,0 +1,106 @@
module JamRuby
class CalendarManager < BaseManager
DATE_FORMAT="%Y%m%dT%H%M%SZ"
def initialize(options={})
super(options)
@log = Logging.logger[self]
end
def cancel_ics_event(music_session, user)
Calendar.where(
user_id: user.id,
target_uid: music_session.id,
name: music_session.description)
.first_or_create(
description: music_session.description,
start_at: music_session.scheduled_start,
end_at: music_session.scheduled_start+music_session.safe_scheduled_duration,
trigger_delete: true)
end
# Remove all "delete" event calendar records older than 4 weeks:
def cleanup()
Calendar.where("trigger_delete=TRUE AND created_at < ?", 4.weeks.ago)
.destroy_all()
end
# @return event (as ICS string) for a given music session
def ics_event_from_music_session(music_session, delete=false)
# Determine properties of calendar event and create:
uid = "#{music_session.id}@JamKazam"
text = "JamKazam Session #{music_session.description}"
rrule = nil
start_at = music_session.scheduled_start
stop_at = music_session.scheduled_start+music_session.safe_scheduled_duration
if !delete && music_session.recurring_mode==MusicSession::RECURRING_WEEKLY
rrule = "FREQ=WEEKLY;INTERVAL=1"
end
create_ics_event(uid, text, text, start_at, stop_at, delete, rrule)
end
# @return event (as ICS string) for a given music session
def ics_event_from_calendar(calendar)
# Determine properties of calendar event and create:
rrule = nil
if !calendar.trigger_delete && calendar.recurring_mode==MusicSession::RECURRING_WEEKLY
rrule = "FREQ=WEEKLY;INTERVAL=1"
end
create_ics_event(
calendar.target_uid,
"JamKazam Session #{calendar.name}",
calendar.description,
calendar.start_at,
calendar.end_at,
calendar.trigger_delete,
rrule
)
end
# @return calendar (as ICS string) for specified user
# Includes all RSVPed sessions, as well as any calendar
# entries for the given user:
def create_ics_feed(user)
ics_events = ""
MusicSession.scheduled_rsvp(user, true).each do |music_session|
ics_events << "\r\n" if(ics_events.length != 0)
ics_events << ics_event_from_music_session(music_session)
end
user.calendars.each do |user|
ics_events << "\r\n" if(ics_events.length != 0)
ics_events << ics_event_from_calendar(user)
end
create_ics_cal(ics_events)
end
# @return event (as ICS string) for given arguments
def create_ics_event(uuid, name, description, start_at, end_at, delete=false, rrule=nil, sequence=nil)
uuid ||= UUID.timestamp_create
event = "BEGIN:VEVENT\r\n"
event << "UID:#{uuid}\r\n"
event << "DTSTAMP:#{Time.now.utc().strftime(DATE_FORMAT)}\r\n"
event << "DTSTART:#{start_at.utc().strftime(DATE_FORMAT)}\r\n"
event << "DTEND:#{end_at.utc().strftime(DATE_FORMAT)}\r\n"
event << "SUMMARY:#{name}\r\n"
event << "DESCRIPTION:#{description}\r\n"
if delete
event << "METHOD:CANCEL\r\n"
event << "STATUS:CANCELLED\r\n"
end
if rrule
event << "RRULE:#{rrule}\r\n"
end
event << "SEQUENCE:#{sequence}\r\n" if sequence
event << "END:VEVENT"
end
# @return calendar (as ICS string) for specified events
def create_ics_cal(ics_events)
"BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:JamKazam\r\n#{ics_events}\r\nEND:VCALENDAR"
end
end # class
end # module

View File

@ -26,7 +26,9 @@ module NotificationTypes
SCHEDULED_SESSION_RSVP_CANCELLED_ORG = "SCHEDULED_SESSION_RSVP_CANCELLED_ORG" SCHEDULED_SESSION_RSVP_CANCELLED_ORG = "SCHEDULED_SESSION_RSVP_CANCELLED_ORG"
SCHEDULED_SESSION_CANCELLED = "SCHEDULED_SESSION_CANCELLED" SCHEDULED_SESSION_CANCELLED = "SCHEDULED_SESSION_CANCELLED"
SCHEDULED_SESSION_RESCHEDULED = "SCHEDULED_SESSION_RESCHEDULED" SCHEDULED_SESSION_RESCHEDULED = "SCHEDULED_SESSION_RESCHEDULED"
SCHEDULED_SESSION_REMINDER = "SCHEDULED_SESSION_REMINDER" SCHEDULED_SESSION_REMINDER_DAY = "SCHEDULED_SESSION_REMINDER_DAY"
SCHEDULED_SESSION_REMINDER_UPCOMING = "SCHEDULED_SESSION_REMINDER_UPCOMING"
SCHEDULED_SESSION_REMINDER_IMMINENT = "SCHEDULED_SESSION_REMINDER_IMMINENT"
SCHEDULED_SESSION_COMMENT = "SCHEDULED_SESSION_COMMENT" SCHEDULED_SESSION_COMMENT = "SCHEDULED_SESSION_COMMENT"
# recording notifications # recording notifications

View File

@ -0,0 +1,360 @@
module JamRuby
# this is probably a one-off class used to map Tency-named stems into JamKazam-named stems
class TencyStemMapping
@@log = Logging.logger[TencyStemMapping]
def s3_manager
@s3_manager ||= S3Manager.new('jamkazam-tency', APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
end
def initialize
@originals_folder = "/Volumes/sethcall/Dropbox/seth@jamkazam.com/JamTracks - Tency Music - Original Folder for Normalization Map"
@mapping_folder = "/Volumes/sethcall/Dropbox/seth@jamkazam.com/JamTracks - Tency Music"
@original_songs = {}
@mapping_songs = {}
@mappings = {}
end
def create_map
tency_originals
tency_maps
dump
end
def create_mapping_map
tency_maps
dump_map
end
def hydrate
@original_songs = YAML.load_file('original_songs.yml')
@mapping_songs = YAML.load_file('mapping_songs.yml')
end
def parse_sanitized_filename(filename)
instrument = nil
part = nil
basename = File.basename(filename)
stem = basename.index('Stem')
if stem
stripped = basename[(stem + 'Stem'.length)..-5] # takes of 'stem' and '.wav'
stripped.strip!
dash = stripped.index('-')
if dash == 0
stripped = stripped[1..-1].strip!
# now we should have something like "Vocal - Lead" (instrument - part)
instrument, part = stripped.split('-')
instrument.strip! if instrument
part.strip! if part
else
"no or misplaced dash for #{filename}"
end
else
raise "no stem for #{filename}"
end
[instrument, part]
end
# For all the tracks that I have labeled manually as
# Instrument = Upright Bass and Part = Upright Bass,
# can you please change both the Instrument and Part to Double Bass instead?
#
def check_mappings
missing_instrument = 0
missing_part = 0
part_names = []
hydrate
@mapping_songs.each do |cache_id, data|
mapped_filename = data[:filename]
@@log.debug("parsing #{mapped_filename}")
instrument, part = parse_sanitized_filename(mapped_filename)
@@log.debug("parsed #{instrument} (#{part})")
missing_instrument = missing_instrument + 1 unless instrument
missing_part = missing_part + 1 unless part
part_names << mapped_filename unless part
end
@@log.info("SUMMARY")
@@log.info("-------")
@@log.info("missing instruments:#{missing_instrument} missing parts: #{missing_part}")
@@log.info("files with no parts: #{part_names}")
# files with no parts:
# ["Huey Lewis And The News - Heart And Soul - 31957/Heart And Soul Stem - Synth 2.wav",
# "ZZ Top - Tush - 20852/Tush Stem - Clicktrack.wav",
# "Crosby Stills And Nash - Teach Your Children - 15440/Teach Your Children Stem - Bass Guitar.wav",
# /Brad Paisley - She's Everything - 19886/She's Everything Stem - Clicktrack.wav",
# "Toby Keith - Beer For My Horses - 7221/Beer For My Horses Stem - Lap Steel.wav",
# Toby Keith - Beer For My Horses - 7221/Beer For My Horses Stem - Acoustic Guitar.wav"
end
def track_mapping(basename, instr_part)
instrument = instr_part[:instrument]
part = instr_part[:part]
basename.downcase!
info = @mappings[basename]
unless info
info = {matches:[]}
@mappings[basename] = info
end
info[:matches] << instr_part
end
def correlate
mapped = 0
unmapped = 0
unmapped_details = []
no_instrument = []
common_unknown_instruments = {}
hydrate
@mapping_songs.each do |cache_id, data|
# go through each track hand-mapped, and find it's matching song if any.
mapped_filename = data[:filename]
found_original = @original_songs[cache_id]
if found_original
# mapping made
original_filename = found_original[:filename]
original_basename = File.basename(original_filename).downcase
mapped = mapped + 1
instrument, part = parse_sanitized_filename(mapped_filename)
instr_part = JamTrackImporter.determine_instrument(instrument, part)
instr_part[:instrument]
if instr_part[:instrument]
# track the mapping of this one
track_mapping(original_basename, instr_part)
else
@@log.error("unable to determine instrument for #{File.basename(mapped_filename)}")
no_instrument << ({filename: File.basename(mapped_filename), instrument: instrument, part: part})
common_unknown_instruments["#{instrument}-(#{part})"] = 1
end
else
unmapped = unmapped + 1
unmapped_details << {filename: mapped_filename}
end
end
puts("SUMMARY")
puts("-------")
puts("MAPPED:#{mapped} UNMAPPED:#{unmapped}")
unmapped_details.each do |unmapped_detail|
puts "UNMAPPED FILE: #{File.basename(unmapped_detail[:filename])}"
end
puts("UNKNOWN INSTRUMENT: #{no_instrument.length}")
no_instrument.each do |item|
puts("UNKNOWN INSTRUMENT: #{item[:filename]}")
end
common_unknown_instruments.each do |key, value|
puts("#{key}")
end
@mappings.each do |basename, mapping|
matches = mapping[:matches]
counts = matches.each_with_object(Hash.new(0)) { |word,counts| counts[word] += 1 }
ordered_matches = counts.sort_by {|k, v| -v}
output = ""
ordered_matches.each do |match|
detail = match[0]
count = match[1]
output << "#{detail[:instrument]}(#{detail[:part]})/#{count}, "
end
puts "map detail: #{basename}: #{output}"
mapping[:ordered] = ordered_matches
mapping[:detail] = output
end
CSV.open("mapping.csv", "wb") do |csv|
@mappings.each do |basename, mapping|
item = mapping[:ordered]
trust_worthy = item.length == 1
unless trust_worthy
# if the 1st item is at least 4 'counts' more than the next item, we can consider it trust_worthy
if item[0][1] - 4 > item[1][1]
trust_worthy = true
end
end
csv << [ basename, item[0][0][:instrument], item[0][0][:part], item[0][1], trust_worthy ]
end
end
CSV.open("determinate-single-matches.csv", "wb") do |csv|
@mappings.each do |basename, mapping|
if mapping[:ordered].length == 1 && mapping[:ordered][0][1] == 1
item = mapping[:ordered]
csv << [ basename, item[0][0][:instrument], item[0][0][:part], item[0][1] ]
end
end
end
CSV.open("determinate-multi-matches.csv", "wb") do |csv|
@mappings.each do |basename, mapping|
if mapping[:ordered].length == 1 && mapping[:ordered][0][1] > 1
item = mapping[:ordered]
csv << [ basename, item[0][0][:instrument], item[0][0][:part], item[0][1] ]
end
end
end
CSV.open("ambiguous-matches.csv", "wb") do |csv|
@mappings.each do |basename, mapping|
if mapping[:ordered].length > 1
csv << [ basename, mapping[:detail] ]
end
end
end
end
def dump
File.open('original_songs.yml', 'w') {|f| f.write(YAML.dump(@original_songs)) }
File.open('mapping_songs.yml', 'w') {|f| f.write(YAML.dump(@mapping_songs)) }
end
def dump_map
File.open('mapping_songs.yml', 'w') {|f| f.write(YAML.dump(@mapping_songs)) }
end
def md5(filepath)
Digest::MD5.file(filepath).hexdigest
end
def tency_original_check
songs = Pathname.new(@originals_folder).children.select { |c| c.directory? }
songs.each do |song|
dirs = Pathname.new(song).children.select {|c| c.directory? }
@@log.debug "SONG #{song}"
dirs.each do |dir|
@@log.debug "#{dir.basename.to_s}"
end
@@log.debug ""
end
end
def tency_originals
songs = Pathname.new(@originals_folder).children.select { |c| c.directory? }
songs.each do |filename|
id = parse_id(filename.basename.to_s )
files = Pathname.new(filename).children.select {|c| c.file? }
# also look into any 1st level folders we might find
dirs = Pathname.new(filename).children.select {|c| c.directory? }
dirs.each do |dir|
more_tracks = Pathname.new(dir).children.select {|c| c.file? }
files = files + more_tracks
end
files.each do |file|
@@log.debug("processing original track #{file.to_s}")
md5 = md5(file.to_s)
song = {md5:md5, filename:file.to_s, id:id}
@original_songs[cache_id(id, md5)] = song
end
end
end
def tency_maps
songs = Pathname.new(@mapping_folder).children.select { |c| c.directory? }
songs.each do |song_filename|
id = parse_id_mapped(song_filename.basename.to_s )
@@log.debug "processing song #{song_filename.to_s}"
tracks = Pathname.new(song_filename).children.select {|c| c.file? }
tracks.each do |track|
if track.to_s.include? "Stem"
@@log.debug("processing mapped track #{track.to_s}")
md5 = md5(track.to_s)
song = {md5:md5, filename:track.to_s}
@mapping_songs[cache_id(id, md5)] = song
end
end
end
end
def cache_id(id, md5)
"#{id}-#{md5}"
end
def parse_id(filename)
#amy-winehouse_you-know-i-m-no-good-feat-ghostface-killah_11767
index = filename.rindex('_')
if index
id = filename[(index + 1)..-1]
if id.end_with?('/')
id = id[0...-1]
end
id = id.to_i
if id == 0
raise "no valid ID in filename: #{filename}"
end
else
raise "no _ in filename: #{filename}"
end
id
end
def parse_id_mapped(filename)
#Flyleaf - I'm So Sick - 15771
index = filename.rindex('-')
if index
id = filename[(index + 1)..-1]
if id.end_with?('/')
id = id[0...-1]
end
id.strip!
id = id.to_i
if id == 0
raise "no valid ID in filename: #{filename}"
end
else
raise "no - in filename: #{filename}"
end
id
end
def tency_originals2
s3_manager.list_directories('mapper').each do |song_folder|
@@log.debug("searching through tency directory. song folder:'#{song_folder}'")
id = parse_id(song_folder)
@@log.debug("ID #{id}")
top_folder = s3_manager.list_directories(song_folder)
end
end
end
end

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ module JamRuby
class Stats class Stats
class << self class << self
attr_accessor :client, :host attr_accessor :client, :host, :ignore
@@log = Logging.logger[JamRuby::Stats] @@log = Logging.logger[JamRuby::Stats]
end end
@ -52,6 +52,7 @@ module JamRuby
end end
def self.init(options) def self.init(options)
influxdb_database = options[:influxdb_database] influxdb_database = options[:influxdb_database]
influxdb_username = options[:influxdb_username] influxdb_username = options[:influxdb_username]
influxdb_password = options[:influxdb_password] influxdb_password = options[:influxdb_password]
@ -71,12 +72,15 @@ module JamRuby
retry: -1 retry: -1
@host = `hostname`.strip @host = `hostname`.strip
else else
self.ignore = true
@@log.debug("stats client not initiated") @@log.debug("stats client not initiated")
end end
end end
def self.write(name, data) def self.write(name, data)
return if self.ignore # doing any writes in a test environment cause annoying puts to occur
if @client && data && data.length > 0 if @client && data && data.length > 0
data['host'] = @host data['host'] = @host
data['time'] = Time.now.to_i data['time'] = Time.now.to_i

View File

@ -3,10 +3,10 @@ module JamRuby
include HtmlSanitize include HtmlSanitize
html_sanitize strict: [:biography, :website, :name] html_sanitize strict: [:biography, :website, :name]
attr_accessible :name, :website, :biography, :city, :state, attr_accessible :name, :website, :biography, :city, :state,
:country, :original_fpfile_photo, :cropped_fpfile_photo, :cropped_large_fpfile_photo, :country, :original_fpfile_photo, :cropped_fpfile_photo, :cropped_large_fpfile_photo,
:cropped_s3_path_photo, :cropped_large_s3_path_photo, :crop_selection_photo, :photo_url, :large_photo_url, :cropped_s3_path_photo, :cropped_large_s3_path_photo, :crop_selection_photo, :photo_url, :large_photo_url,
:band_type, :band_status, :concert_count, :add_new_members, :play_commitment, :touring_option, :paid_gigs, :band_type, :band_status, :concert_count, :add_new_members, :play_commitment, :touring_option, :paid_gigs,
:free_gigs, :hourly_rate, :gig_minimum :free_gigs, :hourly_rate, :gig_minimum
attr_accessor :updating_photo, :skip_location_validation, :skip_genre_validation attr_accessor :updating_photo, :skip_location_validation, :skip_genre_validation
@ -23,6 +23,8 @@ module JamRuby
validate :validate_photo_info validate :validate_photo_info
validate :require_at_least_one_genre, :unless => :skip_genre_validation validate :require_at_least_one_genre, :unless => :skip_genre_validation
validate :limit_max_genres validate :limit_max_genres
validates_numericality_of :hourly_rate, greater_than:0, less_than:100000, :if => :paid_gigs
validates_numericality_of :gig_minimum, greater_than:0, less_than:200000, :if => :paid_gigs
before_save :check_lat_lng before_save :check_lat_lng
before_save :check_website_url before_save :check_website_url
@ -47,10 +49,10 @@ module JamRuby
has_many :recordings, :class_name => "JamRuby::Recording", :foreign_key => "band_id", dependent: :destroy has_many :recordings, :class_name => "JamRuby::Recording", :foreign_key => "band_id", dependent: :destroy
# self.id = likable_id in likes table # self.id = likable_id in likes table
has_many :likers, :as => :likable, :class_name => "JamRuby::Like", :dependent => :destroy, dependent: :destroy has_many :likers, :as => :likable, :class_name => "JamRuby::Like", :dependent => :destroy
# self.id = followable_id in follows table # self.id = followable_id in follows table
has_many :followers, :as => :followable, :class_name => "JamRuby::Follow", :dependent => :destroy, dependent: :destroy has_many :followers, :as => :followable, :class_name => "JamRuby::Follow", :dependent => :destroy
# invitations # invitations
has_many :invitations, :inverse_of => :band, :class_name => "JamRuby::BandInvitation", :foreign_key => "band_id", dependent: :destroy has_many :invitations, :inverse_of => :band, :class_name => "JamRuby::BandInvitation", :foreign_key => "band_id", dependent: :destroy
@ -180,7 +182,7 @@ module JamRuby
band = id.blank? ? Band.new : Band.find(id) band = id.blank? ? Band.new : Band.find(id)
# ensure user updating Band details is a Band member # ensure user updating Band details is a Band member
unless band.new_record? || band.users.exists?(user) unless band.new_record? || band.users.exists?(user)
raise JamPermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR raise JamPermissionError, ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR
end end
@ -193,15 +195,28 @@ module JamRuby
band.photo_url = params[:photo_url] if params.has_key?(:photo_url) band.photo_url = params[:photo_url] if params.has_key?(:photo_url)
band.logo_url = params[:logo_url] if params.has_key?(:logo_url) band.logo_url = params[:logo_url] if params.has_key?(:logo_url)
if params.has_key?(:genres) && params[:genres] band.paid_gigs = params[:paid_gigs] if params.has_key?(:paid_gigs)
band.free_gigs = params[:free_gigs] if params.has_key?(:free_gigs)
band.hourly_rate = (params.has_key?(:hourly_rate) && params[:hourly_rate].to_i > 0) ? params[:hourly_rate] : nil
band.gig_minimum = (params.has_key?(:gig_minimum) && params[:hourly_rate].to_i > 0) ? params[:gig_minimum] : nil
band.add_new_members = params[:add_new_members] if params.has_key?(:add_new_members)
band.touring_option = params[:touring_option] if params.has_key?(:touring_option)
band.band_type = params[:band_type] if params.has_key?(:band_type)
band.band_status = params[:band_status] if params.has_key?(:band_status)
band.concert_count = params[:concert_count] if params.has_key?(:concert_count)
band.play_commitment = params[:play_commitment] if params.has_key?(:play_commitment)
if params[:validate_genres] || params[:genres].present?
# loop through each genre in the array and save to the db # loop through each genre in the array and save to the db
genres = [] genres = []
params[:genres].each { |genre_id| genres << Genre.find(genre_id) } params[:genres].each { |genre_id| genres << Genre.find(genre_id) } if params[:genres].present?
band.genres = genres band.genres = genres
band.skip_genre_validation = false
else
params[:validate_genres]
band.skip_genre_validation = true
end end
band.skip_genre_validation = true unless params[:validate_genres]
unless band.new_record? unless band.new_record?
OnlinePresence.delete_all(["player_id = ?", band.id]) OnlinePresence.delete_all(["player_id = ?", band.id])
PerformanceSample.delete_all(["player_id = ?", band.id]) PerformanceSample.delete_all(["player_id = ?", band.id])
@ -210,7 +225,7 @@ module JamRuby
online_presences = params[:online_presences] online_presences = params[:online_presences]
if online_presences.present? if online_presences.present?
online_presences.each do |op| online_presences.each do |op|
new_presence = OnlinePresence.create(band, op, false) new_presence = OnlinePresence.create(band, op, false)
band.online_presences << new_presence band.online_presences << new_presence
end end
end end
@ -218,15 +233,15 @@ module JamRuby
performance_samples = params[:performance_samples] performance_samples = params[:performance_samples]
if performance_samples.present? if performance_samples.present?
performance_samples.each do |ps| performance_samples.each do |ps|
band.performance_samples << PerformanceSample.create(band, ps, false) band.performance_samples << PerformanceSample.create(band, ps, false)
end end
end end
band band
end end
# helper method for creating / updating a Band # helper method for creating / updating a Band
def self.save(user, params) def self.save(user, params)
band = build_band(user, params) band = build_band(user, params)
if band.save if band.save
@ -284,7 +299,7 @@ module JamRuby
def check_lat_lng def check_lat_lng
if (city_changed? || state_changed? || country_changed?) if (city_changed? || state_changed? || country_changed?)
update_lat_lng update_lat_lng
end end
true true
end end

View File

@ -0,0 +1,14 @@
module JamRuby
class Calendar < ActiveRecord::Base
include HtmlSanitize
html_sanitize strict: [:name, :description]
attr_accessible :name, :description, :target_uid, :trigger_delete, :start_at, :end_at
@@log = Logging.logger[Calendar]
self.table_name = "calendars"
self.primary_key = 'id'
belongs_to :user, :class_name => 'JamRuby::User', :foreign_key => :user_id, :inverse_of => :calendars
end
end

View File

@ -200,7 +200,7 @@ SELECT
tmp_candidate_sessions.creator_score_idx AS creator_score_idx tmp_candidate_sessions.creator_score_idx AS creator_score_idx
INTO TEMP TABLE tmp_candidate_recipients INTO TEMP TABLE tmp_candidate_recipients
FROM users FROM users
INNER JOIN musicians_instruments AS mi ON mi.user_id = users.id INNER JOIN musicians_instruments AS mi ON mi.player_id = users.id
INNER JOIN tmp_candidate_sessions ON tmp_candidate_sessions.is_unstructured_rsvp = TRUE OR INNER JOIN tmp_candidate_sessions ON tmp_candidate_sessions.is_unstructured_rsvp = TRUE OR
(tmp_candidate_sessions.open_rsvps = TRUE AND tmp_candidate_sessions.instrument_id = mi.instrument_id) OR (tmp_candidate_sessions.open_rsvps = TRUE AND tmp_candidate_sessions.instrument_id = mi.instrument_id) OR
tmp_candidate_sessions.invited_user_id = users.id tmp_candidate_sessions.invited_user_id = users.id

View File

@ -16,7 +16,8 @@ module JamRuby
has_and_belongs_to_many :recordings, :class_name => "JamRuby::Recording", :join_table => "recordings_genres" has_and_belongs_to_many :recordings, :class_name => "JamRuby::Recording", :join_table => "recordings_genres"
# jam tracks # jam tracks
has_many :jam_tracks, :class_name => "JamRuby::JamTrack" has_many :genres_jam_tracks, :class_name => "JamRuby::GenreJamTrack", :foreign_key => "genre_id"
has_many :jam_tracks, :through => :genres_jam_tracks, :class_name => "JamRuby::JamTrack", :source => :genre
def to_s def to_s
description description

View File

@ -0,0 +1,8 @@
module JamRuby
class GenreJamTrack < ActiveRecord::Base
self.table_name = 'genres_jam_tracks'
belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
belongs_to :genre, class_name: 'JamRuby::Genre'
end
end

View File

@ -14,12 +14,12 @@ module JamRuby
attr_accessor :uploading_preview attr_accessor :uploading_preview
attr_accessible :name, :description, :bpm, :time_signature, :status, :recording_type, attr_accessible :name, :description, :bpm, :time_signature, :status, :recording_type,
:original_artist, :songwriter, :publisher, :licensor, :licensor_id, :pro, :genre, :genre_id, :sales_region, :price, :original_artist, :songwriter, :publisher, :licensor, :licensor_id, :pro, :genres_jam_tracks_attributes, :sales_region, :price,
:reproduction_royalty, :public_performance_royalty, :reproduction_royalty_amount, :reproduction_royalty, :public_performance_royalty, :reproduction_royalty_amount,
:licensor_royalty_amount, :pro_royalty_amount, :plan_code, :initial_play_silence, :jam_track_tracks_attributes, :licensor_royalty_amount, :pro_royalty_amount, :plan_code, :initial_play_silence, :jam_track_tracks_attributes,
:jam_track_tap_ins_attributes, :version, :jmep_json, :jmep_text, :pro_ascap, :pro_bmi, :pro_sesac, :duration, as: :admin :jam_track_tap_ins_attributes, :genre_ids, :version, :jmep_json, :jmep_text, :pro_ascap, :pro_bmi, :pro_sesac, :duration, as: :admin
validates :name, presence: true, uniqueness: true, length: {maximum: 200} validates :name, presence: true, length: {maximum: 200}
validates :plan_code, presence: true, uniqueness: true, length: {maximum: 50 } validates :plan_code, presence: true, uniqueness: true, length: {maximum: 50 }
validates :description, length: {maximum: 1000} validates :description, length: {maximum: 1000}
validates :time_signature, inclusion: {in: [nil] + [''] + TIME_SIGNATURES} # the empty string is needed because of activeadmin validates :time_signature, inclusion: {in: [nil] + [''] + TIME_SIGNATURES} # the empty string is needed because of activeadmin
@ -39,14 +39,17 @@ module JamRuby
validates :public_performance_royalty, inclusion: {in: [nil, true, false]} validates :public_performance_royalty, inclusion: {in: [nil, true, false]}
validates :duration, numericality: {only_integer: true}, :allow_nil => true validates :duration, numericality: {only_integer: true}, :allow_nil => true
validates_format_of :reproduction_royalty_amount, with: /^\d+\.*\d{0,3}$/ validates_format_of :reproduction_royalty_amount, with: /^\d+\.*\d{0,4}$/, :allow_blank => true
validates_format_of :licensor_royalty_amount, with: /^\d+\.*\d{0,3}$/ validates_format_of :licensor_royalty_amount, with: /^\d+\.*\d{0,4}$/, :allow_blank => true
belongs_to :genre, class_name: "JamRuby::Genre" belongs_to :licensor , class_name: 'JamRuby::JamTrackLicensor', foreign_key: 'licensor_id', :inverse_of => :jam_tracks
belongs_to :licensor , class_name: 'JamRuby::JamTrackLicensor', foreign_key: 'licensor_id'
has_many :genres_jam_tracks, :class_name => "JamRuby::GenreJamTrack", :foreign_key => "jam_track_id"
has_many :genres, :through => :genres_jam_tracks, :class_name => "JamRuby::Genre", :source => :genre
has_many :jam_track_tracks, :class_name => "JamRuby::JamTrackTrack", order: 'track_type ASC, position ASC, part ASC, instrument_id ASC' has_many :jam_track_tracks, :class_name => "JamRuby::JamTrackTrack", order: 'track_type ASC, position ASC, part ASC, instrument_id ASC'
has_many :jam_track_tap_ins, :class_name => "JamRuby::JamTrackTapIn", order: 'offset_time ASC' has_many :jam_track_tap_ins, :class_name => "JamRuby::JamTrackTapIn", order: 'offset_time ASC'
has_many :jam_track_files, :class_name => "JamRuby::JamTrackFile"
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" # '
@ -67,6 +70,82 @@ module JamRuby
accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true accepts_nested_attributes_for :jam_track_tracks, allow_destroy: true
accepts_nested_attributes_for :jam_track_tap_ins, allow_destroy: true accepts_nested_attributes_for :jam_track_tap_ins, allow_destroy: true
# we can make sure a few things stay in sync here.
# 1) the reproduction_royalty_amount has to stay in sync based on duration
# 2) the onboarding_exceptions JSON column
after_save :sync_reproduction_royalty
after_save :sync_onboarding_exceptions
def sync_reproduction_royalty
# reproduction royalty table based on duration
# The statutory mechanical royalty rate for permanent digital downloads is:
# 9.10¢ per copy for songs 5 minutes or less, or
# 1.75¢ per minute or fraction thereof, per copy for songs over 5 minutes.
# So the base rate is 9.1 cents for anything up to 5 minutes.
# 5.01 to 6 minutes should be 10.5 cents.
# 6.01 to 7 minutes should be 12.25 cents.
# Etc.
royalty = nil
if self.duration
minutes = (self.duration - 1) / 60
extra_minutes = minutes - 4
extra_minutes = 0 if extra_minutes < 0
royalty = (0.091 + (0.0175 * extra_minutes)).round(5)
end
self.update_column(:reproduction_royalty_amount, royalty)
true
end
def sync_onboarding_exceptions
exceptions = {}
if self.duration.nil?
exceptions[:no_duration] = true
end
if self.genres.count == 0
exceptions[:no_genres] = true
end
if self.year.nil?
exceptions[:no_year] = true
end
if self.licensor.nil?
exceptions[:no_licensor] = true
end
if self.missing_instrument_info?
exceptions[:unknown_instrument] = true
end
if self.master_track.nil?
exceptions[:no_master] = true
end
if missing_previews?
exceptions[:missing_previews] = true
end
if duplicate_positions?
exceptions[:duplicate_positions] = true
end
if exceptions.keys.length == 0
self.update_column(:onboarding_exceptions, nil)
else
self.update_column(:onboarding_exceptions, exceptions.to_json)
end
true
end
def duplicate_positions? def duplicate_positions?
counter = {} counter = {}
jam_track_tracks.each do |track| jam_track_tracks.each do |track|
@ -87,6 +166,17 @@ module JamRuby
duplicate duplicate
end end
def missing_instrument_info?
missing_instrument_info = false
self.jam_track_tracks.each do |track|
if track.instrument_id == 'other' && (track.part == nil || track.part.start_with?('Other'))
missing_instrument_info = true
break
end
end
missing_instrument_info
end
def missing_previews? def missing_previews?
missing_preview = false missing_preview = false
self.jam_track_tracks.each do |track| self.jam_track_tracks.each do |track|
@ -171,7 +261,7 @@ module JamRuby
end end
if options[:group_artist] if options[:group_artist]
query = query.select("original_artist, array_agg(jam_tracks.id) AS id, MIN(name) AS name, MIN(description) AS description, MIN(recording_type) AS recording_type, MIN(original_artist) AS original_artist, MIN(songwriter) AS songwriter, MIN(publisher) AS publisher, MIN(sales_region) AS sales_region, MIN(price) AS price, MIN(version) AS version, MIN(genre_id) AS genre_id") query = query.select("original_artist, array_agg(jam_tracks.id) AS id, MIN(name) AS name, MIN(description) AS description, MIN(recording_type) AS recording_type, MIN(original_artist) AS original_artist, MIN(songwriter) AS songwriter, MIN(publisher) AS publisher, MIN(sales_region) AS sales_region, MIN(price) AS price, MIN(version) AS version")
query = query.group("original_artist") query = query.group("original_artist")
query = query.order('jam_tracks.original_artist') query = query.order('jam_tracks.original_artist')
else else
@ -180,7 +270,12 @@ module JamRuby
end end
query = query.where("jam_tracks.status = ?", 'Production') unless user.admin query = query.where("jam_tracks.status = ?", 'Production') unless user.admin
query = query.where("jam_tracks.genre_id = '#{options[:genre]}'") unless options[:genre].blank?
unless options[:genre].blank?
query = query.joins(:genres)
query = query.where('genre_id = ? ', options[:genre])
end
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}' and jam_track_tracks.track_type != 'Master'") unless options[:instrument].blank? query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}' and jam_track_tracks.track_type != 'Master'") unless options[:instrument].blank?
query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank? query = query.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?
@ -231,7 +326,12 @@ module JamRuby
query = query.order('jam_tracks.original_artist') query = query.order('jam_tracks.original_artist')
query = query.where("jam_tracks.status = ?", 'Production') unless user.admin query = query.where("jam_tracks.status = ?", 'Production') unless user.admin
query = query.where("jam_tracks.genre_id = '#{options[:genre]}'") unless options[:genre].blank?
unless options[:genre].blank?
query = query.joins(:genres)
query = query.where('genre_id = ? ', options[:genre])
end
query = query.where("jam_track_tracks.instrument_id = '#{options[:instrument]}'") unless options[:instrument].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.where("jam_tracks.sales_region = '#{options[:availability]}'") unless options[:availability].blank?

View File

@ -0,0 +1,78 @@
module JamRuby
# holds a click track or precount file
class JamTrackFile < ActiveRecord::Base
include JamRuby::S3ManagerMixin
# there should only be one Master per JamTrack, but there can be N Track per JamTrack
FILE_TYPE = %w{ClickWav ClickTxt Precount}
@@log = Logging.logger[JamTrackFile]
before_destroy :delete_s3_files
attr_accessible :jam_track_id, :file_type, :filename, as: :admin
attr_accessible :url, :md5, :length, as: :admin
attr_accessor :original_audio_s3_path, :skip_uploader, :preview_generate_error
before_destroy :delete_s3_files
validates :file_type, inclusion: {in: FILE_TYPE }
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
# create storage directory that will house this jam_track, as well as
def store_dir
"jam_track_files"
end
# create name of the file
def filename(original_name)
"#{store_dir}/#{jam_track.original_artist}/#{jam_track.name}/#{original_name}"
end
def manually_uploaded_filename
if click_wav?
filename('click.wav')
elsif click_txt?
filename('click.txt')
elsif precount?
filename('precount.wav')
else
raise 'unknown file type: ' + file_type
end
end
def click_wav?
track_type == 'ClickWav'
end
def click_txt?
track_type == 'ClickTxt'
end
def precount?
track_type == 'Precount'
end
# creates a short-lived URL that has access to the object.
# the idea is that this is used when a user who has the rights to this tries to download this JamTrack
# we would verify their rights (can_download?), and generates a URL in response to the click so that they can download
# but the url is short lived enough so that it wouldn't be easily shared
def sign_url(expiration_time = 120)
s3_manager.sign_url(self[url], {:expires => expiration_time, :response_content_type => 'audio/wav', :secure => true})
end
def can_download?(user)
# 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
def delete_s3_files
s3_manager.delete(self[:url]) if self[:url] && s3_manager.exists?(self[:url])
end
end
end

View File

@ -1,6 +1,8 @@
module JamRuby module JamRuby
class JamTrackLicensor < ActiveRecord::Base class JamTrackLicensor < ActiveRecord::Base
table_name = 'jam_track_licensors'
attr_accessible :name, :description, :attention, :address_line_1, :address_line_2, attr_accessible :name, :description, :attention, :address_line_1, :address_line_2,
:city, :state, :zip_code, :contact, :email, :phone, as: :admin :city, :state, :zip_code, :contact, :email, :phone, as: :admin
@ -16,6 +18,6 @@ module JamRuby
validates :email, length: {maximum: 200} validates :email, length: {maximum: 200}
validates :phone, length: {maximum: 200} validates :phone, length: {maximum: 200}
has_many :jam_tracks, :class_name => "JamRuby::JamTrack", foreign_key: 'licensor_id' has_many :jam_tracks, :class_name => "JamRuby::JamTrack", foreign_key: 'licensor_id', :inverse_of => :licensor
end end
end end

View File

@ -131,81 +131,19 @@ module JamRuby
end end
def generate_preview def generate_preview
begin begin
Dir.mktmpdir do |tmp_dir| Dir.mktmpdir do |tmp_dir|
input = File.join(tmp_dir, 'in.ogg') input = File.join(tmp_dir, 'in.ogg')
output = File.join(tmp_dir, 'out.ogg')
output_mp3 = File.join(tmp_dir, 'out.mp3')
start = self.preview_start_time.to_f / 1000
stop = start + 20
raise 'no track' unless self["url_44"] raise 'no track' unless self["url_44"]
s3_manager.download(self.url_by_sample_rate(44), input) s3_manager.download(self.url_by_sample_rate(44), input)
command = "sox \"#{input}\" \"#{output}\" trim #{sprintf("%.3f", start)} =#{sprintf("%.3f", stop)}" process_preview(input, tmp_dir)
@@log.debug("trimming using: " + command)
sox_output = `#{command}`
result_code = $?.to_i
if result_code != 0
@@log.debug("fail #{result_code}")
@preview_generate_error = "unable to execute cut command #{sox_output}"
else
# now create mp3 off of ogg preview
convert_mp3_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{output}\" -ab 192k \"#{output_mp3}\""
@@log.debug("converting to mp3 using: " + convert_mp3_cmd)
convert_output = `#{convert_mp3_cmd}`
result_code = $?.to_i
if result_code != 0
@@log.debug("fail #{result_code}")
@preview_generate_error = "unable to execute mp3 convert command #{convert_output}"
else
ogg_digest = ::Digest::MD5.file(output)
mp3_digest = ::Digest::MD5.file(output_mp3)
self["preview_md5"] = ogg_md5 = ogg_digest.hexdigest
self["preview_mp3_md5"] = mp3_md5 = mp3_digest.hexdigest
@@log.debug("uploading ogg preview to #{self.preview_filename('ogg')}")
s3_public_manager.upload(self.preview_filename(ogg_md5, 'ogg'), output, content_type: 'audio/ogg', content_md5: ogg_digest.base64digest)
@@log.debug("uploading mp3 preview to #{self.preview_filename('mp3')}")
s3_public_manager.upload(self.preview_filename(mp3_md5, 'mp3'), output_mp3, content_type: 'audio/mpeg', content_md5: mp3_digest.base64digest)
self.skip_uploader = true
original_ogg_preview_url = self["preview_url"]
original_mp3_preview_url = self["preview_mp3_url"]
# and finally update the JamTrackTrack with the new info
self["preview_url"] = self.preview_filename(ogg_md5, 'ogg')
self["preview_length"] = File.new(output).size
# and finally update the JamTrackTrack with the new info
self["preview_mp3_url"] = self.preview_filename(mp3_md5, 'mp3')
self["preview_mp3_length"] = File.new(output_mp3).size
self.save!
# if all that worked, now delete old previews, if present
begin
s3_public_manager.delete(original_ogg_preview_url) if original_ogg_preview_url && original_ogg_preview_url != self["preview_url"]
s3_public_manager.delete(original_mp3_preview_url) if original_mp3_preview_url && original_mp3_preview_url != track["preview_mp3_url"]
rescue
puts "UNABLE TO CLEANUP OLD PREVIEW URL"
end
end
end
end end
rescue Exception => e rescue Exception => e
@@log.error("error in sox command #{e.to_s}") @@log.error("error in sox command #{e.to_s}")
@ -214,6 +152,76 @@ module JamRuby
end end
# input is the original ogg file for the track. tmp_dir is where this code can safely generate output stuff and have it cleaned up later
def process_preview(input, tmp_dir)
uuid = SecureRandom.uuid
output = File.join(tmp_dir, "#{uuid}.ogg")
output_mp3 = File.join(tmp_dir, "#{uuid}.mp3")
start = self.preview_start_time.to_f / 1000
stop = start + 20
command = "sox \"#{input}\" \"#{output}\" trim #{sprintf("%.3f", start)} =#{sprintf("%.3f", stop)}"
@@log.debug("trimming using: " + command)
sox_output = `#{command}`
result_code = $?.to_i
if result_code != 0
@@log.debug("fail #{result_code}")
@preview_generate_error = "unable to execute cut command #{sox_output}"
else
# now create mp3 off of ogg preview
convert_mp3_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{output}\" -ab 192k \"#{output_mp3}\""
@@log.debug("converting to mp3 using: " + convert_mp3_cmd)
convert_output = `#{convert_mp3_cmd}`
result_code = $?.to_i
if result_code != 0
@@log.debug("fail #{result_code}")
@preview_generate_error = "unable to execute mp3 convert command #{convert_output}"
else
ogg_digest = ::Digest::MD5.file(output)
mp3_digest = ::Digest::MD5.file(output_mp3)
self["preview_md5"] = ogg_md5 = ogg_digest.hexdigest
self["preview_mp3_md5"] = mp3_md5 = mp3_digest.hexdigest
@@log.debug("uploading ogg preview to #{self.preview_filename('ogg')}")
s3_public_manager.upload(self.preview_filename(ogg_md5, 'ogg'), output, content_type: 'audio/ogg', content_md5: ogg_digest.base64digest)
@@log.debug("uploading mp3 preview to #{self.preview_filename('mp3')}")
s3_public_manager.upload(self.preview_filename(mp3_md5, 'mp3'), output_mp3, content_type: 'audio/mpeg', content_md5: mp3_digest.base64digest)
self.skip_uploader = true
original_ogg_preview_url = self["preview_url"]
original_mp3_preview_url = self["preview_mp3_url"]
# and finally update the JamTrackTrack with the new info
self["preview_url"] = self.preview_filename(ogg_md5, 'ogg')
self["preview_length"] = File.new(output).size
# and finally update the JamTrackTrack with the new info
self["preview_mp3_url"] = self.preview_filename(mp3_md5, 'mp3')
self["preview_mp3_length"] = File.new(output_mp3).size
self.save!
# if all that worked, now delete old previews, if present
begin
s3_public_manager.delete(original_ogg_preview_url) if original_ogg_preview_url && original_ogg_preview_url != self["preview_url"]
s3_public_manager.delete(original_mp3_preview_url) if original_mp3_preview_url && original_mp3_preview_url != track["preview_mp3_url"]
rescue
puts "UNABLE TO CLEANUP OLD PREVIEW URL"
end
end
end
end
private private
def normalize_position def normalize_position

View File

@ -44,10 +44,10 @@ module JamRuby
has_one :share_token, :class_name => "JamRuby::ShareToken", :inverse_of => :shareable, :foreign_key => 'shareable_id' has_one :share_token, :class_name => "JamRuby::ShareToken", :inverse_of => :shareable, :foreign_key => 'shareable_id'
has_one :feed, :class_name => "JamRuby::Feed", :inverse_of => :music_session, :foreign_key => 'music_session_id', :dependent => :destroy has_one :feed, :class_name => "JamRuby::Feed", :inverse_of => :music_session, :foreign_key => 'music_session_id', :dependent => :destroy
belongs_to :genre, :class_name => "JamRuby::Genre", :inverse_of => :music_sessions, :foreign_key => 'genre_id' belongs_to :genre, :class_name => "JamRuby::Genre", :inverse_of => :music_sessions, :foreign_key => 'genre_id'
has_many :join_requests, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::JoinRequest", :foreign_key => "music_session_id" has_many :join_requests, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::JoinRequest"
has_many :invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::Invitation", :foreign_key => "music_session_id" has_many :invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::Invitation"
has_many :invited_musicians, :through => :invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver has_many :invited_musicians, :through => :invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver
has_many :fan_invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::FanInvitation", :foreign_key => "music_session_id" has_many :fan_invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::FanInvitation"
has_many :invited_fans, :through => :fan_invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver has_many :invited_fans, :through => :fan_invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver
has_many :rsvp_slots, :class_name => "JamRuby::RsvpSlot", :foreign_key => "music_session_id", :dependent => :destroy has_many :rsvp_slots, :class_name => "JamRuby::RsvpSlot", :foreign_key => "music_session_id", :dependent => :destroy
has_many :music_notations, :class_name => "JamRuby::MusicNotation", :foreign_key => "music_session_id" has_many :music_notations, :class_name => "JamRuby::MusicNotation", :foreign_key => "music_session_id"
@ -880,6 +880,21 @@ SQL
end end
result result
end end
def safe_scheduled_duration
duration = scheduled_duration
# you can put seconds into the scheduled_duration field, but once stored, it comes back out as a string
if scheduled_duration.class == String
begin
bits = scheduled_duration.split(':')
duration = bits[0].to_i.hours + bits[1].to_i.minutes + bits[2].to_i.seconds
rescue Exception => e
duration = 1.hours
@@log.error("unable to parse duration #{scheduled_duration}")
end
end
duration
end
# should create a timestamp like: # should create a timestamp like:
# #
# with_timezone = TRUE # with_timezone = TRUE
@ -910,17 +925,7 @@ SQL
end end
end end
duration = scheduled_duration duration = safe_scheduled_duration
# you can put seconds into the scheduled_duration field, but once stored, it comes back out as a string
if scheduled_duration.class == String
begin
bits = scheduled_duration.split(':')
duration = bits[0].to_i.hours + bits[1].to_i.minutes + bits[2].to_i.seconds
rescue Exception => e
duration = 1.hours
@@log.error("unable to parse duration #{scheduled_duration}")
end
end
end_time = start_time + duration end_time = start_time + duration
if with_timezone if with_timezone
"#{start_time.strftime("%A, %B %e")}, #{start_time.strftime("%l:%M").strip}-#{end_time.strftime("%l:%M %p").strip} #{timezone_display}" "#{start_time.strftime("%A, %B %e")}, #{start_time.strftime("%l:%M").strip}-#{end_time.strftime("%l:%M %p").strip} #{timezone_display}"

View File

@ -10,14 +10,8 @@ module JamRuby
attr_accessible :max_concurrent_connections, :session_removed_at, :rating attr_accessible :max_concurrent_connections, :session_removed_at, :rating
validates_inclusion_of :rating, :in => -1..1, :allow_nil => true validates_inclusion_of :rating, :in => -1..1, :allow_nil => true
belongs_to(:user, belongs_to :user, :class_name => "JamRuby::User", :foreign_key => "user_id", :inverse_of => :music_session_user_histories
:class_name => "JamRuby::User", belongs_to :music_session, :class_name => "MusicSession", :foreign_key => "music_session_id"
:foreign_key => "user_id",
:inverse_of => :music_session_user_histories)
belongs_to(:music_session,
:class_name => "MusicSession",
:foreign_key => "music_session_id")
def self.latest_history(client_id) def self.latest_history(client_id)
self.where(:client_id => client_id) self.where(:client_id => client_id)

View File

@ -246,47 +246,54 @@ module JamRuby
return 'Click search button to look for musicians with similar interests, skill levels, etc.' return 'Click search button to look for musicians with similar interests, skill levels, etc.'
end end
jj = self.json jj = self.json
str = 'Current Search: ' str = ''
str += "Sort = #{SORT_ORDERS[json_value(MusicianSearch::KEY_SORT_ORDER)]}" if 0 < (val = jj[KEY_INSTRUMENTS]).length
str += ", Instruments = "
instr_ids = val.collect { |stored_instrument| stored_instrument['id'] }
instrs = Instrument.where(["id IN (?)", instr_ids]).order(:description)
instrs.each_with_index do |ii, idx|
proficiency = val.detect { |stored_instrument| stored_instrument['id'] == ii.id }['level']
str += "#{ii.description} / #{INSTRUMENT_PROFICIENCY[proficiency.to_i]}"
str += ', ' unless idx==(instrs.length-1)
end
end
if (val = jj[KEY_INTERESTS]) != INTEREST_VALS[0] if (val = jj[KEY_INTERESTS]) != INTEREST_VALS[0]
str += "; Interest = #{INTERESTS[val]}" str += ", Interest = #{INTERESTS[val]}"
end end
if (val = jj[KEY_SKILL].to_i) != SKILL_VALS[0] if (val = jj[KEY_SKILL].to_i) != SKILL_VALS[0]
str += "; Skill = #{SKILL_LEVELS[val]}" str += ", Skill = #{SKILL_LEVELS[val]}"
end end
if (val = jj[KEY_STUDIOS].to_i) != STUDIO_COUNTS[0] if (val = jj[KEY_STUDIOS].to_i) != STUDIO_COUNTS[0]
str += "; Studio Sessions = #{STUDIOS_LABELS[val]}" str += ", Studio Sessions = #{STUDIOS_LABELS[val]}"
end end
if (val = jj[KEY_GIGS].to_i) != GIG_COUNTS[0] if (val = jj[KEY_GIGS].to_i) != GIG_COUNTS[0]
str += "; Concert Gigs = #{GIG_LABELS[val]}" str += ", Concert Gigs = #{GIG_LABELS[val]}"
end end
val = jj[KEY_AGES].map(&:to_i) val = jj[KEY_AGES].map(&:to_i)
val.sort! val.sort!
if !val.blank? if !val.blank?
str += "; Ages = " str += ", Ages = "
val.each_with_index do |vv, idx| val.each_with_index do |vv, idx|
str += "#{AGES[vv]}" str += "#{AGES[vv]}"
str += ', ' unless idx==(val.length-1) str += ', ' unless idx==(val.length-1)
end end
end end
if 0 < (val = jj[KEY_GENRES]).length if 0 < (val = jj[KEY_GENRES]).length
str += "; Genres = " str += ", Genres = "
genres = Genre.where(["id IN (?)", val]).order('description').pluck(:description) genres = Genre.where(["id IN (?)", val]).order('description').pluck(:description)
genres.each_with_index do |gg, idx| genres.each_with_index do |gg, idx|
str += "#{gg}" str += "#{gg}"
str += ', ' unless idx==(genres.length-1) str += ', ' unless idx==(genres.length-1)
end end
end end
if 0 < (val = jj[KEY_INSTRUMENTS]).length str += ", Sort = #{SORT_ORDERS[json_value(MusicianSearch::KEY_SORT_ORDER)]}"
str += "; Instruments = "
instr_ids = val.collect { |vv| vv['instrument_id'] } if str.start_with?(', ')
instrs = Instrument.where(["id IN (?)", instr_ids]).order(:description) # trim off any leading ,
instrs.each_with_index do |ii, idx| str = str[2..-1]
proficiency = val.detect { |vv| vv['instrument_id'] == ii.id }['proficiency_level']
str += "#{ii.description} (#{INSTRUMENT_PROFICIENCY[proficiency.to_i]})"
str += ', ' unless idx==(instrs.length-1)
end
end end
str = 'Current Search: ' + str
str str
end end

View File

@ -73,6 +73,10 @@ module JamRuby
@@message_factory = MessageFactory.new @@message_factory = MessageFactory.new
################### HELPERS ################### ################### HELPERS ###################
def notified?(music_session, notification_type)
Notification.where("session_id=? AND description=?", music_session, notification_type).count != 0
end
def retrieve_friends(connection, user_id) def retrieve_friends(connection, user_id)
friend_ids = [] friend_ids = []
connection.exec("SELECT f.friend_id as friend_id FROM friendships f WHERE f.user_id = $1", [user_id]) do |friend_results| connection.exec("SELECT f.friend_id as friend_id FROM friendships f WHERE f.user_id = $1", [user_id]) do |friend_results|
@ -203,9 +207,15 @@ module JamRuby
when NotificationTypes::SCHEDULED_SESSION_RESCHEDULED when NotificationTypes::SCHEDULED_SESSION_RESCHEDULED
return "The following session has been rescheduled." return "The following session has been rescheduled."
when NotificationTypes::SCHEDULED_SESSION_REMINDER when NotificationTypes::SCHEDULED_SESSION_REMINDER_DAY
return "A session to which you have RSVPd will begin in one hour, so get ready to play!" return "A session to which you have RSVPd will begin in one hour, so get ready to play!"
when NotificationTypes::SCHEDULED_SESSION_REMINDER_UPCOMING
return "A session to which you have RSVPd will begin in one hour, so get ready to play!"
when NotificationTypes::SCHEDULED_SESSION_REMINDER_IMMINENT
return "A session to which you have RSVPd is scheduled to start in 5 minutes!"
when NotificationTypes::SCHEDULED_SESSION_COMMENT when NotificationTypes::SCHEDULED_SESSION_COMMENT
return "New message about session." return "New message about session."
@ -515,7 +525,7 @@ module JamRuby
end end
def send_session_join(active_music_session, connection, user) def send_session_join(active_music_session, connection, user)
notification_msg = format_msg(NotificationTypes::SESSION_JOIN, {:user => user}) notification_msg = format_msg(NotificationTypes::SESSION_JOIN, {:user => user})
msg = @@message_factory.session_join( msg = @@message_factory.session_join(
@ -553,8 +563,8 @@ module JamRuby
end end
def send_musician_session_join(music_session, user) def send_musician_session_join(music_session, user)
if music_session.musician_access || music_session.fan_access if music_session.musician_access || music_session.fan_access
friends = Friendship.where(:friend_id => user.id) friends = Friendship.where(:friend_id => user.id)
user_followers = user.followers user_followers = user.followers
@ -804,7 +814,7 @@ module JamRuby
def send_scheduled_session_cancelled(music_session) def send_scheduled_session_cancelled(music_session)
return if music_session.nil? return if music_session.nil?
rsvp_requests = RsvpRequest.index(music_session) rsvp_requests = RsvpRequest.index(music_session)
target_users = rsvp_requests.where(:canceled => false).map { |r| r.user } target_users = rsvp_requests.where(:canceled => false).map { |r| r.user }
@ -890,33 +900,52 @@ module JamRuby
end end
end end
def send_scheduled_session_reminder(music_session) # Send session reminders to sessions that
# start in less than 24 hours, and haven't been
# notified for a particular interval yet:
def send_session_reminders
MusicSession.where("scheduled_start > NOW() AND scheduled_start <= (NOW()+INTERVAL '1 DAYS')").each do |candidate_session|
tm = candidate_session.scheduled_start
if (tm>(12.hours.from_now) && !notified?(candidate_session, NotificationTypes::SCHEDULED_SESSION_REMINDER_DAY))
# Send 24 hour reminders:
send_session_reminder_day(candidate_session)
elsif (tm<=(65.minutes.from_now) && tm>(15.minutes.from_now) && !notified?(candidate_session, NotificationTypes::SCHEDULED_SESSION_REMINDER_UPCOMING))
# Send 1 hour reminders:
send_session_reminder_upcoming(candidate_session)
elsif (tm<=(10.minutes.from_now) && !notified?(candidate_session, NotificationTypes::SCHEDULED_SESSION_REMINDER_IMMINENT))
# Send 5 minute reminders:
send_session_reminder_imminent(candidate_session)
end
end
end
return if music_session.nil? def send_session_reminder_day(music_session)
send_session_reminder(music_session, NotificationTypes::SCHEDULED_SESSION_REMINDER_DAY) do |music_session, target_user, notification|
begin
UserMailer.scheduled_session_reminder_day(target_user, music_session).deliver
rescue => e
@@log.error("Unable to send SCHEDULED_SESSION_REMINDER_DAY email to user #{target_user.email} #{e}")
end
end
end
rsvp_requests = RsvpRequest.index(music_session) def send_session_reminder_upcoming(music_session)
target_users = rsvp_requests.where(:canceled => false).map { |r| r.user } send_session_reminder(music_session, NotificationTypes::SCHEDULED_SESSION_REMINDER_UPCOMING) do |music_session, target_user, notification|
begin
# remove the creator from the array UserMailer.scheduled_session_reminder_upcoming(target_user, music_session).deliver
target_users = target_users.uniq - [music_session.creator] rescue => e
@@log.error("Unable to send SCHEDULED_SESSION_REMINDER_UPCOMING email to user #{target_user.email} #{e}")
target_users.each do |target_user| end
source_user = music_session.creator end
end
notification = Notification.new
notification.description = NotificationTypes::SCHEDULED_SESSION_REMINDER
notification.source_user_id = source_user.id
notification.target_user_id = target_user.id
notification.session_id = music_session.id
notification.save
notification_msg = format_msg(notification.description, {:session => music_session})
def send_session_reminder_imminent(music_session)
send_session_reminder(music_session, NotificationTypes::SCHEDULED_SESSION_REMINDER_IMMINENT) do |music_session, target_user, notification|
if target_user.online if target_user.online
msg = @@message_factory.scheduled_session_reminder( msg = @@message_factory.scheduled_session_reminder(
target_user.id, target_user.id,
music_session.id, music_session.id,
notification_msg, format_msg(notification.description, {:session => music_session}),
music_session.name, music_session.name,
music_session.pretty_scheduled_start(false), music_session.pretty_scheduled_start(false),
notification.id, notification.id,
@ -925,12 +954,27 @@ module JamRuby
@@mq_router.publish_to_user(target_user.id, msg) @@mq_router.publish_to_user(target_user.id, msg)
end end
end
end
begin # @param music_session - the session for which to send reminder
UserMailer.scheduled_session_reminder(target_user, notification_msg, music_session).deliver # @param reminder_type - the type of reminder; one of:
rescue => e # => SCHEDULED_SESSION_REMINDER_DAY 24 hours
@@log.error("Unable to send SCHEDULED_SESSION_REMINDER email to user #{target_user.email} #{e}") # => SCHEDULED_SESSION_REMINDER_UPCOMING 15 minutes
end # => SCHEDULED_SESSION_REMINDER_IMMINENT 5 minutes (in-app)
def send_session_reminder(music_session, reminder_type)
raise ArgumentError, "Block required" unless block_given?
source_user = music_session.creator
rsvp_requests = RsvpRequest.index(music_session)
rsvp_requests.where(:canceled => false).each do |rsvp|
target_user = rsvp.user
notification = Notification.new
notification.description = reminder_type
notification.source_user_id = source_user.id
notification.target_user_id = target_user.id
notification.session_id = music_session.id
notification.save
yield(music_session, target_user, notification)
end end
end end
@ -984,12 +1028,12 @@ module JamRuby
def send_band_session_join(music_session, band) def send_band_session_join(music_session, band)
# if the session is private, don't send any notifications # if the session is private, don't send any notifications
if music_session.musician_access || music_session.fan_access if music_session.musician_access || music_session.fan_access
notification_msg = format_msg(NotificationTypes::BAND_SESSION_JOIN, {:band => band}) notification_msg = format_msg(NotificationTypes::BAND_SESSION_JOIN, {:band => band})
followers = band.followers.map { |bf| bf.user } followers = band.followers.map { |bf| bf.user }
# do not send band session notifications to band members # do not send band session notifications to band members
followers = followers - band.users followers = followers - band.users
@ -1328,7 +1372,7 @@ module JamRuby
end end
def send_band_invitation_accepted(band, band_invitation, sender, receiver) def send_band_invitation_accepted(band, band_invitation, sender, receiver)
notification = Notification.new notification = Notification.new
notification.band_id = band.id notification.band_id = band.id
notification.description = NotificationTypes::BAND_INVITATION_ACCEPTED notification.description = NotificationTypes::BAND_INVITATION_ACCEPTED
@ -1362,7 +1406,7 @@ module JamRuby
msg = @@message_factory.musician_session_fresh( msg = @@message_factory.musician_session_fresh(
music_session.id, music_session.id,
user.id, user.id,
user.name, user.name,
user.photo_url user.photo_url
) )

View File

@ -8,6 +8,7 @@ module JamRuby
validates :user, presence: true validates :user, presence: true
validates :canceled, :inclusion => {:in => [nil, true, false]} validates :canceled, :inclusion => {:in => [nil, true, false]}
validate :creator_rsvp_cancel validate :creator_rsvp_cancel
before_save :cancel_calendar
# pulls all instruments from the associated rsvp_slots # pulls all instruments from the associated rsvp_slots
def instrument_list def instrument_list
@ -305,6 +306,15 @@ module JamRuby
errors.add(:canceled, "can't be canceled by the session organizer") errors.add(:canceled, "can't be canceled by the session organizer")
end end
end end
def cancel_calendar
calendar_manager = CalendarManager.new
if self.canceled
self.rsvp_slots.each do |slot|
calendar_manager.cancel_ics_event(slot.music_session, user)
end
end
end
end end
end end

View File

@ -18,7 +18,7 @@ module JamRuby
raise "blocidispid must be positive" if blocidispid <= 0 raise "blocidispid must be positive" if blocidispid <= 0
raise "score must be positive" if score <= 0 raise "score must be positive" if score <= 0
ascore = Score.create(alocidispid: alocidispid, anodeid: anodeid, aaddr: aaddr, auserid: user_info[:auserid], alatencytestid: user_info[:alatencytestid], blocidispid: blocidispid, bnodeid: bnodeid, baddr: baddr, buserid: user_info[:buserid], blatencytestid: user_info[:blatencytestid], score: score, scorer: 0, score_dt: score_dt, scoring_data: score_data) ascore = Score.create(alocidispid: alocidispid, anodeid: anodeid, aaddr: aaddr, auserid: user_info[:auserid], alatencytestid: user_info[:alatencytestid], blocidispid: blocidispid, bnodeid: bnodeid, baddr: baddr, buserid: user_info[:buserid], blatencytestid: user_info[:blatencytestid], score: score, scorer: 0, score_dt: score_dt, scoring_data: score_data)
bscore = Score.create(alocidispid: blocidispid, anodeid: bnodeid, aaddr: baddr, auserid: user_info[:buserid], blatencytestid: user_info[:blatencytestid], blocidispid: alocidispid, bnodeid: anodeid, baddr: aaddr, buserid: user_info[:auserid], blatencytestid: user_info[:alatencytestid], score: score, scorer: 1, score_dt: score_dt) if alocidispid != blocidispid bscore = Score.create(alocidispid: blocidispid, anodeid: bnodeid, aaddr: baddr, auserid: user_info[:buserid], alatencytestid: user_info[:blatencytestid], blocidispid: alocidispid, bnodeid: anodeid, baddr: aaddr, buserid: user_info[:auserid], blatencytestid: user_info[:alatencytestid], score: score, scorer: 1, score_dt: score_dt) if alocidispid != blocidispid
Score.connection.execute("select update_current_network_scores(#{alocidispid}, #{blocidispid})") Score.connection.execute("select update_current_network_scores(#{alocidispid}, #{blocidispid})")
return [ascore, bscore] return [ascore, bscore]
end end

View File

@ -45,6 +45,9 @@ module JamRuby
# authorizations (for facebook, etc -- omniauth) # authorizations (for facebook, etc -- omniauth)
has_many :user_authorizations, :class_name => "JamRuby::UserAuthorization" has_many :user_authorizations, :class_name => "JamRuby::UserAuthorization"
# calendars (for scheduling NOT in music_session)
has_many :calendars, :class_name => "JamRuby::Calendar"
# connections (websocket-gateway) # connections (websocket-gateway)
has_many :connections, :class_name => "JamRuby::Connection" has_many :connections, :class_name => "JamRuby::Connection"
@ -194,6 +197,11 @@ module JamRuby
validates_numericality_of :last_jam_audio_latency, greater_than:MINIMUM_AUDIO_LATENCY, less_than:MAXIMUM_AUDIO_LATENCY, :allow_nil => true validates_numericality_of :last_jam_audio_latency, greater_than:MINIMUM_AUDIO_LATENCY, less_than:MAXIMUM_AUDIO_LATENCY, :allow_nil => true
validates :last_jam_updated_reason, :inclusion => {:in => [nil, JAM_REASON_REGISTRATION, JAM_REASON_NETWORK_TEST, JAM_REASON_FTUE, JAM_REASON_JOIN, JAM_REASON_IMPORT, JAM_REASON_LOGIN] } validates :last_jam_updated_reason, :inclusion => {:in => [nil, JAM_REASON_REGISTRATION, JAM_REASON_NETWORK_TEST, JAM_REASON_FTUE, JAM_REASON_JOIN, JAM_REASON_IMPORT, JAM_REASON_LOGIN] }
# stored in cents
validates_numericality_of :paid_sessions_hourly_rate, greater_than:0, less_than:200000, :if => :paid_sessions
# stored in cents
validates_numericality_of :paid_sessions_daily_rate, greater_than:0, less_than:5000000, :if => :paid_sessions
# custom validators # custom validators
validate :validate_musician_instruments validate :validate_musician_instruments
validate :validate_current_password validate :validate_current_password
@ -699,6 +707,20 @@ module JamRuby
end end
end end
# Build calendars using given parameter.
# @param calendars (array of hash)
def update_calendars(calendars)
unless self.new_record?
Calendar.where("user_id = ?", self.id).delete_all
end
unless calendars.nil?
calendars.each do |cal|
self.calendars << self.calendars.create(cal)
end
end
end
# given an array of instruments, update a user's instruments # given an array of instruments, update a user's instruments
def update_instruments(instruments) def update_instruments(instruments)
# delete all instruments for this user first # delete all instruments for this user first

View File

@ -0,0 +1,17 @@
module JamRuby
class DailyJob
extend Resque::Plugins::JamLonelyJob
@queue = :scheduled_daily_job
@@log = Logging.logger[DailyJob]
class << self
def perform
@@log.debug("waking up")
calendar_manager = CalendarManager.new
calendar_manager.cleanup()
@@log.debug("done")
end
end
end
end

View File

@ -0,0 +1,31 @@
require 'json'
require 'resque'
require 'resque-retry'
require 'net/http'
require 'digest/md5'
module JamRuby
class MusicSessionReminder
extend Resque::Plugins::JamLonelyJob
@queue = :music_session_reminder
@@log = Logging.logger[MusicSessionReminder]
def self.lock_timeout
120
end
def self.perform
@@log.debug("MusicSessionReminder waking up")
MusicSessionReminder.new.run
@@log.debug("MusicSessionReminder done")
end
def run
Notification.send_session_reminders()
end
end
end

View File

@ -740,7 +740,7 @@ FactoryGirl.define do
licensor_royalty_amount 0.999 licensor_royalty_amount 0.999
sequence(:plan_code) { |n| "jamtrack-#{n}" } sequence(:plan_code) { |n| "jamtrack-#{n}" }
genre JamRuby::Genre.first genres [JamRuby::Genre.first]
association :licensor, factory: :jam_track_licensor association :licensor, factory: :jam_track_licensor
factory :jam_track_with_tracks do factory :jam_track_with_tracks do

View File

@ -0,0 +1,85 @@
require 'spec_helper'
require 'icalendar'
describe CalendarManager do
CALENDAR_NAME="Test Cal"
before :all do
@genre1 = FactoryGirl.create(:genre)
@calendar_manager = JamRuby::CalendarManager.new
# Time resolution is seconds:
@start = Time.at(Time.now.utc.to_i)
@stop =(@start+1.hours)
end
before(:each) do
end
describe "with music sessions" do
before :all do
@creator = FactoryGirl.create(:user)
@music_session = FactoryGirl.create(:music_session, :creator => @creator, :description => CALENDAR_NAME, :genre => @genre1, :scheduled_start=>@start, :scheduled_duration=>3600)
@music_session.reload
end
it "validator detects bad calendar" do
lambda{verify_ical("Bad medicine calendar")}
.should raise_error(RuntimeError)
end
it "can create calendar feed" do
ics = @calendar_manager.create_ics_feed(@creator)
# Basic format checking...there are some online tools that
# check a lot more, but no ruby libs that I could find:
lines = ics.split("\r\n")
lines.should have(12).items
lines.first.should eq("BEGIN:VCALENDAR")
lines.last.should eq("END:VCALENDAR")
lines[-2].should eq("END:VEVENT")
verify_ical(ics)
end
end
describe "with manual calendars" do
before :all do
@creator = FactoryGirl.create(:user)
@creator.calendars<<Calendar.new({:name=>CALENDAR_NAME, :description=>"This is a test", :start_at=>(@start), :end_at=>@stop, :trigger_delete=>false, :target_uid=>"2112"})
end
it "can create calendar feed" do
#pending "foobar"
ics = @calendar_manager.create_ics_feed(@creator)
# Basic format checking...there are some online tools that
# check a lot more, but no ruby libs that I could find:
lines = ics.split("\r\n")
lines.should have(12).items
lines.first.should eq("BEGIN:VCALENDAR")
lines.last.should eq("END:VCALENDAR")
lines[-2].should eq("END:VEVENT")
verify_ical(ics)
end
end
def verify_ical(ics)
strict_parser = Icalendar::Parser.new(ics, true)
cals = strict_parser.parse
cals.should_not be_nil
cals.should have(1).items
cal = cals.first
cal.should_not be_nil
cal.events.should have(1).items
event = cal.events.first
event.should_not be_nil
event.summary.should eq("JamKazam Session #{CALENDAR_NAME}")
event.dtstart.to_i.should_not be_nil
event.dtend.to_i.should_not be_nil
(event.dtstart).to_time.utc.to_i.should eq(@start.to_i)
(event.dtend).to_time.utc.to_i.should eq(@stop.to_i)
end
end

View File

@ -22,11 +22,13 @@ describe JamTrackImporter do
in_directory_with_file(metafile) in_directory_with_file(metafile)
before(:each) do before(:each) do
JamTrackImporter.storage_format = 'default'
content_for_file(YAML.dump(sample_yml)) content_for_file(YAML.dump(sample_yml))
end end
it "no meta" do it "no meta" do
s3_metalocation = 'audio/Artist 1/Bogus Place/meta.yml' s3_metalocation = 'audio/Artist 1/Bogus Place/meta.yml'
JamTrackImporter.storage_format = 'default'
JamTrackImporter.load_metalocation(s3_metalocation).should be_nil JamTrackImporter.load_metalocation(s3_metalocation).should be_nil
end end
@ -38,9 +40,105 @@ describe JamTrackImporter do
end end
end end
describe "sort_tracks" do
let(:jam_track) { FactoryGirl.create(:jam_track) }
let(:importer) { JamTrackImporter.new() }
let(:vocal) {Instrument.find('voice')}
let(:drums) {Instrument.find('drums')}
let(:bass_guitar) {Instrument.find('bass guitar')}
let(:piano) {Instrument.find('piano')}
let(:keyboard) {Instrument.find('keyboard')}
let(:acoustic_guitar) {Instrument.find('acoustic guitar')}
let(:electric_guitar) {Instrument.find('electric guitar')}
let(:other) {Instrument.find('other')}
it "the big sort" do
# specified in https://jamkazam.atlassian.net/browse/VRFS-3296
vocal_lead = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Lead')
vocal_lead_female = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Lead Female')
vocal_lead_male = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Lead Male')
vocal_backing = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Backing')
vocal_random = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: vocal, part: 'Random')
drums_drums = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'Drums')
drums_percussion = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'Percussion')
drums_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'A')
drums_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: drums, part: 'C')
bass_guitar_bass = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: bass_guitar, part: 'Bass')
bass_guitar_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: bass_guitar, part: 'some bass')
bass_guitar_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: bass_guitar, part: 'zome bass')
piano_piano = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: piano, part: 'Piano')
keyboard_synth_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Synth 1')
keyboard_synth_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Synth 2')
keyboard_pads = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Pads')
keyboard_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'A')
keyboard_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: keyboard, part: 'Z')
acoust_guitar_lead = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Lead')
acoust_guitar_lead_x = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Lead X')
acoust_guitar_solo_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Solo 1')
acoust_guitar_solo_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Solo 2')
acoust_guitar_rhythm = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Rhythm')
acoust_guitar_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'A')
acoust_guitar_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: acoustic_guitar, part: 'Z')
elect_guitar_lead = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Lead')
elect_guitar_lead_x = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Lead X')
elect_guitar_solo_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Solo 1')
elect_guitar_solo_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Solo 2')
elect_guitar_rhythm = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Rhythm')
elect_guitar_random_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'A')
elect_guitar_random_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: electric_guitar, part: 'Z')
other_1 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: other, part: 'Other 1')
other_2 = FactoryGirl.build(:jam_track_track, jam_track: jam_track, instrument: other, part: 'Other 2')
expected = [
vocal_lead,
vocal_lead_female,
vocal_lead_male,
vocal_backing,
vocal_random,
drums_drums,
drums_percussion,
drums_random_1,
drums_random_2,
bass_guitar_bass,
piano_piano,
keyboard_synth_1,
keyboard_synth_2,
keyboard_pads,
keyboard_random_1,
keyboard_random_2,
acoust_guitar_lead,
acoust_guitar_lead_x,
acoust_guitar_rhythm,
acoust_guitar_random_1,
acoust_guitar_solo_1,
acoust_guitar_solo_2,
acoust_guitar_random_2,
elect_guitar_lead,
elect_guitar_lead_x,
elect_guitar_solo_1,
elect_guitar_solo_2,
elect_guitar_rhythm,
elect_guitar_random_1,
elect_guitar_random_2,
bass_guitar_random_1,
bass_guitar_random_2,
other_1,
other_2
]
shuffled = expected.shuffle
sorted_tracks = importer.sort_tracks(shuffled)
importer.set_custom_weight(vocal_lead).should eq(100)
expected.each_with_index do |expected_track, i|
sorted_tracks[i].should eq(expected_track)
end
end
end
describe "synchronize" do describe "synchronize" do
let(:jam_track) { JamTrack.new } let(:jam_track) { JamTrack.new }
let(:importer) { JamTrackImporter.new } let(:importer) { JamTrackImporter.new() }
let(:minimum_meta) { nil } let(:minimum_meta) { nil }
let(:metalocation) { 'audio/Artist 1/Song 1/meta.yml' } let(:metalocation) { 'audio/Artist 1/Song 1/meta.yml' }
let(:options) {{ skip_audio_upload:true }} let(:options) {{ skip_audio_upload:true }}
@ -64,7 +162,7 @@ describe JamTrackImporter do
describe "parse_wav" do describe "parse_wav" do
it "Guitar" do it "Guitar" do
result = JamTrackImporter.new.parse_wav('blah/Ready for Love Stem - Guitar - Main.wav') result = JamTrackImporter.new.parse_file('blah/Ready for Love Stem - Guitar - Main.wav')
result[:instrument].should eq('electric guitar') result[:instrument].should eq('electric guitar')
result[:part].should eq('Main') result[:part].should eq('Main')
end end

View File

@ -15,8 +15,12 @@ describe 'Band Search Model' do
let!(:to_join) { search.search_filter_for_subtype(BandSearch::TO_JOIN) } let!(:to_join) { search.search_filter_for_subtype(BandSearch::TO_JOIN) }
let!(:to_hire) { search.search_filter_for_subtype(BandSearch::TO_HIRE) } let!(:to_hire) { search.search_filter_for_subtype(BandSearch::TO_HIRE) }
before(:each) do before(:all) do
Recording.delete_all
Band.delete_all Band.delete_all
end
before(:each) do
@bands = [] @bands = []
@bands << @band1 = FactoryGirl.create(:band) @bands << @band1 = FactoryGirl.create(:band)
@bands << @band2 = FactoryGirl.create(:band) @bands << @band2 = FactoryGirl.create(:band)

View File

@ -1,6 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe User do describe "Band Search" do
let(:user) { FactoryGirl.create(:user) } let(:user) { FactoryGirl.create(:user) }
let(:band) { FactoryGirl.create(:band, name: "Example Band") } let(:band) { FactoryGirl.create(:band, name: "Example Band") }
@ -15,6 +15,11 @@ describe User do
} }
} }
before(:all) do
Recording.delete_all
Band.delete_all
end
before(:each) do before(:each) do
@user = FactoryGirl.create(:user) @user = FactoryGirl.create(:user)
band.touch band.touch

View File

@ -19,6 +19,17 @@ describe Band do
} }
} }
let(:band_params_no_genre) {
{
name: "The Band",
biography: "Biography",
city: 'Austin',
state: 'TX',
country: 'US',
validate_genres:true
}
}
describe 'with instruments' do describe 'with instruments' do
it 'builds with instruments' do it 'builds with instruments' do
band.musician_instruments << FactoryGirl.build(:musician_instrument, player: band) band.musician_instruments << FactoryGirl.build(:musician_instrument, player: band)
@ -46,6 +57,9 @@ describe Band do
it "minimum genres" do it "minimum genres" do
new_band.save.should be_false new_band.save.should be_false
new_band.errors[:genres].should == [ValidationMessages::BAND_GENRE_MINIMUM_NOT_MET] new_band.errors[:genres].should == [ValidationMessages::BAND_GENRE_MINIMUM_NOT_MET]
new_band.genres = [Genre.first]
new_band.save.should be_true
end end
it "maximum genres" do it "maximum genres" do
@ -56,6 +70,22 @@ describe Band do
end end
describe "save" do describe "save" do
it "genres validate" do
band=Band.save(user, band_params_no_genre)
band.errors.any?.should be_true
band.errors[:genres].should == [ValidationMessages::BAND_GENRE_MINIMUM_NOT_MET]
band = Band.save(user, band_params)
band.errors.any?.should be_false
# Save again without a genre and make sure we get an error:
p = band_params_no_genre.clone
p[:id] = band.id
band = Band.save(user, p)
band.errors.any?.should be_true
band.errors[:genres].should == [ValidationMessages::BAND_GENRE_MINIMUM_NOT_MET]
end
it "can succeed" do it "can succeed" do
band = Band.save(user, band_params) band = Band.save(user, band_params)
band.errors.any?.should be_false band.errors.any?.should be_false
@ -67,6 +97,33 @@ describe Band do
band.country.should == band_params[:country] band.country.should == band_params[:country]
end end
it "saves current interests" do
parms = band_params
parms[:paid_gigs]=true
parms[:free_gigs]=false
parms[:hourly_rate]=5000
parms[:gig_minimum]=30000
parms[:add_new_members]=true
parms[:touring_option]=false
parms[:band_type]="virtual"
parms[:band_status]="amateur"
parms[:concert_count]=3
band = Band.save(user, parms)
band.errors.any?.should be_false
band.paid_gigs.should == true
band.free_gigs.should == false
band.hourly_rate.should == 5000
parms[:gig_minimum]=30000
band.add_new_members.should == true
band.touring_option.should == false
band.band_type.should == "virtual"
band.band_status.should == "amateur"
band.concert_count.should == 3
end
it "ensures user is a musician" do it "ensures user is a musician" do
expect{ Band.save(fan, band_params) }.to raise_error("must be a musician") expect{ Band.save(fan, band_params) }.to raise_error("must be a musician")
end end
@ -173,5 +230,5 @@ describe Band do
history = band.recent_history(nil, claimed_recording.id) history = band.recent_history(nil, claimed_recording.id)
history.size.should == 0 history.size.should == 0
end end
end end
end end

View File

@ -42,8 +42,10 @@ describe BroadcastNotification do
bns = BroadcastNotification.viewable_notifications(user1) bns = BroadcastNotification.viewable_notifications(user1)
expect(bns.count).to be(3) expect(bns.count).to be(3)
expect(bns[0].id).to eq(broadcast3.id) expect(bns[0].id).to eq(broadcast4.id)
expect(bns.detect {|bb| bb.id==broadcast2.id }).to be_nil expect(bns.detect {|bb| bb.id==broadcast2.id }).to be_nil
# now view broadcast 4, since it hasn't been seen, which should bring broadcast 3 up as next since it was seen longest ago
broadcast4.did_view(user1)
expect(BroadcastNotification.next_broadcast(user1).id).to eq(broadcast3.id) expect(BroadcastNotification.next_broadcast(user1).id).to eq(broadcast3.id)
end end

View File

@ -2,6 +2,13 @@ require 'spec_helper'
describe Feed do describe Feed do
before(:all) do
MusicSession.delete_all
Recording.delete_all
IcecastMount.delete_all
end
let (:user1) { FactoryGirl.create(:user) } let (:user1) { FactoryGirl.create(:user) }
let (:user2) { FactoryGirl.create(:user) } let (:user2) { FactoryGirl.create(:user) }
let (:user3) { FactoryGirl.create(:user) } let (:user3) { FactoryGirl.create(:user) }

View File

@ -12,6 +12,90 @@ describe JamTrack do
jam_track = FactoryGirl.create(:jam_track) jam_track = FactoryGirl.create(:jam_track)
jam_track.licensor.should_not be_nil jam_track.licensor.should_not be_nil
jam_track.licensor.jam_tracks.should == [jam_track] jam_track.licensor.jam_tracks.should == [jam_track]
jam_track.genres.length.should eq(1)
end
describe 'sync_reproduction_royalty' do
it "all possible conditions" do
jam_track = FactoryGirl.create(:jam_track)
jam_track.reproduction_royalty_amount.should be_nil
jam_track.duration = 0
jam_track.save!
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
jam_track.duration = 1
jam_track.save!
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
jam_track.duration = 5 * 60 - 1 # just under 5 minutes
jam_track.save!
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
jam_track.duration = 5 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.to_f.should eq(0.091)
jam_track.duration = 6 * 60 - 1 # just under 6 minutes
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175)
jam_track.duration = 6 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175)
jam_track.duration = 7 * 60 - 1
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 2)
jam_track.duration = 7 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 2)
jam_track.duration = 8 * 60 - 1
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 3)
jam_track.duration = 8 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 3)
jam_track.duration = 9 * 60 - 1
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 4)
jam_track.duration = 9 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 4)
jam_track.duration = 10 * 60 - 1
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 5)
jam_track.duration = 10 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 5)
jam_track.duration = 11 * 60 - 1
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 6)
jam_track.duration = 11 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 6)
jam_track.duration = 12 * 60 - 1
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 7)
jam_track.duration = 12 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 7)
jam_track.duration = 13 * 60
jam_track.save!
jam_track.reproduction_royalty_amount.should eq(0.091 + 0.0175 * 8)
end
end end
describe 'plays' do describe 'plays' do
@ -98,6 +182,26 @@ describe JamTrack do
query[1].should eq(jam_track1) query[1].should eq(jam_track1)
end end
it "queries on genre" do
jam_track1 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'a')
jam_track2 = FactoryGirl.create(:jam_track_with_tracks, original_artist: 'artist', name: 'b')
jam_track1.genres = [Genre.find('rock')]
jam_track2.genres = [Genre.find('asian')]
jam_track1.save!
jam_track2.save!
query, pager = JamTrack.index({genre: 'rock'}, user)
query.size.should == 1
query[0].should eq(jam_track1)
query, pager = JamTrack.index({genre: 'asian'}, user)
query.size.should == 1
query[0].should eq(jam_track2)
query, pager = JamTrack.index({genre: 'african'}, user)
query.size.should == 0
end
it "supports showing purchased only" do it "supports showing purchased only" do
jam_track1 = FactoryGirl.create(:jam_track_with_tracks, name: 'a') jam_track1 = FactoryGirl.create(:jam_track_with_tracks, name: 'a')
@ -170,7 +274,7 @@ describe JamTrack do
end end
it "100.1234" do it "100.1234" do
jam_track = FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.1234) jam_track = FactoryGirl.build(:jam_track, reproduction_royalty_amount: 100.12345)
jam_track.valid?.should be_false jam_track.valid?.should be_false
jam_track.errors[:reproduction_royalty_amount].should == ['is invalid'] jam_track.errors[:reproduction_royalty_amount].should == ['is invalid']
end end

View File

@ -7,6 +7,7 @@ describe JamTrackTrack do
it "created" do it "created" do
jam_track_track = FactoryGirl.create(:jam_track_track) jam_track_track = FactoryGirl.create(:jam_track_track)
jam_track_track.jam_track.should_not be_nil jam_track_track.jam_track.should_not be_nil
jam_track_track.jam_track.reload
jam_track_track.jam_track.jam_track_tracks.should == [jam_track_track] jam_track_track.jam_track.jam_track_tracks.should == [jam_track_track]
end end

View File

@ -17,6 +17,8 @@ describe 'Musician Search Model' do
describe "creates search obj" do describe "creates search obj" do
before(:all) do before(:all) do
User.delete_all User.delete_all
Score.connection.execute('delete from current_network_scores').check
Score.connection.execute('delete from scores').check
end end
it "associates to user" do it "associates to user" do
@ -132,12 +134,13 @@ describe 'Musician Search Model' do
describe "filters interests" do describe "filters interests" do
before(:all) do before(:all) do
MusicianSearch::INTEREST_VALS[1..-1].each do |val|
user_types.each { |utype| FactoryGirl.create(utype, val => true) }
end
end end
it "get expected number per interest" do it "get expected number per interest" do
MusicianSearch::INTEREST_VALS[1..-1].each do |val|
user_types.each { |utype| FactoryGirl.create(utype, val => true, :paid_sessions_hourly_rate=>2300, :paid_sessions_daily_rate=>15000) }
end
search.update_json_value(MusicianSearch::KEY_INTERESTS, MusicianSearch::INTEREST_VALS[1]) search.update_json_value(MusicianSearch::KEY_INTERESTS, MusicianSearch::INTEREST_VALS[1])
expect(search.do_search.count).to eq(user_types.count) expect(search.do_search.count).to eq(user_types.count)
end end
@ -169,8 +172,8 @@ describe 'Musician Search Model' do
end end
it "gets expected number of users" do it "gets expected number of users" do
instjson = [{ instrument_id: Instrument.first.id, proficiency_level: 2 }, instjson = [{ id: Instrument.first.id, level: 2 },
{ instrument_id: Instrument.first(2)[1].id, proficiency_level: 2 } { id: Instrument.first(2)[1].id, level: 2 }
] ]
search.update_json_value(MusicianSearch::KEY_INSTRUMENTS, instjson) search.update_json_value(MusicianSearch::KEY_INSTRUMENTS, instjson)
expect(search.do_search.count).to eq(3) expect(search.do_search.count).to eq(3)
@ -201,6 +204,7 @@ describe 'Musician Search Model' do
describe "sort order by latency" do describe "sort order by latency" do
before(:each) do before(:each) do
User.delete_all User.delete_all
Score.delete_all
t = Time.now - 10.minute t = Time.now - 10.minute
@user1 = FactoryGirl.create(:user, created_at: t+1.minute, last_jam_locidispid: 1) @user1 = FactoryGirl.create(:user, created_at: t+1.minute, last_jam_locidispid: 1)
@ -232,12 +236,12 @@ describe 'Musician Search Model' do
Score.createx(2, 'b', 2, 4, 'd', 4, 70) Score.createx(2, 'b', 2, 4, 'd', 4, 70)
end end
it "sorts by latency" do it "sorts by latency", intermittent: true do
search.update_json_value(MusicianSearch::KEY_SORT_ORDER, MusicianSearch::SORT_VALS[0]) search.update_json_value(MusicianSearch::KEY_SORT_ORDER, MusicianSearch::SORT_VALS[0])
results = search.do_search results = search.do_search
expect(results[0].id).to eq(@user1.id) expect(results[0].id).to eq(@user1.id) # HAS FAILED HERE TOO
expect(results[1].id).to eq(@user2.id) expect(results[1].id).to eq(@user2.id)
expect(results[2].id).to eq(@user3.id) expect(results[2].id).to eq(@user3.id) # HAS FAILED INTERMITTENTLY
expect(results[3].id).to eq(@user4.id) expect(results[3].id).to eq(@user4.id)
end end
@ -286,28 +290,28 @@ describe 'Musician Search Model' do
selections.each do |hash| selections.each do |hash|
search.update_json_value(hash[:key], hash[:value]) search.update_json_value(hash[:key], hash[:value])
json_val = search.json_value(hash[:key]) json_val = search.json_value(hash[:key])
expect(search.description).to match(/; #{hash[:description]} = #{hash[:lookup][json_val]}/) expect(search.description).to match(/ #{hash[:description]} = #{hash[:lookup][json_val]}/)
end end
end end
it 'has correct description for genres' do it 'has correct description for genres' do
search.update_json_value(MusicianSearch::KEY_GENRES, [Genre.first.id, Genre.last.id]) search.update_json_value(MusicianSearch::KEY_GENRES, [Genre.first.id, Genre.last.id])
expect(search.description).to match(/; Genres = #{Genre.first.description}, #{Genre.last.description}/) expect(search.description).to match(/ Genres = #{Genre.first.description}, #{Genre.last.description}/)
end end
it 'has correct description for ages' do it 'has correct description for ages' do
search.update_json_value(MusicianSearch::KEY_AGES, [MusicianSearch::AGE_COUNTS[0],MusicianSearch::AGE_COUNTS[1]]) search.update_json_value(MusicianSearch::KEY_AGES, [MusicianSearch::AGE_COUNTS[0],MusicianSearch::AGE_COUNTS[1]])
expect(search.description).to match(/; Ages = #{MusicianSearch::AGES[MusicianSearch::AGE_COUNTS[0]]}, #{MusicianSearch::AGES[MusicianSearch::AGE_COUNTS[1]]}/) expect(search.description).to match(/ Ages = #{MusicianSearch::AGES[MusicianSearch::AGE_COUNTS[0]]}, #{MusicianSearch::AGES[MusicianSearch::AGE_COUNTS[1]]}/)
end end
it 'has correct description for instruments' do it 'has correct description for instruments' do
instrs = Instrument.limit(2).order(:description) instrs = Instrument.limit(2).order(:description)
instjson = [{ instrument_id: instrs[0].id, proficiency_level: 2 }, instjson = [{ id: instrs[0].id, level: 2 },
{ instrument_id: instrs[1].id, proficiency_level: 1 } { id: instrs[1].id, level: 1 }
] ]
search.update_json_value(MusicianSearch::KEY_INSTRUMENTS, instjson) search.update_json_value(MusicianSearch::KEY_INSTRUMENTS, instjson)
instr_descrip = "#{instrs[0].description} (#{MusicianSearch::INSTRUMENT_PROFICIENCY[2]}), #{instrs[1].description} (#{MusicianSearch::INSTRUMENT_PROFICIENCY[1]})" instr_descrip = "#{instrs[0].description} / #{MusicianSearch::INSTRUMENT_PROFICIENCY[2]}, #{instrs[1].description} / #{MusicianSearch::INSTRUMENT_PROFICIENCY[1]}"
expect(search.description).to match(/; Instruments = #{Regexp.escape(instr_descrip)}/) expect(search.description).to match(/ Instruments = #{Regexp.escape(instr_descrip)}/)
end end
end end

View File

@ -18,6 +18,13 @@ describe Notification do
@session = FactoryGirl.create(:music_session) @session = FactoryGirl.create(:music_session)
@band = FactoryGirl.create(:band) @band = FactoryGirl.create(:band)
@slot1 = FactoryGirl.build(:rsvp_slot, :music_session => @session, :instrument => JamRuby::Instrument.find('electric guitar'))
@slot1.save
@slot2 = FactoryGirl.build(:rsvp_slot, :music_session => @session, :instrument => JamRuby::Instrument.find('drums'))
@slot2.save
@friend_request = FactoryGirl.create(:friend_request, user: @sender, friend: @receiver) @friend_request = FactoryGirl.create(:friend_request, user: @sender, friend: @receiver)
end end
@ -199,7 +206,7 @@ describe Notification do
it "does not send email when user is offline and opts out of emails" do it "does not send email when user is offline and opts out of emails" do
FactoryGirl.create(:friendship, :user => @receiver, :friend => @recording.owner) FactoryGirl.create(:friendship, :user => @receiver, :friend => @recording.owner)
FactoryGirl.create(:friendship, :user => @recording.owner, :friend => @receiver) FactoryGirl.create(:friendship, :user => @recording.owner, :friend => @receiver)
@receiver.subscribe_email = false @receiver.subscribe_email = false
@receiver.save! @receiver.save!
@ -284,7 +291,7 @@ describe Notification do
@recording.band = @band @recording.band = @band
@recording.save! @recording.save!
follower.subscribe_email = false follower.subscribe_email = false
follower.save! follower.save!
@ -671,35 +678,14 @@ describe Notification do
end end
end end
describe "send scheduled session reminder" do describe "reminders" do
# it "sends email when user is offline and subscribes to emails" do let(:mail) { UserMailer.deliveries[0] }
# session.creator = sender before :each do
# session.save! UserMailer.deliveries.clear
end
# calls = count_publish_to_user_calls
# notification = Notification.send_scheduled_session_cancelled(session)
# UserMailer.deliveries.length.should == 1
# calls[:count].should == 1
# end
# it "does not send email when user is offline and opts out of emails" do
# session.creator = sender
# session.save!
# receiver.subscribe_email = false
# receiver.save!
# calls = count_publish_to_user_calls
# notification = Notification.send_scheduled_session_cancelled(session)
# UserMailer.deliveries.length.should == 0
# calls[:count].should == 1
# end
it "sends no notification if session is nil" do it "sends no notification if session is nil" do
calls = count_publish_to_user_calls calls = count_publish_to_user_calls
notification = Notification.send_scheduled_session_reminder(nil) notification = Notification.send_session_reminders()
UserMailer.deliveries.length.should == 0 UserMailer.deliveries.length.should == 0
calls[:count].should == 0 calls[:count].should == 0
@ -707,12 +693,65 @@ describe Notification do
it "sends no notification if there are no rsvp requests" do it "sends no notification if there are no rsvp requests" do
calls = count_publish_to_user_calls calls = count_publish_to_user_calls
notification = Notification.send_scheduled_session_reminder(@session) notification = Notification.send_session_reminders()
UserMailer.deliveries.length.should == 0 UserMailer.deliveries.length.should == 0
calls[:count].should == 0 calls[:count].should == 0
end end
end
it "sends email 24 hours before" do
@session.creator = @sender
@session.scheduled_start = Time.now + 23.hours
@session.save!
notification = Notification.send_session_reminders()
UserMailer.deliveries.length.should == 1
calls = count_publish_to_user_calls
calls[:count].should == 0
mail.html_part.body.include?("is scheduled for tomorrow").should be_true
mail.text_part.body.include?("is scheduled for tomorrow").should be_true
mail.html_part.body.include?("starts in 1 hour").should be_false
mail.text_part.body.include?("starts in 1 hour").should be_false
end
it "sends email 1 hour before" do
@session.creator = @sender
@session.scheduled_start = Time.now + 59.minutes
@session.save!
notification = Notification.send_session_reminders()
UserMailer.deliveries.length.should == 1
calls = count_publish_to_user_calls
calls[:count].should == 0
mail.html_part.body.include?("is scheduled for tomorrow").should be_false
mail.text_part.body.include?("is scheduled for tomorrow").should be_false
mail.html_part.body.include?("starts in 1 hour").should be_true
mail.text_part.body.include?("starts in 1 hour").should be_true
end
it "sends notice 5 minutes before" do
UserMailer.deliveries.length.should == 0
receiver_connection = FactoryGirl.create(:connection, user: @receiver)
@receiver.reload
rsvp = RsvpRequest.create({:session_id => @session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "We be jammin!"}, @receiver)
UserMailer.deliveries.clear
calls = count_publish_to_user_calls
@session.creator = @sender
@session.scheduled_start = Time.now + 4.minutes
@session.save!
notification = Notification.send_session_reminders()
calls[:count].should == 1
UserMailer.deliveries.length.should == 0
end
end # reminders
describe "send scheduled session comment" do describe "send scheduled session comment" do
# it "sends email when user is offline and subscribes to emails" do # it "sends email when user is offline and subscribes to emails" do

View File

@ -162,6 +162,10 @@ describe OnlinePresence do
let(:player1) { FactoryGirl.create(:user) } let(:player1) { FactoryGirl.create(:user) }
let(:player2) { FactoryGirl.create(:user) } let(:player2) { FactoryGirl.create(:user) }
end end
after(:all) {
Band.delete_all
}
end end
describe "with a band" do describe "with a band" do
@ -169,5 +173,10 @@ describe OnlinePresence do
let(:player1) { FactoryGirl.create(:band) } let(:player1) { FactoryGirl.create(:band) }
let(:player2) { FactoryGirl.create(:band) } let(:player2) { FactoryGirl.create(:band) }
end end
after(:all) {
Band.delete_all
}
end end
end end

View File

@ -125,6 +125,15 @@ describe PerformanceSample do
let(:player1) { FactoryGirl.create(:user) } let(:player1) { FactoryGirl.create(:user) }
let(:player2) { FactoryGirl.create(:user) } let(:player2) { FactoryGirl.create(:user) }
end end
after(:all) {
User.delete_all
RecordedTrack.delete_all
ClaimedRecording.delete_all
Recording.delete_all
ActiveMusicSession.delete_all
MusicSession.delete_all
}
end end
describe "with a band" do describe "with a band" do
@ -132,5 +141,14 @@ describe PerformanceSample do
let(:player1) { FactoryGirl.create(:band) } let(:player1) { FactoryGirl.create(:band) }
let(:player2) { FactoryGirl.create(:band) } let(:player2) { FactoryGirl.create(:band) }
end end
after(:all) {
Band.delete_all
RecordedTrack.delete_all
ClaimedRecording.delete_all
Recording.delete_all
ActiveMusicSession.delete_all
MusicSession.delete_all
}
end end
end end

View File

@ -30,10 +30,10 @@ describe RsvpRequest do
@slot1 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('electric guitar')) @slot1 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('electric guitar'))
@slot1.save @slot1.save
@slot2 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('drums')) @slot2 = FactoryGirl.build(:rsvp_slot, :music_session => @music_session, :instrument => JamRuby::Instrument.find('drums'))
@slot2.save @slot2.save
@invitation = FactoryGirl.build(:invitation, :sender => @session_creator, :receiver => @session_invitee, :music_session => @music_session) @invitation = FactoryGirl.build(:invitation, :sender => @session_creator, :receiver => @session_invitee, :music_session => @music_session)
@invitation.save @invitation.save
end end
@ -53,12 +53,12 @@ describe RsvpRequest do
@music_session.save @music_session.save
RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee) RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)
expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to raise_error(JamRuby::StateError) expect {RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id]}, @non_session_invitee)}.to raise_error(JamRuby::StateError)
end end
it "should allow invitee to RSVP to session with closed RSVPs" do it "should allow invitee to RSVP to session with closed RSVPs" do
rsvp = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "We be jammin!"}, @session_invitee) rsvp = RsvpRequest.create({:session_id => @music_session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "We be jammin!"}, @session_invitee)
# verify comment # verify comment
comment = SessionInfoComment.find_by_creator_id(@session_invitee) comment = SessionInfoComment.find_by_creator_id(@session_invitee)
comment.comment.should == "We be jammin!" comment.comment.should == "We be jammin!"
@ -373,12 +373,14 @@ describe RsvpRequest do
comment = SessionInfoComment.find_by_creator_id(@session_invitee) comment = SessionInfoComment.find_by_creator_id(@session_invitee)
comment.comment.should == "Let's Jam!" comment.comment.should == "Let's Jam!"
# cancel calendar_count = Calendar.find(:all).count
expect {RsvpRequest.cancel({:id => rsvp.id, :session_id => @music_session.id, :cancelled => "all", :message => "Sorry, I'm bailing for all sessions"}, @session_invitee)}.to_not raise_error
# cancel & check that calendar has been added:
expect {RsvpRequest.cancel({:id => rsvp.id, :session_id => @music_session.id, :cancelled => "all", :message => "Sorry, I'm bailing for all sessions"}, @session_invitee)}.to_not raise_error
rsvp = RsvpRequest.find_by_id(rsvp.id) rsvp = RsvpRequest.find_by_id(rsvp.id)
rsvp.canceled.should == true rsvp.canceled.should == true
rsvp.cancel_all.should == true rsvp.cancel_all.should == true
(Calendar.find(:all).count - calendar_count).should eq(1)
# verify comment # verify comment
comment = SessionInfoComment.find_by_creator_id(@session_invitee) comment = SessionInfoComment.find_by_creator_id(@session_invitee)

View File

@ -195,7 +195,9 @@ describe Sale do
end end
it "for a normally priced jam track" do it "for a normally priced jam track", intermittent: true do
# intermittent: sometimes recurly won't mark it 'collected' soon enough for the test to pass
user.has_redeemable_jamtrack = false user.has_redeemable_jamtrack = false
user.save! user.save!
shopping_cart = ShoppingCart.create user, jamtrack, 1, false shopping_cart = ShoppingCart.create user, jamtrack, 1, false
@ -236,6 +238,7 @@ describe Sale do
sale_line_item.recurly_adjustment_credit_uuid.should be_nil sale_line_item.recurly_adjustment_credit_uuid.should be_nil
sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid) sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid)
# verify subscription is in Recurly # verify subscription is in Recurly
recurly_account = client.get_account(user) recurly_account = client.get_account(user)
adjustments = recurly_account.adjustments adjustments = recurly_account.adjustments

View File

@ -3,6 +3,8 @@ require 'spec_helper'
describe "ActiveMusicSessionCleaner" do describe "ActiveMusicSessionCleaner" do
before(:all) do before(:all) do
MusicSession.delete_all
ActiveMusicSession.delete_all
@cleaner = ActiveMusicSessionCleaner.new @cleaner = ActiveMusicSessionCleaner.new
@cleaner.interval = "INTERVAL '1 second'" @cleaner.interval = "INTERVAL '1 second'"
end end

View File

@ -0,0 +1,82 @@
require 'spec_helper'
describe 'MusicSessionReminder' do
let(:mail) { UserMailer.deliveries[0] }
before :each do
UserMailer.deliveries.clear
MusicSession.delete_all
User.delete_all
@receiver = FactoryGirl.create(:user)
@sender = FactoryGirl.create(:user)
@session = FactoryGirl.create(:music_session)
@slot1 = FactoryGirl.build(:rsvp_slot, :music_session => @session, :instrument => JamRuby::Instrument.find('electric guitar'))
@slot1.save
@slot2 = FactoryGirl.build(:rsvp_slot, :music_session => @session, :instrument => JamRuby::Instrument.find('drums'))
@slot2.save
end
it "sends email 24 hours before" do
@session.creator = @sender
@session.scheduled_start = Time.now + 23.hours
@session.save!
JamRuby::MusicSessionReminder.perform
UserMailer.deliveries.length.should == 1
calls = count_publish_to_user_calls
calls[:count].should == 0
mail.html_part.body.include?("is scheduled for tomorrow").should be_true
mail.text_part.body.include?("is scheduled for tomorrow").should be_true
mail.html_part.body.include?("starts in 1 hour").should be_false
mail.text_part.body.include?("starts in 1 hour").should be_false
end
it "sends email 1 hour before" do
@session.creator = @sender
@session.scheduled_start = Time.now + 59.minutes
@session.save!
JamRuby::MusicSessionReminder.perform
UserMailer.deliveries.length.should == 1
calls = count_publish_to_user_calls
calls[:count].should == 0
mail.html_part.body.include?("is scheduled for tomorrow").should be_false
mail.text_part.body.include?("is scheduled for tomorrow").should be_false
mail.html_part.body.include?("starts in 1 hour").should be_true
mail.text_part.body.include?("starts in 1 hour").should be_true
end
it "sends notice 5 minutes before" do
UserMailer.deliveries.length.should == 0
receiver_connection = FactoryGirl.create(:connection, user: @receiver)
@receiver.reload
rsvp = RsvpRequest.create({:session_id => @session.id, :rsvp_slots => [@slot1.id, @slot2.id], :message => "We be jammin!"}, @receiver)
UserMailer.deliveries.clear
calls = count_publish_to_user_calls
@session.creator = @sender
@session.scheduled_start = Time.now + 4.minutes
@session.save!
JamRuby::MusicSessionReminder.perform
calls[:count].should == 1
UserMailer.deliveries.length.should == 0
end
def count_publish_to_user_calls
result = {count: 0}
MQRouter.any_instance.stub(:publish_to_user) do |receiver_id, msg|
result[:count] += 1
result[:msg] = msg
end
result
end
end #spec

View File

@ -3,6 +3,7 @@ require 'spec_helper'
describe "MusicSessionScheduler" do describe "MusicSessionScheduler" do
before(:all) do before(:all) do
MusicSession.delete_all
@scheduler = MusicSessionScheduler.new @scheduler = MusicSessionScheduler.new
end end

View File

@ -0,0 +1,43 @@
require 'spec_helper'
describe 'DailyJob' do
describe "calendar cleanup" do
shared_examples_for :calendar_cleanup do |trigger_delete, end_count|
before :each do
Calendar.destroy_all
@creator = FactoryGirl.create(:user)
@creator.calendars << Calendar.new(
:name=>"Test Cal",
:description=>"This is a test",
:start_at=>(Time.now),
:end_at=>Time.now,
:trigger_delete=>trigger_delete,
:target_uid=>"2112"
)
end
it "properly purges old 'delete' calendars" do
@creator.reload
@creator.calendars.should have(1).items
JamRuby::DailyJob.perform
@creator.reload
@creator.calendars.should have(1).items
Timecop.travel(Time.now + 5.weeks)
JamRuby::DailyJob.perform
@creator.reload
@creator.calendars.should have(end_count).items
Timecop.return
end
end
describe "whacks old 'delete' calendars" do
it_behaves_like :calendar_cleanup, true, 0
end
describe "doesn't whacks non 'delete' calendars" do
it_behaves_like :calendar_cleanup, false, 1
end
end # calendar cleanpu
end #spec

View File

@ -2,14 +2,18 @@ require 'spec_helper'
describe 'ScheduledMusicSessionCleaner' do describe 'ScheduledMusicSessionCleaner' do
before(:all) {
MusicSession.delete_all
}
it "purges old music sessions" do it "purges old music sessions" do
[MusicSession::UNSTARTED_INTERVAL_DAYS_PURGE, [MusicSession::UNSTARTED_INTERVAL_DAYS_PURGE,
MusicSession::UNSTARTED_INTERVAL_DAYS_PURGE_RECUR].each do |interval| MusicSession::UNSTARTED_INTERVAL_DAYS_PURGE_RECUR].each do |interval|
dd = Time.now - (interval.to_i + 1).days dd = Time.now - (interval.to_i + 1).days
Timecop.travel(dd) Timecop.travel(dd)
FactoryGirl.create(:music_session, scheduled_start: dd) FactoryGirl.create(:music_session, scheduled_start: dd)
Timecop.return Timecop.return
end end
msess2 = FactoryGirl.create(:music_session, scheduled_start: Time.now) msess2 = FactoryGirl.create(:music_session, scheduled_start: Time.now)
expect(MusicSession.count).to be(3) expect(MusicSession.count).to be(3)

View File

@ -123,7 +123,7 @@ describe UserMailer do
before(:each) do before(:each) do
user.update_email = "my_new_email@jamkazam.com" user.update_email = "my_new_email@jamkazam.com"
UserMailer.updating_email(user).deliver UserMailer.updating_email(user).deliver
end end
it { UserMailer.deliveries.length.should == 1 } it { UserMailer.deliveries.length.should == 1 }
@ -137,6 +137,48 @@ describe UserMailer do
it { mail.text_part.body.include?("to confirm your change in email").should be_true } it { mail.text_part.body.include?("to confirm your change in email").should be_true }
end end
describe "notifications" do
let(:mail) { UserMailer.deliveries[0] }
let(:music_session) { FactoryGirl.create(:music_session) }
it "should send upcoming email" do
user.update_email = "my_new_email@jamkazam.com"
UserMailer.scheduled_session_reminder_upcoming(music_session.creator, music_session).deliver
UserMailer.deliveries.length.should == 1
mail['from'].to_s.should == UserMailer::DEFAULT_SENDER
mail['to'].to_s.should == music_session.creator.email# rsvp_requests.first.user.email
mail.multipart?.should == true # because we send plain + htm
# verify that the messages are correctly configured
mail.html_part.body.include?("This is a reminder that your JamKazam session").should be_true
mail.text_part.body.include?("This is a reminder that your JamKazam session").should be_true
mail.html_part.body.include?("starts in 1 hour").should be_true
mail.text_part.body.include?("starts in 1 hour").should be_true
end
it "should send 1-day reminder" do
user.update_email = "my_new_email@jamkazam.com"
UserMailer.scheduled_session_reminder_day(music_session.creator, music_session).deliver
UserMailer.deliveries.length.should == 1
mail['from'].to_s.should == UserMailer::DEFAULT_SENDER
mail['to'].to_s.should == music_session.creator.email# rsvp_requests.first.user.email
mail.multipart?.should == true # because we send plain + htm
# verify that the messages are correctly configured
mail.html_part.body.include?("This is a reminder that your JamKazam session").should be_true
mail.text_part.body.include?("This is a reminder that your JamKazam session").should be_true
mail.html_part.body.include?("is scheduled for tomorrow").should be_true
mail.text_part.body.include?("is scheduled for tomorrow").should be_true
end
end
# describe "sends new musicians email" do # describe "sends new musicians email" do

View File

@ -14,7 +14,7 @@ require 'resque_failed_job_mailer'
# to prevent embedded resque code from forking # to prevent embedded resque code from forking
ENV['FORK_PER_JOB'] = 'false' ENV['FORK_PER_JOB'] = 'false'
IS_BUILD_SERVER = !ENV['BUILD_SERVER'].nil?
# recreate test database and migrate it # recreate test database and migrate it
SpecDb::recreate_database SpecDb::recreate_database
@ -85,9 +85,13 @@ end
config.run_all_when_everything_filtered = true config.run_all_when_everything_filtered = true
config.filter_run :focus config.filter_run :focus
#config.formatter = :documentation
# you can mark a test as slow so that developers won't commonly hit it, but build server will http://blog.davidchelimsky.net/2010/06/14/filtering-examples-in-rspec-2/ # you can mark a test as slow so that developers won't commonly hit it, but build server will http://blog.davidchelimsky.net/2010/06/14/filtering-examples-in-rspec-2/
config.filter_run_excluding slow: true unless run_tests? :slow config.filter_run_excluding slow: true unless run_tests? :slow
config.filter_run_excluding aws: true unless run_tests? :aws config.filter_run_excluding aws: true unless run_tests? :aws
config.filter_run_excluding intermittent: true if IS_BUILD_SERVER
config.before(:suite) do config.before(:suite) do
DatabaseCleaner.strategy = :transaction DatabaseCleaner.strategy = :transaction
@ -108,7 +112,6 @@ end
config.before(:each) do config.before(:each) do
stub_const("APP_CONFIG", app_config) stub_const("APP_CONFIG", app_config)
end end
config.after(:each) do config.after(:each) do

View File

@ -206,6 +206,10 @@ def app_config
1 1
end end
def google_public_server_key
"AIzaSyCPTPq5PEcl4XWcm7NZ2IGClZlbsiE8JNo"
end
private private
def audiomixer_workspace_path def audiomixer_workspace_path

View File

@ -18,10 +18,11 @@ else
end end
end end
#gem 'license_finder'
gem 'oj', '2.10.2' gem 'oj', '2.10.2'
gem 'builder' gem 'builder'
gem 'rails', '~>3.2.11' gem 'rails', '~>3.2.22'
gem 'railties', '~>3.2.11' gem 'railties', '~>3.2.22'
gem 'jquery-rails' gem 'jquery-rails'
gem 'jquery-ui-rails', '4.2.1' gem 'jquery-ui-rails', '4.2.1'
gem 'bootstrap-sass', '2.0.4' gem 'bootstrap-sass', '2.0.4'
@ -36,7 +37,7 @@ gem 'pg', '0.17.1'
gem 'compass-rails', '1.1.3' # 1.1.4 throws an exception on startup about !initialize on nil gem 'compass-rails', '1.1.3' # 1.1.4 throws an exception on startup about !initialize on nil
gem 'rabl', '0.11.0' # for JSON API development gem 'rabl', '0.11.0' # for JSON API development
gem 'gon', '~>4.1.0' # for passthrough of Ruby variables to Javascript variables gem 'gon', '~>4.1.0' # for passthrough of Ruby variables to Javascript variables
gem 'eventmachine', '1.0.3' gem 'eventmachine', '1.0.4'
gem 'faraday', '~>0.9.0' gem 'faraday', '~>0.9.0'
gem 'amqp', '0.9.8' gem 'amqp', '0.9.8'
gem 'logging-rails', :require => 'logging/rails' gem 'logging-rails', :require => 'logging/rails'
@ -85,7 +86,7 @@ gem 'slim'
gem 'htmlentities' gem 'htmlentities'
gem 'sanitize' gem 'sanitize'
gem 'recurly' gem 'recurly'
gem 'guard', '2.7.3' #gem 'guard', '2.7.3'
gem 'influxdb', '0.1.8' gem 'influxdb', '0.1.8'
gem 'influxdb-rails', '0.1.10' gem 'influxdb-rails', '0.1.10'
gem 'sitemap_generator' gem 'sitemap_generator'
@ -95,18 +96,23 @@ gem 'react-rails', '~> 1.0'
source 'https://rails-assets.org' do source 'https://rails-assets.org' do
gem 'rails-assets-reflux' gem 'rails-assets-reflux'
gem 'rails-assets-classnames'
end end
#group :development, :production do
# gem 'rack-timeout'
#end
group :development, :test do group :development, :test do
gem 'rspec-rails', '2.14.2' gem 'rspec-rails', '2.14.2'
gem "activerecord-import", "~> 0.4.1" gem "activerecord-import", "~> 0.4.1"
gem 'guard-rspec', '0.5.5' # gem 'guard-rspec', '0.5.5'
# gem 'jasmine', '1.3.1' # gem 'jasmine', '1.3.1'
gem 'pry' gem 'pry'
gem 'execjs', '1.4.0' gem 'execjs', '1.4.0'
gem 'factory_girl_rails', '4.1.0' # in dev because in use by rake task gem 'factory_girl_rails', '4.1.0' # in dev because in use by rake task
gem 'database_cleaner', '1.3.0' #in dev because in use by rake task gem 'database_cleaner', '1.3.0' #in dev because in use by rake task
gem 'test-unit'
# gem 'teaspoon' # gem 'teaspoon'
# gem 'teaspoon-jasmine' # gem 'teaspoon-jasmine'
gem 'puma' gem 'puma'
@ -136,8 +142,8 @@ group :test, :cucumber do
#end #end
gem 'capybara-screenshot', '0.3.22' # 1.0.0 broke compat with rspec. maybe we need newer rspec gem 'capybara-screenshot', '0.3.22' # 1.0.0 broke compat with rspec. maybe we need newer rspec
gem 'selenium-webdriver' gem 'selenium-webdriver'
gem 'cucumber-rails', :require => false #, '1.3.0', :require => false # gem 'cucumber-rails', :require => false #, '1.3.0', :require => false
gem 'guard-spork', '0.3.2' # gem 'guard-spork', '0.3.2'
gem 'spork', '0.9.0' gem 'spork', '0.9.0'
gem 'launchy', '2.1.1' gem 'launchy', '2.1.1'
gem 'rack-test' gem 'rack-test'

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Some files were not shown because too many files have changed in this diff Show More