VRFS-1654 issue fixed without test

This commit is contained in:
Bert Owen 2014-05-09 23:50:50 +08:00
commit 6ecb7abcad
192 changed files with 3978 additions and 2074 deletions

1
.gitignore vendored
View File

@ -6,4 +6,3 @@
HTML
.DS_Store
coverage

View File

@ -1,7 +1,7 @@
source 'http://rubygems.org'
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
if devenv
gem 'jam_db', :path=> "../db/target/ruby_package"
@ -102,7 +102,6 @@ group :development, :test do
gem 'rspec-rails'
gem 'guard-rspec', '0.5.5'
gem 'jasmine', '1.3.1'
# gem 'pry'
gem 'execjs', '1.4.0'
gem 'therubyracer' #, '0.11.0beta8'
gem 'factory_girl_rails', '4.1.0'
@ -114,6 +113,9 @@ end
group :test do
gem 'simplecov', '~> 0.7.1'
gem 'simplecov-rcov'
gem 'capybara-webkit'
gem 'capybara-screenshot'
gem 'poltergeist'
end
gem 'pry'

View File

@ -20,7 +20,7 @@ ActiveAdmin.register_page "Dashboard" do
column do
panel "Recent Sessions" do
ul do
MusicSessionHistory.order('created_at desc').limit(5).map do |music_session|
MusicSession.order('created_at desc').limit(5).map do |music_session|
li do
text_node "'#{music_session.description}' created by #{User.find(music_session.user_id).name} at #{music_session.created_at}, "
text_node " members: "
@ -38,7 +38,7 @@ ActiveAdmin.register_page "Dashboard" do
end
end
end
end
end
end
# column do

View File

@ -3,36 +3,58 @@ ActiveAdmin.register_page 'Feed' do
# get user information via params
user_id = nil
user_id = params[:feed][:user_id] if params[:feed]
user_name = User.find(user_id).name if user_id
user_name = "All" unless user_id
user_id = params[:feed][:user_id] if params[:feed] && params[:feed][:user_id] != ''
user_name = 'All'
user_name = User.find(user_id).to_label if user_id
render :partial => 'form', :locals => {param: params}
render :partial => 'form', locals: {user_name: user_name, user_id: user_id }
offset = 0
limit = 10
page = (params[:page] ||= 1).to_i
per_page = 10
offset = (page - 1) * per_page
# get feed ids
where_sql = ''
where_sql = "where user_id = '#{user_id}'" if user_id
sql_feed_ids = "SELECT id, 'music_session_histories' as type, created_at FROM music_sessions_history #{where_sql}
sql_feed_ids = "SELECT id, 'music_sessions' as type, created_at FROM music_sessions #{where_sql}
UNION ALL
SELECT DISTINCT recording_id as id, 'recordings' as type, created_at FROM recorded_tracks #{where_sql}
UNION ALL
SELECT id, 'diagnostics' as type, created_at FROM diagnostics #{where_sql}
ORDER BY created_at DESC
OFFSET #{offset}
LIMIT #{limit};"
LIMIT #{per_page};"
models = []
sql_feed_count = "SELECT COUNT(*) FROM (
SELECT id, 'music_sessions' as type, created_at FROM music_sessions #{where_sql}
UNION ALL
SELECT DISTINCT recording_id as id, 'recordings' as type, created_at FROM recorded_tracks #{where_sql}
UNION ALL
SELECT id, 'diagnostics' as type, created_at FROM diagnostics #{where_sql}
ORDER BY created_at DESC
) AS IDS;"
feed_count = ActiveRecord::Base.connection.execute(sql_feed_count).values[0][0].to_i
id_types = ActiveRecord::Base.connection.execute(sql_feed_ids).values
@feed_pages = WillPaginate::Collection.create(page, per_page) do |pager|
pager.total_entries = feed_count
pager.replace(id_types)
end
div class: 'feed-pagination' do
will_paginate @feed_pages
end
recordings = []
sessions = []
diagnostics = []
id_types.each do |id_and_type|
if id_and_type[1] == "music_session_histories"
models << JamRuby::MusicSessionHistory.find(id_and_type[0])
# elsif id_and_type[1] == "recordings"
# models << JamRuby::Recording.find(id_and_type[0])
if id_and_type[1] == "music_sessions"
sessions << JamRuby::MusicSession.find(id_and_type[0])
elsif id_and_type[1] == "recordings"
models << JamRuby::Diagnostics.find(id_and_type[0])
recordings << JamRuby::Recording.find(id_and_type[0])
elsif id_and_type[1] == "diagnostics"
diagnostics << JamRuby::Diagnostic.find(id_and_type[0])
else
raise "Unknown type returned from feed ids"
end
@ -40,22 +62,160 @@ ActiveAdmin.register_page 'Feed' do
columns do
column do
panel "Activity - #{user_name}" do
para id_types.inspect
ul do
models.each do |model|
li do
text_node model.inspect
panel "Music Sessions - #{user_name}" do
if sessions.count > 0
table_for(sessions) do
column :creator do |msh|
link_to msh.creator.to_label, admin_feed_path({feed: {user_id: msh.creator.id}})
end
column :created_at do |msh| msh.created_at.strftime('%b %d %Y, %H:%M') end
column :duration do |msh| "#{msh.duration_minutes.round(2)} minutes" end
column :members do |msh|
uu = msh.unique_users
if uu.length > 0
uu.each do |u|
span link_to u.to_label + ', ', admin_feed_path({feed: {user_id: u.id}})
end
else
span para 'No members'
end
end
column :band do |msh| auto_link(msh.band, msh.band.try(:name)) end
column :fan_access do |msh| msh.fan_access end
column :plays do |msh| msh.plays.count end
column :likes do |msh| msh.likes.count end
column :comments do |msh|
if msh.comment_count > 0
text_node "(#{msh.comment_count}) "
msh.comments.each do |comment|
text_node comment.user.to_label + ', '
end
else
span para 'No comments'
end
end
end
else
span class: 'text-center' do
para 'No session activities.'
end
end
end
panel "Recordings - #{user_name}" do
if recordings.count > 0
table_for(recordings) do
column :starter do |rec|
link_to rec.owner.to_label, admin_feed_path({feed: {user_id: rec.owner.id}})
end
column :mixes do |rec|
ul do
mixes = rec.mixes
if mixes.count > 0
mixes.each do |mix|
li do
text_node "Created At: #{mix.created_at.strftime('%b %d %Y, %H:%M')}, "
text_node "Started At: #{mix.started_at.strftime('%b %d %Y, %H:%M')}, "
text_node "Completed At: #{mix.completed_at.strftime('%b %d %Y, %H:%M')}, "
text_node "Error Count: #{mix.error_count}, "
text_node "Error Reason: #{mix.error_reason}, "
text_node "Error Detail: #{mix.error_detail}, "
text_node "Download Count: #{mix.download_count}, "
if !mix.nil? && !mix[:ogg_url].nil?
span link_to 'Download OGG', mix.sign_url(3600, 'ogg')
else
text_node 'OGG download not available'
end
if !mix.nil? && !mix[:mp3_url].nil?
span link_to 'Download MP3', mix.sign_url(3600, 'mp3')
else
text_node 'MP3 download not available'
end
end
end
else
span para 'No mixes'
end
end
end
column :recorded_tracks do |rec|
ul do
rts = rec.recorded_tracks
if rts.count > 0
rts.each do |gt|
li do
span link_to gt.musician.to_label, admin_feed_path({feed: {user_id: gt.musician.id}})
span ", #{gt.instrument_id}, "
span "Download Count: #{gt.download_count}, "
span "Fully uploaded: #{gt.fully_uploaded}, "
span "Upload failures: #{gt.upload_failures}, "
span "Part failures: #{gt.part_failures}, "
if gt[:url]
# span link_to 'Download', gt.sign_url(3600)
else
span 'No track available'
end
end
end
else
span para 'No recorded tracks'
end
end
end
column :claimed_recordings do |rec|
ul do
crs = rec.claimed_recordings
if crs.count > 0
crs.each do |cr|
li do
span cr.name
span link_to cr.user.to_label, admin_feed_path({feed: {user_id: cr.user.id}})
span ", Public: #{cr.is_public}"
end
end
else
span para 'No claimed recordings'
end
end
end
end
else
span class: 'text-center' do
para 'No recording activities.'
end
end
end
panel "Diagnostics - #{user_name}" do
if diagnostics.count > 0 then
table_for(diagnostics) do
column :user do |d|
span link_to d.user.to_label, admin_feed_path({feed: {user_id: d.user.id}})
end
column :created_at do |d| d.created_at.strftime('%b %d %Y, %H:%M') end
column :type
column :creator
column :data do |d|
span style: "white-space: pre;" do
if JSON.parse(d.data).all?
JSON.pretty_generate(JSON.parse(d.data))
else
d.data
end
end
end
end
else
span class: 'text-center' do
para 'No diagnostic activities.'
end
end
end
end
end
end
controller do
def index
div class: 'feed-pagination' do
will_paginate @feed_pages
end
end
end

View File

@ -24,8 +24,8 @@ ActiveAdmin.register JamRuby::Mix, :as => 'Mixes' do
attributes_table_for(mix) do
row :recording do |mix| auto_link(mix.recording, mix.recording.id) end
row :created_at do |mix| mix.created_at.strftime('%b %d %Y, %H:%M') end
# row :s3_url do |mix| mix.url end
# row :manifest do |mix| mix.manifest end
row :s3_url do |mix| mix.sign_url end
row :manifest do |mix| mix.manifest end
row :completed do |mix| "#{mix.completed ? "finished" : "not finished"}" end
if mix.completed
row :completed_at do |mix| mix.completed_at.strftime('%b %d %Y, %H:%M') end

View File

@ -1,4 +1,4 @@
ActiveAdmin.register JamRuby::MusicSessionHistory, :as => 'Music Session History' do
ActiveAdmin.register JamRuby::MusicSession, :as => 'Music Session' do
config.filters = false
config.per_page = 50
@ -9,14 +9,14 @@ ActiveAdmin.register JamRuby::MusicSessionHistory, :as => 'Music Session History
controller do
def scoped_collection
if params['admin'].blank? || '1' == params['admin']
@music_session_histories ||= end_of_association_chain
.includes([:user, :band])
@music_sessions ||= end_of_association_chain
.includes([:creator, :band])
.order('created_at DESC')
else
@music_session_histories ||= end_of_association_chain
.joins('INNER JOIN users AS uu ON uu.id = music_sessions_history.user_id')
@music_sessions ||= end_of_association_chain
.joins('INNER JOIN users AS uu ON uu.id = music_sessions.user_id')
.where(['uu.admin = ?','f'])
.includes([:user, :band])
.includes([:creator, :band])
.order('created_at DESC')
end
end
@ -33,9 +33,9 @@ ActiveAdmin.register JamRuby::MusicSessionHistory, :as => 'Music Session History
row :description
row :duration do |msh| "#{msh.duration_minutes} minutes" end
row :active do |msh| msh.session_removed_at.nil? end
row :creator do |msh| auto_link(msh.user, msh.user.try(:email)) end
row :creator do |msh| auto_link(msh.creator, msh.creator.try(:email)) end
row :band do |msh| auto_link(msh.band, msh.band.try(:name)) end
row :genres
row :genre
end
end
end

View File

@ -4,8 +4,13 @@
color:lightgray;
}
.text-center {
text-align: center;
}
.feed-pagination {
height: 20px;
margin-bottom: 15px;
.pagination {
float: left !important;

View File

@ -1,6 +1,6 @@
<%= semantic_form_for :feed, url: admin_feed_path, method: :get do |f| %>
<%= f.inputs do %>
<%= f.input :user, :as => :autocomplete, :url => autocomplete_user_email_admin_users_path, :input_html => { :id_element => "#feed_user_id" }%>
<%= f.input :user, :as => :autocomplete, :url => autocomplete_user_email_admin_users_path, :input_html => { :id_element => "#feed_user_id" } %>
<%= f.input :user_id, :as => :hidden %>
<% end %>
<% end %>

View File

@ -1,23 +0,0 @@
<table class="index_table index">
<thead>
<tr>
<td>User Name - <%= @user_id %></td>
</tr>
</thead>
<tbody>
<% @users.each do |user| %>
<tr class="odd">
<td>
<p>
<%= link_to admin_feed_path(feed: {user_id: user.id}) do %>
<%= user.name %>
<% end %></p>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="feed-pagination">
<%= will_paginate @users %>
</div>

0
admin/log/phantomjs.out Normal file
View File

View File

@ -23,7 +23,7 @@ FactoryGirl.define do
factory :single_user_session do
after(:create) do |user, evaluator|
music_session = FactoryGirl.create(:music_session, :creator => user)
music_session = FactoryGirl.create(:active_music_session, :creator => user)
connection = FactoryGirl.create(:connection, :user => user, :music_session => music_session)
end
end
@ -46,4 +46,131 @@ FactoryGirl.define do
description { |n| "Instrument #{n}" }
end
factory :genre, :class => JamRuby::Genre do
description { |n| "Genre #{n}" }
end
factory :music_session, :class => JamRuby::MusicSession do
sequence(:name) { |n| "Music Session #{n}" }
sequence(:description) { |n| "Music Session Description #{n}" }
fan_chat true
fan_access true
approval_required false
musician_access true
legal_terms true
language 'english'
legal_policy 'standard'
genre JamRuby::Genre.first
association :creator, :factory => :user
end
factory :music_session_user_history, :class => JamRuby::MusicSessionUserHistory do
ignore do
history nil
user nil
end
music_session_id { history.id }
user_id { user.id }
sequence(:client_id) { |n| "Connection #{n}" }
end
factory :recorded_track, :class => JamRuby::RecordedTrack do
instrument JamRuby::Instrument.first
sound 'stereo'
sequence(:client_id) { |n| "client_id-#{n}"}
sequence(:track_id) { |n| "track_id-#{n}"}
sequence(:client_track_id) { |n| "client_track_id-#{n}"}
md5 'abc'
length 1
fully_uploaded true
association :user, factory: :user
association :recording, factory: :recording
end
factory :recording, :class => JamRuby::Recording do
association :owner, factory: :user
association :music_session, factory: :active_music_session
factory :recording_with_track do
before(:create) { |recording|
recording.recorded_tracks << FactoryGirl.create(:recorded_track, recording: recording, user: recording.owner)
}
end
end
factory :claimed_recording, :class => JamRuby::ClaimedRecording do
sequence(:name) { |n| "name-#{n}" }
sequence(:description) { |n| "description-#{n}" }
is_public true
association :genre, factory: :genre
association :user, factory: :user
before(:create) { |claimed_recording|
claimed_recording.recording = FactoryGirl.create(:recording_with_track, owner: claimed_recording.user)
}
end
factory :mix, :class => JamRuby::Mix do
started_at Time.now
completed_at Time.now
ogg_md5 'abc'
ogg_length 1
sequence(:ogg_url) { |n| "recordings/ogg/#{n}" }
mp3_md5 'abc'
mp3_length 1
sequence(:mp3_url) { |n| "recordings/mp3/#{n}" }
completed true
before(:create) {|mix|
user = FactoryGirl.create(:user)
mix.recording = FactoryGirl.create(:recording_with_track, owner: user)
mix.recording.claimed_recordings << FactoryGirl.create(:claimed_recording, user: user, recording: mix.recording)
}
end
factory :diagnostic, :class => JamRuby::Diagnostic do
type JamRuby::Diagnostic::NO_HEARTBEAT_ACK
creator JamRuby::Diagnostic::CLIENT
data Faker::Lorem.sentence
association :user, factory: :user
end
factory :active_music_session_no_user_history, :class => JamRuby::ActiveMusicSession do
association :creator, factory: :user
ignore do
name "My Music Session"
description "Come Music Session"
fan_chat true
fan_access true
approval_required false
musician_access true
legal_terms true
genre JamRuby::Genre.first
band nil
end
before(:create) do |session, evaluator|
music_session = FactoryGirl.create(:music_session, name: evaluator.name, description: evaluator.description, fan_chat: evaluator.fan_chat,
fan_access: evaluator.fan_access, approval_required: evaluator.approval_required, musician_access: evaluator.musician_access,
genre: evaluator.genre, creator: evaluator.creator, band: evaluator.band)
session.id = music_session.id
end
factory :active_music_session do
after(:create) { |session|
FactoryGirl.create(:music_session_user_history, :history => session.music_session, :user => session.creator)
}
factory :music_session_with_mount do
association :mount, :factory => :icecast_mount
end
end
end
end

View File

@ -0,0 +1,81 @@
require 'spec_helper'
describe 'Feeds' do
subject { page }
before do
MusicSession.delete_all
Recording.delete_all
Diagnostic.delete_all
User.delete_all
end
let(:admin) { FactoryGirl.create(:admin) }
let(:user) { FactoryGirl.create(:user) }
let(:music_session) { FactoryGirl.create(:music_session, :creator => user) }
let(:recording) { FactoryGirl.create(:recording, :owner => user) }
let(:diagnostic) { FactoryGirl.create(:diagnostic, :user => user) }
describe 'empty dashboard' do
before do
visit admin_feed_path
end
it { should have_selector('h2', text: 'Feed') }
it 'has no feeds' do
should have_selector('p', text: 'No session activities.')
should have_selector('p', text: 'No recording activities.')
should have_selector('p', text: 'No diagnostic activities.')
end
describe 'admin enters user name' do
it 'auto-completes with email + full name', :js => true do
within('form.feed') do
fill_in 'feed_user', with: user.email[0..3]
end
page.execute_script %Q{ $('form.feed input#feed_user').trigger('focus') }
page.execute_script %Q{ $('form.feed input#feed_user').trigger('keydown') }
sleep 5
find('a.ui-corner-all', text: user.to_label).trigger(:click)
should have_selector('form.feed #feed_user', user.to_label)
should have_selector('form.feed #feed_user_id', user.id)
end
end
end
describe 'activities' do
before do
visit admin_feed_path
end
it 'shows session, recording, diagnostic' do
should have_selector("tr#jam_ruby_music_session_#{music_session.id}")
should have_selector("tr#jam_ruby_recording_#{recording.id}")
should have_selector("tr#jam_ruby_diagnostic_#{diagnostic.id}")
end
it 'shows activities for one user', :js => true do
within('form.feed') do
fill_in 'feed_user', with: user.email[0..3]
end
page.execute_script %Q{ $('form.feed input#feed_user').trigger('focus') }
page.execute_script %Q{ $('form.feed input#feed_user').trigger('keydown') }
sleep 5
find('a.ui-corner-all', text: user.to_label).trigger(:click)
should have_selector('form.feed #feed_user', user.to_label)
should have_selector('form.feed #feed_user_id', user.id)
find('form.feed').trigger(:submit)
should have_selector("tr#jam_ruby_music_session_#{music_session.id}")
should have_selector("tr#jam_ruby_recording_#{recording.id}")
should have_selector("tr#jam_ruby_diagnostic_#{diagnostic.id}")
end
end
end

View File

@ -22,6 +22,9 @@ require 'rspec/autorun'
# load capybara
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara-screenshot/rspec'
require 'capybara/poltergeist'
#include Rails.application.routes.url_helpers
@ -30,6 +33,11 @@ require 'capybara/rails'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
Capybara.register_driver :poltergeist do |app|
driver = Capybara::Poltergeist::Driver.new(app, { debug: false, phantomjs_logger: File.open('log/phantomjs.out', 'w') })
end
Capybara.javascript_driver = :poltergeist
Capybara.default_wait_time = 10
RSpec.configure do |config|
# ## Mock Framework

View File

@ -0,0 +1,30 @@
module Snapshot
SS_PATH = 'snapshots.html'
def set_up_snapshot(filepath = SS_PATH)
@size = [1280, 720] #arbitrary
@file = File.new(filepath, "w+")
@file.puts "<HTML><BODY BGCOLOR=grey>"
@file.puts "<H1>Snapshot #{ENV["BUILD_NUMBER"]} - #{@size[0]}x#{@size[1]}</H1>"
end
def snapshot_example
page.driver.resize(@size[0], @size[1])
@file.puts "<H3>Example name: #{get_description}</H3><BR><BR>"
end
def snap!(title = get_description)
base64 = page.driver.render_base64(:png)
@file.puts '<H3>' + title + '</H3>'
@file.puts '<img alt="' + title +'" src="data:image/png;base64,' + base64 + '" />'
@file.puts '<BR><BR><BR>'
end
def tear_down_snapshot
@file.puts "</BODY></HTML>"
@file.close()
end
end

View File

@ -151,3 +151,5 @@ user_mods.sql
connection_stale_expire.sql
rename_chat_messages.sql
fix_connection_fields.sql
session_ratings.sql
scheduled_sessions.sql

View File

@ -0,0 +1,151 @@
-- track the last measured audio gear latency
ALTER TABLE users ADD COLUMN audio_latency double precision;
-- begin moving all the fields traditionally on music_sessions to music_sessions_history
ALTER TABLE music_sessions_history ADD COLUMN scheduled_start TIMESTAMP WITH TIME ZONE;
ALTER TABLE music_sessions_history ADD COLUMN scheduled_duration INTERVAL;
ALTER TABLE music_sessions_history ADD COLUMN musician_access BOOLEAN NOT NULL DEFAULT TRUE;
ALTER TABLE music_sessions_history ADD COLUMN approval_required BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE music_sessions_history ADD COLUMN fan_chat BOOLEAN NOT NULL DEFAULT TRUE;
ALTER TABLE music_sessions_history ADD COLUMN genre_id VARCHAR(64) REFERENCES genres(id);
ALTER TABLE music_sessions_history ADD COLUMN legal_policy VARCHAR(255) NOT NULL DEFAULT 'standard';
ALTER TABLE music_sessions_history ADD COLUMN language VARCHAR(255) NOT NULL DEFAULT 'en';
ALTER TABLE music_sessions_history ADD COLUMN name TEXT;
-- get rid of genres in favor of just genre_id (no more multi-genres for a session)
UPDATE music_sessions_history SET name = description;
ALTER TABLE music_sessions_history ALTER COLUMN name SET NOT NULL;
-- production db has some null genres on older sessions
UPDATE music_sessions_history SET genres = 'rock' where genres = '';
UPDATE music_sessions_history SET genre_id = genres;
ALTER TABLE music_sessions_history ALTER COLUMN genre_id SET NOT NULL;
ALTER TABLE music_sessions_history DROP COLUMN genres;
-- likers should refer to id field of music_sessions_history (not music_session_id)
ALTER TABLE music_sessions_likers ADD COLUMN music_session_id2 VARCHAR(64) REFERENCES music_sessions_history(id) ON DELETE CASCADE;
-- production db has some bad data
DELETE from music_sessions_likers where music_session_id NOT IN (select id from music_sessions_history);
UPDATE music_sessions_likers SET music_session_id2 = music_session_id;
ALTER TABLE music_sessions_likers DROP COLUMN music_session_id;
ALTER TABLE music_sessions_likers RENAME COLUMN music_session_id2 to music_session_id;
-- comments should refer to id field of music_sessions_history (not music_session_id)
ALTER TABLE music_sessions_comments ADD COLUMN music_session_id2 VARCHAR(64) REFERENCES music_sessions_history(id) ON DELETE CASCADE;
-- production db has some bad data
DELETE from music_sessions_comments where music_session_id NOT IN (select id from music_sessions_history);
UPDATE music_sessions_comments SET music_session_id2 = music_session_id;
ALTER TABLE music_sessions_comments DROP COLUMN music_session_id;
ALTER TABLE music_sessions_comments RENAME COLUMN music_session_id2 to music_session_id;
-- user_history should refer to id field of music_sessions_history (not music_session_id)
ALTER TABLE music_sessions_user_history ADD COLUMN music_session_id2 VARCHAR(64) REFERENCES music_sessions_history(id) ON DELETE CASCADE;
-- production db has some bad data
DELETE from music_sessions_user_history where music_session_id NOT IN (select id from music_sessions_history);
UPDATE music_sessions_user_history SET music_session_id2 = music_session_id;
ALTER TABLE music_sessions_user_history DROP COLUMN music_session_id;
ALTER TABLE music_sessions_user_history RENAME COLUMN music_session_id2 to music_session_id;
-- get rid of display fields on music_sessions
ALTER TABLE music_sessions DROP COLUMN musician_access;
ALTER TABLE music_sessions DROP COLUMN fan_access;
ALTER TABLE music_sessions DROP COLUMN description;
ALTER TABLE music_sessions DROP COLUMN fan_chat;
ALTER TABLE music_sessions DROP COLUMN approval_required;
ALTER TABLE music_sessions DROP COLUMN band_id;
ALTER TABLE music_sessions_history ALTER COLUMN music_session_id DROP NOT NULL;
-- create RSVP slots
CREATE TABLE rsvp_slots (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
instrument_id VARCHAR(64) REFERENCES instruments (id),
proficiency_level VARCHAR(255) NOT NULL,
music_session_id VARCHAR(64) NOT NULL REFERENCES music_sessions_history (id) ON DELETE CASCADE,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
-- create RSVP requests
CREATE TABLE rsvp_requests (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64) NOT NULL REFERENCES users (id) ON DELETE CASCADE,
rsvp_slot_id VARCHAR(64) NOT NULL REFERENCES rsvp_slots(id) ON DELETE CASCADE,
message TEXT,
chosen BOOLEAN DEFAULT FALSE,
canceled BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
CREATE TABLE recurring_sessions (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
description VARCHAR(8000),
scheduled_start TIMESTAMP WITH TIME ZONE,
scheduled_duration INTERVAL,
musician_access BOOLEAN NOT NULL,
approval_required BOOLEAN NOT NULL,
fan_chat BOOLEAN NOT NULL,
genre_id VARCHAR(64) REFERENCES genres(id),
legal_policy VARCHAR(255) NOT NULL DEFAULT 'standard',
language VARCHAR(255) NOT NULL DEFAULT 'en',
name TEXT,
user_id VARCHAR(64) NOT NULL REFERENCES users (id) ON DELETE CASCADE,
band_id VARCHAR(64) REFERENCES bands(id) ON DELETE CASCADE,
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
ALTER TABLE music_sessions_history ADD COLUMN recurring_session_id VARCHAR(64) REFERENCES recurring_sessions(id);
-- make these 3 tables be LOGGED, and refer to music_sessions_history instead of music_sessions
DROP TABLE fan_invitations;
DROP TABLE invitations;
DROP TABLE join_requests;
CREATE TABLE fan_invitations (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
sender_id VARCHAR(64),
receiver_id VARCHAR(64),
music_session_id VARCHAR(64),
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
ALTER TABLE ONLY fan_invitations ADD CONSTRAINT fan_invitations_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions_history(id) ON DELETE CASCADE;
CREATE UNLOGGED TABLE join_requests (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
user_id VARCHAR(64),
music_session_id VARCHAR(64),
text VARCHAR(2000),
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL
);
ALTER TABLE ONLY join_requests ADD CONSTRAINT user_music_session_uniqkey UNIQUE (user_id, music_session_id);
ALTER TABLE ONLY join_requests ADD CONSTRAINT join_requests_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions_history(id) ON DELETE CASCADE;
-- INVITATIONS
--------------
CREATE UNLOGGED TABLE invitations (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
sender_id VARCHAR(64),
receiver_id VARCHAR(64),
music_session_id VARCHAR(64),
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL,
join_request_id VARCHAR(64)
);
ALTER TABLE ONLY invitations ADD CONSTRAINT invitations_uniqkey UNIQUE (sender_id, receiver_id, music_session_id);
ALTER TABLE ONLY invitations ADD CONSTRAINT invitations_join_request_id_fkey FOREIGN KEY (join_request_id) REFERENCES join_requests(id) ON DELETE CASCADE;
ALTER TABLE ONLY invitations ADD CONSTRAINT invitations_music_session_id_fkey FOREIGN KEY (music_session_id) REFERENCES music_sessions_history(id) ON DELETE CASCADE;
-- finally, rename music_sessions and music_sessions_history to reflect true nature better
ALTER TABLE music_sessions RENAME TO active_music_sessions;
ALTER TABLE music_sessions_history RENAME TO music_sessions;
-- add fk to chat_messages so they delete cleanly when users are deleted
ALTER TABLE ONLY chat_messages ADD CONSTRAINT chat_messages_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-- fix any promotionals
UPDATE promotionals SET latest_type = 'JamRuby::MusicSession' WHERE latest_type = 'JamRuby::MusicSessionHistory';

View File

@ -0,0 +1 @@
ALTER TABLE music_sessions_user_history ADD COLUMN rating_comment TEXT;

View File

@ -186,6 +186,7 @@ message LoginAck {
optional string music_session_id = 5; // the music session that the user was in very recently (likely due to dropped connection)
optional bool reconnected = 6; // if reconnect_music_session_id is specified, and the server could log the user into that session, then true is returned.
optional string user_id = 7; // the database user id
optional int32 connection_expire_time = 8; // this is how long the server gives you before killing your connection entirely after missing heartbeats
}
// route_to: server

View File

@ -4,7 +4,7 @@ unless ENV["LOCAL_DEV"] == "1"
source 'https://jamjam:blueberryjam@int.jamkazam.com/gems/'
end
devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
if devenv
gem 'jam_db', :path=> "../db/target/ruby_package"

View File

@ -31,6 +31,7 @@ require "jam_ruby/lib/module_overrides"
require "jam_ruby/lib/s3_util"
require "jam_ruby/lib/s3_manager"
require "jam_ruby/lib/profanity"
require "jam_ruby/lib/json_validator"
require "jam_ruby/lib/em_helper.rb"
require "jam_ruby/lib/nav.rb"
require "jam_ruby/resque/audiomixer"
@ -75,10 +76,11 @@ require "jam_ruby/models/artifact_update"
require "jam_ruby/models/band_invitation"
require "jam_ruby/models/band_musician"
require "jam_ruby/models/connection"
require "jam_ruby/models/diagnostic"
require "jam_ruby/models/friendship"
require "jam_ruby/models/music_session"
require "jam_ruby/models/active_music_session"
require "jam_ruby/models/music_session_comment"
require "jam_ruby/models/music_session_history"
require "jam_ruby/models/music_session"
require "jam_ruby/models/music_session_liker"
require "jam_ruby/models/music_session_user_history"
require "jam_ruby/models/music_session_perf_data"

View File

@ -39,12 +39,12 @@ module JamRuby
# this simulates music_session destroy callbacks with activerecord
def before_destroy_music_session(music_session_id)
music_session = MusicSession.find_by_id(music_session_id)
music_session = ActiveMusicSession.find_by_id(music_session_id)
music_session.before_destroy if music_session
end
# reclaim the existing connection, if ip_address is not nil then perhaps a new address as well
def reconnect(conn, reconnect_music_session_id, ip_address)
def reconnect(conn, reconnect_music_session_id, ip_address, connection_stale_time, connection_expire_time)
music_session_id = nil
reconnected = false
@ -86,7 +86,7 @@ module JamRuby
end
sql =<<SQL
UPDATE connections SET (aasm_state, updated_at, music_session_id, joined_session_at) = ('#{Connection::CONNECT_STATE.to_s}', NOW(), #{music_session_id_expression}, #{joined_session_at_expression})
UPDATE connections SET (aasm_state, updated_at, music_session_id, joined_session_at, stale_time, expire_time) = ('#{Connection::CONNECT_STATE.to_s}', NOW(), #{music_session_id_expression}, #{joined_session_at_expression}, #{connection_stale_time}, #{connection_expire_time})
WHERE
client_id = '#{conn.client_id}'
RETURNING music_session_id
@ -114,7 +114,6 @@ WHERE
aasm_state = '#{Connection::CONNECT_STATE.to_s}'
RETURNING music_session_id
SQL
# @log.info("*** flag_connection_stale_with_client_id: client_id = #{client_id}; sql = #{sql}")
self.pg_conn.exec(sql) do |result|
# if we did update a client to stale, retriee music_session_id
@ -127,24 +126,22 @@ SQL
end
# flag connections as stale
def flag_stale_connections(max_seconds)
def flag_stale_connections()
ConnectionManager.active_record_transaction do |connection_manager|
conn = connection_manager.pg_conn
sql =<<SQL
SELECT count(user_id) FROM connections
WHERE
updated_at < (NOW() - interval '#{max_seconds} second') AND
updated_at < (NOW() - (interval '1 second' * stale_time))AND
aasm_state = '#{Connection::CONNECT_STATE.to_s}'
SQL
conn.exec(sql) do |result|
count = result.getvalue(0, 0)
# @log.info("flag_stale_connections: flagging #{count} stale connections")
if 0 < count.to_i
# @log.info("flag_stale_connections: flagging #{count} stale connections")
sql =<<SQL
UPDATE connections SET aasm_state = '#{Connection::STALE_STATE.to_s}'
WHERE
updated_at < (NOW() - interval '#{max_seconds} second') AND
updated_at < (NOW() - (interval '1 second' * stale_time)) AND
aasm_state = '#{Connection::CONNECT_STATE.to_s}'
SQL
conn.exec(sql)
@ -155,33 +152,31 @@ SQL
# NOTE this is only used for testing purposes;
# actual deletes will be processed in the websocket context which cleans up dependencies
def expire_stale_connections(max_seconds)
self.stale_connection_client_ids(max_seconds).each { |cid| self.delete_connection(cid) }
def expire_stale_connections()
self.stale_connection_client_ids().each { |client| self.delete_connection(client[:client_id]) }
end
# expiring connections in stale state, which deletes them
def stale_connection_client_ids(max_seconds)
client_ids = []
def stale_connection_client_ids()
clients = []
ConnectionManager.active_record_transaction do |connection_manager|
conn = connection_manager.pg_conn
sql =<<SQL
SELECT client_id, music_session_id, user_id FROM connections
SELECT client_id, music_session_id, user_id, client_type FROM connections
WHERE
updated_at < (NOW() - interval '#{max_seconds} second') AND
aasm_state = '#{Connection::STALE_STATE.to_s}'
updated_at < (NOW() - (interval '1 second' * expire_time))
SQL
conn.exec(sql) do |result|
result.each { |row|
client_id = row['client_id']
music_session_id = row['music_session_id']
user_id = row['user_id']
client_ids << client_id
client_type = row['client_type']
clients << {client_id: client_id, music_session_id: music_session_id, client_type: client_type, user_id: user_id}
}
end
end
client_ids
clients
end
@ -189,7 +184,7 @@ SQL
# this number is used by notification logic elsewhere to know
# 'oh the user joined for the 1st time, so send a friend update', or
# 'don't bother because the user has connected somewhere else already'
def create_connection(user_id, client_id, ip_address, client_type, &blk)
def create_connection(user_id, client_id, ip_address, client_type, connection_stale_time, connection_expire_time, &blk)
# validate client_type
raise "invalid client_type: #{client_type}" if client_type != 'client' && client_type != 'browser'
@ -221,8 +216,8 @@ SQL
lock_connections(conn)
conn.exec("INSERT INTO connections (user_id, client_id, ip_address, client_type, addr, locidispid, aasm_state) VALUES ($1, $2, $3, $4, $5, $6, $7)",
[user_id, client_id, ip_address, client_type, addr, locidispid, Connection::CONNECT_STATE.to_s]).clear
conn.exec("INSERT INTO connections (user_id, client_id, ip_address, client_type, addr, locidispid, aasm_state, stale_time, expire_time) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
[user_id, client_id, ip_address, client_type, addr, locidispid, Connection::CONNECT_STATE.to_s, connection_stale_time, connection_expire_time]).clear
# we just created a new connection-if this is the first time the user has shown up, we need to send out a message to his friends
conn.exec("SELECT count(user_id) FROM connections WHERE user_id = $1", [user_id]) do |result|
@ -280,7 +275,7 @@ SQL
# same for session-if we are down to the last participant, delete the session
unless music_session_id.nil?
before_destroy_music_session(music_session_id)
result = conn.exec("DELETE FROM music_sessions WHERE id = $1 AND 0 = (select count(music_session_id) FROM connections where music_session_id = $1)", [music_session_id])
result = conn.exec("DELETE FROM active_music_sessions WHERE id = $1 AND 0 = (select count(music_session_id) FROM connections where music_session_id = $1)", [music_session_id])
if result.cmd_tuples == 1
music_session_id = nil
end
@ -321,12 +316,12 @@ SQL
if num_participants == 0
# delete the music_session
before_destroy_music_session(previous_music_session_id)
conn.exec("DELETE from music_sessions WHERE id = $1",
conn.exec("DELETE from active_music_sessions WHERE id = $1",
[previous_music_session_id]) do |result|
if result.cmd_tuples == 1
# music session deleted!
@log.debug("deleted music session #{previous_music_session_id}")
JamRuby::MusicSessionHistory.removed_music_session(previous_music_session_id)
JamRuby::MusicSession.removed_music_session(previous_music_session_id)
elsif 1 < result.cmd_tuples
msg = "music_sessions table data integrity violation; multiple rows found with music_session_id=#{previous_music_session_id}"
@log.error(msg)
@ -337,7 +332,7 @@ SQL
# there are still people in the session
#ensure that there is no active claimed recording if the owner of that recording left the session
conn.exec("UPDATE music_sessions set claimed_recording_id = NULL, claimed_recording_initiator_id = NULL where claimed_recording_initiator_id = $1 and id = $2",
conn.exec("UPDATE active_music_sessions set claimed_recording_id = NULL, claimed_recording_initiator_id = NULL where claimed_recording_initiator_id = $1 and id = $2",
[user_id, previous_music_session_id])
end

View File

@ -0,0 +1,15 @@
# This needs to be outside the module to work.
class JsonValidator < ActiveModel::EachValidator
# implement the method called during validation
def is_json?(value)
begin
!!JSON.parse(value)
rescue
false
end
end
def validate_each(record, attribute, value)
record.errors[attribute] << 'must be JSON' unless value.nil? || is_json?(value)
end
end

View File

@ -33,7 +33,7 @@ end
class NoProfanityValidator < ActiveModel::EachValidator
# implement the method called during validation
def validate_each(record, attribute, value)
record.errors[attribute] << 'cannot contain profanity' if Profanity.is_profane?(value)
record.errors[attribute] << 'cannot contain profanity' if JamRuby::Profanity.is_profane?(value)
end
end

View File

@ -53,7 +53,7 @@ module JamRuby
end
# create a login ack (login was successful)
def login_ack(public_ip, client_id, token, heartbeat_interval, music_session_id, reconnected, user_id)
def login_ack(public_ip, client_id, token, heartbeat_interval, music_session_id, reconnected, user_id, connection_expire_time)
login_ack = Jampb::LoginAck.new(
:public_ip => public_ip,
:client_id => client_id,
@ -61,7 +61,8 @@ module JamRuby
:heartbeat_interval => heartbeat_interval,
:music_session_id => music_session_id,
:reconnected => reconnected,
:user_id => user_id
:user_id => user_id,
:connection_expire_time => connection_expire_time
)
Jampb::ClientMessage.new(

View File

@ -0,0 +1,482 @@
module JamRuby
class ActiveMusicSession < ActiveRecord::Base
self.primary_key = 'id'
self.table_name = 'active_music_sessions'
attr_accessor :legal_terms, :max_score
belongs_to :claimed_recording, :class_name => "JamRuby::ClaimedRecording", :foreign_key => "claimed_recording_id", :inverse_of => :playing_sessions
belongs_to :claimed_recording_initiator, :class_name => "JamRuby::User", :inverse_of => :playing_claimed_recordings, :foreign_key => "claimed_recording_initiator_id"
has_one :music_session, :class_name => "JamRuby::MusicSession", :foreign_key => 'music_session_id'
has_one :mount, :class_name => "JamRuby::IcecastMount", :inverse_of => :music_session, :foreign_key => 'music_session_id'
belongs_to :creator, :class_name => 'JamRuby::User', :foreign_key => :user_id
has_many :connections, :class_name => "JamRuby::Connection", foreign_key: :music_session_id
has_many :users, :through => :connections, :class_name => "JamRuby::User"
has_many :recordings, :class_name => "JamRuby::Recording", :inverse_of => :music_session, foreign_key: :music_session_id
has_many :chats, :class_name => "JamRuby::ChatMessages", :foreign_key => "session_id"
validates :creator, :presence => true
validate :creator_is_musician
validate :no_new_playback_while_playing
after_create :started_session
after_destroy do |obj|
JamRuby::MusicSession.removed_music_session(obj.id)
end
#default_scope :select => "*, 0 as score"
def attributes
super.merge('max_score' => self.max_score)
end
def max_score
nil unless has_attribute?(:max_score)
read_attribute(:max_score).to_i
end
before_create :create_uuid
def create_uuid
#self.id = SecureRandom.uuid
end
def before_destroy
self.mount.destroy if self.mount
end
def creator_is_musician
unless creator.musician?
errors.add(:creator, ValidationMessages::MUST_BE_A_MUSICIAN)
end
end
def no_new_playback_while_playing
# if we previous had a claimed recording and are trying to set one
# and if also the previous initiator is different than the current one... it's a no go
if !claimed_recording_id_was.nil? && !claimed_recording_id.nil? &&
claimed_recording_initiator_id_was != claimed_recording_initiator_id
errors.add(:claimed_recording, ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS)
end
end
# returns an array of client_id's that are in this session
# if as_musician is nil, all connections in the session ,regardless if it's a musician or not or not
# you can also exclude a client_id from the returned set by setting exclude_client_id
def get_connection_ids(options = {})
as_musician = options[:as_musician]
exclude_client_id = options[:exclude_client_id]
where = { :music_session_id => self.id }
where[:as_musician] = as_musician unless as_musician.nil?
exclude = "client_id != '#{exclude_client_id}'"unless exclude_client_id.nil?
Connection.select(:client_id).where(where).where(exclude).map(&:client_id)
end
# This is a little confusing. You can specify *BOTH* friends_only and my_bands_only to be true
# If so, then it's an OR condition. If both are false, you can get sessions with anyone.
def self.index(current_user, options = {})
participants = options[:participants]
genres = options[:genres]
keyword = options[:keyword]
friends_only = options[:friends_only].nil? ? false : options[:friends_only]
my_bands_only = options[:my_bands_only].nil? ? false : options[:my_bands_only]
as_musician = options[:as_musician].nil? ? true : options[:as_musician]
query = ActiveMusicSession
.joins(
%Q{
INNER JOIN
music_sessions
ON
active_music_sessions.id = music_sessions.id
}
)
.joins(
%Q{
INNER JOIN
connections
ON
active_music_sessions.id = connections.music_session_id
}
)
.joins(
%Q{
LEFT OUTER JOIN
friendships
ON
connections.user_id = friendships.user_id
AND
friendships.friend_id = '#{current_user.id}'
}
)
.joins(
%Q{
LEFT OUTER JOIN
invitations
ON
invitations.music_session_id = active_music_sessions.id
AND
invitations.receiver_id = '#{current_user.id}'
}
)
.group(
%Q{
active_music_sessions.id
}
)
.order(
%Q{
SUM(CASE WHEN invitations.id IS NULL THEN 0 ELSE 1 END) DESC,
SUM(CASE WHEN friendships.user_id IS NULL THEN 0 ELSE 1 END) DESC,
active_music_sessions.created_at DESC
}
)
if as_musician
query = query.where(
%Q{
musician_access = true
OR
invitations.id IS NOT NULL
}
)
else
# if you are trying to join the session as a fan/listener,
# we have to have a mount, fan_access has to be true, and we have to allow for the reload of icecast to have taken effect
query = query.joins('INNER JOIN icecast_mounts ON icecast_mounts.music_session_id = active_music_sessions.id INNER JOIN icecast_servers ON icecast_mounts.icecast_server_id = icecast_servers.id')
query = query.where('music_sessions.fan_access = true')
query = query.where("(active_music_sessions.created_at < icecast_servers.config_updated_at)")
end
query = query.where("music_sessions.description like '%#{keyword}%'") unless keyword.nil?
query = query.where("connections.user_id" => participants.split(',')) unless participants.nil?
query = query.where("music_sessions.genre_id in (?)", genres) unless genres.nil?
if my_bands_only
query = query.joins(
%Q{
LEFT OUTER JOIN
bands_musicians
ON
bands_musicians.user_id = '#{current_user.id}'
}
)
end
if my_bands_only || friends_only
query = query.where(
%Q{
#{friends_only ? "friendships.user_id IS NOT NULL" : "false"}
OR
#{my_bands_only ? "bands_musicians.band_id = music_sessions.band_id" : "false"}
}
)
end
return query
end
# This is a little confusing. You can specify *BOTH* friends_only and my_bands_only to be true
# If so, then it's an OR condition. If both are false, you can get sessions with anyone.
# note, this is mostly the same as above but includes paging through the result and and scores.
# thus it needs the client_id...
def self.nindex(current_user, options = {})
client_id = options[:client_id]
participants = options[:participants]
genres = options[:genres]
keyword = options[:keyword]
friends_only = options[:friends_only].nil? ? false : options[:friends_only]
my_bands_only = options[:my_bands_only].nil? ? false : options[:my_bands_only]
as_musician = options[:as_musician].nil? ? true : options[:as_musician]
offset = options[:offset]
limit = options[:limit]
connection = Connection.where(client_id: client_id).first!
locidispid = connection.locidispid
query = ActiveMusicSession
.select("active_music_sessions.*, max(coalesce(current_scores.score, 1000)) as max_score") # 1000 is higher than the allowed max of 999
.joins(
%Q{
INNER JOIN
music_sessions
ON
active_music_sessions.id = music_sessions.id
}
)
.joins(
%Q{
INNER JOIN
connections
ON
active_music_sessions.id = connections.music_session_id
}
)
.joins(
%Q{
LEFT OUTER JOIN
current_scores
ON
current_scores.alocidispid = connections.locidispid
AND
current_scores.blocidispid = #{locidispid}
}
)
.joins(
%Q{
LEFT OUTER JOIN
friendships
ON
connections.user_id = friendships.user_id
AND
friendships.friend_id = '#{current_user.id}'
}
)
.joins(
%Q{
LEFT OUTER JOIN
invitations
ON
invitations.music_session_id = active_music_sessions.id
AND
invitations.receiver_id = '#{current_user.id}'
}
)
.group(
%Q{
active_music_sessions.id
}
)
.order(
%Q{
SUM(CASE WHEN invitations.id IS NULL THEN 0 ELSE 1 END) DESC,
SUM(CASE WHEN friendships.user_id IS NULL THEN 0 ELSE 1 END) DESC,
active_music_sessions.created_at DESC
}
)
if (offset)
query = query.offset(offset)
end
if (limit)
query = query.limit(limit)
end
if as_musician
query = query.where(
%Q{
musician_access = true
OR
music_sessions.user_id = '#{current_user.id}'
OR
invitations.id IS NOT NULL
}
)
else
# if you are trying to join the session as a fan/listener,
# we have to have a mount, fan_access has to be true, and we have to allow for the reload of icecast to have taken effect
query = query.joins('INNER JOIN icecast_mounts ON icecast_mounts.music_session_id = active_music_sessions.id INNER JOIN icecast_servers ON icecast_mounts.icecast_server_id = icecast_servers.id')
query = query.where('music_sessions.fan_access = true')
query = query.where("(active_music_sessions.created_at < icecast_servers.config_updated_at)")
end
query = query.where("music_sessions.description like '%#{keyword}%'") unless keyword.nil?
query = query.where("connections.user_id" => participants.split(',')) unless participants.nil?
query = query.where("music_sessions.genre_id in (?)", genres) unless genres.nil?
if my_bands_only
query = query.joins(
%Q{
LEFT OUTER JOIN
bands_musicians
ON
bands_musicians.user_id = '#{current_user.id}'
}
)
end
if my_bands_only || friends_only
query = query.where(
%Q{
#{friends_only ? "friendships.user_id IS NOT NULL" : "false"}
OR
#{my_bands_only ? "bands_musicians.band_id = music_sessions.band_id" : "false"}
}
)
end
return query
end
# Verifies that the specified user can join this music session
def can_join? user, as_musician
if as_musician
if !user.musician
return false # "a fan can not join a music session as a musician"
raise PermissionError, "a fan can not join a music session as a musician"
end
if self.musician_access
if self.approval_required
return self.invited_musicians.exists?(user)
else
return true
end
else
# the creator can always join, and the invited users can join
return self.creator == user || self.invited_musicians.exists?(user)
end
else
# it's a fan, and the only way a fan can join is if fan_access is true
return self.fan_access
end
end
# Verifies that the specified user can see this music session
def can_see? user
if self.musician_access || self.fan_access
true
else
self.creator == user || self.invited_musicians.exists?(user)
end
end
# Verifies that the specified user can delete this music session
def can_delete? user
# the creator can delete
self.creator == user
end
def access? user
music_session.part_of_session? user
end
def most_recent_recording
recordings.where(:music_session_id => self.id).order('created_at desc').limit(1).first
end
# is this music session currently recording?
def is_recording?
recordings.where(:duration => nil).count > 0
end
def is_playing_recording?
!self.claimed_recording.nil?
end
def recording
recordings.where(:duration => nil).first
end
# stops any active recording
def stop_recording
current_recording = self.recording
current_recording.stop unless current_recording.nil?
end
def claimed_recording_start(owner, claimed_recording)
self.claimed_recording = claimed_recording
self.claimed_recording_initiator = owner
self.save
end
def claimed_recording_stop
self.claimed_recording = nil
self.claimed_recording_initiator = nil
self.save
end
def invitations
music_session.invitations
end
def invited_musicians
music_session.invited_musicians
end
def join_requests
music_session.join_requests
end
def fan_invitations
music_session.fan_invitations
end
def to_s
description
end
def musician_access
music_session.musician_access
end
def fan_access
music_session.fan_access
end
def description
music_session.description
end
def genre
music_session.genre
end
def fan_chat
music_session.fan_chat
end
def band
music_session.band
end
def approval_required
music_session.approval_required
end
def tick_track_changes
self.track_changes_counter += 1
self.save!(:validate => false)
end
def connected_participant_count
Connection.where(:music_session_id => self.id,
:aasm_state => Connection::CONNECT_STATE.to_s,
:as_musician => true)
.count
end
def started_session
raise "active_music_sessions.id must be set by caller" unless self.id
# associate this active_music_session with the music_session formally
session = MusicSession.find(self.id)
session.active_music_session = self
session.save!
GoogleAnalyticsEvent.track_session_duration(self)
GoogleAnalyticsEvent.track_band_real_session(self)
end
def self.sync(session_history)
music_session = MusicSession.find_by_id(session_history.id)
if music_session.nil?
music_session = MusicSession.new
music_session.id = session_history.id
end
music_session.user_id = session_history.creator.id
music_session.band_id = session_history.band.id unless session_history.band.nil?
session_history.save!
end
end
end

View File

@ -44,8 +44,7 @@ module JamRuby
has_many :invitations, :inverse_of => :band, :class_name => "JamRuby::BandInvitation", :foreign_key => "band_id"
# music_sessions
has_many :music_sessions, :class_name => "JamRuby::MusicSession", :foreign_key => "band_id"
has_many :music_session_history, :class_name => "JamRuby::MusicSessionHistory", :foreign_key => "band_id", :inverse_of => :band
has_many :music_sessions, :class_name => "JamRuby::MusicSession", foreign_key: :band_id, :inverse_of => :band
# events
has_many :event_sessions, :class_name => "JamRuby::EventSession"
@ -54,19 +53,19 @@ module JamRuby
acts_as_mappable
def liker_count
return self.likers.size
self.likers.size
end
def follower_count
return self.followers.size
self.followers.size
end
def recording_count
return self.recordings.size
self.recordings.size
end
def session_count
return self.music_sessions.size
self.music_sessions.size
end
def recent_history
@ -74,7 +73,7 @@ module JamRuby
.order('created_at DESC')
.limit(10)
msh = MusicSessionHistory.where(:band_id => self.id)
msh = MusicSession.where(:band_id => self.id)
.order('created_at DESC')
.limit(10)

View File

@ -11,6 +11,7 @@ module JamRuby
belongs_to :user
belongs_to :music_session
validates :user, presence: true
validates :message, length: {minimum: 1, maximum: 255}, no_profanity: true
class << self

View File

@ -7,7 +7,7 @@ module JamRuby
belongs_to :user, :class_name => "JamRuby::User", :inverse_of => :claimed_recordings
belongs_to :genre, :class_name => "JamRuby::Genre"
has_many :recorded_tracks, :through => :recording, :class_name => "JamRuby::RecordedTrack"
has_many :playing_sessions, :class_name => "JamRuby::MusicSession"
has_many :playing_sessions, :class_name => "JamRuby::ActiveMusicSession"
has_many :likes, :class_name => "JamRuby::RecordingLiker", :foreign_key => "claimed_recording_id"
has_many :plays, :class_name => "JamRuby::PlayablePlay", :foreign_key => "claimed_recording_id", :dependent => :destroy
has_one :share_token, :class_name => "JamRuby::ShareToken", :inverse_of => :shareable, :foreign_key => 'shareable_id'

View File

@ -3,18 +3,20 @@ require 'aasm'
module JamRuby
class Connection < ActiveRecord::Base
# client_types
TYPE_CLIENT = 'client'
TYPE_BROWSER = 'browser'
attr_accessor :joining_session
self.primary_key = 'id'
belongs_to :user, :class_name => "JamRuby::User"
belongs_to :music_session, :class_name => "JamRuby::MusicSession"
belongs_to :music_session, :class_name => "JamRuby::ActiveMusicSession", foreign_key: :music_session_id
has_many :tracks, :class_name => "JamRuby::Track", :inverse_of => :connection, :foreign_key => 'connection_id', :dependent => :delete_all
validates :as_musician, :inclusion => {:in => [true, false]}
validates :client_type, :inclusion => {:in => ['client', 'browser']}
validates :client_type, :inclusion => {:in => [TYPE_CLIENT, TYPE_BROWSER]}
validate :can_join_music_session, :if => :joining_session?
after_save :require_at_least_one_track_when_in_session, :if => :joining_session?
after_create :did_create

View File

@ -0,0 +1,89 @@
module JamRuby
class Diagnostic < ActiveRecord::Base
# occurs when the client does not see a heartbeat from the server in a while
NO_HEARTBEAT_ACK = 'NO_HEARTBEAT_ACK'
# occurs when the client sees the socket go down
WEBSOCKET_CLOSED_REMOTELY = 'WEBSOCKET_CLOSED_REMOTELY'
# occurs when the client makes the socket go down
WEBSOCKET_CLOSED_LOCALLY = 'WEBSOCKET_CLOSED_LOCALLY'
# occurs when the websocket-gateway has finally given up entirely on a connection with no heartbeats seen in a while
EXPIRED_STALE_CONNECTION = 'EXPIRED_STALE_CONNECTION'
# occurs when the websocket-gateway is trying to handle a heartbeat, but can't find any state for the user.
# this implies a coding error
MISSING_CLIENT_STATE = 'MISSING_CLIENT_STATE'
# websocket gateway did not recognize message. indicates out-of-date websocket-gateway
UNKNOWN_MESSAGE_TYPE = 'UNKNOWN_MESSAGE_TYPE'
# empty route_to in message; which is invalid. indicates programming error
MISSING_ROUTE_TO = 'MISSING_ROUTE_TO'
# websocket gateway got a client with the same client_id as an already-connected client
DUPLICATE_CLIENT = 'DUPLICATE_CLIENT'
DIAGNOSTIC_TYPES = [NO_HEARTBEAT_ACK, WEBSOCKET_CLOSED_REMOTELY, EXPIRED_STALE_CONNECTION,
MISSING_CLIENT_STATE, UNKNOWN_MESSAGE_TYPE, MISSING_ROUTE_TO,
DUPLICATE_CLIENT, WEBSOCKET_CLOSED_LOCALLY]
# creator types #
CLIENT = 'client'
WEBSOCKET_GATEWAY = 'websocket-gateway'
CREATORS = [CLIENT, WEBSOCKET_GATEWAY]
self.primary_key = 'id'
self.inheritance_column = 'nothing'
belongs_to :user, :inverse_of => :diagnostics, :class_name => "JamRuby::User", :foreign_key => "user_id"
validates :user, :presence => true
validates :type, :inclusion => {:in => DIAGNOSTIC_TYPES}
validates :creator, :inclusion => {:in => CREATORS}
validates :data, length: {maximum: 100000}
def self.expired_stale_connection(user, context)
Diagnostic.save(EXPIRED_STALE_CONNECTION, user, WEBSOCKET_GATEWAY, context.to_json) if user
end
def self.missing_client_state(user, context)
Diagnostic.save(MISSING_CLIENT_STATE, user, WEBSOCKET_GATEWAY, context.to_json) if user
end
def self.missing_connection(user, context)
Diagnostic.save(MISSING_CONNECTION, user, WEBSOCKET_GATEWAY, context.to_json) if user
end
def self.duplicate_client(user, context)
Diagnostic.save(DUPLICATE_CLIENT, user, WEBSOCKET_GATEWAY, context.to_json) if user
end
def self.unknown_message_type(user, client_msg)
Diagnostic.save(UNKNOWN_MESSAGE_TYPE, user, WEBSOCKET_GATEWAY, client_msg.to_json) if user
end
def self.missing_route_to(user, client_msg)
Diagnostic.save(MISSING_ROUTE_TO, user, WEBSOCKET_GATEWAY, client_msg.to_json) if user
end
def self.save(type, user, creator, data)
diagnostic = Diagnostic.new
if user.class == String
diagnostic.user_id = user
else
diagnostic.user = user
end
diagnostic.data = data
diagnostic.type = type
diagnostic.creator = creator
diagnostic.save
end
end
end

View File

@ -13,7 +13,7 @@ module JamRuby
VAR_LAST_NAME = '@LASTNAME'
DEFAULT_SENDER = "noreply@jamkazam.com"
BATCH_SIZE = 1000
BATCH_SIZE = 5
BODY_TEMPLATE =<<FOO
Hello #{VAR_FIRST_NAME},

View File

@ -38,7 +38,7 @@ class JamRuby::EventSession < ActiveRecord::Base
# ideally this is based on some proper association with the event, not such a slushy time grab
def sessions
if ready_display
query = MusicSessionHistory.where(fan_access: true).where(created_at: (self.starts_at - 12.hours)..(self.ends_at + 12.hours))
query = MusicSession.where(fan_access: true).where(created_at: (self.starts_at - 12.hours)..(self.ends_at + 12.hours))
if self.user_id
query = query.where(user_id: self.user_id)
elsif self.band_id

View File

@ -7,7 +7,7 @@ module JamRuby
self.primary_key = 'id'
belongs_to :sender, :inverse_of => :sent_fan_invitations, :class_name => "JamRuby::User", :foreign_key => "sender_id"
belongs_to :receiver, :inverse_of => :received_fan_invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id"
belongs_to :music_session, :inverse_of => :fan_invitations, :class_name => "JamRuby::MusicSession"
belongs_to :music_session, :inverse_of => :fan_invitations, :class_name => "JamRuby::MusicSession", :foreign_key => "music_session_id"
validates :sender, :presence => true
validates :receiver, :presence => true
@ -18,7 +18,7 @@ module JamRuby
private
def require_sender_in_music_session
unless music_session.users.exists? sender
unless music_session.part_of_session? sender
errors.add(:music_session, MEMBERSHIP_REQUIRED_OF_MUSIC_SESSION)
end
end

View File

@ -3,12 +3,12 @@ module JamRuby
class Feed < ActiveRecord::Base
belongs_to :recording, class_name: "JamRuby::Recording", inverse_of: :feed, foreign_key: 'recording_id'
belongs_to :music_session_history, class_name: "JamRuby::MusicSessionHistory", inverse_of: :feed, foreign_key: 'music_session_id'
belongs_to :music_session, class_name: "JamRuby::MusicSession", inverse_of: :feed, foreign_key: 'music_session_id'
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
SORT_TYPES = ['date', 'plays', 'likes']
TIME_RANGES = { "today" => 1 , "week" => 7, "month" => 30, "all" => 0}
TYPE_FILTERS = ['music_session_history', 'recording', 'all']
TYPE_FILTERS = ['music_session', 'recording', 'all']
def self.index(user, params = {})
limit = params[:limit]
@ -39,9 +39,9 @@ module JamRuby
target_user = params[:user]
target_band = params[:band]
#query = Feed.includes([:recording]).includes([:music_session_history]).limit(limit)
#query = Feed.includes([:recording]).includes([:music_session]).limit(limit)
query = Feed.joins("LEFT OUTER JOIN recordings ON recordings.id = feeds.recording_id")
.joins("LEFT OUTER JOIN music_sessions_history ON music_sessions_history.id = feeds.music_session_id")
.joins("LEFT OUTER JOIN music_sessions ON music_sessions.id = feeds.music_session_id")
.limit(limit)
# handle sort
@ -50,10 +50,10 @@ module JamRuby
query = query.order('feeds.id DESC')
elsif sort == 'plays'
query = query.offset(start)
query = query.order("COALESCE(recordings.play_count, music_sessions_history.play_count) DESC ")
query = query.order("COALESCE(recordings.play_count, music_sessions.play_count) DESC ")
elsif sort == 'likes'
query = query.offset(start)
query = query.order("COALESCE(recordings.like_count, music_sessions_history.like_count) DESC ")
query = query.order("COALESCE(recordings.like_count, music_sessions.like_count) DESC ")
else
raise "sort not implemented: #{sort}"
end
@ -65,7 +65,7 @@ module JamRuby
end
# handle type filters
if type_filter == 'music_session_history'
if type_filter == 'music_session'
query = query.where('feeds.music_session_id is not NULL')
elsif type_filter == 'recording'
query = query.where('feeds.recording_id is not NULL')
@ -76,48 +76,48 @@ module JamRuby
if target_user != user.id
require_public_recordings = "claimed_recordings.is_public = TRUE AND"
require_public_sessions = "music_sessions_history.fan_access = TRUE AND"
require_public_sessions = "music_sessions.fan_access = TRUE AND"
end
query = query.joins("LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND #{require_public_recordings} (claimed_recordings.user_id = '#{target_user}' OR (recordings.band_id IN (SELECT band_id FROM bands_musicians where user_id='#{target_user}')))")
query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions_history.id = music_sessions_user_history.music_session_id AND #{require_public_sessions} music_sessions_user_history.user_id = '#{target_user}'")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id")
query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions.id = music_sessions_user_history.music_session_id AND #{require_public_sessions} music_sessions_user_history.user_id = '#{target_user}'")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions.id")
if sort == 'plays'
query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)")
query = query.group("COALESCE(recordings.play_count, music_sessions.play_count)")
elsif sort == 'likes'
query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)")
query = query.group("COALESCE(recordings.like_count, music_sessions.like_count)")
end
query = query.where('recordings.id is NULL OR claimed_recordings.id IS NOT NULL')
query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL')
query = query.where('music_sessions.id is NULL OR music_sessions_user_history.id IS NOT NULL')
elsif target_band
unless Band.find(target_band).users.include?(user)
require_public_recordings = "claimed_recordings.is_public = TRUE AND"
require_public_sessions = "music_sessions_history.fan_access = TRUE AND"
require_public_sessions = "music_sessions.fan_access = TRUE AND"
end
query = query.joins("LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND #{require_public_recordings} recordings.band_id = '#{target_band}'")
query = query.where("music_sessions_history IS NULL OR #{require_public_sessions} music_sessions_history.band_id = '#{target_band}'")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id")
query = query.where("music_sessions IS NULL OR #{require_public_sessions} music_sessions.band_id = '#{target_band}'")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions.id")
if sort == 'plays'
query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)")
query = query.group("COALESCE(recordings.play_count, music_sessions.play_count)")
elsif sort == 'likes'
query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)")
query = query.group("COALESCE(recordings.like_count, music_sessions.like_count)")
end
query = query.where('recordings.id is NULL OR claimed_recordings.id IS NOT NULL')
#query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL')
#query = query.where('music_sessions.id is NULL OR music_sessions_user_history.id IS NOT NULL')
else
query = query.joins('LEFT OUTER JOIN claimed_recordings ON recordings.id = claimed_recordings.recording_id AND claimed_recordings.is_public = TRUE')
query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions_history.id = music_sessions_user_history.music_session_id AND music_sessions_history.fan_access = TRUE")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions_history.id")
query = query.joins("LEFT OUTER JOIN music_sessions_user_history ON music_sessions.id = music_sessions_user_history.music_session_id AND music_sessions.fan_access = TRUE")
query = query.group("feeds.id, feeds.recording_id, feeds.music_session_id, feeds.created_at, feeds.updated_at, recordings.id, music_sessions.id")
if sort == 'plays'
query = query.group("COALESCE(recordings.play_count, music_sessions_history.play_count)")
query = query.group("COALESCE(recordings.play_count, music_sessions.play_count)")
elsif sort == 'likes'
query = query.group("COALESCE(recordings.like_count, music_sessions_history.like_count)")
query = query.group("COALESCE(recordings.like_count, music_sessions.like_count)")
end
query = query.where('recordings.id is NULL OR claimed_recordings.is_public = TRUE')
query = query.where('music_sessions_history.id is NULL OR music_sessions_user_history.id IS NOT NULL')
query = query.where('music_sessions.id is NULL OR music_sessions_user_history.id IS NOT NULL')
end

View File

@ -34,7 +34,7 @@ module JamRuby
ActiveRecord::Base.transaction do
friend_request = FriendRequest.find(id)
friend_request.status = status
friend_request.updated_at = Time.now.getutc
friend_request.updated_at = Time.now
friend_request.save
# create both records for this friendship

View File

@ -7,11 +7,13 @@ module JamRuby
has_many :band_genres, class_name: "JamRuby::BandGenre"
has_many :bands, class_name: "JamRuby::Band", :through => :band_genres
# music sessions
has_many :music_sessions, :class_name => "JamRuby::MusicSession"
# genres
has_and_belongs_to_many :recordings, :class_name => "JamRuby::Recording", :join_table => "recordings_genres"
# music sessions
has_and_belongs_to_many :music_sessions, :class_name => "JamRuby::MusicSession", :join_table => "genres_music_sessions"
def to_s
description

View File

@ -11,7 +11,7 @@ module JamRuby
:sourced_needs_changing_at, as: :admin
belongs_to :authentication, class_name: "JamRuby::IcecastUserAuthentication", inverse_of: :mount, :foreign_key => 'authentication_id'
belongs_to :music_session, class_name: "JamRuby::MusicSession", inverse_of: :mount, foreign_key: 'music_session_id'
belongs_to :music_session, class_name: "JamRuby::ActiveMusicSession", inverse_of: :mount, foreign_key: 'music_session_id'
belongs_to :server, class_name: "JamRuby::IcecastServer", inverse_of: :mounts, foreign_key: 'icecast_server_id'
belongs_to :mount_template, class_name: "JamRuby::IcecastMountTemplate", inverse_of: :mounts, foreign_key: 'icecast_mount_template_id'
@ -76,7 +76,7 @@ module JamRuby
end
# creates a templated
def self.build_session_mount(music_session, icecast_server)
def self.build_session_mount(music_session, active_music_session, icecast_server)
# only public sessions get mounts currently
return nil unless music_session.fan_access
@ -84,7 +84,7 @@ module JamRuby
mount = nil
if icecast_server && icecast_server.mount_template_id
# we have a server with an associated mount_template; we can create a mount automatically
mount = icecast_server.mount_template.build_session_mount(music_session)
mount = icecast_server.mount_template.build_session_mount(music_session, active_music_session)
mount.server = icecast_server
end
mount

View File

@ -44,7 +44,7 @@ module JamRuby
end
# pick a server that's in the same group as the user that is under the least load
def build_session_mount(music_session)
def build_session_mount(music_session, active_music_session)
mount = IcecastMount.new
mount.authentication = authentication
mount.mount_template = self
@ -55,7 +55,7 @@ module JamRuby
mount.stream_name = "JamKazam music session created by #{music_session.creator.name}"
mount.stream_description = music_session.description
mount.stream_url = "http://www.jamkazam.com" ## TODO/XXX, the jamkazam url should be the page hosting the widget
mount.genre = music_session.genres.map {|genre| genre.description}.join(',')
mount.genre = music_session.genre.description
mount
end
end

View File

@ -41,7 +41,7 @@ module JamRuby
has_many :recorded_tracks, :class_name => "JamRuby::RecordedTrack", :inverse_of => :instrument
# music sessions
has_and_belongs_to_many :music_sessions, :class_name => "JamRuby::MusicSession", :join_table => "genres_music_sessions"
has_and_belongs_to_many :music_sessions, :class_name => "JamRuby::ActiveMusicSession", :join_table => "genres_music_sessions"
def self.standard_list
return Instrument.where('instruments.popularity > 0').order('instruments.popularity DESC, instruments.description ASC')

View File

@ -8,7 +8,7 @@ module JamRuby
self.primary_key = 'id'
belongs_to :sender, :inverse_of => :sent_invitations, :class_name => "JamRuby::User", :foreign_key => "sender_id"
belongs_to :receiver, :inverse_of => :received_invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id"
belongs_to :music_session, :inverse_of => :invitations, :class_name => "JamRuby::MusicSession"
belongs_to :music_session, :inverse_of => :invitations, :class_name => "JamRuby::MusicSession", :foreign_key => "music_session_id"
belongs_to :join_request, :inverse_of => :invitations, :class_name => "JamRuby::JoinRequest"
validates :sender, :presence => true
@ -20,7 +20,7 @@ module JamRuby
private
def require_sender_in_music_session
unless music_session.users.exists? sender
unless music_session.part_of_session? sender
errors.add(:music_session, MEMBERSHIP_REQUIRED_OF_MUSIC_SESSION)
end
end

View File

@ -6,7 +6,7 @@ module JamRuby
self.primary_key = 'id'
belongs_to :user, :class_name => "JamRuby::User"
belongs_to :music_session, :class_name => "JamRuby::MusicSession"
belongs_to :music_session, :class_name => "JamRuby::MusicSession", :foreign_key => "music_session_id"
has_many :invitations, :inverse_of => :join_request, :class_name => "JamRuby::Invitation"
validates :user, :presence => true

View File

@ -1,39 +1,32 @@
module JamRuby
class MusicSession < ActiveRecord::Base
attr_accessor :legal_terms
self.table_name = "music_sessions"
self.primary_key = 'id'
attr_accessor :legal_terms, :skip_genre_validation, :max_score
attr_accessible :creator, :description, :musician_access, :approval_required, :fan_chat, :fan_access, :genres
belongs_to :creator,:class_name => 'JamRuby::User', :foreign_key => :user_id, :inverse_of => :music_session_histories
belongs_to :creator, :inverse_of => :music_sessions, :class_name => "JamRuby::User", :foreign_key => "user_id"
belongs_to :claimed_recording, :class_name => "JamRuby::ClaimedRecording", :foreign_key => "claimed_recording_id", :inverse_of => :playing_sessions
belongs_to :claimed_recording_initiator, :class_name => "JamRuby::User", :inverse_of => :playing_claimed_recordings, :foreign_key => "claimed_recording_initiator_id"
belongs_to :band, :class_name => 'JamRuby::Band', :foreign_key => :band_id, :inverse_of => :music_sessions
has_one :music_session_history, :class_name => "JamRuby::MusicSessionHistory"
has_one :mount, :class_name => "JamRuby::IcecastMount", :inverse_of => :music_session, :foreign_key => 'music_session_id'
belongs_to :active_music_session, :class_name => 'JamRuby::ActiveMusicSession', foreign_key: :music_session_id
has_many :connections, :class_name => "JamRuby::Connection"
has_many :users, :through => :connections, :class_name => "JamRuby::User"
has_and_belongs_to_many :genres, :class_name => "::JamRuby::Genre", :join_table => "genres_music_sessions"
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"
has_many :music_session_user_histories, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id", :dependent => :delete_all
has_many :comments, :class_name => "JamRuby::MusicSessionComment", :foreign_key => "music_session_id"
has_many :likes, :class_name => "JamRuby::MusicSessionLiker", :foreign_key => "session_id"
has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy
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
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 :invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::Invitation", :foreign_key => "music_session_id"
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"
has_many :fan_invitations, :foreign_key => "music_session_id", :inverse_of => :music_session, :class_name => "JamRuby::FanInvitation", :foreign_key => "music_session_id"
has_many :invited_fans, :through => :fan_invitations, :class_name => "JamRuby::User", :foreign_key => "receiver_id", :source => :receiver
has_many :recordings, :class_name => "JamRuby::Recording", :inverse_of => :music_session
has_many :chats, :class_name => "JamRuby::ChatMessages", :foreign_key => "session_id"
belongs_to :band, :inverse_of => :music_sessions, :class_name => "JamRuby::Band", :foreign_key => "band_id"
after_create :started_session
validate :require_at_least_one_genre, :limit_max_genres
after_save :sync_music_session_history
after_destroy do |obj|
JamRuby::MusicSessionHistory.removed_music_session(obj.id)
end
validates :genre, :presence => true
validates :description, :presence => true, :no_profanity => true
validates :fan_chat, :inclusion => {:in => [true, false]}
validates :fan_access, :inclusion => {:in => [true, false]}
@ -42,400 +35,184 @@ module JamRuby
validates :legal_terms, :inclusion => {:in => [true]}, :on => :create
validates :creator, :presence => true
validate :creator_is_musician
validate :no_new_playback_while_playing
#default_scope :select => "*, 0 as score"
before_create :generate_share_token
before_create :add_to_feed
def attributes
super.merge('max_score' => self.max_score)
SHARE_TOKEN_LENGTH = 8
SEPARATOR = '|'
def add_to_feed
feed = Feed.new
feed.music_session = self
end
def max_score
nil unless has_attribute?(:max_score)
read_attribute(:max_score).to_i
def comment_count
self.comments.size
end
before_create :create_uuid
def create_uuid
#self.id = SecureRandom.uuid
end
def before_destroy
self.mount.destroy if self.mount
end
def creator_is_musician
unless creator.musician?
errors.add(:creator, ValidationMessages::MUST_BE_A_MUSICIAN)
end
end
def no_new_playback_while_playing
# if we previous had a claimed recording and are trying to set one
# and if also the previous initiator is different than the current one... it's a no go
if !claimed_recording_id_was.nil? && !claimed_recording_id.nil? &&
claimed_recording_initiator_id_was != claimed_recording_initiator_id
errors.add(:claimed_recording, ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS)
end
end
# returns an array of client_id's that are in this session
# if as_musician is nil, all connections in the session ,regardless if it's a musician or not or not
# you can also exclude a client_id from the returned set by setting exclude_client_id
def get_connection_ids(options = {})
as_musician = options[:as_musician]
exclude_client_id = options[:exclude_client_id]
where = { :music_session_id => self.id }
where[:as_musician] = as_musician unless as_musician.nil?
exclude = "client_id != '#{exclude_client_id}'"unless exclude_client_id.nil?
Connection.select(:client_id).where(where).where(exclude).map(&:client_id)
end
# This is a little confusing. You can specify *BOTH* friends_only and my_bands_only to be true
# If so, then it's an OR condition. If both are false, you can get sessions with anyone.
def self.index(current_user, options = {})
participants = options[:participants]
genres = options[:genres]
keyword = options[:keyword]
friends_only = options[:friends_only].nil? ? false : options[:friends_only]
my_bands_only = options[:my_bands_only].nil? ? false : options[:my_bands_only]
as_musician = options[:as_musician].nil? ? true : options[:as_musician]
query = MusicSession
.joins(
%Q{
INNER JOIN
connections
ON
music_sessions.id = connections.music_session_id
}
)
.joins(
%Q{
LEFT OUTER JOIN
friendships
ON
connections.user_id = friendships.user_id
AND
friendships.friend_id = '#{current_user.id}'
}
)
.joins(
%Q{
LEFT OUTER JOIN
invitations
ON
invitations.music_session_id = music_sessions.id
AND
invitations.receiver_id = '#{current_user.id}'
}
)
.group(
%Q{
music_sessions.id
}
)
.order(
%Q{
SUM(CASE WHEN invitations.id IS NULL THEN 0 ELSE 1 END) DESC,
SUM(CASE WHEN friendships.user_id IS NULL THEN 0 ELSE 1 END) DESC,
music_sessions.created_at DESC
}
)
if as_musician
query = query.where(
%Q{
musician_access = true
OR
invitations.id IS NOT NULL
}
)
else
# if you are trying to join the session as a fan/listener,
# we have to have a mount, fan_access has to be true, and we have to allow for the reload of icecast to have taken effect
query = query.joins('INNER JOIN icecast_mounts ON icecast_mounts.music_session_id = music_sessions.id INNER JOIN icecast_servers ON icecast_mounts.icecast_server_id = icecast_servers.id')
query = query.where(:fan_access => true)
query = query.where("(music_sessions.created_at < icecast_servers.config_updated_at)")
end
query = query.where("music_sessions.description like '%#{keyword}%'") unless keyword.nil?
query = query.where("connections.user_id" => participants.split(',')) unless participants.nil?
query = query.joins(:genres).where("genres.id" => genres.split(',')) unless genres.nil?
if my_bands_only
query = query.joins(
%Q{
LEFT OUTER JOIN
bands_musicians
ON
bands_musicians.user_id = '#{current_user.id}'
}
)
end
if my_bands_only || friends_only
query = query.where(
%Q{
#{friends_only ? "friendships.user_id IS NOT NULL" : "false"}
OR
#{my_bands_only ? "bands_musicians.band_id = music_sessions.band_id" : "false"}
}
)
end
return query
end
# This is a little confusing. You can specify *BOTH* friends_only and my_bands_only to be true
# If so, then it's an OR condition. If both are false, you can get sessions with anyone.
# note, this is mostly the same as above but includes paging through the result and and scores.
# thus it needs the client_id...
def self.nindex(current_user, options = {})
client_id = options[:client_id]
participants = options[:participants]
genres = options[:genres]
keyword = options[:keyword]
friends_only = options[:friends_only].nil? ? false : options[:friends_only]
my_bands_only = options[:my_bands_only].nil? ? false : options[:my_bands_only]
as_musician = options[:as_musician].nil? ? true : options[:as_musician]
offset = options[:offset]
limit = options[:limit]
connection = Connection.where(client_id: client_id).first!
locidispid = connection.locidispid
query = MusicSession
.select("music_sessions.*, max(coalesce(current_scores.score, 1000)) as max_score") # 1000 is higher than the allowed max of 999
.joins(
%Q{
INNER JOIN
connections
ON
music_sessions.id = connections.music_session_id
}
)
.joins(
%Q{
LEFT OUTER JOIN
current_scores
ON
current_scores.alocidispid = connections.locidispid
AND
current_scores.blocidispid = #{locidispid}
}
)
.joins(
%Q{
LEFT OUTER JOIN
friendships
ON
connections.user_id = friendships.user_id
AND
friendships.friend_id = '#{current_user.id}'
}
)
.joins(
%Q{
LEFT OUTER JOIN
invitations
ON
invitations.music_session_id = music_sessions.id
AND
invitations.receiver_id = '#{current_user.id}'
}
)
.group(
%Q{
music_sessions.id
}
)
.order(
%Q{
SUM(CASE WHEN invitations.id IS NULL THEN 0 ELSE 1 END) DESC,
SUM(CASE WHEN friendships.user_id IS NULL THEN 0 ELSE 1 END) DESC,
music_sessions.created_at DESC
}
)
if (offset)
query = query.offset(offset)
end
if (limit)
query = query.limit(limit)
end
if as_musician
query = query.where(
%Q{
musician_access = true
OR
music_sessions.user_id = '#{current_user.id}'
OR
invitations.id IS NOT NULL
}
)
else
# if you are trying to join the session as a fan/listener,
# we have to have a mount, fan_access has to be true, and we have to allow for the reload of icecast to have taken effect
query = query.joins('INNER JOIN icecast_mounts ON icecast_mounts.music_session_id = music_sessions.id INNER JOIN icecast_servers ON icecast_mounts.icecast_server_id = icecast_servers.id')
query = query.where(:fan_access => true)
query = query.where("(music_sessions.created_at < icecast_servers.config_updated_at)")
end
query = query.where("music_sessions.description like '%#{keyword}%'") unless keyword.nil?
query = query.where("connections.user_id" => participants.split(',')) unless participants.nil?
query = query.joins(:genres).where("genres.id" => genres.split(',')) unless genres.nil?
if my_bands_only
query = query.joins(
%Q{
LEFT OUTER JOIN
bands_musicians
ON
bands_musicians.user_id = '#{current_user.id}'
}
)
end
if my_bands_only || friends_only
query = query.where(
%Q{
#{friends_only ? "friendships.user_id IS NOT NULL" : "false"}
OR
#{my_bands_only ? "bands_musicians.band_id = music_sessions.band_id" : "false"}
}
)
end
return query
end
# Verifies that the specified user can join this music session
def can_join? user, as_musician
if as_musician
if !user.musician
return false # "a fan can not join a music session as a musician"
raise PermissionError, "a fan can not join a music session as a musician"
end
if self.musician_access
if self.approval_required
return self.invited_musicians.exists?(user)
else
return true
def grouped_tracks
tracks = []
self.music_session_user_histories.each do |msuh|
user = User.find(msuh.user_id)
t = Track.new
t.musician = user
t.instrument_ids = []
# this treats each track as a "user", which has 1 or more instruments in the session
unless msuh.instruments.blank?
instruments = msuh.instruments.split(SEPARATOR)
instruments.each do |instrument|
if !t.instrument_ids.include? instrument
t.instrument_ids << instrument
end
end
else
# the creator can always join, and the invited users can join
return self.creator == user || self.invited_musicians.exists?(user)
end
else
# it's a fan, and the only way a fan can join is if fan_access is true
return self.fan_access
tracks << t
end
tracks
end
def self.index(current_user, user_id, band_id = nil, genre = nil)
hide_private = false
if current_user.id != user_id
hide_private = false # TODO: change to true once public flag exists
end
query = MusicSession
.joins(
%Q{
LEFT OUTER JOIN
music_sessions_user_history
ON
music_sessions.id = music_sessions_user_history.music_session_id
}
)
.where(
%Q{
music_sessions.user_id = '#{user_id}'
}
)
#query = query.where("public = false") unless !hide_private
query = query.where("music_sessions.band_id = '#{band_id}") unless band_id.nil?
query = query.where("music_sessions.genres like '%#{genre}%'") unless genre.nil?
return query
end
def unique_users
User
.joins(:music_session_user_histories)
.group("users.id")
.order("users.id")
.where(%Q{ music_sessions_user_history.music_session_id = '#{id}'})
end
# returns one user history per user, with instruments all crammed together, and with total duration
def unique_user_histories
MusicSessionUserHistory
.joins(:user)
.select("STRING_AGG(instruments, '|') AS total_instruments,
SUM(date_part('epoch', COALESCE(music_sessions_user_history.session_removed_at, music_sessions_user_history.created_at) - music_sessions_user_history.created_at)) AS total_duration,
music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.group("music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.order("music_sessions_user_history.user_id")
.where(%Q{ music_sessions_user_history.music_session_id = '#{id}'})
end
def duration_minutes
end_time = self.session_removed_at || Time.now
(end_time - self.created_at) / 60.0
end
def music_session_user_histories
@msuh ||= JamRuby::MusicSessionUserHistory
.where(:music_session_id => self.id)
.order('created_at DESC')
end
def comments
@comments ||= JamRuby::MusicSessionComment
.where(:music_session_id => self.id)
.order('created_at DESC')
end
def likes
@likes ||= JamRuby::MusicSessionLiker
.where(:music_session_id => self.music_session_id)
end
# these are 'users that are a part of this session'
# which means are currently in the music_session, or, rsvp'ed, or creator
def part_of_session? user
# XXX check RSVP'ed
user == self.creator || (active_music_session ? active_music_session.users.exists?(user) : false)
end
def is_over?
active_music_session.nil?
end
def has_mount?
active_music_session && active_music_session.mount
end
def recordings
Recording.where(music_session_id: self.id)
end
def end_history
self.update_attribute(:session_removed_at, Time.now)
# ensure all user histories are closed
music_session_user_histories.each do |music_session_user_history|
music_session_user_history.end_history
# then update any users that need their user progress updated
if music_session_user_history.duration_minutes > 15 && music_session_user_history.max_concurrent_connections >= 3
music_session_user_history.user.update_progression_field(:first_real_music_session_at)
end
end
end
# Verifies that the specified user can see this music session
def can_see? user
if self.musician_access || self.fan_access
return true
else
return self.creator == user || self.invited_musicians.exists?(user)
end
def self.removed_music_session(session_id)
hist = self
.where(:id => session_id)
.limit(1)
.first
hist.end_history if hist
Notification.send_session_ended(session_id)
end
# Verifies that the specified user can delete this music session
def can_delete? user
# the creator can delete
return self.creator == user
end
def access? user
return self.users.exists? user
end
def most_recent_recording
recordings.where(:music_session_id => self.id).order('created_at desc').limit(1).first
end
# is this music session currently recording?
def is_recording?
recordings.where(:duration => nil).count > 0
end
def is_playing_recording?
!self.claimed_recording.nil?
end
def recording
recordings.where(:duration => nil).first
end
# stops any active recording
def stop_recording
current_recording = self.recording
current_recording.stop unless current_recording.nil?
end
def claimed_recording_start(owner, claimed_recording)
self.claimed_recording = claimed_recording
self.claimed_recording_initiator = owner
self.save
end
def claimed_recording_stop
self.claimed_recording = nil
self.claimed_recording_initiator = nil
self.save
end
def to_s
description
end
def tick_track_changes
self.track_changes_counter += 1
self.save!(:validate => false)
end
def connected_participant_count
Connection.where(:music_session_id => self.id,
:aasm_state => Connection::CONNECT_STATE.to_s,
:as_musician => true)
.count
end
def started_session
GoogleAnalyticsEvent.track_session_duration(self)
GoogleAnalyticsEvent.track_band_real_session(self)
def remove_non_alpha_num(token)
token.gsub(/[^0-9A-Za-z]/, '')
end
private
def require_at_least_one_genre
unless skip_genre_validation
if self.genres.length < Limits::MIN_GENRES_PER_SESSION
errors.add(:genres, ValidationMessages::SESSION_GENRE_MINIMUM_NOT_MET)
end
def generate_share_token
token = loop do
token = SecureRandom.urlsafe_base64(SHARE_TOKEN_LENGTH, false)
token = remove_non_alpha_num(token)
token.upcase!
break token unless ShareToken.exists?(token: token)
end
self.share_token = ShareToken.new
self.share_token.token = token
self.share_token.shareable_type = "session"
end
def creator_is_musician
unless creator && creator.musician?
errors.add(:creator, ValidationMessages::MUST_BE_A_MUSICIAN)
end
end
def limit_max_genres
unless skip_genre_validation
if self.genres.length > Limits::MAX_GENRES_PER_SESSION
errors.add(:genres, ValidationMessages::SESSION_GENRE_LIMIT_EXCEEDED)
end
end
end
def sync_music_session_history
MusicSessionHistory.save(self)
end
end
end

View File

@ -7,8 +7,8 @@ module JamRuby
default_scope order('created_at DESC')
belongs_to(:music_session_history,
:class_name => "JamRuby::MusicSessionHistory",
belongs_to(:music_session,
:class_name => "JamRuby::MusicSession",
:foreign_key => "music_session_id")
belongs_to(:user,

View File

@ -1,212 +0,0 @@
module JamRuby
class MusicSessionHistory < ActiveRecord::Base
self.table_name = "music_sessions_history"
self.primary_key = 'id'
belongs_to(:user,
:class_name => 'JamRuby::User',
:foreign_key => :user_id,
:inverse_of => :music_session_histories)
belongs_to(:band,
:class_name => 'JamRuby::Band',
:foreign_key => :band_id,
:inverse_of => :music_session_history)
belongs_to(:music_session,
:class_name => 'JamRuby::MusicSession',
:foreign_key => 'music_session_id')
has_many :music_session_user_histories, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id", :dependent => :delete_all
has_many :comments, :class_name => "JamRuby::MusicSessionComment", :foreign_key => "music_session_id"
has_many :likes, :class_name => "JamRuby::MusicSessionLiker", :foreign_key => "session_id"
has_many :plays, :class_name => "JamRuby::PlayablePlay", :as => :playable, :dependent => :destroy
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_history, :foreign_key => 'music_session_id', :dependent => :destroy
before_create :generate_share_token
before_create :add_to_feed
SHARE_TOKEN_LENGTH = 8
SEPARATOR = '|'
def add_to_feed
feed = Feed.new
feed.music_session_history = self
end
def comment_count
self.comments.size
end
def grouped_tracks
tracks = []
self.music_session_user_histories.each do |msuh|
user = User.find(msuh.user_id)
t = Track.new
t.musician = user
t.instrument_ids = []
# this treats each track as a "user", which has 1 or more instruments in the session
unless msuh.instruments.blank?
instruments = msuh.instruments.split(SEPARATOR)
instruments.each do |instrument|
if !t.instrument_ids.include? instrument
t.instrument_ids << instrument
end
end
end
tracks << t
end
tracks
end
def self.index(current_user, user_id, band_id = nil, genre = nil)
hide_private = false
if current_user.id != user_id
hide_private = false # TODO: change to true once public flag exists
end
query = MusicSessionHistory
.joins(
%Q{
LEFT OUTER JOIN
music_sessions_user_history
ON
music_sessions_history.music_session_id = music_sessions_user_history.music_session_id
}
)
.where(
%Q{
music_sessions_history.user_id = '#{user_id}'
}
)
#query = query.where("public = false") unless !hide_private
query = query.where("music_sessions_history.band_id = '#{band_id}") unless band_id.nil?
query = query.where("music_sessions_history.genres like '%#{genre}%'") unless genre.nil?
return query
end
def unique_users
User
.joins(:music_session_user_histories)
.group("users.id")
.order("users.id")
.where(%Q{ music_sessions_user_history.music_session_id = '#{music_session_id}'})
end
# returns one user history per user, with instruments all crammed together, and with total duration
def unique_user_histories
MusicSessionUserHistory
.joins(:user)
.select("STRING_AGG(instruments, '|') AS total_instruments,
SUM(date_part('epoch', COALESCE(music_sessions_user_history.session_removed_at, music_sessions_user_history.created_at) - music_sessions_user_history.created_at)) AS total_duration,
music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.group("music_sessions_user_history.user_id, music_sessions_user_history.music_session_id, users.first_name, users.last_name, users.photo_url")
.order("music_sessions_user_history.user_id")
.where(%Q{ music_sessions_user_history.music_session_id = '#{music_session_id}'})
end
def duration_minutes
end_time = self.session_removed_at || Time.now
(end_time - self.created_at) / 60.0
end
def music_session_user_histories
@msuh ||= JamRuby::MusicSessionUserHistory
.where(:music_session_id => self.music_session_id)
.order('created_at DESC')
end
def comments
@comments ||= JamRuby::MusicSessionComment
.where(:music_session_id => self.music_session_id)
.order('created_at DESC')
end
def likes
@likes ||= JamRuby::MusicSessionLiker
.where(:music_session_id => self.music_session_id)
end
def self.save(music_session)
session_history = MusicSessionHistory.find_by_music_session_id(music_session.id)
if session_history.nil?
session_history = MusicSessionHistory.new
end
session_history.music_session_id = music_session.id
session_history.description = music_session.description unless music_session.description.nil?
session_history.user_id = music_session.creator.id
session_history.band_id = music_session.band.id unless music_session.band.nil?
session_history.genres = music_session.genres.map { |g| g.id }.join SEPARATOR if music_session.genres.count > 0
session_history.fan_access = music_session.fan_access
session_history.save!
end
def is_over?
music_session.nil? || !session_removed_at.nil?
end
def has_mount?
music_session && music_session.mount
end
def recordings
Recording.where(music_session_id: self.id)
end
def end_history
self.update_attribute(:session_removed_at, Time.now)
# ensure all user histories are closed
music_session_user_histories.each do |music_session_user_history|
music_session_user_history.end_history
# then update any users that need their user progress updated
if music_session_user_history.duration_minutes > 15 && music_session_user_history.max_concurrent_connections >= 3
music_session_user_history.user.update_progression_field(:first_real_music_session_at)
end
end
end
def self.removed_music_session(session_id)
hist = self
.where(:music_session_id => session_id)
.limit(1)
.first
hist.end_history if hist
Notification.send_session_ended(session_id)
end
def remove_non_alpha_num(token)
token.gsub(/[^0-9A-Za-z]/, '')
end
private
def generate_share_token
self.id = music_session.id # unify music_session.id and music_session_history.id
token = loop do
token = SecureRandom.urlsafe_base64(SHARE_TOKEN_LENGTH, false)
token = remove_non_alpha_num(token)
token.upcase!
break token unless ShareToken.exists?(token: token)
end
self.share_token = ShareToken.new
self.share_token.token = token
self.share_token.shareable_type = "session"
end
end
end

View File

@ -5,7 +5,7 @@ module JamRuby
self.primary_key = 'id'
belongs_to :music_session_history, class_name:"JamRuby::MusicSessionHistory", foreign_key: "music_session_id", :counter_cache => :like_count
belongs_to :music_session, class_name:"JamRuby::MusicSession", foreign_key: "music_session_id", :counter_cache => :like_count
belongs_to :user, class_name: "JamRuby::User", foreign_key: "liker_id"

View File

@ -7,13 +7,13 @@ module JamRuby
attr_accessible :uri
belongs_to(:music_session_history,
:class_name => "JamRuby::MusicSessionHistory",
belongs_to(:music_session,
:class_name => "JamRuby::MusicSession",
:foreign_key => :music_session_id)
# mount_uploader :uri, PerfDataUploader
validates :music_session_history, :presence => true
validates :music_session, :presence => true
validates :client_id, :presence => true
validates :uri, :presence => true

View File

@ -6,21 +6,27 @@ module JamRuby
self.primary_key = 'id'
attr_accessible :max_concurrent_connections, :session_removed_at, :rating
validates_inclusion_of :rating, :in => -1..1, :allow_nil => true
belongs_to(:user,
:class_name => "JamRuby::User",
:foreign_key => "user_id",
:inverse_of => :music_session_user_histories)
belongs_to(:music_session_history,
:class_name => "MusicSessionHistory",
belongs_to(:music_session,
:class_name => "MusicSession",
:foreign_key => "music_session_id")
validates_inclusion_of :rating, :in => 0..2, :allow_nil => true
after_save :track_user_progression
def self.latest_history(client_id)
self.where(:client_id => client_id)
.order('created_at DESC')
.limit(1)
.includes(:user)
.first
end
def music_session_history
@msh ||= JamRuby::MusicSessionHistory.find_by_music_session_id(self.music_session_id)
def music_session
@msh ||= JamRuby::MusicSession.find_by_music_session_id(self.music_session_id)
end
def perf_data
@ -104,10 +110,23 @@ module JamRuby
self.perf_data.try(:uri)
end
def track_user_progression
if self.rating == 0
user.update_progression_field(:first_good_music_session_at)
end
def add_rating(rval, comment='')
rval = rval.to_i
self.rating = rval if 0 != rval
self.rating_comment = comment
end
MIN_SESSION_DURATION_RATING = 60
def should_rate_session?
(2 <= music_session.unique_users.all.count &&
MIN_SESSION_DURATION_RATING < (Time.now - music_session.created_at).seconds) ||
Rails.env.development?
end
def good_rating?
0 < self.rating.to_i
end
end
end

View File

@ -10,7 +10,7 @@ module JamRuby
belongs_to :target_user, :class_name => "JamRuby::User", :foreign_key => "target_user_id"
belongs_to :source_user, :class_name => "JamRuby::User", :foreign_key => "source_user_id"
belongs_to :band, :class_name => "JamRuby::Band", :foreign_key => "band_id"
belongs_to :session, :class_name => "JamRuby::MusicSession", :foreign_key => "session_id"
belongs_to :session, :class_name => "JamRuby::ActiveMusicSession", :foreign_key => "session_id"
belongs_to :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id"
validates :target_user, :presence => true

View File

@ -83,8 +83,8 @@ class JamRuby::PromoLatest < JamRuby::Promotional
attr_accessible :latest
def music_session_history
self.latest if self.latest.is_a? MusicSessionHistory
def music_session
self.latest if self.latest.is_a? MusicSession
end
def recording
@ -101,7 +101,7 @@ class JamRuby::PromoLatest < JamRuby::Promotional
def update_with_params(params)
if (latest_id = params[:latest_id]).present?
self.latest = Recording.where(:id => latest_id).limit(1).first ||
MusicSessionHistory.where(:id => latest_id).limit(1).first
MusicSession.where(:id => latest_id).limit(1).first
end
self.position = params[:position]
self.aasm_state = params[:aasm_state]

View File

@ -16,7 +16,7 @@ module JamRuby
belongs_to :owner, :class_name => "JamRuby::User", :inverse_of => :owned_recordings, :foreign_key => 'owner_id'
belongs_to :band, :class_name => "JamRuby::Band", :inverse_of => :recordings
belongs_to :music_session, :class_name => "JamRuby::MusicSession", :inverse_of => :recordings
belongs_to :music_session, :class_name => "JamRuby::ActiveMusicSession", :inverse_of => :recordings, foreign_key: :music_session_id
accepts_nested_attributes_for :recorded_tracks, :mixes, :claimed_recordings, allow_destroy: true

View File

@ -109,7 +109,7 @@ module JamRuby
F_SORT_OPTS = [F_SORT_RECENT, F_SORT_LENGTH, F_SORT_OLDEST]
SHOW_BOTH = ['Sessions & Recordings', :all]
SHOW_SESSIONS = ['Sessions', :music_session_history]
SHOW_SESSIONS = ['Sessions', :music_session]
SHOW_RECORDINGS = ['Recordings', :recording]
SHOW_OPTS = [SHOW_BOTH, SHOW_SESSIONS, SHOW_RECORDINGS]
@ -300,8 +300,8 @@ module JamRuby
sel_str = 'bands.*'
case ordering = self.order_param(params)
when :plays # FIXME: double counting?
sel_str = "COUNT(records)+COUNT(sessions) AS play_count, #{sel_str}"
rel = rel.joins("LEFT JOIN music_sessions AS sessions ON sessions.band_id = bands.id")
sel_str = "COUNT(records)+COUNT(msh) AS play_count, #{sel_str}"
rel = rel.joins("LEFT JOIN music_sessions AS msh ON msh.band_id = bands.id")
.joins("LEFT JOIN recordings AS records ON records.band_id = bands.id")
.group("bands.id")
.order("play_count DESC, bands.created_at DESC")
@ -311,7 +311,7 @@ module JamRuby
.group("bands.id")
.order("COUNT(follows) DESC, bands.created_at DESC")
when :playing
rel = rel.joins("LEFT JOIN music_sessions_history AS msh ON msh.band_id = bands.id")
rel = rel.joins("LEFT JOIN music_sessions AS msh ON msh.band_id = bands.id")
.where('msh.music_session_id IS NOT NULL AND msh.session_removed_at IS NULL')
.order("bands.created_at DESC")
end

View File

@ -151,7 +151,7 @@ module JamRuby
track.client_track_id = client_track_id
end
track.updated_at = Time.now.getutc
track.updated_at = Time.now
track.save
return track
end

View File

@ -17,7 +17,7 @@ module JamRuby
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection, :lat, :lng
# updating_password corresponds to a lost_password
attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field
attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json
belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id'
@ -43,7 +43,7 @@ module JamRuby
has_many :owned_recordings, :class_name => "JamRuby::Recording", :foreign_key => "owner_id"
has_many :recordings, :through => :claimed_recordings, :class_name => "JamRuby::Recording"
has_many :claimed_recordings, :class_name => "JamRuby::ClaimedRecording", :inverse_of => :user
has_many :playing_claimed_recordings, :class_name => "JamRuby::MusicSession", :inverse_of => :claimed_recording_initiator
has_many :playing_claimed_recordings, :class_name => "JamRuby::ActiveMusicSession", :inverse_of => :claimed_recording_initiator
# self.id = user_id in likes table
has_many :likings, :class_name => "JamRuby::Like", :inverse_of => :user, :dependent => :destroy
@ -71,8 +71,8 @@ module JamRuby
has_many :inverse_friends, :through => :inverse_friendships, :source => :user, :class_name => "JamRuby::User"
# connections / music sessions
has_many :created_music_sessions, :foreign_key => "user_id", :inverse_of => :user, :class_name => "JamRuby::MusicSession" # sessions *created* by the user
has_many :music_sessions, :through => :connections, :class_name => "JamRuby::MusicSession"
has_many :created_music_sessions, :foreign_key => "user_id", :inverse_of => :user, :class_name => "JamRuby::ActiveMusicSession" # sessions *created* by the user
has_many :music_sessions, :through => :connections, :class_name => "JamRuby::ActiveMusicSession"
# invitations
has_many :received_invitations, :foreign_key => "receiver_id", :inverse_of => :receiver, :class_name => "JamRuby::Invitation"
@ -87,7 +87,7 @@ module JamRuby
has_many :sent_band_invitations, :inverse_of => :sender, :foreign_key => "creator_id", :class_name => "JamRuby::BandInvitation"
# session history
has_many :music_session_histories, :foreign_key => "user_id", :class_name => "JamRuby::MusicSessionHistory", :inverse_of => :user
has_many :music_session_histories, :foreign_key => "user_id", :class_name => "JamRuby::MusicSession", :inverse_of => :user
has_many :music_session_user_histories, :foreign_key => "user_id", :class_name => "JamRuby::MusicSessionUserHistory", :inverse_of => :user
# saved tracks
@ -105,6 +105,8 @@ module JamRuby
# affiliate_partner
has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id
belongs_to :affiliate_referral, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :affiliate_referral_id, :counter_cache => :referral_user_count
# diagnostics
has_many :diagnostics, :class_name => "JamRuby::Diagnostic"
# This causes the authenticate method to be generated (among other stuff)
#has_secure_password
@ -126,6 +128,7 @@ module JamRuby
validates :subscribe_email, :inclusion => {:in => [nil, true, false]}
validates :musician, :inclusion => {:in => [true, false]}
validates :show_whats_next, :inclusion => {:in => [nil, true, false]}
validates :mods, json: true
# custom validators
validate :validate_musician_instruments
@ -287,12 +290,25 @@ module JamRuby
self.music_sessions.size
end
# mods comes back as text; so give ourselves a parsed version
def mods_json
@mods_json ||= mods ? JSON.parse(mods, symbolize_names: true) : {}
end
def heartbeat_interval_client
mods_json[:heartbeat_interval_client]
end
def connection_expire_time_client
mods_json[:connection_expire_time_client]
end
def recent_history
recordings = Recording.where(:owner_id => self.id)
.order('created_at DESC')
.limit(10)
msh = MusicSessionHistory.where(:user_id => self.id)
msh = MusicSession.where(:user_id => self.id)
.order('created_at DESC')
.limit(10)
@ -339,7 +355,7 @@ module JamRuby
end
def session_history(user_id, band_id = nil, genre = nil)
return MusicSessionHistory.index(self, user_id, band_id, genre)
return MusicSession.index(self, user_id, band_id, genre)
end
def session_user_history(user_id, session_id)
@ -363,7 +379,7 @@ module JamRuby
return first_name + ' ' + last_name
end
return id
id
end
def set_password(old_password, new_password, new_password_confirmation)
@ -551,7 +567,7 @@ module JamRuby
self.biography = biography
end
self.updated_at = Time.now.getutc
self.updated_at = Time.now
self.save
end
@ -640,7 +656,7 @@ module JamRuby
end
# def create_session_like(targetSessionId)
# targetSession = MusicSessionHistory.find(targetSessionId)
# targetSession = MusicSession.find(targetSessionId)
# like = Like.new
# like.likable = targetSession
@ -688,15 +704,7 @@ module JamRuby
unless user.nil?
# only save genre id and description
genres = []
unless music_session.genres.nil?
music_session.genres.each do |genre|
g = Hash.new
g["id"] = genre.id
g["description"] = genre.description
genres << g
end
end
genres = [{id: music_session.genre.id, description: music_session.genre.description}]
# only save invitation receiver id and name
invitees = []

View File

@ -25,7 +25,7 @@ module JamRuby
def self.perform(args={})
session_id, interval_idx = args['session_id'], args['interval_idx'].to_i
return unless session_id && session = MusicSession.find(session_id)
return unless session_id && session = MusicSession.find_by_id(session_id)
GoogleAnalyticsEvent.enqueue(CAT_SESS_DUR, ACTION_SESS_DUR, SESSION_INTERVALS[interval_idx])
interval_idx += 1
@ -47,7 +47,7 @@ module JamRuby
@queue = QUEUE_BAND_TRACKER
def self.perform(session_id)
return unless session = MusicSession.find(session_id)
return unless session = ActiveMusicSession.find(session_id)
band = session.band
if band.in_real_session?(session)
band.update_attribute(:did_real_session, true)

View File

@ -31,46 +31,66 @@ FactoryGirl.define do
factory :single_user_session do
after(:create) do |user, evaluator|
music_session = FactoryGirl.create(:music_session, :creator => user)
connection = FactoryGirl.create(:connection, :user => user, :music_session => music_session)
active_music_session = FactoryGirl.create(:active_music_session, :creator => user)
connection = FactoryGirl.create(:connection, :user => user, :music_session => active_music_session)
end
end
end
factory :music_session_no_history, :class => JamRuby::MusicSession do
sequence(:description) { |n| "Music Session #{n}" }
factory :musician_instrument, :class => JamRuby::MusicianInstrument do
instrument { JamRuby::Instrument.find('electric guitar') }
proficiency_level 1
priority 0
end
factory :active_music_session_no_user_history, :class => JamRuby::ActiveMusicSession do
association :creator, factory: :user
ignore do
name "My Music Session"
description "Come Music Session"
fan_chat true
fan_access true
approval_required false
musician_access true
legal_terms true
genre JamRuby::Genre.first
band nil
end
before(:create) do |session, evaluator|
music_session = FactoryGirl.create(:music_session, name: evaluator.name, description: evaluator.description, fan_chat: evaluator.fan_chat,
fan_access: evaluator.fan_access, approval_required: evaluator.approval_required, musician_access: evaluator.musician_access,
genre: evaluator.genre, creator: evaluator.creator, band: evaluator.band)
session.id = music_session.id
end
factory :active_music_session do
after(:create) { |session|
FactoryGirl.create(:music_session_user_history, :history => session.music_session, :user => session.creator)
}
factory :active_music_session_with_mount do
association :mount, :factory => :icecast_mount
end
end
end
factory :music_session, :class => JamRuby::MusicSession do
sequence(:name) { |n| "Music Session #{n}" }
sequence(:description) { |n| "Music Session Description #{n}" }
fan_chat true
fan_access true
approval_required false
musician_access true
legal_terms true
genres [JamRuby::Genre.first]
language 'english'
legal_policy 'standard'
genre JamRuby::Genre.first
association :creator, :factory => :user
factory :music_session do
after(:create) { |session|
FactoryGirl.create(:music_session_user_history, :history => session.music_session_history, :user => session.creator)
}
factory :music_session_with_mount do
association :mount, :factory => :icecast_mount
end
end
end
factory :music_session_history, :class => JamRuby::MusicSessionHistory do
ignore do
music_session nil
end
fan_access true
music_session_id { music_session.id }
description { music_session.description }
user_id { music_session.user_id }
band_id { music_session.band_id }
end
factory :music_session_user_history, :class => JamRuby::MusicSessionUserHistory do
@ -80,7 +100,7 @@ FactoryGirl.define do
end
instruments 'guitar'
music_session_id { history.music_session_id }
music_session_id { history.id }
user_id { user.id }
sequence(:client_id) { |n| "Connection #{n}" }
end
@ -154,7 +174,7 @@ FactoryGirl.define do
factory :recording, :class => JamRuby::Recording do
association :owner, factory: :user
association :music_session, factory: :music_session
association :music_session, factory: :active_music_session
association :band, factory: :band
factory :recording_with_track do
@ -196,12 +216,6 @@ FactoryGirl.define do
}
end
factory :musician_instrument, :class => JamRuby::MusicianInstrument do
instrument { Instrument.find('electric guitar') }
proficiency_level 1
priority 0
end
factory :invited_user, :class => JamRuby::InvitedUser do
sequence(:email) { |n| "user#{n}@someservice.com" }
autofriend false
@ -305,7 +319,7 @@ FactoryGirl.define do
association :mount_template, :factory => :icecast_mount_template
factory :iceast_mount_with_music_session do
association :music_session, :factory => :music_session
association :music_session, :factory => :active_music_session
end
end
end
@ -438,4 +452,10 @@ FactoryGirl.define do
message Faker::Lorem.characters(10)
end
end
factory :diagnostic, :class => JamRuby::Diagnostic do
type JamRuby::Diagnostic::NO_HEARTBEAT_ACK
creator JamRuby::Diagnostic::CLIENT
data Faker::Lorem.sentence
end
end

View File

@ -4,6 +4,10 @@ require 'spec_helper'
describe ConnectionManager do
TRACKS = [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "some_client_track_id"}]
STALE_TIME = 40
EXPIRE_TIME = 60
STALE_BUT_NOT_EXPIRED = 50
DEFINITELY_EXPIRED = 70
before do
@conn = PG::Connection.new(:dbname => SpecDb::TEST_DB_NAME, :user => "postgres", :password => "postgres", :host => "localhost")
@ -17,17 +21,6 @@ describe ConnectionManager do
end
end
def create_music_session(user_id, options={})
default_options = {:musician_access => true, :fan_chat => true, :fan_access => true, :approval_required=> false}
options = default_options.merge(options)
description = "some session"
@conn.exec("INSERT INTO music_sessions (user_id, description, musician_access, approval_required, fan_chat, fan_access) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id", [user_id, description, options[:musician_access], options[:approval_required], options[:fan_chat], options[:fan_access]]) do |result|
session_id = result.getvalue(0, 0)
@conn.exec("INSERT INTO music_sessions_history (music_session_id, description, user_id, fan_access) VALUES ($1, $2, $3, $4)", [session_id, description, user_id, true])
return session_id
end
end
def assert_num_connections(client_id, expected_num_connections)
# make sure the connection is still there
@conn.exec("SELECT count(*) FROM connections where client_id = $1", [client_id]) do |result|
@ -36,7 +29,7 @@ describe ConnectionManager do
end
def assert_session_exists(music_session_id, exists)
@conn.exec("SELECT count(*) FROM music_sessions where id = $1", [music_session_id]) do |result|
@conn.exec("SELECT count(*) FROM active_music_sessions where id = $1", [music_session_id]) do |result|
if exists
result.getvalue(0, 0).should == "1"
else
@ -53,8 +46,8 @@ describe ConnectionManager do
user.save!
user = nil
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
expect { @connman.create_connection(user_id, client_id, "1.1.1.1", 'client') }.to raise_error(PG::Error)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
expect { @connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME) }.to raise_error(PG::Error)
end
it "create connection then delete it" do
@ -63,7 +56,7 @@ describe ConnectionManager do
#user_id = create_user("test", "user2", "user2@jamkazam.com")
user = FactoryGirl.create(:user)
count = @connman.create_connection(user.id, client_id, "1.1.1.1", 'client')
count = @connman.create_connection(user.id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
count.should == 1
@ -93,7 +86,7 @@ describe ConnectionManager do
#user_id = create_user("test", "user2", "user2@jamkazam.com")
user = FactoryGirl.create(:user)
count = @connman.create_connection(user.id, client_id, "1.1.1.1", 'client')
count = @connman.create_connection(user.id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
count.should == 1
@ -109,7 +102,7 @@ describe ConnectionManager do
cc.addr.should == 0x01010101
cc.locidispid.should == 17192000002
@connman.reconnect(cc, nil, "33.1.2.3")
@connman.reconnect(cc, nil, "33.1.2.3", STALE_TIME, EXPIRE_TIME)
cc = Connection.find_by_client_id!(client_id)
cc.connected?.should be_true
@ -222,20 +215,21 @@ describe ConnectionManager do
it "flag stale connection" do
client_id = "client_id8"
user_id = create_user("test", "user8", "user8@jamkazam.com")
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
num = JamRuby::Connection.count(:conditions => ['aasm_state = ?','connected'])
num.should == 1
assert_num_connections(client_id, num)
@connman.flag_stale_connections(60)
@connman.flag_stale_connections()
assert_num_connections(client_id, num)
sleep(1)
conn = Connection.find_by_client_id(client_id)
set_updated_at(conn, Time.now - STALE_BUT_NOT_EXPIRED)
num = JamRuby::Connection.count(:conditions => ["updated_at < (NOW() - interval '#{1} second') AND aasm_state = 'connected'"])
num.should == 1
# this should change the aasm_state to stale
@connman.flag_stale_connections(1)
@connman.flag_stale_connections()
num = JamRuby::Connection.count(:conditions => ["updated_at < (NOW() - interval '#{1} second') AND aasm_state = 'connected'"])
num.should == 0
@ -244,31 +238,39 @@ describe ConnectionManager do
num.should == 1
assert_num_connections(client_id, 1)
cids = @connman.stale_connection_client_ids(1)
cids.size.should == 1
cids[0].should == client_id
cids.each { |cid| @connman.delete_connection(cid) }
conn = Connection.find_by_client_id(client_id)
set_updated_at(conn, Time.now - DEFINITELY_EXPIRED)
cids = @connman.stale_connection_client_ids()
cids.size.should == 1
cids[0][:client_id].should == client_id
cids[0][:client_type].should == Connection::TYPE_CLIENT
cids[0][:music_session_id].should be_nil
cids[0][:user_id].should == user_id
cids.each { |cid| @connman.delete_connection(cid[:client_id]) }
sleep(1)
assert_num_connections(client_id, 0)
end
it "expires stale connection" do
client_id = "client_id8"
user_id = create_user("test", "user8", "user8@jamkazam.com")
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
sleep(1)
@connman.flag_stale_connections(1)
conn = Connection.find_by_client_id(client_id)
set_updated_at(conn, Time.now - STALE_BUT_NOT_EXPIRED)
@connman.flag_stale_connections
assert_num_connections(client_id, 1)
# assert_num_connections(client_id, JamRuby::Connection.count(:conditions => ['aasm_state = ?','stale']))
@connman.expire_stale_connections(60)
@connman.expire_stale_connections
assert_num_connections(client_id, 1)
sleep(1)
set_updated_at(conn, Time.now - DEFINITELY_EXPIRED)
# this should delete the stale connection
@connman.expire_stale_connections(1)
@connman.expire_stale_connections
assert_num_connections(client_id, 0)
end
@ -276,12 +278,11 @@ describe ConnectionManager do
client_id = "client_id9"
user_id = create_user("test", "user9", "user9@jamkazam.com")
music_session_id = create_music_session(user_id)
music_session = FactoryGirl.create(:active_music_session, user_id: user_id)
music_session_id = music_session.id
user = User.find(user_id)
music_session = MusicSession.find(music_session_id)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
connection = @connman.join_music_session(user, client_id, music_session, true, TRACKS)
connection.errors.any?.should be_false
@ -302,10 +303,10 @@ describe ConnectionManager do
client_id = "client_id10"
user_id = create_user("test", "user10", "user10@jamkazam.com")
music_session_id = create_music_session(user_id)
music_session = FactoryGirl.create(:active_music_session, user_id: user_id)
music_session_id = music_session.id
user = User.find(user_id)
music_session = MusicSession.find(music_session_id)
expect { @connman.join_music_session(user, client_id, music_session, true, TRACKS) }.to raise_error(ActiveRecord::RecordNotFound)
@ -317,13 +318,12 @@ describe ConnectionManager do
client_id2 = "client_id10.12"
user_id = create_user("test", "user10.11", "user10.11@jamkazam.com", :musician => true)
user_id2 = create_user("test", "user10.12", "user10.12@jamkazam.com", :musician => false)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id2, client_id2, "1.1.1.1", 'client')
music_session_id = create_music_session(user_id)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
@connman.create_connection(user_id2, client_id2, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
music_session = FactoryGirl.create(:active_music_session, user_id: user_id)
music_session_id = music_session.id
user = User.find(user_id)
music_session = MusicSession.find(music_session_id)
@connman.join_music_session(user, client_id, music_session, true, TRACKS)
@ -336,13 +336,12 @@ describe ConnectionManager do
it "as_musician is coerced to boolean" do
client_id = "client_id10.2"
user_id = create_user("test", "user10.2", "user10.2@jamkazam.com", :musician => false)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
music_session_id = create_music_session(user_id)
user_id = create_user("test", "user10.2", "user10.2@jamkazam.com")
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
music_session = FactoryGirl.create(:active_music_session, user_id: user_id)
user = User.find(user_id)
music_session = MusicSession.find(music_session_id)
connection = @connman.join_music_session(user, client_id, music_session, 'blarg', TRACKS)
connection.errors.size.should == 0
@ -355,13 +354,13 @@ describe ConnectionManager do
fan_client_id = "client_id10.4"
musician_id = create_user("test", "user10.3", "user10.3@jamkazam.com")
fan_id = create_user("test", "user10.4", "user10.4@jamkazam.com", :musician => false)
@connman.create_connection(musician_id, musician_client_id, "1.1.1.1", 'client')
@connman.create_connection(fan_id, fan_client_id, "1.1.1.1", 'client')
@connman.create_connection(musician_id, musician_client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
@connman.create_connection(fan_id, fan_client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
music_session_id = create_music_session(musician_id, :fan_access => false)
music_session = FactoryGirl.create(:active_music_session, :fan_access => false, user_id: musician_id)
music_session_id = music_session.id
user = User.find(musician_id)
music_session = MusicSession.find(music_session_id)
@connman.join_music_session(user, musician_client_id, music_session, true, TRACKS)
@ -376,12 +375,11 @@ describe ConnectionManager do
client_id = "client_id20"
user_id = create_user("test", "user20", "user20@jamkazam.com")
user_id2 = create_user("test", "user21", "user21@jamkazam.com")
music_session_id = create_music_session(user_id)
music_session = FactoryGirl.create(:active_music_session, user_id: user_id)
music_session_id = music_session.id
user = User.find(user_id2)
music_session = MusicSession.find(music_session_id)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
# specify real user id, but not associated with this session
expect { @connman.join_music_session(user, client_id, music_session, true, TRACKS) } .to raise_error(ActiveRecord::RecordNotFound)
end
@ -391,9 +389,9 @@ describe ConnectionManager do
user_id = create_user("test", "user11", "user11@jamkazam.com")
user = User.find(user_id)
music_session = MusicSession.new
music_session = ActiveMusicSession.new
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
connection = @connman.join_music_session(user, client_id, music_session, true, TRACKS)
connection.errors.size.should == 1
connection.errors.get(:music_session).should == [ValidationMessages::MUSIC_SESSION_MUST_BE_SPECIFIED]
@ -403,12 +401,11 @@ describe ConnectionManager do
client_id = "client_id11.1"
user_id = create_user("test", "user11.1", "user11.1@jamkazam.com")
user_id2 = create_user("test", "user11.2", "user11.2@jamkazam.com")
music_session_id = create_music_session(user_id, :approval_required => true)
music_session = FactoryGirl.create(:active_music_session, :approval_required => true, user_id: user_id)
music_session_id = music_session.id
user = User.find(user_id2)
music_session = MusicSession.find(music_session_id)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
# specify real user id, but not associated with this session
expect { @connman.join_music_session(user, client_id, music_session, true, TRACKS) } .to raise_error(ActiveRecord::RecordNotFound)
end
@ -420,9 +417,9 @@ describe ConnectionManager do
user_id = create_user("test", "user12", "user12@jamkazam.com")
user = User.find(user_id)
dummy_music_session = MusicSession.new
dummy_music_session = ActiveMusicSession.new
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
expect { @connman.leave_music_session(user, Connection.find_by_client_id(client_id), dummy_music_session) }.to raise_error(JamRuby::StateError)
end
@ -431,14 +428,13 @@ describe ConnectionManager do
client_id = "client_id13"
user_id = create_user("test", "user13", "user13@jamkazam.com")
music_session_id = create_music_session(user_id)
music_session = FactoryGirl.create(:active_music_session, user_id: user_id)
music_session_id = music_session.id
user = User.find(user_id)
music_session = MusicSession.find(music_session_id)
dummy_music_session = MusicSession.new
dummy_music_session = ActiveMusicSession.new
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
@connman.join_music_session(user, client_id, music_session, true, TRACKS)
expect { @connman.leave_music_session(user, Connection.find_by_client_id(client_id), dummy_music_session) }.to raise_error(JamRuby::StateError)
end
@ -447,12 +443,11 @@ describe ConnectionManager do
client_id = "client_id14"
user_id = create_user("test", "user14", "user14@jamkazam.com")
music_session_id = create_music_session(user_id)
music_session = FactoryGirl.create(:active_music_session, user_id: user_id)
music_session_id = music_session.id
user = User.find(user_id)
music_session = MusicSession.find(music_session_id)
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client')
@connman.create_connection(user_id, client_id, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
@connman.join_music_session(user, client_id, music_session, true, TRACKS)
assert_session_exists(music_session_id, true)
@ -490,19 +485,17 @@ describe ConnectionManager do
# and a connection can only point to one active music_session at a time. this is a test of
# the latter but we need a test of the former, too.
user_id = create_user("test", "user11", "user11@jamkazam.com")
user = User.find(user_id)
client_id1 = Faker::Number.number(20)
@connman.create_connection(user_id, client_id1, "1.1.1.1", 'client')
music_session1 = MusicSession.find(create_music_session(user_id))
@connman.create_connection(user_id, client_id1, "1.1.1.1", 'client', STALE_TIME, EXPIRE_TIME)
music_session1 = FactoryGirl.create(:active_music_session, :user_id => user_id)
connection1 = @connman.join_music_session(user, client_id1, music_session1, true, TRACKS)
connection1.errors.size.should == 0
music_session2 = MusicSession.find(create_music_session(user_id))
music_session2 = FactoryGirl.create(:active_music_session, :user_id => user_id)
connection2 = @connman.join_music_session(user, client_id1, music_session2, true, TRACKS)
connection2.errors.size.should == 1

View File

@ -105,7 +105,7 @@ describe 'Band search' do
def make_session(band)
usr = band.users[0]
session = FactoryGirl.create(:music_session, :creator => usr, :description => "Session", :band => band)
session = FactoryGirl.create(:active_music_session, :creator => usr, :description => "Session", :band => band)
FactoryGirl.create(:connection, :user => usr, :music_session => session)
user = FactoryGirl.create(:user)
session
@ -159,7 +159,7 @@ describe 'Band search' do
it "by now playing" do
# should get 1 result with 1 active session
session = make_session(@band3)
#FactoryGirl.create(:music_session_history, :music_session => session)
#FactoryGirl.create(:active_music_session, :music_session => session)
results = Search.band_filter({ :orderby => 'playing' })
expect(results.results.count).to be 1
@ -168,7 +168,7 @@ describe 'Band search' do
# should get 2 results with 2 active sessions
# sort order should be created_at DESC
session = make_session(@band4)
#FactoryGirl.create(:music_session_history, :music_session => session)
#FactoryGirl.create(:active_music_session, :music_session => session)
results = Search.band_filter({ :orderby => 'playing' })
expect(results.results.count).to be 2
expect(results.results[0].id).to eq(@band4.id)

View File

@ -18,7 +18,7 @@ describe ClaimedRecording do
@connection = FactoryGirl.create(:connection, :user => @user)
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
@music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true)
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
# @music_session.connections << @connection
@music_session.save
@connection.join_the_session(@music_session, true, nil)

View File

@ -2,7 +2,7 @@ require 'spec_helper'
describe JamRuby::Connection do
let(:user) { FactoryGirl.create(:user) }
let (:music_session) { FactoryGirl.create(:music_session, :creator => user) }
let (:music_session) { FactoryGirl.create(:active_music_session, :creator => user) }
it 'starts in the correct state' do
connection = FactoryGirl.create(:connection,
@ -37,7 +37,7 @@ describe JamRuby::Connection do
pending 'distance search changes'
uu = FactoryGirl.create(:user)
uu.lat.should == nil
msess = FactoryGirl.create(:music_session, :creator => uu)
msess = FactoryGirl.create(:active_music_session, :creator => uu)
geocode = FactoryGirl.create(:geocoder)
connection = FactoryGirl.create(:connection,
:user => uu,

View File

@ -0,0 +1,18 @@
require 'spec_helper'
describe Diagnostic do
let (:user) { FactoryGirl.create(:user) }
let (:diagnostic) { FactoryGirl.create(:diagnostic, user: user) }
it 'can be made' do
diagnostic.save!
end
it "validates type" do
diagnostic = FactoryGirl.build(:diagnostic, user: user, type: 'bleh')
diagnostic.errors[:type].should == []
end
end

View File

@ -16,7 +16,7 @@ describe Feed do
it "one claimed recording" do
claimed_recording = FactoryGirl.create(:claimed_recording)
MusicSessionUserHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
MusicSessionHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
MusicSession.delete_all # the factory makes a music_session while making the recording/claimed_recording
feeds, start = Feed.index(user1)
feeds.length.should == 1
feeds[0].recording == claimed_recording.recording
@ -28,7 +28,7 @@ describe Feed do
recording.recorded_tracks << second_track
FactoryGirl.create(:claimed_recording, recording: recording, user: second_track.user)
MusicSessionUserHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
MusicSessionHistory.delete_all
MusicSession.delete_all
# verify the mess above only made one recording
Recording.count.should == 1
@ -38,16 +38,16 @@ describe Feed do
end
it "one music session" do
music_session = FactoryGirl.create(:music_session)
music_session = FactoryGirl.create(:active_music_session)
feeds, start = Feed.index(user1)
feeds.length.should == 1
feeds[0].music_session_history == music_session.music_session_history
feeds[0].music_session == music_session.music_session
end
it "does not return a recording with no claimed recordings" do
recording = FactoryGirl.create(:recording)
MusicSessionUserHistory.delete_all # the factory makes a music_session while making the recording/claimed_recording
MusicSessionHistory.delete_all
MusicSession.delete_all
feeds, start = Feed.index(user1)
feeds.length.should == 0
@ -60,7 +60,7 @@ describe Feed do
feeds, start = Feed.index(user1)
feeds.length.should == 2
feeds[0].recording.should == claimed_recording.recording
feeds[1].music_session_history.should == claimed_recording.recording.music_session.music_session_history
feeds[1].music_session.should == claimed_recording.recording.music_session.music_session
end
it "sort by plays DESC" do
@ -80,14 +80,14 @@ describe Feed do
feeds[0].recording.should == claimed_recording2.recording
feeds[1].recording.should == claimed_recording1.recording
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session_history, user: user1)
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session_history, user: user2)
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session_history, user: user3)
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user1)
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user2)
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user3)
feeds, start = Feed.index(user1, :sort => 'plays')
feeds.length.should == 4
feeds[0].music_session_history.should == claimed_recording1.recording.music_session.music_session_history
feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session
feeds[1].recording.should == claimed_recording2.recording
feeds[2].recording.should == claimed_recording1.recording
end
@ -109,13 +109,13 @@ describe Feed do
feeds[0].recording.should == claimed_recording2.recording
feeds[1].recording.should == claimed_recording1.recording
FactoryGirl.create(:music_session_like, music_session_history: claimed_recording1.recording.music_session.music_session_history, user: user1)
FactoryGirl.create(:music_session_like, music_session_history: claimed_recording1.recording.music_session.music_session_history, user: user2)
FactoryGirl.create(:music_session_like, music_session_history: claimed_recording1.recording.music_session.music_session_history, user: user3)
FactoryGirl.create(:music_session_like, music_session: claimed_recording1.recording.music_session.music_session, user: user1)
FactoryGirl.create(:music_session_like, music_session: claimed_recording1.recording.music_session.music_session, user: user2)
FactoryGirl.create(:music_session_like, music_session: claimed_recording1.recording.music_session.music_session, user: user3)
feeds, start = Feed.index(user1, :sort => 'likes')
feeds.length.should == 4
feeds[0].music_session_history.should == claimed_recording1.recording.music_session.music_session_history
feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session
feeds[1].recording.should == claimed_recording2.recording
feeds[2].recording.should == claimed_recording1.recording
end
@ -126,18 +126,18 @@ describe Feed do
# creates both recording and history record in feed
claimed_recording1 = FactoryGirl.create(:claimed_recording)
feeds, start = Feed.index(user1, :type => 'music_session_history')
feeds, start = Feed.index(user1, :type => 'music_session')
feeds.length.should == 1
feeds[0].music_session_history == claimed_recording1.recording.music_session.music_session_history
feeds[0].music_session == claimed_recording1.recording.music_session.music_session
end
it "returns only sessions" do
# creates both recording and history record in feed
claimed_recording1 = FactoryGirl.create(:claimed_recording)
feeds, start = Feed.index(user1, :type => 'music_session_history')
feeds, start = Feed.index(user1, :type => 'music_session')
feeds.length.should == 1
feeds[0].music_session_history == claimed_recording1.recording.music_session.music_session_history
feeds[0].music_session == claimed_recording1.recording.music_session.music_session
end
end
@ -203,7 +203,7 @@ describe Feed do
options[:start] = start
feeds, start = Feed.index(user1, options)
feeds.length.should == 1
feeds[0].music_session_history.should == claimed_recording.recording.music_session.music_session_history
feeds[0].music_session.should == claimed_recording.recording.music_session.music_session
options[:start] = start
feeds, start = Feed.index(user1, options)
@ -214,12 +214,12 @@ describe Feed do
it "supports likes pagination" do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
FactoryGirl.create(:music_session_like, music_session_history: claimed_recording1.recording.music_session.music_session_history, user: user1)
FactoryGirl.create(:music_session_like, music_session: claimed_recording1.recording.music_session.music_session, user: user1)
options = {limit: 1, sort: 'likes'}
feeds, start = Feed.index(user1, options)
feeds.length.should == 1
feeds[0].music_session_history.should == claimed_recording1.recording.music_session.music_session_history
feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session
options[:start] = start
feeds, start = Feed.index(user1, options)
@ -235,12 +235,12 @@ describe Feed do
it "supports plays pagination" do
claimed_recording1 = FactoryGirl.create(:claimed_recording)
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session_history, user: user1)
FactoryGirl.create(:playable_play, playable: claimed_recording1.recording.music_session.music_session, user: user1)
options = {limit: 1, sort: 'plays'}
feeds, start = Feed.index(user1, options)
feeds.length.should == 1
feeds[0].music_session_history.should == claimed_recording1.recording.music_session.music_session_history
feeds[0].music_session.should == claimed_recording1.recording.music_session.music_session
options[:start] = start
feeds, start = Feed.index(user1, options)
@ -263,8 +263,8 @@ describe Feed do
feeds, start = Feed.index(claimed_recording1.user)
feeds.length.should == 1
claimed_recording1.recording.music_session.fan_access = false
claimed_recording1.recording.music_session.save!
claimed_recording1.recording.music_session.music_session.fan_access = false
claimed_recording1.recording.music_session.music_session.save!
feeds, start = Feed.index(claimed_recording1.user)
feeds.length.should == 0
@ -274,8 +274,8 @@ describe Feed do
describe "band feeds" do
it "does show other band's stuff in this feed" do
other_band = FactoryGirl.create(:band)
music_session = FactoryGirl.create(:music_session, band: other_band)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user1)
music_session = FactoryGirl.create(:active_music_session, band: other_band)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user1)
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = true
@ -290,28 +290,28 @@ describe Feed do
it "shows public recordings to you and to others" do
user1.bands << band
user1.save!
music_session = FactoryGirl.create(:music_session, band: band)
music_session.music_session_history.fan_access.should be_true
music_session = FactoryGirl.create(:active_music_session, band: band)
music_session.music_session.fan_access.should be_true
feeds, start = Feed.index(user1, band: band.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session.should == music_session.music_session
feeds, start = Feed.index(user2, band: band.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session.should == music_session.music_session
end
it "shows private sessions to you, not to others" do
user1.bands << band
user1.save!
music_session = FactoryGirl.create(:music_session, band: band, fan_access: false)
music_session.music_session_history.fan_access.should be_false
music_session = FactoryGirl.create(:active_music_session, band: band, fan_access: false)
music_session.music_session.fan_access.should be_false
feeds, start = Feed.index(user1, band: band.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session_history.fan_access.should be_false
feeds[0].music_session.should == music_session.music_session
feeds[0].music_session.fan_access.should be_false
feeds, start = Feed.index(user2, band: band.id)
@ -355,8 +355,8 @@ describe Feed do
describe "user feeds" do
it "does not show stuff from other people" do
music_session = FactoryGirl.create(:music_session)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user2)
music_session = FactoryGirl.create(:active_music_session)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user2)
claimed_recording1 = FactoryGirl.create(:claimed_recording)
claimed_recording1.is_public = true
@ -367,28 +367,28 @@ describe Feed do
end
it "shows public sessions to you and to others" do
music_session = FactoryGirl.create(:music_session)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user1)
music_session = FactoryGirl.create(:active_music_session)
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user1)
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session.should == music_session.music_session
feeds, start = Feed.index(user2, user: user1.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session.should == music_session.music_session
end
it "shows private sessions to you, not to others" do
music_session = FactoryGirl.create(:music_session, fan_access: false)
music_session.music_session_history.fan_access.should be_false
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user1)
music_session = FactoryGirl.create(:active_music_session, fan_access: false)
music_session.music_session.fan_access.should be_false
FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user1)
feeds, start = Feed.index(user1, user: user1.id)
feeds.length.should == 1
feeds[0].music_session_history.should == music_session.music_session_history
feeds[0].music_session_history.fan_access.should be_false
feeds[0].music_session.should == music_session.music_session
feeds[0].music_session.fan_access.should be_false
feeds, start = Feed.index(user2, user: user1.id)

View File

@ -166,39 +166,39 @@ describe IcecastMount do
let(:server1) {FactoryGirl.create(:icecast_server_minimal)}
let(:server2) {FactoryGirl.create(:icecast_server_with_overrides)}
let(:server3) {FactoryGirl.create(:icecast_server_with_overrides)}
let(:hidden_music_session) { FactoryGirl.create(:music_session, :fan_access => false)}
let(:public_music_session) { FactoryGirl.create(:music_session, :fan_access => true)}
let(:public_music_session2) { FactoryGirl.create(:music_session, :fan_access => true)}
let(:public_music_session3) { FactoryGirl.create(:music_session, :fan_access => true)}
let(:hidden_music_session) { FactoryGirl.create(:active_music_session, :fan_access => false)}
let(:public_music_session) { FactoryGirl.create(:active_music_session, :fan_access => true)}
let(:public_music_session2) { FactoryGirl.create(:active_music_session, :fan_access => true)}
let(:public_music_session3) { FactoryGirl.create(:active_music_session, :fan_access => true)}
before(:each) do
end
it "no fan access means no mount" do
mount = IcecastMount.build_session_mount(hidden_music_session, IcecastServer.find_best_server_for_user(hidden_music_session.creator))
mount = IcecastMount.build_session_mount(hidden_music_session.music_session, hidden_music_session, IcecastServer.find_best_server_for_user(hidden_music_session.creator))
mount.should be_nil
end
it "with no servers" do
IcecastServer.count.should == 0
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount = IcecastMount.build_session_mount(public_music_session.music_session, public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.should be_nil
end
it "with a server that has a mount template" do
server1.mount_template.should_not be_nil
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount = IcecastMount.build_session_mount(public_music_session.music_session, public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.should_not be_nil
mount.save!
end
it "with a server that already has an associated mount" do
server1.mount_template.should_not be_nil
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount = IcecastMount.build_session_mount(public_music_session.music_session, public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.save!
mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount = IcecastMount.build_session_mount(public_music_session2.music_session, public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount.save!
server1.reload
server1.mounts.length.should == 2
@ -207,13 +207,13 @@ describe IcecastMount do
it "picks a second server once the 1st has been chosen" do
server1.touch
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount = IcecastMount.build_session_mount(public_music_session.music_session, public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.listeners = 1 # affect the weight
mount.save!
server2.touch
mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount = IcecastMount.build_session_mount(public_music_session2.music_session, public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount.save!
server1.reload
server1.mounts.length.should == 1
@ -224,17 +224,17 @@ describe IcecastMount do
it "picks the 1st server again once the 2nd has higher weight" do
server1.touch
mount = IcecastMount.build_session_mount(public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount = IcecastMount.build_session_mount(public_music_session.music_session, public_music_session, IcecastServer.find_best_server_for_user(public_music_session.creator))
mount.listeners = 1 # affect the weight
mount.save!
server2.touch
mount = IcecastMount.build_session_mount(public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount = IcecastMount.build_session_mount(public_music_session2.music_session, public_music_session2, IcecastServer.find_best_server_for_user(public_music_session2.creator))
mount.sourced = 1
mount.save!
mount = IcecastMount.build_session_mount(public_music_session3, IcecastServer.find_best_server_for_user(public_music_session3.creator))
mount = IcecastMount.build_session_mount(public_music_session3.music_session, public_music_session3, IcecastServer.find_best_server_for_user(public_music_session3.creator))
mount.listeners = 1
mount.save!

View File

@ -10,11 +10,11 @@ describe IcecastMountTemplate do
describe "poke configs" do
let(:server) { a = FactoryGirl.create(:icecast_server_with_overrides); a.config_updated; IcecastServer.find(a.id) }
let(:music_session) { FactoryGirl.create(:music_session, :fan_access => true)}
let(:music_session) { FactoryGirl.create(:active_music_session, :fan_access => true)}
before(:each) do
server.touch
mount = IcecastMount.build_session_mount(music_session, IcecastServer.find_best_server_for_user(music_session.creator))
mount = IcecastMount.build_session_mount(music_session.music_session, music_session, IcecastServer.find_best_server_for_user(music_session.creator))
mount.save!
server.save!
server.config_updated

View File

@ -1,18 +1,18 @@
require 'spec_helper'
describe MusicSession do
describe ActiveMusicSession do
it 'cant create invitation to non-friend' do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :ip_address => "2.2.2.2", :client_id => "2")
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session)
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session.music_session)
invitation.save.should be_false
invitation.errors.size.should == 1
@ -24,7 +24,7 @@ describe MusicSession do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :ip_address => "2.2.2.2", :client_id => "2")
@ -32,7 +32,7 @@ describe MusicSession do
FactoryGirl.create(:friendship, :user => user1, :friend => user2)
FactoryGirl.create(:friendship, :user => user2, :friend => user1)
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session)
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session.music_session)
invitation.save.should be_true
end
@ -41,14 +41,14 @@ describe MusicSession do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
connection2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "2.2.2.2", :client_id => "2")
join_request = FactoryGirl.create(:join_request, :user => user2, :music_session => music_session)
join_request = FactoryGirl.create(:join_request, :user => user2, :music_session => music_session.music_session)
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session, :join_request => join_request)
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session.music_session, :join_request => join_request)
invitation.save.should be_true
end
@ -57,15 +57,15 @@ describe MusicSession do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session2 = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session2 = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
connection2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "2.2.2.2", :client_id => "2")
join_request = FactoryGirl.create(:join_request, :user => user2, :music_session => music_session2)
join_request = FactoryGirl.create(:join_request, :user => user2, :music_session => music_session2.music_session)
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session, :join_request => join_request)
invitation = Invitation.new(:sender => user1, :receiver => user2, :music_session => music_session.music_session, :join_request => join_request)
invitation.save.should be_false
invitation.errors.get(:join_request).should == [Invitation::JOIN_REQUEST_IS_NOT_FOR_RECEIVER_AND_MUSIC_SESSION ]

View File

@ -4,9 +4,9 @@ describe JoinRequest do
it 'can create a join request' do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
join_request = JoinRequest.new(:user => user1, :music_session => music_session, :text => "Let me join yo")
join_request = JoinRequest.new(:user => user1, :music_session => music_session.music_session, :text => "Let me join yo")
join_request.save.should be_true
@ -18,9 +18,9 @@ describe JoinRequest do
it 'fans cant create a join request' do
user1 = FactoryGirl.create(:user, :musician => true)
user2 = FactoryGirl.create(:user, :musician => false)
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
join_request = JoinRequest.new(:user => user2, :music_session => music_session, :text => "Let me join yo")
join_request = JoinRequest.new(:user => user2, :music_session => music_session.music_session, :text => "Let me join yo")
join_request.save.should be_false
join_request.errors.size.should == 1
@ -29,12 +29,12 @@ describe JoinRequest do
it 'cant create a dup join_request' do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
join_request = JoinRequest.new(:user => user1, :music_session => music_session, :text => "Let me join yo")
join_request = JoinRequest.new(:user => user1, :music_session => music_session.music_session, :text => "Let me join yo")
join_request.save.should be_true
join_request2 = JoinRequest.new(:user => user1, :music_session => music_session, :text => "Let me join yo")
join_request2 = JoinRequest.new(:user => user1, :music_session => music_session.music_session, :text => "Let me join yo")
join_request2.save.should be_false
join_request2.errors.get(:user_id) == ["has already been taken"]
@ -42,9 +42,9 @@ describe JoinRequest do
it "cant contain profanity in the text" do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
join_request = JoinRequest.new(:user => user1, :music_session => music_session, :text => "fuck you")
join_request = JoinRequest.new(:user => user1, :music_session => music_session.music_session, :text => "fuck you")
join_request.save
join_request.valid?.should be_false
end

View File

@ -7,7 +7,7 @@ describe Mix do
@connection = FactoryGirl.create(:connection, :user => @user)
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
@music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true)
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
# @music_session.connections << @connection
@music_session.save
@connection.join_the_session(@music_session, true, nil)

View File

@ -1,23 +1,57 @@
require 'spec_helper'
describe MusicSessionHistory do
describe MusicSession do
let(:creator) {FactoryGirl.create(:user)}
let(:some_user) { FactoryGirl.create(:user) }
let(:music_session) { FactoryGirl.create(:music_session_no_history) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => music_session.creator, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) }
let(:user_history3) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => music_session.creator, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) }
let(:user_history4) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) }
let(:music_session) { FactoryGirl.create(:active_music_session_no_user_history) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user, :created_at => 2.days.ago, :session_removed_at => 1.days.ago) }
let(:user_history3) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) }
let(:user_history4) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user, :created_at => 3.days.ago, :session_removed_at => 2.days.ago) }
it "create" do
music_session.music_session_history.description.should eql(music_session.description)
describe "validations" do
it "genre must be set" do
music_session = FactoryGirl.build(:music_session)
music_session.genre = nil
music_session.save.should be_false
music_session.errors[:genre].should == ["can't be blank"]
end
it "updates the fields of a music session properly" do
genre1 = FactoryGirl.create(:genre)
genre2 = FactoryGirl.create(:genre)
genre3 = FactoryGirl.create(:genre)
genre4 = FactoryGirl.create(:genre)
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :genre => genre3)
session.update_attributes({:description => "Session2", :genre => genre1})
session.reload
session.description.should == "Session2"
session.genre.should == genre1
end
it "must have legal_terms accepted" do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.build(:music_session, :creator => user1, legal_terms: false)
music_session.save
music_session.valid?.should be_false
music_session.errors["legal_terms"].should == ["is not included in the list"]
end
it "cannot have profanity in the description" do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.build(:music_session, :creator => user1, legal_terms: false, :description => "fuck you")
music_session.save
music_session.valid?.should be_false
end
end
it "unique users" do
user_history1.should_not be_nil
user_history2.should_not be_nil
users = music_session.music_session_history.unique_users
users = music_session.music_session.unique_users
users.length.should eql(2)
@ -26,7 +60,7 @@ describe MusicSessionHistory do
user_history3.should_not be_nil
user_history4.should_not be_nil
users = music_session.music_session_history.unique_users
users = music_session.music_session.unique_users
users.length.should eql(2)
users.include?(some_user).should be_true
@ -44,7 +78,7 @@ describe MusicSessionHistory do
user_history2.session_removed_at = session_removed_at
user_history2.save!
histories = music_session.music_session_history.unique_user_histories
histories = music_session.music_session.unique_user_histories
histories.length.should eql(2)
histories[0].first_name.should_not be_nil
histories[0].last_name.should_not be_nil
@ -62,7 +96,7 @@ describe MusicSessionHistory do
user_history4.session_removed_at = session_removed_at
user_history4.save!
histories = music_session.music_session_history.unique_user_histories
histories = music_session.music_session.unique_user_histories
histories.length.should eql(2)
histories[0].total_duration.to_i.should == 2.day.to_i
histories[0].total_instruments.should == 'guitar|guitar'

View File

@ -3,7 +3,7 @@ require 'spec_helper'
describe MusicSessionPerfData do
before do
#music_session = FactoryGirl.create(:music_session)
#music_session = FactoryGirl.create(:active_music_session)
#connection = FactoryGirl.create(:connection, :music_session => music_session)
end

View File

@ -1,28 +1,20 @@
require 'spec_helper'
describe MusicSession do
describe ActiveMusicSession do
before(:each) do
MusicSession.delete_all
ActiveMusicSession.delete_all
IcecastServer.delete_all
IcecastMount.delete_all
end
describe "validations" do
it "genre must be set" do
music_session = FactoryGirl.build(:music_session)
music_session.genres = []
music_session.save.should be_false
music_session.errors[:genres].should == [ValidationMessages::SESSION_GENRE_MINIMUM_NOT_MET]
end
end
it 'can grant access to valid user' do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
user3 = FactoryGirl.create(:user) # not in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1, :musician_access => false)
music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false)
FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
FactoryGirl.create(:connection, :user => user2, :music_session => music_session)
@ -38,7 +30,7 @@ describe MusicSession do
user2 = FactoryGirl.create(:user) # in the jam session
user3 = FactoryGirl.create(:user) # not in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1, :musician_access => true)
music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => true)
music_session.can_join?(user1, true).should == true
music_session.can_join?(user2, true).should == true
@ -50,7 +42,7 @@ describe MusicSession do
user2 = FactoryGirl.create(:user) # in the jam session
user3 = FactoryGirl.create(:user) # not in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1, :musician_access => false)
music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false)
FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
music_session.can_join?(user1, true).should == true
@ -60,7 +52,7 @@ describe MusicSession do
# invite user 2
FactoryGirl.create(:friendship, :user => user1, :friend => user2)
FactoryGirl.create(:friendship, :user => user2, :friend => user1)
FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session)
FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session.music_session)
music_session.can_join?(user1, true).should == true
music_session.can_join?(user2, true).should == true
@ -72,7 +64,7 @@ describe MusicSession do
user2 = FactoryGirl.create(:user) # in the jam session
user3 = FactoryGirl.create(:user) # not in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1, :musician_access => false, :fan_access => false)
music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false, :fan_access => false)
FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
music_session.can_see?(user1).should == true
@ -82,29 +74,28 @@ describe MusicSession do
# invite user 2
FactoryGirl.create(:friendship, :user => user1, :friend => user2)
FactoryGirl.create(:friendship, :user => user2, :friend => user1)
FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session)
FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session.music_session)
music_session.can_see?(user1).should == true
music_session.can_see?(user2).should == true
music_session.can_see?(user3).should == false
end
describe "index" do
it "orders two sessions by created_at starting with most recent" do
creator = FactoryGirl.create(:user)
creator2 = FactoryGirl.create(:user)
earlier_session = FactoryGirl.create(:music_session, :creator => creator, :description => "Earlier Session")
earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session")
FactoryGirl.create(:connection, :user => creator, :music_session => earlier_session)
later_session = FactoryGirl.create(:music_session, :creator => creator2, :description => "Later Session")
later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
FactoryGirl.create(:connection, :user => creator2, :music_session => later_session)
user = FactoryGirl.create(:user)
#ActiveRecord::Base.logger = Logger.new(STDOUT)
music_sessions = MusicSession.index(user)
music_sessions = ActiveMusicSession.index(user)
music_sessions.length.should == 2
music_sessions.first.id.should == later_session.id
end
@ -113,17 +104,17 @@ describe MusicSession do
creator1 = FactoryGirl.create(:user)
creator2 = FactoryGirl.create(:user)
earlier_session = FactoryGirl.create(:music_session, :creator => creator1, :description => "Earlier Session")
earlier_session = FactoryGirl.create(:active_music_session, :creator => creator1, :description => "Earlier Session")
FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
later_session = FactoryGirl.create(:music_session, :creator => creator2, :description => "Later Session")
later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
FactoryGirl.create(:connection, :user => creator2, :music_session => later_session)
user = FactoryGirl.create(:user)
FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
FactoryGirl.create(:friendship, :user => creator1, :friend => user)
FactoryGirl.create(:friendship, :user => user, :friend => creator1)
FactoryGirl.create(:invitation, :sender => creator1, :receiver => user, :music_session => earlier_session)
FactoryGirl.create(:invitation, :sender => creator1, :receiver => user, :music_session => earlier_session.music_session)
music_sessions = MusicSession.index(user)
music_sessions = ActiveMusicSession.index(user)
music_sessions.length.should == 2
music_sessions.first.id.should == earlier_session.id
end
@ -133,9 +124,9 @@ describe MusicSession do
creator1 = FactoryGirl.create(:user)
creator2 = FactoryGirl.create(:user)
earlier_session = FactoryGirl.create(:music_session, :creator => creator1, :description => "Earlier Session")
earlier_session = FactoryGirl.create(:active_music_session, :creator => creator1, :description => "Earlier Session")
FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
later_session = FactoryGirl.create(:music_session, :creator => creator2, :description => "Later Session")
later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
FactoryGirl.create(:connection, :user => creator2, :music_session => later_session)
user = FactoryGirl.create(:user)
@ -144,41 +135,41 @@ describe MusicSession do
FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
FactoryGirl.create(:connection, :user => creator2, :music_session => earlier_session)
music_sessions = MusicSession.index(user)
music_sessions = ActiveMusicSession.index(user)
music_sessions.length.should == 2
music_sessions.first.id.should == earlier_session.id
end
it "doesn't list a session if musician_access is set to false" do
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :musician_access => false)
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :musician_access => false)
user = FactoryGirl.create(:user)
music_sessions = MusicSession.index(user)
music_sessions = ActiveMusicSession.index(user)
music_sessions.length.should == 0
end
it "does list a session if musician_access is set to false but user was invited" do
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :musician_access => false)
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :musician_access => false)
user = FactoryGirl.create(:user)
FactoryGirl.create(:connection, :user => creator, :music_session => session)
FactoryGirl.create(:friendship, :user => creator, :friend => user)
FactoryGirl.create(:friendship, :user => user, :friend => creator)
FactoryGirl.create(:invitation, :sender => creator, :receiver => user, :music_session => session)
FactoryGirl.create(:invitation, :sender => creator, :receiver => user, :music_session => session.music_session)
music_sessions = MusicSession.index(user)
music_sessions = ActiveMusicSession.index(user)
music_sessions.length.should == 1
end
it "lists a session if the genre matches" do
creator = FactoryGirl.create(:user)
genre = FactoryGirl.create(:genre)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :genres => [genre])
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :genre => genre)
FactoryGirl.create(:connection, :user => creator, :music_session => session)
user = FactoryGirl.create(:user)
music_sessions = MusicSession.index(user, genres: [genre.id])
music_sessions = ActiveMusicSession.index(user, genres: [genre.id])
music_sessions.length.should == 1
end
@ -186,37 +177,37 @@ describe MusicSession do
creator = FactoryGirl.create(:user)
genre1 = FactoryGirl.create(:genre)
genre2 = FactoryGirl.create(:genre)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :genres => [genre1])
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :genre => genre1)
user = FactoryGirl.create(:user)
music_sessions = MusicSession.index(user, genres: [genre2.id])
music_sessions = ActiveMusicSession.index(user, genres: [genre2.id])
music_sessions.length.should == 0
end
it "does not list a session if friends_only is set and no friends are in it" do
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session")
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
user = FactoryGirl.create(:user)
music_sessions = MusicSession.index(user, friends_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: true)
music_sessions.length.should == 0
end
it "lists a session properly if a friend is in it" do
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session")
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
user = FactoryGirl.create(:user)
FactoryGirl.create(:friendship, :user => creator, :friend => user)
FactoryGirl.create(:friendship, :user => user, :friend => creator)
FactoryGirl.create(:connection, :user => creator, :music_session => session)
music_sessions = MusicSession.index(user)
music_sessions = ActiveMusicSession.index(user)
music_sessions.length.should == 1
music_sessions = MusicSession.index(user, friends_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: true)
music_sessions.length.should == 1
music_sessions = MusicSession.index(user, friends_only: false, my_bands_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true)
music_sessions.length.should == 0
music_sessions = MusicSession.index(user, friends_only: true, my_bands_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: true, my_bands_only: true)
music_sessions.length.should == 1
end
@ -225,46 +216,46 @@ describe MusicSession do
# however, this bug continually crops up so the .index method will protect against this common bug
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session")
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
session.connections.delete_all # should leave a bogus, 0 participant session around
music_sessions = MusicSession.index(creator)
music_sessions = ActiveMusicSession.index(creator)
music_sessions.length.should == 0
end
it "does not list a session if my_bands_only is set and it's not my band" do
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session")
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
user = FactoryGirl.create(:user)
music_sessions = MusicSession.index(user, friends_only: false, my_bands_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true)
music_sessions.length.should == 0
end
it "lists a session properly if it's my band's session" do
band = FactoryGirl.create(:band)
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :band => band)
session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :band => band)
FactoryGirl.create(:connection, :user => creator, :music_session => session)
user = FactoryGirl.create(:user)
FactoryGirl.create(:band_musician, :band => band, :user => creator)
FactoryGirl.create(:band_musician, :band => band, :user => user)
music_sessions = MusicSession.index(user)
music_sessions = ActiveMusicSession.index(user)
music_sessions.length.should == 1
music_sessions = MusicSession.index(user, friends_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: true)
music_sessions.length.should == 0
music_sessions = MusicSession.index(user, friends_only: false, my_bands_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true)
music_sessions.length.should == 1
music_sessions = MusicSession.index(user, friends_only: true, my_bands_only: true)
music_sessions = ActiveMusicSession.index(user, friends_only: true, my_bands_only: true)
music_sessions.length.should == 1
end
describe "index(as_musician: false)" do
let(:fan_access) { true }
let(:creator) { FactoryGirl.create(:user) }
let(:session) { FactoryGirl.create(:music_session, creator: creator, fan_access: fan_access ) }
let(:session) { FactoryGirl.create(:active_music_session, creator: creator, fan_access: fan_access ) }
let(:connection) { FactoryGirl.create(:connection, user: creator, :music_session => session) }
let(:user) {FactoryGirl.create(:user) }
@ -277,13 +268,13 @@ describe MusicSession do
it "no session listed if mount is nil" do
connection.touch
sessions = MusicSession.index(user, as_musician: false)
sessions = ActiveMusicSession.index(user, as_musician: false)
sessions.length.should == 0
end
end
describe "with mount" do
let(:session_with_mount) { FactoryGirl.create(:music_session_with_mount) }
let(:session_with_mount) { FactoryGirl.create(:active_music_session_with_mount) }
let(:connection_with_mount) { FactoryGirl.create(:connection, user: creator, :music_session => session_with_mount) }
@ -293,7 +284,7 @@ describe MusicSession do
it "no session listed if icecast_server config hasn't been updated" do
connection_with_mount.touch
sessions = MusicSession.index(user, as_musician: false)
sessions = ActiveMusicSession.index(user, as_musician: false)
sessions.length.should == 0
end
@ -303,7 +294,7 @@ describe MusicSession do
session_with_mount.save!(:validate => false)
session_with_mount.mount.server.config_updated_at = 1.minute.ago
session_with_mount.mount.server.save!(:validate => false)
sessions = MusicSession.index(user, as_musician: false)
sessions = ActiveMusicSession.index(user, as_musician: false)
sessions.length.should == 1
end
end
@ -316,10 +307,10 @@ describe MusicSession do
creator = FactoryGirl.create(:user)
creator2 = FactoryGirl.create(:user)
earlier_session = FactoryGirl.create(:music_session, :creator => creator, :description => "Earlier Session")
earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session")
c1 = FactoryGirl.create(:connection, user: creator, music_session: earlier_session, addr: 0x01020304, locidispid: 1)
later_session = FactoryGirl.create(:music_session, :creator => creator2, :description => "Later Session")
later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
c2 = FactoryGirl.create(:connection, user: creator2, music_session: later_session, addr: 0x21020304, locidispid: 2)
user = FactoryGirl.create(:user)
@ -331,7 +322,7 @@ describe MusicSession do
# scores!
#ActiveRecord::Base.logger = Logger.new(STDOUT)
music_sessions = MusicSession.nindex(user, client_id: c3.client_id).take(100)
music_sessions = ActiveMusicSession.nindex(user, client_id: c3.client_id).take(100)
#music_sessions = MusicSession.index(user).take(100)
#ActiveRecord::Base.logger = nil
@ -341,50 +332,22 @@ describe MusicSession do
end
end
it "updates the fields of a music session properly" do
genre1 = FactoryGirl.create(:genre)
genre2 = FactoryGirl.create(:genre)
genre3 = FactoryGirl.create(:genre)
genre4 = FactoryGirl.create(:genre)
creator = FactoryGirl.create(:user)
session = FactoryGirl.create(:music_session, :creator => creator, :description => "Session", :genres => [genre3,genre4])
session.update_attributes({:description => "Session2", :genre => [genre1, genre2]})
session.genres = [genre1, genre2]
session.reload
session.description.should == "Session2"
session.genres.length.should == 2
session.genres[0].id.should == genre1.id
end
it 'uninvited users cant join approval-required sessions without invitation' do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1, :musician_access => true, :approval_required => true)
music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => true, :approval_required => true)
connection1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
expect { FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :joining_session => true) }.to raise_error(ActiveRecord::RecordInvalid)
end
it "must have legal_terms accepted" do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.build(:music_session, :creator => user1, :legal_terms=> false)
music_session.save
music_session.valid?.should be_false
music_session.errors["legal_terms"].should == ["is not included in the list"]
end
it "cannot have profanity in the description" do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.build(:music_session, :creator => user1, :legal_terms=> false, :description => "fuck you")
music_session.save
music_session.valid?.should be_false
end
it "is_recording? returns false if not recording" do
user1 = FactoryGirl.create(:user)
music_session = FactoryGirl.build(:music_session, :creator => user1)
music_session = FactoryGirl.build(:active_music_session, :creator => user1)
music_session.is_recording?.should be_false
end
@ -395,7 +358,7 @@ describe MusicSession do
@connection = FactoryGirl.create(:connection, :user => @user1)
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
@music_session = FactoryGirl.create(:music_session, :creator => @user1, :musician_access => true)
@music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true)
# @music_session.connections << @connection
@music_session.save!
@connection.join_the_session(@music_session, true, nil)
@ -474,7 +437,7 @@ describe MusicSession do
before(:each) do
@user1 = FactoryGirl.create(:user)
@user2 = FactoryGirl.create(:user)
@music_session = FactoryGirl.create(:music_session, :creator => @user1, :musician_access => true)
@music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true)
@connection1 = FactoryGirl.create(:connection, :user => @user1, :music_session => @music_session, :as_musician => true)
@connection2 = FactoryGirl.create(:connection, :user => @user2, :music_session => @music_session, :as_musician => false)
@ -500,14 +463,5 @@ describe MusicSession do
@music_session.get_connection_ids(exclude_client_id: @connection2.client_id, as_musician: true).should == [@connection1.client_id]
end
end
describe "autosave of music session history" do
it "is created on initial music session create" do
music_session = FactoryGirl.create(:music_session)
history = MusicSessionHistory.find(music_session.id)
history.genres.should == music_session.genres.first.id
end
end
end

View File

@ -3,11 +3,12 @@ require 'spec_helper'
describe MusicSessionUserHistory do
let(:some_user) { FactoryGirl.create(:user) }
let(:music_session) { FactoryGirl.create(:music_session_no_history) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => music_session.creator) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user) }
let(:music_session) { FactoryGirl.create(:active_music_session_no_user_history) }
let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator) }
let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user) }
describe "create" do
pending
it {user_history1.music_session_id.should == music_session.id }
it {user_history1.created_at.should_not be_nil }
it {user_history1.session_removed_at.should be_nil }
@ -15,28 +16,35 @@ describe MusicSessionUserHistory do
describe "rating" do
describe "success" do
before(:each) do
user_history1.update_attribute(:rating ,0)
end
it { user_history1.errors.any?.should be_false}
it "success" do
user_history1.update_attribute(:rating, 1)
expect( user_history1.errors.any? ).to eq(false)
end
describe "out of range" do
before(:each) do
user_history1.update_attribute(:rating, 3)
user_history1.save
end
it "out of range" do
user_history1.rating = 2
user_history1.save
expect( user_history1.errors.any? ).to eq(true)
end
it { user_history1.errors.any?.should be_true}
it 'should rate success' do
users = [user_history1, user_history2]
Timecop.travel(Time.now + (MusicSessionUserHistory::MIN_SESSION_DURATION_RATING * 1.5).seconds)
expect( user_history1.should_rate_session? ).to eq(true)
Timecop.return
end
it 'should rate fails' do
users = [user_history1]
expect( user_history1.should_rate_session? ).to eq(false)
users = [user_history1, user_history2]
expect( user_history2.should_rate_session? ).to eq(false)
end
end
describe "end_history" do
pending
it "histories created at the same time" do
user_history1.reload
user_history2.reload
@ -77,7 +85,7 @@ describe MusicSessionUserHistory do
end
it "two histories with same user within bounds of history1" do
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => some_user)
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user)
# if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
user_history1.session_removed_at = user_history1.created_at + 5
@ -98,7 +106,7 @@ describe MusicSessionUserHistory do
it "two histories with different user within bounds of history1" do
third_user = FactoryGirl.create(:user);
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => third_user)
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => third_user)
# if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
user_history1.session_removed_at = user_history1.created_at + 5
@ -119,7 +127,7 @@ describe MusicSessionUserHistory do
it "two overlapping histories with different user within bounds of history1" do
third_user = FactoryGirl.create(:user);
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => third_user)
user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => third_user)
# if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
user_history1.session_removed_at = user_history1.created_at + 5
@ -136,10 +144,7 @@ describe MusicSessionUserHistory do
user_history1.end_history
user_history1.max_concurrent_connections.should == 3
end
end
end

View File

@ -112,7 +112,7 @@ describe 'Musician search' do
connection = FactoryGirl.create(:connection, :user => usr)
instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
track = FactoryGirl.create(:track, :connection => connection, :instrument => instrument)
music_session = FactoryGirl.create(:music_session, :creator => usr, :musician_access => true)
music_session = FactoryGirl.create(:active_music_session, :creator => usr, :musician_access => true)
# music_session.connections << connection
music_session.save
connection.join_the_session(music_session, true, nil)
@ -127,7 +127,7 @@ describe 'Musician search' do
def make_session(usr)
connection = FactoryGirl.create(:connection, :user => usr)
music_session = FactoryGirl.create(:music_session, :creator => usr, :musician_access => true)
music_session = FactoryGirl.create(:active_music_session, :creator => usr, :musician_access => true)
# music_session.connections << connection
music_session.save
connection.join_the_session(music_session, true, nil)

View File

@ -9,7 +9,7 @@ describe RecordedTrack do
@user = FactoryGirl.create(:user)
@connection = FactoryGirl.create(:connection, :user => @user)
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
@music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true)
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
@recording = FactoryGirl.create(:recording, :music_session => @music_session, :owner => @user)
end

View File

@ -5,7 +5,7 @@ describe Recording do
before do
@user = FactoryGirl.create(:user)
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
@music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true)
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
@connection = FactoryGirl.create(:connection, :user => @user, :music_session => @music_session)
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
end

View File

@ -3,7 +3,7 @@ require 'spec_helper'
describe ShareToken do
let(:user) { FactoryGirl.create(:user) }
let(:music_session) {FactoryGirl.create(:music_session) }
let(:music_session) {FactoryGirl.create(:active_music_session) }
let(:claimed_recording) {FactoryGirl.create(:claimed_recording) }
before(:each) do
@ -13,9 +13,9 @@ describe ShareToken do
it "can reference a music session" do
music_session.touch # should create a MSH, and a token, too
ShareToken.count.should == 1
music_session.music_session_history.share_token.should_not be_nil
music_session.music_session.share_token.should_not be_nil
token = ShareToken.find_by_shareable_id!(music_session.id)
token.should == music_session.music_session_history.share_token
token.should == music_session.music_session.share_token
token.shareable_id.should == music_session.id
token.shareable_type.should == 'session'
end

View File

@ -3,11 +3,11 @@ require 'spec_helper'
describe Track do
let (:user) {FactoryGirl.create(:user) }
let (:music_session) { FactoryGirl.create(:music_session, :creator => user)}
let (:music_session) { FactoryGirl.create(:active_music_session, :creator => user)}
let (:connection) { FactoryGirl.create(:connection, :user => user, :music_session => music_session) }
let (:track) { FactoryGirl.create(:track, :connection => connection)}
let (:track2) { FactoryGirl.create(:track, :connection => connection)}
let (:msuh) {FactoryGirl.create(:music_session_user_history, :history => music_session.music_session_history, :user => user, :client_id => connection.client_id) }
let (:msuh) {FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user, :client_id => connection.client_id) }
let (:track_hash) { {:client_track_id => 'client_guid', :sound => 'stereo', :instrument_id => 'drums'} }
before(:each) do
@ -74,14 +74,7 @@ describe Track do
it "updates a single track using .id to correlate" do
track.id.should_not be_nil
connection.tracks.length.should == 1
begin
ActiveRecord::Base.record_timestamps = false
track.updated_at = 1.days.ago
track.save!
ensure
# very important to turn it back; it'll break all tests otherwise
ActiveRecord::Base.record_timestamps = true
end
set_updated_at(track, 1.days.ago)
tracks = Track.sync(connection.client_id, [{:id => track.id, :client_track_id => 'client_guid_new', :sound => 'mono', :instrument_id => 'drums'}])
tracks.length.should == 1
found = tracks[0]
@ -105,14 +98,7 @@ describe Track do
it "does not touch updated_at when nothing changes" do
track.id.should_not be_nil
connection.tracks.length.should == 1
begin
ActiveRecord::Base.record_timestamps = false
track.updated_at = 1.days.ago
track.save!
ensure
# very important to turn it back; it'll break all tests otherwise
ActiveRecord::Base.record_timestamps = true
end
set_updated_at(track, 1.days.ago)
tracks = Track.sync(connection.client_id, [{:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id}])
tracks.length.should == 1
found = tracks[0]

View File

@ -21,6 +21,7 @@ describe User do
it { should respond_to(:admin) }
it { should respond_to(:valid_password?) }
it { should respond_to(:can_invite) }
it { should respond_to(:mods) }
it { should be_valid }
it { should_not be_admin }
@ -69,6 +70,24 @@ describe User do
it { should_not be_valid }
end
describe "when mods is null" do
before { @user.mods = nil }
it { should be_valid }
end
describe "when mods is empty" do
before { @user.mods = 'nil' }
it { should_not be_valid }
end
describe "when mods is json object" do
before { @user.mods = '{"key":"value"}' }
it { should be_valid }
end
describe "first or last name cant have profanity" do
it "should not let the first name have profanity" do
@user.first_name = "fuck you"
@ -118,6 +137,7 @@ describe User do
it "should be saved as all lower-case" do
pending
@user.email = mixed_case_email
@user.save!
@user.reload.email.should == mixed_case_email.downcase
@ -428,6 +448,29 @@ describe User do
end
describe "mods" do
it "should allow update of JSON" do
@user.mods = {some_field: 5}.to_json
@user.save!
end
it "should return heartbeart interval" do
@user.heartbeat_interval_client.should be_nil
@user.mods = {heartbeat_interval_client: 5}.to_json
@user.save!
@user = User.find(@user.id) # necessary because mods_json is cached in the model
@user.heartbeat_interval_client.should == 5
end
it "should return connection_expire_time" do
@user.connection_expire_time_client.should be_nil
@user.mods = {connection_expire_time_client: 5}.to_json
@user.save!
@user = User.find(@user.id) # necessary because mods_json is cached in the model
@user.connection_expire_time_client.should == 5
end
end
=begin
describe "update avatar" do

View File

@ -11,7 +11,7 @@ describe MQRouter do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :ip_address => "2.2.2.2", :client_id => "2")
@ -37,7 +37,7 @@ describe MQRouter do
user1 = FactoryGirl.create(:user) # in the jam session
user2 = FactoryGirl.create(:user) # in the jam session
music_session = FactoryGirl.create(:music_session, :creator => user1)
music_session = FactoryGirl.create(:active_music_session, :creator => user1)
music_session_member1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session, :ip_address => "1.1.1.1", :client_id => "1")
music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :ip_address => "2.2.2.2", :client_id => "2")

View File

@ -154,7 +154,7 @@ describe AudioMixer do
@connection = FactoryGirl.create(:connection, :user => @user)
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
@music_session = FactoryGirl.create(:music_session, :creator => @user, :musician_access => true)
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
# @music_session.connections << @connection
@music_session.save
@connection.join_the_session(@music_session, true, nil)

View File

@ -13,7 +13,7 @@ describe GoogleAnalyticsEvent do
ResqueSpec.reset!
user = FactoryGirl.create(:user)
band = FactoryGirl.create(:band)
music_session = FactoryGirl.create(:music_session,
music_session = FactoryGirl.create(:active_music_session,
:creator => user,
:musician_access => true,
:band => band)
@ -34,7 +34,7 @@ describe GoogleAnalyticsEvent do
band.users << user
band.users << user1
band.reload
music_session = FactoryGirl.create(:music_session, :creator => user,
music_session = FactoryGirl.create(:active_music_session, :creator => user,
:musician_access => true, :band => band)
expect(band.band_musicians.count).to eq(2)
expect(band.did_real_session).to eq(false)
@ -73,7 +73,7 @@ describe GoogleAnalyticsEvent do
end
it 'reports size increment' do
user = FactoryGirl.create(:user)
music_session = FactoryGirl.create(:music_session,
music_session = FactoryGirl.create(:active_music_session,
:creator => user,
:musician_access => true)
connection = FactoryGirl.create(:connection, :user => user,
@ -88,7 +88,7 @@ describe GoogleAnalyticsEvent do
it 'reports duration' do
user = FactoryGirl.create(:user)
JamRuby::GoogleAnalyticsEvent::SessionDurationTracker.should have_schedule_size_of(0)
music_session = FactoryGirl.create(:music_session,
music_session = FactoryGirl.create(:active_music_session,
:creator => user,
:musician_access => true)
GoogleAnalyticsEvent::SessionDurationTracker.should have_schedule_size_of(1)

View File

@ -136,14 +136,7 @@ describe IcecastConfigWriter do
pending "failing on build server"
server.touch
begin
ActiveRecord::Base.record_timestamps = false
server.updated_at = Time.now.ago(APP_CONFIG.icecast_max_missing_check + 1)
server.save!
ensure
# very important to turn it back; it'll break all tests otherwise
ActiveRecord::Base.record_timestamps = true
end
set_updated_at(server, Time.now.ago(APP_CONFIG.icecast_max_missing_check + 1))
# should enqueue 1 job
IcecastConfigWriter.queue_jobs_needing_retry

View File

@ -122,6 +122,18 @@ def run_tests? type
ENV["RUN_#{type}_TESTS"] == "1" || ENV[type] == "1" || ENV['ALL_TESTS'] == "1"
end
# you have go out of your way to update 'updated_at '
def set_updated_at(resource, time)
begin
ActiveRecord::Base.record_timestamps = false
resource.updated_at = time
resource.save!(validate: false)
ensure
# very important to turn it back; it'll break all tests otherwise
ActiveRecord::Base.record_timestamps = true
end
end
def wipe_s3_test_bucket
# don't bother if the user isn't doing AWS tests
if run_tests? :aws

2
update
View File

@ -17,7 +17,7 @@ pushd pb
popd
echo ""
echo "updating database"
echo "updating ruby"
echo ""
pushd ruby
bundle update

View File

@ -5,7 +5,7 @@ unless ENV["LOCAL_DEV"] == "1"
end
# Look for $WORKSPACE, otherwise use "workspace" as dev path.
devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable
devenv = ENV["BUILD_NUMBER"].nil? || ENV["TEST_WWW"] == "1"
if devenv
gem 'jam_db', :path=> "../db/target/ruby_package"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 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: 3.5 KiB

View File

@ -15,6 +15,12 @@
'exception', 'table'
];
var log_methods = {
'log':null, 'debug':null, 'info':null, 'warn':null, 'error':null, 'assert':null, 'trace':null, 'exception':null
}
var logCache = [];
if ('undefined' === typeof(context.console)) {
context.console = {};
$.each(console_methods, function(index, value) {
@ -27,23 +33,39 @@
context.console.debug = function() { console.log(arguments); }
}
context.JK.logger = context.console;
// http://tobyho.com/2012/07/27/taking-over-console-log/
function takeOverConsole(){
var console = window.console
if (!console) return
function intercept(method){
var original = console[method]
console[method] = function(){
// JW - some code to tone down logging. Uncomment the following, and
// then do your logging to logger.dbg - and it will be the only thing output.
// TODO - find a way to wrap this up so that debug logs can stay in, but this
// class can provide a way to enable/disable certain namespaces of logs.
/*
var fakeLogger = {};
$.each(console_methods, function(index, value) {
fakeLogger[value] = $.noop;
});
fakeLogger.dbg = function(m) {
context.console.debug(m);
};
context.JK.logger = fakeLogger;
*/
logCache.push([method].concat(arguments));
if(logCache.length > 50) {
// keep the cache size 50 or lower
logCache.pop();
}
if (original.apply){
// Do this for normal browsers
original.apply(console, arguments)
}else{
// Do this for IE
var message = Array.prototype.slice.apply(arguments).join(' ')
original(message)
}
}
}
var methods = ['log', 'warn', 'error']
for (var i = 0; i < methods.length; i++)
intercept(methods[i])
}
takeOverConsole();
context.JK.logger = context.console;
context.JK.logger.logCache = logCache;
})(window, jQuery);

View File

@ -14,15 +14,22 @@
context.JK.JamServer = function (app) {
// uniquely identify the websocket connection
var channelId = null;
var clientType = null;
// heartbeat
var heartbeatInterval = null;
var heartbeatMS = null;
var heartbeatMissedMS = 10000; // if 5 seconds go by and we haven't seen a heartbeat ack, get upset
var connection_expire_time = null;
var lastHeartbeatSentTime = null;
var lastHeartbeatAckTime = null;
var lastHeartbeatFound = false;
var lastDisconnectedReason = null;
var heartbeatAckCheckInterval = null;
var notificationLastSeenAt = undefined;
var notificationLastSeen = undefined;
var clientClosedConnection = false;
// reconnection logic
var connectDeferred = null;
@ -53,17 +60,23 @@
server.connected = false;
function heartbeatStateReset() {
lastHeartbeatSentTime = null;
lastHeartbeatAckTime = null;
lastHeartbeatFound = false;
}
// if activeElementVotes is null, then we are assuming this is the initial connect sequence
function initiateReconnect(activeElementVotes, in_error) {
var initialConnect = !!activeElementVotes;
freezeInteraction = activeElementVotes && ((activeElementVotes.dialog && activeElementVotes.dialog.freezeInteraction === true) || (activeElementVotes.screen && activeElementVotes.screen.freezeInteraction === true));
if(!initialConnect) {
if (!initialConnect) {
context.JK.CurrentSessionModel.onWebsocketDisconnected(in_error);
}
if(in_error) {
if (in_error) {
reconnectAttempt = 0;
$currentDisplay = renderDisconnected();
beginReconnectPeriod();
@ -87,7 +100,7 @@
if (server.connected) {
server.connected = false;
if(app.clientUpdating) {
if (app.clientUpdating) {
// we don't want to do a 'cover the whole screen' dialog
// because the client update is already showing.
return;
@ -126,8 +139,9 @@
// check if the server is still sending heartbeat acks back down
// this logic equates to 'if we have not received a heartbeat within heartbeatMissedMS, then get upset
if (new Date().getTime() - lastHeartbeatAckTime.getTime() > heartbeatMissedMS) {
logger.error("no heartbeat ack received from server after ", heartbeatMissedMS, " seconds . giving up on socket connection");
if (new Date().getTime() - lastHeartbeatAckTime.getTime() > connection_expire_time) {
logger.error("no heartbeat ack received from server after ", connection_expire_time, " seconds . giving up on socket connection");
lastDisconnectedReason = 'NO_HEARTBEAT_ACK';
context.JK.JamServer.close(true);
}
else {
@ -140,6 +154,16 @@
var message = context.JK.MessageFactory.heartbeat(notificationLastSeen, notificationLastSeenAt);
notificationLastSeenAt = undefined;
notificationLastSeen = undefined;
// for debugging purposes, see if the last time we've sent a heartbeat is way off (500ms) of the target interval
var now = new Date();
if (lastHeartbeatSentTime) {
var drift = new Date().getTime() - lastHeartbeatSentTime.getTime() - heartbeatMS;
if (drift > 500) {
logger.error("significant drift between heartbeats: " + drift + 'ms beyond target interval')
}
}
lastHeartbeatSentTime = now;
context.JK.JamServer.send(message);
lastHeartbeatFound = false;
}
@ -147,11 +171,13 @@
function loggedIn(header, payload) {
if(!connectTimeout) {
if (!connectTimeout) {
clearTimeout(connectTimeout);
connectTimeout = null;
}
heartbeatStateReset();
app.clientId = payload.client_id;
// tell the backend that we have logged in
@ -159,12 +185,13 @@
$.cookie('client_id', payload.client_id);
heartbeatMS = payload.heartbeat_interval * 1000;
logger.debug("jamkazam.js.loggedIn(): clientId now " + app.clientId + "; Setting up heartbeat every " + heartbeatMS + " MS");
connection_expire_time = payload.connection_expire_time * 1000;
logger.debug("jamkazam.js.loggedIn(): clientId=" + app.clientId + ", heartbeat=" + payload.heartbeat_interval + "s, expire_time=" + payload.connection_expire_time + 's');
heartbeatInterval = context.setInterval(_heartbeat, heartbeatMS);
heartbeatAckCheckInterval = context.setInterval(_heartbeatAckCheck, 1000);
lastHeartbeatAckTime = new Date(new Date().getTime() + heartbeatMS); // add a little forgiveness to server for initial heartbeat
connectDeferred.resolve();
app.activeElementEvent('afterConnect', payload);
@ -209,10 +236,10 @@
function internetUp() {
var start = new Date().getTime();
server.connect()
.done(function() {
.done(function () {
guardAgainstRapidTransition(start, performReconnect);
})
.fail(function() {
.fail(function () {
guardAgainstRapidTransition(start, closedOnReconnectAttempt);
});
}
@ -224,18 +251,37 @@
function performReconnect() {
if($currentDisplay.is('.no-websocket-connection')) {
$currentDisplay.hide();
if(!clientClosedConnection) {
lastDisconnectedReason = 'WEBSOCKET_CLOSED_REMOTELY'
clientClosedConnection = false;
}
else if(!lastDisconnectedReason) {
// let's have at least some sort of type, however generci
lastDisconnectedReason = 'WEBSOCKET_CLOSED_LOCALLY'
}
rest.createDiagnostic({
type: lastDisconnectedReason,
data: {logs: logger.logCache, client_type: clientType, client_id: server.clientID, channel_id: channelId}
})
.always(function() {
if ($currentDisplay.is('.no-websocket-connection')) {
// this path is the 'not in session path'; so there is nothing else to do
$currentDisplay.hide();
// TODO: tell certain elements that we've reconnected
}
else {
// this path is the 'in session' path, where we actually reload the page
context.JK.CurrentSessionModel.leaveCurrentSession()
.always(function () {
window.location.reload();
});
}
server.reconnecting = false;
});
// TODO: tell certain elements that we've reconnected
}
else {
context.JK.CurrentSessionModel.leaveCurrentSession()
.always(function() {
window.location.reload();
});
}
server.reconnecting = false;
}
function buildOptions() {
@ -245,14 +291,14 @@
function renderDisconnected() {
var content = null;
if(freezeInteraction) {
if (freezeInteraction) {
var template = $templateDisconnected.html();
var templateHtml = $(context.JK.fillTemplate(template, buildOptions()));
templateHtml.find('.reconnect-countdown').html(formatDelaySecs(reconnectDelaySecs()));
content = context.JK.Banner.show({
html : templateHtml,
html: templateHtml,
type: 'reconnect'
}) ;
});
}
else {
var $inSituContent = $(context._.template($templateServerConnection.html(), buildOptions(), { variable: 'data' }));
@ -267,7 +313,7 @@
}
function formatDelaySecs(secs) {
return $('<span class="countdown-seconds"><span class="countdown">' + secs + '</span> ' + (secs == 1 ? ' second.<span style="visibility:hidden">s</span>' : 'seconds.') + '</span>');
return $('<span class="countdown-seconds"><span class="countdown">' + secs + '</span> ' + (secs == 1 ? ' second.<span style="visibility:hidden">s</span>' : 'seconds.') + '</span>');
}
function setCountdown($parent) {
@ -281,7 +327,7 @@
function renderReconnecting() {
$currentDisplay.find('.reconnect-progress-msg').text('Attempting to reconnect...')
if($currentDisplay.is('.no-websocket-connection')) {
if ($currentDisplay.is('.no-websocket-connection')) {
$currentDisplay.find('.disconnected-reconnect').removeClass('reconnect-enabled').addClass('reconnect-disabled');
}
else {
@ -299,7 +345,7 @@
var now = new Date().getTime();
if ((now - start) < 1500) {
setTimeout(function() {
setTimeout(function () {
nextStep();
}, 1500 - (now - start))
}
@ -315,12 +361,12 @@
renderReconnecting();
rest.serverHealthCheck()
.done(function() {
.done(function () {
guardAgainstRapidTransition(start, internetUp);
})
.fail(function(xhr, textStatus, errorThrown) {
.fail(function (xhr, textStatus, errorThrown) {
if(xhr && xhr.status >= 100) {
if (xhr && xhr.status >= 100) {
// we could connect to the server, and it's alive
guardAgainstRapidTransition(start, internetUp);
}
@ -333,7 +379,7 @@
}
function clearReconnectTimers() {
if(countdownInterval) {
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
@ -341,8 +387,8 @@
function beginReconnectPeriod() {
// allow user to force reconnect
$currentDisplay.find('a.disconnected-reconnect').unbind('click').click(function() {
if($(this).is('.button-orange') || $(this).is('.reconnect-enabled')) {
$currentDisplay.find('a.disconnected-reconnect').unbind('click').click(function () {
if ($(this).is('.button-orange') || $(this).is('.reconnect-enabled')) {
clearReconnectTimers();
attemptReconnect();
}
@ -353,9 +399,9 @@
reconnectDueTime = reconnectingWaitPeriodStart + reconnectDelaySecs() * 1000;
// update count down timer periodically
countdownInterval = setInterval(function() {
countdownInterval = setInterval(function () {
var now = new Date().getTime();
if(now > reconnectDueTime) {
if (now > reconnectDueTime) {
clearReconnectTimers();
attemptReconnect();
}
@ -404,9 +450,14 @@
};
server.connect = function () {
if(!clientType) {
clientType = context.JK.clientType();
}
connectDeferred = new $.Deferred();
logger.log("server.connect");
var uri = context.JK.websocket_gateway_uri; // Set in index.html.erb.
channelId = context.JK.generateUUID(); // create a new channel ID for every websocket connection
logger.log("connecting websocket, channel_id: " + channelId);
var uri = context.JK.websocket_gateway_uri + '?channel_id=' + channelId; // Set in index.html.erb.
//var uri = context.gon.websocket_gateway_uri; // Leaving here for now, as we're looking for a better solution.
server.socket = new context.WebSocket(uri);
@ -414,9 +465,10 @@
server.socket.onmessage = server.onMessage;
server.socket.onclose = server.onClose;
connectTimeout = setTimeout(function() {
connectTimeout = setTimeout(function () {
connectTimeout = null;
if(connectDeferred.state() === 'pending') {
if (connectDeferred.state() === 'pending') {
server.close(true);
connectDeferred.reject();
}
}, 4000);
@ -427,6 +479,7 @@
server.close = function (in_error) {
logger.log("closing websocket");
clientClosedConnection = true;
server.socket.close();
closedCleanup(in_error);
@ -435,7 +488,7 @@
server.rememberLogin = function () {
var token, loginMessage;
token = $.cookie("remember_token");
var clientType = context.jamClient.IsNativeClient() ? 'client' : 'browser';
loginMessage = msg_factory.login_with_token(token, null, clientType);
server.send(loginMessage);
};
@ -471,10 +524,11 @@
}
};
// onClose is called if either client or server closes connection
server.onClose = function () {
logger.log("Socket to server closed.");
if(connectDeferred.state() === "pending") {
if (connectDeferred.state() === "pending") {
connectDeferred.reject();
}
@ -521,19 +575,19 @@
//console.timeEnd('sendP2PMessage');
};
server.updateNotificationSeen = function(notificationId, notificationCreatedAt) {
server.updateNotificationSeen = function (notificationId, notificationCreatedAt) {
var time = new Date(notificationCreatedAt);
if(!notificationCreatedAt) {
if (!notificationCreatedAt) {
throw 'invalid value passed to updateNotificationSeen'
}
if(!notificationLastSeenAt) {
if (!notificationLastSeenAt) {
notificationLastSeenAt = notificationCreatedAt;
notificationLastSeen = notificationId;
logger.debug("updated notificationLastSeenAt with: " + notificationCreatedAt);
}
else if(time.getTime() > new Date(notificationLastSeenAt).getTime()) {
else if (time.getTime() > new Date(notificationLastSeenAt).getTime()) {
notificationLastSeenAt = notificationCreatedAt;
notificationLastSeen = notificationId;
logger.debug("updated notificationLastSeenAt with: " + notificationCreatedAt);
@ -573,6 +627,7 @@
}
function initialize() {
registerLoginAck();
registerHeartbeatAck();
registerSocketClosed();
@ -584,12 +639,24 @@
$templateServerConnection = $('#template-server-connection');
$templateDisconnected = $('#template-disconnected');
if($inSituBanner.length != 1) { throw "found wrong number of .server-connection: " + $inSituBanner.length; }
if($inSituBannerHolder.length != 1) { throw "found wrong number of .no-websocket-connection: " + $inSituBannerHolder.length; }
if($messageContents.length != 1) { throw "found wrong number of .message-contents: " + $messageContents.length; }
if($dialog.length != 1) { throw "found wrong number of #banner: " + $dialog.length; }
if($templateServerConnection.length != 1) { throw "found wrong number of #template-server-connection: " + $templateServerConnection.length; }
if($templateDisconnected.length != 1) { throw "found wrong number of #template-disconnected: " + $templateDisconnected.length; }
if ($inSituBanner.length != 1) {
throw "found wrong number of .server-connection: " + $inSituBanner.length;
}
if ($inSituBannerHolder.length != 1) {
throw "found wrong number of .no-websocket-connection: " + $inSituBannerHolder.length;
}
if ($messageContents.length != 1) {
throw "found wrong number of .message-contents: " + $messageContents.length;
}
if ($dialog.length != 1) {
throw "found wrong number of #banner: " + $dialog.length;
}
if ($templateServerConnection.length != 1) {
throw "found wrong number of #template-server-connection: " + $templateServerConnection.length;
}
if ($templateDisconnected.length != 1) {
throw "found wrong number of #template-disconnected: " + $templateDisconnected.length;
}
}
this.initialize = initialize;

View File

@ -7,18 +7,8 @@
var logger = context.JK.logger;
var myTrackCount;
var ASSIGNMENT = {
CHAT: -2,
OUTPUT: -1,
UNASSIGNED: 0,
TRACK1: 1,
TRACK2: 2
};
var VOICE_CHAT = {
NO_CHAT: "0",
CHAT: "1"
};
var ASSIGNMENT = context.JK.ASSIGNMENT;
var VOICE_CHAT = context.JK.VOICE_CHAT;
var instrument_array = [];

View File

@ -179,51 +179,42 @@
// Defaulting to 1st instrument in profile always at the moment.
data.tracks = tracks;
var jsonData = JSON.stringify(data);
$('#btn-create-session').addClass('button-disabled');
$('#btn-create-session').bind('click', false);
var url = "/api/sessions";
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: url,
processData:false,
data: jsonData,
success: function(response) {
var newSessionId = response.id;
var invitationCount = inviteMusiciansUtil.createInvitations(newSessionId, function() {
context.location = '/client#/session/' + newSessionId;
});
// Re-loading the session settings will cause the form to reset with the right stuff in it.
// This is an extra xhr call, but it keeps things to a single codepath
loadSessionSettings();
$('#btn-create-session').removeClass('button-disabled');
$('#btn-create-session').unbind('click', false);
rest.legacyCreateSession(data)
.done(function(response) {
var newSessionId = response.id;
var invitationCount = inviteMusiciansUtil.createInvitations(newSessionId, function() {
context.location = '/client#/session/' + newSessionId;
});
// Re-loading the session settings will cause the form to reset with the right stuff in it.
// This is an extra xhr call, but it keeps things to a single codepath
loadSessionSettings();
$('#btn-create-session').removeClass('button-disabled');
$('#btn-create-session').unbind('click', false);
context.JK.GA.trackSessionCount(data.musician_access, data.fan_access, invitationCount);
context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create);
},
error: function(jqXHR) {
var handled = false;
if(jqXHR.status = 422) {
var response = JSON.parse(jqXHR.responseText);
if(response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track") {
app.notifyAlert("No Inputs Configured", $('<span>You will need to reconfigure your audio device.</span>'));
handled = true;
}
}
if(!handled) {
app.notifyServerError(jqXHR, "Unable to Create Session");
}
$('#btn-create-session').removeClass('button-disabled');
$('#btn-create-session').unbind('click', false);
context.JK.GA.trackSessionCount(data.musician_access, data.fan_access, invitationCount);
context.JK.GA.trackSessionMusicians(context.JK.GA.SessionCreationTypes.create);
})
.fail(function(jqXHR) {
var handled = false;
if(jqXHR.status = 422) {
var response = JSON.parse(jqXHR.responseText);
if(response["errors"] && response["errors"]["tracks"] && response["errors"]["tracks"][0] == "Please select at least one track") {
app.notifyAlert("No Inputs Configured", $('<span>You will need to reconfigure your audio device.</span>'));
handled = true;
}
}
});
if(!handled) {
app.notifyServerError(jqXHR, "Unable to Create Session");
}
$('#btn-create-session').removeClass('button-disabled');
$('#btn-create-session').unbind('click', false);
})
return false;
}

View File

@ -286,7 +286,7 @@
function renderFeeds(feeds) {
$.each(feeds.entries, function(i, feed) {
if(feed.type == 'music_session_history') {
if(feed.type == 'music_session') {
var options = {
feed_item: feed,
status_class: feed['is_over?'] ? 'ended' : 'inprogress',

View File

@ -19,6 +19,11 @@
join : "Join"
};
var sessionQualityTypes = {
good : "Good",
poor : "Poor"
};
var invitationTypes = {
email : "Email",
facebook : "Facebook",
@ -83,6 +88,7 @@
audioTest : "AudioTest",
sessionCount : "SessionCount",
sessionMusicians : "SessionMusicians",
sessionQuality : "SessionQuality",
invite : "Invite",
findSession : "FindSession",
friendConnect : "Connect",
@ -174,6 +180,11 @@
context.ga('send', 'event', categories.sessionMusicians, joinOrCreate);
}
function trackSessionQuality(goodOrPoor) {
assertOneOf(goodOrPoor, sessionQualityTypes);
context.ga('send', 'event', categories.sessionQuality, goodOrPoor);
}
function trackServiceInvitations(invitationType, numInvited) {
assertOneOf(invitationType, invitationTypes);
assertNumber(numInvited);
@ -271,6 +282,7 @@
var GA = {};
GA.Categories = categories;
GA.SessionCreationTypes = sessionCreationTypes;
GA.SessionQualityTypes = sessionQualityTypes;
GA.InvitationTypes = invitationTypes;
GA.FriendConnectTypes = friendConnectTypes;
GA.RecordingActions = recordingActions;
@ -281,6 +293,7 @@
GA.trackFTUECompletion = trackFTUECompletion;
GA.trackSessionCount = trackSessionCount;
GA.trackSessionMusicians = trackSessionMusicians;
GA.trackSessionQuality = trackSessionQuality;
GA.trackServiceInvitations = trackServiceInvitations;
GA.trackFindSessions = trackFindSessions;
GA.virtualPageView = virtualPageView;

View File

@ -6,6 +6,8 @@
context.JK = context.JK || {};
context.JK.GearWizard = function (app) {
var ASSIGNMENT = context.JK.ASSIGNMENT;
var VOICE_CHAT = context.JK.VOICE_CHAT;
var $dialog = null;
var $wizardSteps = null;
@ -20,11 +22,11 @@
// populated by loadDevices
var deviceInformation = null;
var musicInputPorts = null;
var musicOutputPorts = null;
var musicPorts = null;
// SELECT DEVICE STATE
var validScore = false;
var validLatencyScore = false;
var validIOScore = false;
// SELECT TRACKS STATE
@ -46,7 +48,7 @@
display: 'MacOSX Built-In',
videoURL: undefined
},
MACOSX_interface: {
MacOSX_interface: {
display: 'MacOSX external interface',
videoURL: undefined
},
@ -86,13 +88,19 @@
var $bufferIn = $currentWizardStep.find('.select-buffer-in');
var $bufferOut = $currentWizardStep.find('.select-buffer-out');
var $frameSize = $currentWizardStep.find('.select-frame-size');
var $inputPorts = $currentWizardStep.find('.input-ports');
var $outputPorts = $currentWizardStep.find('.output-ports');
var $inputChannels = $currentWizardStep.find('.input-ports');
var $outputChannels = $currentWizardStep.find('.output-ports');
var $scoreReport = $currentWizardStep.find('.results');
var $latencyScoreSection = $scoreReport.find('.latency-score-section');
var $latencyScore = $scoreReport.find('.latency-score');
var $ioScoreSection = $scoreReport.find('.io-score-section');
var $ioRateScore = $scoreReport.find('.io-rate-score');
var $ioVarScore = $scoreReport.find('.io-var-score');
var $ioCountdown = $scoreReport.find('.io-countdown');
var $ioCountdownSecs = $scoreReport.find('.io-countdown .secs');
var $nextButton = $ftueButtons.find('.btn-next');
var $asioControlPanelBtn = $currentWizardStep.find('.asio-settings-btn');
var $resyncBtn = $currentWizardStep.find('resync-btn')
// should return one of:
// * MacOSX_builtin
@ -126,22 +134,31 @@
}
}
function loadDevices() {
var devices = context.jamClient.FTUEGetDevices(false);
var oldDevices = context.jamClient.FTUEGetDevices(false);
var devices = context.jamClient.FTUEGetAudioDevices();
console.log("oldDevices: " + JSON.stringify(oldDevices));
console.log("devices: " + JSON.stringify(devices));
var loadedDevices = {};
// augment these devices by determining their type
context._.each(devices, function (displayName, deviceId) {
context._.each(devices.devices, function (device) {
if(device.name == "JamKazam Virtual Monitor") {
return;
}
var deviceInfo = {};
deviceInfo.id = deviceId;
deviceInfo.type = determineDeviceType(deviceId, displayName);
deviceInfo.id = device.guid;
deviceInfo.type = determineDeviceType(device.guid, device.display_name);
console.log("deviceInfo.type: " + deviceInfo.type)
deviceInfo.displayType = audioDeviceBehavior[deviceInfo.type].display;
deviceInfo.displayName = displayName;
deviceInfo.displayName = device.display_name;
loadedDevices[deviceId] = deviceInfo;
loadedDevices[device.guid] = deviceInfo;
logger.debug("loaded device: ", deviceInfo);
})
@ -179,7 +196,7 @@
function initializeNextButtonState() {
$nextButton.removeClass('button-orange button-grey');
if (validScore) $nextButton.addClass('button-orange');
if (validLatencyScore) $nextButton.addClass('button-orange');
else $nextButton.addClass('button-grey');
}
@ -218,71 +235,66 @@
context.JK.dropdown($bufferOut);
}
// finds out if the $port argument is from a different port pair than what's currently selected
function isNewlySelectedPair($port) {
var portId = $port.attr('data-id');
// get all inputs currently selected except this one
var $selectedInputs = $inputPorts.find('input[type="checkbox"]:checked').filter('[data-id="' + portId + '"]');
console.log("$selectedInputs", $selectedInputs);
var isNewlySelected = true;
context._.each($selectedInputs, function($current) {
var testPairInfo = $($current).data('pair');
// reloads the backend's channel state for the currently selected audio devices,
// and update's the UI accordingly
function initializeChannels() {
musicPorts = jamClient.FTUEGetChannels();
console.log("musicPorts: %o", JSON.stringify(musicPorts));
context._.each(testPairInfo.ports, function(port) {
// if we can find the newly selected item in this pair, then it's not a different pair...
if(port.id == portId) {
isNewlySelected = false;
return false; // break loop
}
});
initializeInputPorts(musicPorts);
initializeOutputPorts(musicPorts);
}
if(isNewlySelected) return false; // break loop
// during this phase of the FTUE, we have to assign selected input channels
// to tracks. The user, however, does not have a way to indicate which channel
// goes to which track (that's not until the next step of the wizard).
// so, we just auto-generate a valid assignment
function newInputAssignment() {
var assigned = 0;
context._.each(musicPorts.inputs, function(inputChannel) {
if(isChannelAssigned(inputChannel)) {
assigned += 1;
}
});
return isNewlySelected;
var newAssignment = Math.floor(assigned / 2) + 1;
return newAssignment;
}
// set checkbox state for all items in the pair
function setCheckedForAllInPair($portBox, pairInfo, checked, signalBackend) {
context._.each(pairInfo.ports, function(port) {
var portId = port.id;
var $input = $portBox.find('input[type="checkbox"][data-id="' + portId + '"]');
if($input.is(':checked') != checked) {
if(checked) {
$input.iCheck('check').attr('checked', 'checked');
//context.jamClient.FTUESetMusicInput2($input.id);
}
else {
$input.iCheck('uncheck').removeAttr('checked');
//context.jamClient.FTUEUnsetMusicInput2($input.id);
}
}
})
}
function inputPortChanged() {
function inputChannelChanged() {
if(iCheckIgnore) return;
var $checkbox = $(this);
var portId = $checkbox.data('data-id');
var inputPortChecked = $checkbox.is(':checked');
console.log('inputPortChecked: ' + inputPortChecked);
var channelId = $checkbox.attr('data-id');
var isChecked = $checkbox.is(':checked');
if(inputPortChecked) {
if(isNewlySelectedPair($checkbox)) {
setCheckedForAllInPair($inputPorts, $checkbox.data('pair'), true, true);
}
else {
//context.jamClient.FTUESetMusicInput2($input.id);
}
if(isChecked) {
var newAssignment = newInputAssignment();
logger.debug("assigning input channel %o to track: %o", channelId, newAssignment);
context.jamClient.TrackSetAssignment(channelId, true, newAssignment);
}
else {
// context.jamClient.FTUEUnsetMusicInput2($input.id);;
logger.debug("unassigning input channel %o", channelId);
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.UNASSIGNED);
// unassigning creates a hole in our auto-assigned tracks. reassign them all to keep it consistent
var $assignedInputs = $inputChannels.find('input[type="checkbox"]:checked');
var assigned = 0;
context._.each($assignedInputs, function(assignedInput) {
var $assignedInput = $(assignedInput);
var assignedChannelId = $assignedInput.attr('data-id');
var newAssignment = Math.floor(assigned / 2) + 1;
logger.debug("re-assigning input channel %o to track: %o", assignedChannelId, newAssignment);
context.jamClient.TrackSetAssignment(assignedChannelId, true, newAssignment);
assigned += 1;
});
}
initializeChannels();
}
// should be called in a ifChanged callback if you want to cancel. bleh.
// should be called in a ifChanged callback if you want to cancel.
// you have to use this instead of 'return false' like a typical input 'change' event.
function cancelICheckChange($checkbox) {
iCheckIgnore = true;
var checked = $checkbox.is(':checked');
@ -293,58 +305,64 @@
}, 1);
}
function outputPortChanged() {
function outputChannelChanged() {
if(iCheckIgnore) return;
var $checkbox = $(this);
var portId = $checkbox.data('data-id');
var outputPortChecked = $checkbox.is(':checked');
console.log('outputPortChecked: ' + outputPortChecked);
var channelId = $checkbox.attr('data-id');
var isChecked = $checkbox.is(':checked');
if(outputPortChecked) {
var $selectedInputs = $outputPorts.find('input[type="checkbox"]:checked').filter('[data-id="' + portId + '"]');
$selectedInputs.iCheck('uncheck').removeAttr('checked');
var pairInfo = $checkbox.data('pair');
setCheckedForAllInPair($outputPorts, pairInfo, true, false);
console.log("Setting music output");
context.jamClient.FTUESetMusicOutput(pairInfo.ports.map(function(i) {return i.id}).join(PROFILE_DEV_SEP_TOKEN));
}
else {
context.JK.Banner.showAlert('You must have at least one output pair selected.');
// don't allow more than 2 output channels selected at once
if($outputChannels.find('input[type="checkbox"]:checked').length > 2) {
context.JK.Banner.showAlert('You can only have a maximum of 2 output ports selected.');
// can't allow uncheck of last output
cancelICheckChange($checkbox);
return;
}
if(isChecked) {
logger.debug("assigning output channel %o", channelId);
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.OUTPUT);
}
else {
logger.debug("unassigning output channel %o", channelId);
context.jamClient.TrackSetAssignment(channelId, true, ASSIGNMENT.UNASSIGNED);
}
initializeChannels();
}
function initializeInputPorts(inputPorts) {
context._.each(inputPorts, function(inputPairs) {
// there is no guarantee that a pair has two items.
context._.each(inputPairs.ports, function(inputInPair) {
var inputPort = $(context._.template($templateAudioPort.html(), inputInPair, { variable: 'data' }));
var $checkbox = inputPort.find('input');
$checkbox.data('pair', inputPairs); // so when it's selected, we can see what other ports, if any, are in the same pair
context.JK.checkbox($checkbox);
$checkbox.on('ifChanged', inputPortChanged);
$inputPorts.append(inputPort);
});
// checks if it's an assigned OUTPUT or ASSIGNED CHAT
function isChannelAssigned(channel) {
return channel.assignment == ASSIGNMENT.CHAT || channel.assignment == ASSIGNMENT.OUTPUT || channel.assignment > 0;
}
function initializeInputPorts(musicPorts) {
$inputChannels.empty();
var inputPorts = musicPorts.inputs;
context._.each(inputPorts, function(inputChannel) {
var $inputChannel = $(context._.template($templateAudioPort.html(), inputChannel, { variable: 'data' }));
var $checkbox = $inputChannel.find('input');
if(isChannelAssigned(inputChannel)) {
$checkbox.attr('checked', 'checked');
}
context.JK.checkbox($checkbox);
$checkbox.on('ifChanged', inputChannelChanged);
$inputChannels.append($inputChannel);
});
}
function initializeOutputPorts(outputPorts) {
var first = true;
context._.each(outputPorts, function(outputPairs) {
context._.each(outputPairs.ports, function(outputInPair) {
var outputPort = $(context._.template($templateAudioPort.html(), outputInPair, { variable: 'data' }));
var $checkbox = outputPort.find('input');
$checkbox.data('pair', outputPairs); // so when it's selected, we can see what other ports, if any, are in the same pair
context.JK.checkbox($checkbox);
$checkbox.on('ifChanged', outputPortChanged);
$outputPorts.append(outputPort);
});
if(first) {
first = false;
setCheckedForAllInPair($outputPorts, outputPairs, true, false);
function initializeOutputPorts(musicPorts) {
$outputChannels.empty();
var outputChannels = musicPorts.outputs;
context._.each(outputChannels, function(outputChannel) {
var $outputPort = $(context._.template($templateAudioPort.html(), outputChannel, { variable: 'data' }));
var $checkbox = $outputPort.find('input');
if(isChannelAssigned(outputChannel)) {
$checkbox.attr('checked', 'checked');
}
context.JK.checkbox($checkbox);
$checkbox.on('ifChanged', outputChannelChanged);
$outputChannels.append($outputPort);
});
}
@ -364,11 +382,11 @@
}
function clearInputPorts() {
$inputPorts.empty();
$inputChannels.empty();
}
function clearOutputPorts() {
$outputPorts.empty();
$outputChannels.empty();
}
function resetScoreReport() {
@ -377,6 +395,27 @@
$latencyScore.empty();
}
function renderLatencyScore(latencyValue, latencyClass) {
if(latencyValue) {
$latencyScore.text(latencyValue + ' ms');
}
else {
$latencyScore.text('');
}
$latencyScoreSection.removeClass('good acceptable bad unknown starting').addClass(latencyClass);
}
// std deviation is the worst value between in/out
// media is the worst value between in/out
// io is the value returned by the backend, which has more info
// ioClass is the pre-computed rollup class describing the result in simple terms of 'good', 'acceptable', bad'
function renderIOScore(std, median, ioData, ioClass) {
$ioRateScore.text(median ? median : '');
$ioVarScore.text(std ? std : '');
$ioScoreSection.removeClass('good acceptable bad unknown starting skip').addClass(ioClass);
// TODO: show help bubble of all data in IO data
}
function updateScoreReport(latencyResult) {
var latencyClass = "neutral";
var latencyValue = 'N/A';
@ -387,37 +426,69 @@
if (latencyValue <= 10) {
latencyClass = "good";
validLatency = true;
} else if (latency.latency <= 20) {
} else if (latencyValue <= 20) {
latencyClass = "acceptable";
validLatency = true;
} else {
latencyClass = "bad";
}
}
else {
latencyClass = 'unknown';
}
validScore = validLatency; // validScore may become based on IO variance too
validLatencyScore = validLatency;
$latencyScore.html(latencyValue + ' ms');
renderLatencyScore(latencyValue, latencyClass);
}
function audioInputDeviceUnselected() {
validScore = false;
validLatencyScore = false;
initializeNextButtonState();
resetFrameBuffers();
clearInputPorts();
}
function renderScoringStarted() {
validScore = false;
validLatencyScore = false;
initializeNextButtonState();
resetScoreReport();
freezeAudioInteraction();
renderLatencyScore(null, 'starting');
}
function renderScoringStopped() {
initializeNextButtonState();
unfreezeAudioInteraction();
}
function freezeAudioInteraction() {
$audioInput.attr("disabled", "disabled").easyDropDown('disable');
$audioOutput.attr("disabled", "disabled").easyDropDown('disable');
$frameSize.attr("disabled", "disabled").easyDropDown('disable');
$bufferIn.attr("disabled", "disabled").easyDropDown('disable');
$bufferOut.attr("disabled", "disabled").easyDropDown('disable');
$asioControlPanelBtn.on("click", false);
$resyncBtn.on('click', false);
iCheckIgnore = true;
$inputChannels.find('input[type="checkbox"]').iCheck('disable');
$outputChannels.find('input[type="checkbox"]').iCheck('disable');
}
function unfreezeAudioInteraction() {
$audioInput.removeAttr("disabled").easyDropDown('enable');
$audioOutput.removeAttr("disabled").easyDropDown('enable');
$frameSize.removeAttr("disabled").easyDropDown('enable');
$bufferIn.removeAttr("disabled").easyDropDown('enable');
$bufferOut.removeAttr("disabled").easyDropDown('enable');
$asioControlPanelBtn.off("click", false);
$resyncBtn.off('click', false);
$inputChannels.find('input[type="checkbox"]').iCheck('enable');
$outputChannels.find('input[type="checkbox"]').iCheck('enable');
iCheckIgnore = false;
}
// Given a latency structure, update the view.
function newFtueUpdateLatencyView(latency) {
var $report = $('.ftue-new .latency .report');
@ -506,44 +577,52 @@
});
}
function initializeAudioInputChanged() {
$audioInput.unbind('change').change(function (evt) {
function renderIOScoringStarted(secondsLeft) {
$ioCountdownSecs.text(secondsLeft);
$ioCountdown.show();
}
var audioDeviceId = selectedAudioInput();
if (!audioDeviceId) {
function renderIOScoringStopped() {
$ioCountdown.hide();
}
function renderIOCountdown(secondsLeft) {
$ioCountdownSecs.text(secondsLeft);
}
function attemptScore() {
var audioInputDeviceId = selectedAudioInput();
var audioOutputDeviceId = selectedAudioOutput();
if (!audioInputDeviceId) {
audioInputDeviceUnselected();
return false;
}
var audioDevice = findDevice(selectedAudioInput());
if (!audioDevice) {
context.JK.alertSupportedNeeded('Unable to find device information for: ' + audioDeviceId);
var audioInputDevice = findDevice(audioInputDeviceId);
if (!audioInputDevice) {
context.JK.alertSupportedNeeded('Unable to find information for input device: ' + audioInputDeviceId);
return false;
}
if(!audioOutputDeviceId) {
audioOutputDeviceId = audioInputDeviceId;
}
var audioOutputDevice = findDevice(audioOutputDeviceId);
if (!audioInputDevice) {
context.JK.alertSupportedNeeded('Unable to find information for output device: ' + audioOutputDeviceId);
return false;
}
jamClient.FTUESetInputMusicDevice(audioInputDeviceId);
jamClient.FTUESetOutputMusicDevice(audioOutputDeviceId);
renderScoringStarted();
initializeChannels();
jamClient.FTUESetMusicDevice(audioDeviceId);
// enumerate input and output ports
musicInputPorts = jamClient.FTUEGetMusicInputs2();
console.log(JSON.stringify(musicInputPorts));
// [{"inputs":[{"id":"i~5~Built-in Microph~0~0","name":"Built-in Microph - Left"},{"id":"i~5~Built-in Microph~1~0","name":"Built-in Microph - Right"}]}]
musicOutputPorts = jamClient.FTUEGetMusicOutputs2();
console.log(JSON.stringify(musicOutputPorts));
// [{"outputs":[{"id":"o~5~Built-in Output~0~0","name":"Built-in Output - Left"},{"id":"o~5~Built-in Output~1~0","name":"Built-in Output - Right"}]}]
initializeInputPorts(musicInputPorts);
initializeOutputPorts(musicOutputPorts);
jamClient.FTUESetInputLatency(selectedAudioInput());
jamClient.FTUESetOutputLatency(selectedAudioOutput());
jamClient.FTUESetInputLatency(selectedBufferIn());
jamClient.FTUESetOutputLatency(selectedBufferOut());
jamClient.FTUESetFrameSize(selectedFramesize());
renderScoringStarted();
logger.debug("Calling FTUESave(false)");
jamClient.FTUESave(false);
@ -551,8 +630,67 @@
console.log("FTUEGetExpectedLatency: %o", latency);
updateScoreReport(latency);
renderScoringStopped();
});
// if there was a valid latency score, go on to the next step
if(validLatencyScore) {
renderIOScore(null, null, null, 'starting');
var testTimeSeconds = 10; // allow 10 seconds for IO to establish itself
context.jamClient.FTUEStartIoPerfTest();
renderIOScoringStarted(testTimeSeconds);
renderIOCountdown(testTimeSeconds);
var interval = setInterval(function() {
testTimeSeconds -= 1;
renderIOCountdown(testTimeSeconds);
if(testTimeSeconds == 0) {
clearInterval(interval);
renderIOScoringStopped();
var io = context.jamClient.FTUEGetIoPerfData();
console.log("io: ", io);
// take the higher variance, which is apparently actually std dev
var std = io.in_var > io.out_var ? io.in_var : io.out_var;
std = Math.round(std * 100) / 100;
// take the furthest-off-from-target io rate
var median = Math.abs(io.in_median - io.in_target ) > Math.abs(io.out_median - io.out_target ) ? [io.in_median, io.in_target] : [io.out_median, io.out_target];
var medianTarget = median[1];
median = Math.round(median[0]);
var stdIOClass = 'bad';
if(std <= 0.50) {
stdIOClass = 'good';
}
else if(std <= 1.00) {
stdIOClass = 'acceptable';
}
var medianIOClass = 'bad';
if(Math.abs(median - medianTarget) <= 1) {
medianIOClass = 'good';
}
else if(Math.abs(median - medianTarget) <= 2) {
medianIOClass = 'acceptable';
}
// now base the overall IO score based on both values.
renderIOScore(std, median, io, ioClass);
// lie for now until IO questions finalize
validIOScore = true;
renderScoringStopped();
}
}, 1000);
}
else {
renderIOScore(null, null, null, 'skip');
renderScoringStopped();
}
}
function initializeAudioInputChanged() {
$audioInput.unbind('change').change(attemptScore);
}
function initializeAudioOutputChanged() {
@ -677,7 +815,31 @@
$currentWizardStep = null;
}
// checks if we already have a profile called 'FTUE...'; if not, create one. if so, re-use it.
function findOrCreateFTUEProfile() {
var profileName = context.jamClient.FTUEGetMusicProfileName();
logger.debug("current profile name: " + profileName);
if(profileName && profileName.indexOf('FTUE') == 0) {
}
else {
var newProfileName = 'FTUEAttempt-' + new Date().getTime().toString();
logger.debug("setting FTUE-prefixed profile name to: " + newProfileName);
context.jamClient.FTUESetMusicProfileName(newProfileName);
}
var profileName = context.jamClient.FTUEGetMusicProfileName();
logger.debug("name on exit: " + profileName);
}
function beforeShow(args) {
context.jamClient.FTUECancel();
findOrCreateFTUEProfile();
step = args.d1;
if (!step) step = 0;
step = parseInt(step);
@ -689,7 +851,7 @@
}
function afterHide() {
context.jamClient.FTUECancel();
}
function back() {

View File

@ -14,7 +14,20 @@
UNIX: "Unix"
};
// TODO: store these client_id values in instruments table, or store
context.JK.ASSIGNMENT = {
CHAT: -2,
OUTPUT: -1,
UNASSIGNED: 0,
TRACK1: 1,
TRACK2: 2
};
context.JK.VOICE_CHAT = {
NO_CHAT: "0",
CHAT: "1"
};
// TODO: store these client_id values in instruments table, or store
// server_id as the client_id to prevent maintenance nightmares. As it's
// set up now, we will have to deploy each time we add new instruments.
context.JK.server_to_client_instrument_map = {

View File

@ -32,8 +32,8 @@
$.each(response.musicians, function(index, val) {
var instrumentHtml = '';
musicianHtml += '<tr><td width="50"><a href="#" class="avatar-tiny"><img src="' + context.JK.resolveAvatarUrl(val.photo_url) + '" /></a></td>';
musicianHtml += '<td width="75"><a href="#">' + val.name + '</a></td>';
musicianHtml += '<tr><td width="50"><a user-id="' + val.id + '" profileaction="musician" class="avatar-tiny"><img src="' + context.JK.resolveAvatarUrl(val.photo_url) + '" /></a></td>';
musicianHtml += '<td width="75"><<a user-id="' + val.id + '" profileaction="musician">' + val.name + '</a></td>';
instrumentHtml = '<td><div class="nowrap">';
if (val.instruments) { // @FIXME: edge case for Test user that has no instruments?
@ -75,6 +75,8 @@
});
$(hoverSelector).append('<h2>Band Detail</h2>' + bandHtml);
context.JK.bindProfileClickEvents(hoverSelector);
configureActionButtons(response);
})
.fail(function(xhr) {

View File

@ -36,19 +36,21 @@
followingHtml += '<tr>';
}
var avatarUrl, profilePath;
var avatarUrl, attrId, type;
if (val.type === "band") {
avatarUrl = context.JK.resolveBandAvatarUrl(val.photo_url);
profilePath = "bandProfile";
attrId = "band-id";
type = "band";
}
else {
avatarUrl = context.JK.resolveAvatarUrl(val.photo_url);
profilePath = "profile";
attrId = "user-id";
type = "musician";
}
followingHtml += '<td width="24"><a href="#" class="avatar-tiny"><img src="' + avatarUrl + '" /></a></td>';
followingHtml += '<td><a href="/client#/' + profilePath + '/' + val.id + '"><strong>' + val.name + '</strong></a></td>';
followingHtml += '<td width="24"><a ' + attrId + '="' + val.id + '" profileaction="' + type + '" class="avatar-tiny"><img src="' + avatarUrl + '" /></a></td>';
followingHtml += '<td><a ' + attrId + '="' + val.id + '" profileaction="' + type + '"><strong>' + val.name + '</strong></a></td>';
if (index % 2 > 0) {
followingHtml += '</tr>';
@ -76,6 +78,8 @@
});
$(hoverSelector).append('<h2>Fan Detail</h2>' + fanHtml);
context.JK.bindProfileClickEvents(hoverSelector);
configureActionButtons(response);
})
.fail(function(xhr) {

View File

@ -42,19 +42,21 @@
followingHtml += '<tr>';
}
var avatarUrl, profilePath;
var avatarUrl, attrId, type;
if (val.type === "band") {
avatarUrl = context.JK.resolveBandAvatarUrl(val.photo_url);
profilePath = "bandProfile";
attrId = "band-id";
type = "band";
}
else {
avatarUrl = context.JK.resolveAvatarUrl(val.photo_url);
profilePath = "profile";
attrId = "user-id";
type = "musician";
}
followingHtml += '<td width="24"><a href="#" class="avatar-tiny"><img src="' + avatarUrl + '" /></a></td>';
followingHtml += '<td><a href="/client#/' + profilePath + '/' + val.id + '"><strong>' + val.name + '</strong></a></td>';
followingHtml += '<td width="24"><a ' + attrId + '="' + val.id + '" profileaction="' + type + '" class="avatar-tiny"><img src="' + avatarUrl + '" /></a></td>';
followingHtml += '<td><a ' + attrId + '="' + val.id + '" profileaction="' + type + '"><strong>' + val.name + '</strong></a></td>';
if (index % 2 > 0) {
followingHtml += '</tr>';
@ -101,6 +103,8 @@
});
$(hoverSelector).append('<h2>Musician Detail</h2>' + musicianHtml);
context.JK.bindProfileClickEvents(hoverSelector);
configureActionButtons(response);
})
.fail(function(xhr) {

View File

@ -34,6 +34,30 @@
});
}
function legacyCreateSession(options) {
return $.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/legacy",
processData:false,
data: JSON.stringify(options)});
}
function legacyJoinSession(options) {
var sessionId = options["session_id"];
delete options["session_id"];
return $.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: "/api/sessions/" + sessionId + "/participants/legacy",
data: JSON.stringify(options),
processData:false
});
}
function findSessions(query) {
return $.ajax({
type: "GET",
@ -109,7 +133,7 @@
function addPlayablePlay(playableId, playableType, claimedRecordingId, userId) {
if (playableType == 'JamRuby::Recording') {
context.JK.GA.trackRecordingPlay();
} else if (playableType == 'JamRuby::MusicSessionHistory') {
} else if (playableType == 'JamRuby::MusicSession') {
context.JK.GA.trackSessionPlay();
}
return $.ajax({
@ -961,6 +985,16 @@
url: '/api/sessions/' + musciSessionId + '/chats?' + $.param(options),
dataType: "json",
contentType: 'application/json'
})
};
function createDiagnostic(options) {
return $.ajax({
type: "POST",
url: '/api/diagnostics',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(options)
});
}
@ -970,6 +1004,8 @@
// Expose publics
this.initialize = initialize;
this.legacyCreateSession = legacyCreateSession;
this.legacyJoinSession = legacyJoinSession;
this.getUserDetail = getUserDetail;
this.getCities = getCities;
this.getRegions = getRegions;
@ -1048,6 +1084,7 @@
this.getNotifications = getNotifications;
this.createChatMessage = createChatMessage;
this.getChatMessages = getChatMessages;
this.createDiagnostic = createDiagnostic;
return this;
};

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