diff --git a/admin/Gemfile b/admin/Gemfile index a14387965..7ca5eda28 100644 --- a/admin/Gemfile +++ b/admin/Gemfile @@ -11,6 +11,7 @@ else gem 'jam_db', "0.1.#{ENV["BUILD_NUMBER"]}" gem 'jampb', "0.1.#{ENV["BUILD_NUMBER"]}" gem 'jam_ruby', "0.1.#{ENV["BUILD_NUMBER"]}" + ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true" end gem 'rails' diff --git a/admin/app/admin/icecast_bootstrap.rb b/admin/app/admin/icecast_bootstrap.rb index 5a87155d7..90aac8826 100644 --- a/admin/app/admin/icecast_bootstrap.rb +++ b/admin/app/admin/icecast_bootstrap.rb @@ -222,7 +222,7 @@ ActiveAdmin.register_page "Bootstrap" do elsif IcecastMountTemplate.count == 0 semantic_form_for IcecastMountTemplate.new, :url => admin_bootstrap_create_mount_template_path, :builder => ActiveAdmin::FormBuilder do |f| f.inputs "New Mount Template" do - f.input :hostname, :label => "jam-web hostname:port" + f.input :hostname, :label => "jam-web public hostname:port (such that icecast can reach it)" f.input :default_mime_type, :as => :select, :collection => ["ogg", "mp3"] end f.actions diff --git a/admin/app/admin/user_progression.rb b/admin/app/admin/user_progression.rb index cbd54744c..6ea4bb285 100644 --- a/admin/app/admin/user_progression.rb +++ b/admin/app/admin/user_progression.rb @@ -70,6 +70,13 @@ ActiveAdmin.register JamRuby::User, :as => 'User Progression' do '' end end + column 'Recorded' do |uu| + if dd = uu.first_recording_at + dd.strftime(PROGRESSION_DATE) + else + '' + end + end column 'Promoted' do |uu| if dd = uu.first_social_promoted_at dd.strftime(PROGRESSION_DATE) @@ -77,10 +84,6 @@ ActiveAdmin.register JamRuby::User, :as => 'User Progression' do '' end end - column 'Recorded' do |uu| - uu.first_recording_at - end - end end diff --git a/admin/app/controllers/application_controller.rb b/admin/app/controllers/application_controller.rb index ba9580ff2..a28952746 100644 --- a/admin/app/controllers/application_controller.rb +++ b/admin/app/controllers/application_controller.rb @@ -4,7 +4,6 @@ class ApplicationController < ActionController::Base before_filter :prepare_gon def prepare_gon - gon.another = 'hello' gon.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] || '/' end end diff --git a/admin/config/unicorn.rb b/admin/config/unicorn.rb index 6a901300b..de93769c2 100644 --- a/admin/config/unicorn.rb +++ b/admin/config/unicorn.rb @@ -32,7 +32,7 @@ listen 3100, :tcp_nopush => true timeout 30 # feel free to point this anywhere accessible on the filesystem -pid "/var/run/jam-admin.pid" +pid "/var/run/jam-admin/jam-admin.pid" # By default, the Unicorn logger will write to stderr. # Additionally, ome applications/frameworks log to stderr or stdout, diff --git a/admin/jenkins b/admin/jenkins index cfc6734ab..9a8e7e5b8 100755 --- a/admin/jenkins +++ b/admin/jenkins @@ -7,24 +7,6 @@ echo "starting build..." if [ "$?" = "0" ]; then echo "build succeeded" - - if [ ! -z "$PACKAGE" ]; then - if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* ]]; then - echo "publishing ubuntu package (.deb)" - DEBPATH=`find target/deb -name *.deb` - DEBNAME=`basename $DEBPATH` - - curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME - - if [ "$?" != "0" ]; then - echo "deb publish failed" - exit 1 - fi - echo "done publishing deb" - else - echo "Skipping publish since branch is neither master or develop..." - fi - fi else echo "build failed" exit 1 diff --git a/admin/script/package/jam-admin.conf b/admin/script/package/jam-admin.conf index 7c5fbc998..43e8a34cc 100644 --- a/admin/script/package/jam-admin.conf +++ b/admin/script/package/jam-admin.conf @@ -3,5 +3,7 @@ description "jam-admin" start on startup start on runlevel [2345] stop on runlevel [016] +setuid jam-admin +setgid jam-admin exec start-stop-daemon --start --chdir /var/lib/jam-admin --exec /var/lib/jam-admin/script/package/upstart-run.sh diff --git a/admin/script/package/post-install.sh b/admin/script/package/post-install.sh index 1ed894877..9949dce43 100755 --- a/admin/script/package/post-install.sh +++ b/admin/script/package/post-install.sh @@ -14,7 +14,9 @@ mkdir -p /var/lib/$NAME/log mkdir -p /var/lib/$NAME/tmp mkdir -p /etc/$NAME mkdir -p /var/log/$NAME +mkdir -p /var/run/$NAME chown -R $USER:$GROUP /var/lib/$NAME chown -R $USER:$GROUP /etc/$NAME chown -R $USER:$GROUP /var/log/$NAME +chown -R $USER:$GROUP /var/run/$NAME diff --git a/build b/build new file mode 100755 index 000000000..6fc0ce391 --- /dev/null +++ b/build @@ -0,0 +1,133 @@ +#!/bin/bash + +# RUN_SLOW_TESTS, RUN_AWS_TESTS, SKIP_KARMA=1 SHOW_JS_ERRORS=1 PACKAGE=1 +# WORKSPACE=/var/lib/jenkins/jobs/jam-web/workspace + +export BUNDLE_JOBS=1 # 6, which i want to use, makes the whole server crawl + +echo "" + +echo "BUILDING JAM-DB" +pushd db > /dev/null + ./jenkins +popd > /dev/null + +echo "" + +echo "BUILDING JAM-PB" +pushd pb > /dev/null +bash -l ./jenkins +popd > /dev/null + +echo "" + +echo "BUILDING JAM-RUBY" +pushd ruby > /dev/null +rm -f *.gem +bash -l ./jenkins +popd > /dev/null + +echo "" + +echo "BUILDING WEBSOCKET GATEWAY" +pushd websocket-gateway > /dev/null +bash -l ./jenkins +popd > /dev/null + +echo "" + +echo "BUILDING JAM-WEB" +pushd web > /dev/null +echo "kill any stuck rspec tests from previous run. need to debug how/why this happens on build server" +set +e +ps aux | grep -ie "jam-cloud.*rspec" | awk '{print $2}' | xargs kill -9 +set -e + +PACKAGE=1 bash ./jenkins + +# we do this so that the build won't fail in jenkins if no capybara error screenshot isn't there +mkdir -p tmp/capybara +touch tmp/capybara/success.png +popd > /dev/null + +echo "" + +echo "BUILDING JAM-ADMIN" +pushd admin /dev/null +bash -l ./jenkins +popd > /dev/null + + +if [ ! -z "$PACKAGE" ]; then + +DEB_SERVER=http://localhost:9010/apt-`uname -p` +GEM_SERVER=http://localhost:9000/gems + + # if still going, then push all debs up + if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* ]]; then + + echo "" + echo "PUSHING DB ARTIFACTS" + pushd db > /dev/null + echo "publishing ubuntu packages (.deb)" + for f in `find target -name '*.deb'`; do + DEBNAME=`basename $f` + DEBPATH="$f" + echo "publishing $DEBPATH to deb server" + curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME + if [ "$?" != "0" ]; then + echo "deb publish failed of $DEBPATH" + exit 1 + fi + done + echo "done publishing debs" + popd > /dev/null + + + echo "" + echo "PUSHING WEB" + pushd web > /dev/null + echo "publishing ubuntu package (.deb)" + DEBPATH=`find target/deb -name *.deb` + DEBNAME=`basename $DEBPATH` + curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME + if [ "$?" != "0" ]; then + echo "deb publish failed" + exit 1 + fi + echo "done publishing deb" + popd > /dev/null + + echo "" + echo "PUSHING WEBSOCKET-GATEWAY" + pushd websocket-gateway > /dev/null + echo "publishing ubuntu package (.deb)" + DEBPATH=`find target/deb -name *.deb` + DEBNAME=`basename $DEBPATH` + curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME + if [ "$?" != "0" ]; then + echo "deb publish failed" + exit 1 + fi + echo "done publishing deb" + popd > /dev/null + + echo "" + echo "PUSHING ADMIN" + pushd admin > /dev/null + echo "publishing ubuntu package (.deb)" + DEBPATH=`find target/deb -name *.deb` + DEBNAME=`basename $DEBPATH` + curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME + if [ "$?" != "0" ]; then + echo "deb publish failed" + exit 1 + fi + echo "done publishing deb" + popd > /dev/null + + else + echo "Skipping publish since branch is neither master or develop..." + fi + +fi \ No newline at end of file diff --git a/db/jenkins b/db/jenkins index 3c3f5b055..275cb28a4 100755 --- a/db/jenkins +++ b/db/jenkins @@ -8,37 +8,17 @@ echo "starting build..." if [ "$?" = "0" ]; then echo "build succeeded" - if [[ "$GIT_BRANCH" == *develop* || "$GIT_BRANCH" == *master* ]]; then - echo "publishing gem" - pushd "target/ruby_package" - find . -name *.gem -exec curl -f -T {} $GEM_SERVER/{} \; + echo "publishing gem" + pushd "target/ruby_package" + find . -name *.gem -exec curl -f -T {} $GEM_SERVER/{} \; - if [ "$?" != "0" ]; then - echo "publish failed" - exit 1 - fi + if [ "$?" != "0" ]; then + echo "publish failed" + exit 1 + fi - popd - echo "done publishing gems" - - if [ ! -z "$PACKAGE" ]; then - echo "publishing ubuntu packages (.deb)" - for f in `find target -name '*.deb'`; do - DEBNAME=`basename $f` - DEBPATH="$f" - echo "publishing $DEBPATH to deb server" - curl -f -T $DEBPATH $DEB_SERVER/$DEBNAME - if [ "$?" != "0" ]; then - echo "deb publish failed of $DEBPATH" - exit 1 - fi - done - - echo "done publishing debs" - fi - else - echo "Skipping publish since branch is neither master or develop..." - fi + popd + echo "done publishing gems" else echo "build failed" exit 1 diff --git a/db/manifest b/db/manifest index 7825af66d..ec3b567a2 100755 --- a/db/manifest +++ b/db/manifest @@ -93,4 +93,7 @@ music_sessions_unlogged.sql integrate_icecast_into_sessions.sql ms_recording_anonymous_likes.sql ms_user_history_add_instruments.sql -icecast_config_changed.sql \ No newline at end of file +icecast_config_changed.sql +invited_users_facebook_support.sql +first_recording_at.sql +share_token.sql \ No newline at end of file diff --git a/db/up/first_recording_at.sql b/db/up/first_recording_at.sql new file mode 100644 index 000000000..1052ca36f --- /dev/null +++ b/db/up/first_recording_at.sql @@ -0,0 +1 @@ +alter table users add column first_recording_at TIMESTAMP; \ No newline at end of file diff --git a/db/up/invited_users_facebook_support.sql b/db/up/invited_users_facebook_support.sql new file mode 100644 index 000000000..efc79b5de --- /dev/null +++ b/db/up/invited_users_facebook_support.sql @@ -0,0 +1,3 @@ +ALTER TABLE invited_users ALTER COLUMN email DROP NOT NULL; +ALTER TABLE invited_users ADD COLUMN invite_medium VARCHAR(64); + diff --git a/db/up/share_token.sql b/db/up/share_token.sql new file mode 100644 index 000000000..0eb2f643f --- /dev/null +++ b/db/up/share_token.sql @@ -0,0 +1,2 @@ +alter table music_sessions_history add column share_token varchar(15); +alter table claimed_recordings add column share_token varchar(15); \ No newline at end of file diff --git a/pb/jenkins b/pb/jenkins index 2d3bb662f..74e4ccbb0 100755 --- a/pb/jenkins +++ b/pb/jenkins @@ -10,7 +10,7 @@ if [ "$?" = "0" ]; then echo "publishing gem" pushd "target/ruby/jampb" find . -name *.gem -exec curl -f -T {} $GEM_SERVER/{} \; - + if [ "$?" != "0" ]; then echo "publish failed" exit 1 diff --git a/ruby/Gemfile b/ruby/Gemfile index f8a1643ac..1925a2033 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -6,6 +6,15 @@ end devenv = ENV["BUILD_NUMBER"].nil? # Jenkins sets a build number environment variable +if devenv + gem 'jam_db', :path=> "../db/target/ruby_package" + gem 'jampb', :path => "../pb/target/ruby/jampb" +else + gem 'jam_db' + gem 'jampb' + ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true" +end + gem 'pg', '0.15.1', :platform => [:mri, :mswin, :mingw] gem 'jdbc_postgres', :platform => [:jruby] @@ -33,14 +42,6 @@ gem 'resque-lonely_job', '~> 1.0.0' gem 'oj' gem 'builder' -if devenv - gem 'jam_db', :path=> "../db/target/ruby_package" - gem 'jampb', :path => "../pb/target/ruby/jampb" -else - gem 'jam_db' - gem 'jampb' -end - group :test do gem "factory_girl", '4.1.0' gem "rspec", "2.11" diff --git a/ruby/jenkins b/ruby/jenkins index e80e1c1b9..8d4742fc6 100755 --- a/ruby/jenkins +++ b/ruby/jenkins @@ -26,7 +26,7 @@ EOF echo "publishing gem" curl -f -T $GEMNAME $GEM_SERVER/$GEMNAME - + if [ "$?" != "0" ]; then echo "publish failed" exit 1 diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index ce77bf09d..6ab7a51bb 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -31,6 +31,7 @@ require "jam_ruby/lib/profanity" require "jam_ruby/lib/em_helper.rb" require "jam_ruby/resque/audiomixer" require "jam_ruby/resque/icecast_config_writer" +require "jam_ruby/resque/resque_hooks" require "jam_ruby/resque/scheduled/audiomixer_retry" require "jam_ruby/resque/scheduled/icecast_config_retry" require "jam_ruby/resque/scheduled/icecast_source_check" diff --git a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb index a443f9c6d..ce1a007ac 100644 --- a/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb +++ b/ruby/lib/jam_ruby/app/mailers/invited_user_mailer.rb @@ -48,7 +48,8 @@ module JamRuby end def generate_signup_url(invited_user) - "http://www.jamkazam.com/signup?invitation_code=#{invited_user.invitation_code}" + invited_user.generate_signup_url + # "http://www.jamkazam.com/signup?invitation_code=#{invited_user.invitation_code}" end end end diff --git a/ruby/lib/jam_ruby/models/band.rb b/ruby/lib/jam_ruby/models/band.rb index 1ae5b26a0..e40817623 100644 --- a/ruby/lib/jam_ruby/models/band.rb +++ b/ruby/lib/jam_ruby/models/band.rb @@ -63,8 +63,15 @@ module JamRuby end def recent_history - recordings = ClaimedRecording.joins(:recordings).where(:recordings => {:band_id => "#{self.id}"}).limit(10) - msh = MusicSessionHistory.where(:band_id => self.id).limit(10) + recordings = ClaimedRecording.joins(:recordings) + .where(:recordings => {:band_id => "#{self.id}"}) + .order('created_at DESC') + .limit(10) + + msh = MusicSessionHistory.where(:band_id => self.id) + .order('created_at DESC') + .limit(10) + recordings.concat(msh) recordings.sort! {|a,b| b.created_at <=> a.created_at}.first(5) end diff --git a/ruby/lib/jam_ruby/models/claimed_recording.rb b/ruby/lib/jam_ruby/models/claimed_recording.rb index 6764150b5..7396b9a6a 100644 --- a/ruby/lib/jam_ruby/models/claimed_recording.rb +++ b/ruby/lib/jam_ruby/models/claimed_recording.rb @@ -15,6 +15,10 @@ module JamRuby has_many :recorded_tracks, :through => :recording, :class_name => "JamRuby::RecordedTrack" has_many :playing_sessions, :class_name => "JamRuby::MusicSession" + before_create :generate_share_token + + SHARE_TOKEN_LENGTH = 8 + # user must own this object # params is a hash, and everything is optional def update_fields(user, params) @@ -42,5 +46,20 @@ module JamRuby self.destroy end end + + def remove_non_alpha_num(token) + token.gsub(/[^0-9A-Za-z]/, '') + end + + private + + def generate_share_token + self.share_token = loop do + token = SecureRandom.urlsafe_base64(SHARE_TOKEN_LENGTH, false) + token = remove_non_alpha_num(token) + token.upcase! + break token unless MusicSessionHistory.exists?(share_token: token) + end + end end end diff --git a/ruby/lib/jam_ruby/models/icecast_server.rb b/ruby/lib/jam_ruby/models/icecast_server.rb index 588f4abea..e8fe4a7ed 100644 --- a/ruby/lib/jam_ruby/models/icecast_server.rb +++ b/ruby/lib/jam_ruby/models/icecast_server.rb @@ -3,8 +3,9 @@ module JamRuby attr_accessor :skip_config_changed_flag - attr_accessible :template_id, :mount_template_id, :limit_id, :admin_auth_id, :directory_id, :master_relay_id, :path_id, :logging_id, - :security_id, :config_changed, :config_updated_at, :hostname, :location, :admin_email, :fileserve, :icecast_server_group_id, as: :admin + attr_accessible :template_id, :mount_template_id, :limit_id, :admin_auth_id, :directory_id, :master_relay_id, + :path_id, :logging_id, :security_id, :config_changed, :config_updated_at, :hostname, :location, + :admin_email, :fileserve, :icecast_server_group_id, :server_id, as: :admin belongs_to :template, class_name: "JamRuby::IcecastTemplate", foreign_key: 'template_id', inverse_of: :servers diff --git a/ruby/lib/jam_ruby/models/invited_user.rb b/ruby/lib/jam_ruby/models/invited_user.rb index 6481a6bdb..579766cf7 100644 --- a/ruby/lib/jam_ruby/models/invited_user.rb +++ b/ruby/lib/jam_ruby/models/invited_user.rb @@ -14,13 +14,15 @@ module JamRuby belongs_to :sender , :inverse_of => :invited_users, :class_name => "JamRuby::User", :foreign_key => "sender_id" # who is the invitation sent to? - validates :email, :presence => true, format: {with: VALID_EMAIL_REGEX} + validates :email, format: {with: VALID_EMAIL_REGEX}, :if => lambda { |iu| iu.email.present? } validates :autofriend, :inclusion => {:in => [nil, true, false]} validates :invitation_code, :presence => true validates :note, length: {maximum: 400}, no_profanity: true # 400 == arbitrary. + validate :one_facebook_invite_per_user, :if => lambda { |iu| iu.invite_medium == FB_MEDIUM } validate :valid_personalized_invitation - validate :not_accepted_twice + # validate :not_accepted_twice + validate :not_accepted_twice, :if => lambda { |iu| iu.email } validate :can_invite? after_save :track_user_progression @@ -31,6 +33,12 @@ module JamRuby self.sender_id = nil if self.sender_id.blank? # this coercion was done just to make activeadmin work end + FB_MEDIUM = 'facebook' + + def self.facebook_invite(user) + where(:sender_id => user.id, :invite_medium => FB_MEDIUM).limit(1).first + end + def track_user_progression self.sender.update_progression_field(:first_invited_at) unless self.sender.nil? end @@ -54,6 +62,15 @@ module JamRuby def invited_by_administrator? sender.nil? || sender.admin # a nil sender can only be created by someone using jam-admin end + + def generate_signup_url + if 'development'==Rails.env + "http://jamkazamdev.local:3000/signup?invitation_code=#{self.invitation_code}" + else + "http://www.jamkazam.com/signup?invitation_code=#{self.invitation_code}" + end + end + private def can_invite? @@ -67,5 +84,12 @@ module JamRuby def not_accepted_twice errors.add(:accepted, "you can only accept an invitation once") if accepted_twice end + + def one_facebook_invite_per_user + rel = InvitedUser.where(:invite_medium => FB_MEDIUM, :sender_id => self.sender_id) + rel = rel.where(['id != ?',self.id]) if self.id + errors.add(:invite_medium, "one facebook invite allowed per user") if 0 < rel.count + end + end end diff --git a/ruby/lib/jam_ruby/models/invited_user_observer.rb b/ruby/lib/jam_ruby/models/invited_user_observer.rb index a4a007a93..cd62bd2d1 100644 --- a/ruby/lib/jam_ruby/models/invited_user_observer.rb +++ b/ruby/lib/jam_ruby/models/invited_user_observer.rb @@ -8,7 +8,7 @@ module JamRuby InvitedUserMailer.welcome_betauser(invited_user).deliver else InvitedUserMailer.friend_invitation(invited_user).deliver - end + end if invited_user.email.present? end end -end \ No newline at end of file +end diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 929da08ba..d280e4f4e 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -9,6 +9,7 @@ module JamRuby 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_history, :class_name => "JamRuby::MusicSessionHistory" has_one :mount, :class_name => "JamRuby::IcecastMount", :inverse_of => :music_session, :foreign_key => 'music_session_id' has_many :connections, :class_name => "JamRuby::Connection" diff --git a/ruby/lib/jam_ruby/models/music_session_comment.rb b/ruby/lib/jam_ruby/models/music_session_comment.rb index 71fa8ae9a..b23383b33 100644 --- a/ruby/lib/jam_ruby/models/music_session_comment.rb +++ b/ruby/lib/jam_ruby/models/music_session_comment.rb @@ -7,8 +7,13 @@ module JamRuby default_scope order('created_at DESC') - belongs_to :music_session, :class_name => "JamRuby::MusicSessionHistory", :foreign_key => "music_session_id" - belongs_to :user, :class_name => "JamRuby::User", :foreign_key => "creator_id" + belongs_to(:music_session_history, + :class_name => "JamRuby::MusicSessionHistory", + :foreign_key => "music_session_id") + + belongs_to(:user, + :class_name => "JamRuby::User", + :foreign_key => "creator_id") end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/music_session_history.rb b/ruby/lib/jam_ruby/models/music_session_history.rb index 7b552c08b..8b3c787d3 100644 --- a/ruby/lib/jam_ruby/models/music_session_history.rb +++ b/ruby/lib/jam_ruby/models/music_session_history.rb @@ -15,10 +15,18 @@ module JamRuby :foreign_key => :band_id, :inverse_of => :music_session_history) - has_many :music_session_user_history, :class_name => "JamRuby::MusicSessionUserHistory", :foreign_key => "music_session_id" + 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" has_many :comments, :class_name => "JamRuby::MusicSessionComment", :foreign_key => "music_session_id" has_many :likes, :class_name => "JamRuby::MusicSessionLiker", :foreign_key => "music_session_id" + before_create :generate_share_token + + SHARE_TOKEN_LENGTH = 8 + SEPARATOR = '|' def comment_count @@ -31,12 +39,12 @@ module JamRuby def tracks tracks = [] - self.music_session_user_history.each do |msuh| + self.music_session_user_histories.each do |msuh| user = User.find(msuh.user_id) instruments = msuh.instruments.split(SEPARATOR) instruments.each do |instrument| t = Track.new - t.user = user + t.musician = user t.instrument_id = instrument tracks << t end @@ -79,11 +87,33 @@ module JamRuby .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() + session_history = MusicSessionHistory.new end session_history.music_session_id = music_session.id @@ -119,15 +149,18 @@ module JamRuby hist.end_history if hist end - def duration_minutes - end_time = self.session_removed_at || Time.now - (end_time - self.created_at) / 60.0 + def remove_non_alpha_num(token) + token.gsub(/[^0-9A-Za-z]/, '') end - def music_session_user_histories - @msuh ||= JamRuby::MusicSessionUserHistory - .where(:music_session_id => self.music_session_id) - .order('created_at DESC') + private + def generate_share_token + self.share_token = loop do + token = SecureRandom.urlsafe_base64(SHARE_TOKEN_LENGTH, false) + token = remove_non_alpha_num(token) + token.upcase! + break token unless MusicSessionHistory.exists?(share_token: token) + end end end diff --git a/ruby/lib/jam_ruby/models/music_session_liker.rb b/ruby/lib/jam_ruby/models/music_session_liker.rb index a7d89fc72..538822c6e 100644 --- a/ruby/lib/jam_ruby/models/music_session_liker.rb +++ b/ruby/lib/jam_ruby/models/music_session_liker.rb @@ -5,8 +5,13 @@ module JamRuby self.primary_key = 'id' - belongs_to :music_session, :class_name => "JamRuby::MusicSessionHistory", :foreign_key => "music_session_id" - belongs_to :user, :class_name => "JamRuby::User", :foreign_key => "liker_id" + belongs_to(:music_session_history, + :class_name => "JamRuby::MusicSessionHistory", + :foreign_key => "music_session_id") + + belongs_to(:user, + :class_name => "JamRuby::User", + :foreign_key => "liker_id") end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/recorded_track.rb b/ruby/lib/jam_ruby/models/recorded_track.rb index b67ec410d..69933a560 100644 --- a/ruby/lib/jam_ruby/models/recorded_track.rb +++ b/ruby/lib/jam_ruby/models/recorded_track.rb @@ -29,6 +29,9 @@ module JamRuby validate :validate_part_complete validate :validate_too_many_upload_failures + def musician + self.user + end def can_download?(some_user) !ClaimedRecording.find_by_user_id_and_recording_id(some_user.id, recording.id).nil? diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index dfc0b2195..450385067 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -156,6 +156,8 @@ module JamRuby # the user votes to keep their tracks for this recording def keep(user) recorded_tracks_for_user(user).update_all(:discard => false) + + User.where(:id => user.id).update_all(:first_recording_at => Time.now ) unless user.first_recording_at end diff --git a/ruby/lib/jam_ruby/models/track.rb b/ruby/lib/jam_ruby/models/track.rb index 21f45c40f..d91f00f42 100644 --- a/ruby/lib/jam_ruby/models/track.rb +++ b/ruby/lib/jam_ruby/models/track.rb @@ -7,6 +7,8 @@ module JamRuby default_scope order('created_at ASC') + attr_accessor :musician + SOUND = %w(mono stereo) belongs_to :connection, :class_name => "JamRuby::Connection", :inverse_of => :tracks @@ -18,6 +20,14 @@ module JamRuby self.connection.user end + def musician + @musician + end + + def musician=(user) + @musician = user + end + def self.index(current_user, music_session_id) query = Track .joins( diff --git a/ruby/lib/jam_ruby/models/user.rb b/ruby/lib/jam_ruby/models/user.rb index 17c5cfc47..00011b407 100644 --- a/ruby/lib/jam_ruby/models/user.rb +++ b/ruby/lib/jam_ruby/models/user.rb @@ -147,7 +147,7 @@ module JamRuby scope :musicians_geocoded, musicians.geocoded_users def user_progression_fields - @user_progression_fields ||= Set.new ["first_downloaded_client_at", "first_ran_client_at", "first_music_session_at", "first_real_music_session_at", "first_good_music_session_at", "first_certified_gear_at", "first_invited_at", "first_friended_at", "first_social_promoted_at" ] + @user_progression_fields ||= Set.new ["first_downloaded_client_at", "first_ran_client_at", "first_music_session_at", "first_real_music_session_at", "first_good_music_session_at", "first_certified_gear_at", "first_invited_at", "first_friended_at", "first_recording_at", "first_social_promoted_at" ] end def update_progression_field(field_name, time = DateTime.now) @@ -290,8 +290,15 @@ module JamRuby end def recent_history - recordings = ClaimedRecording.joins(:recording).where(:recordings => {:owner_id => "#{self.id}"}).limit(10) - msh = MusicSessionHistory.where(:user_id => self.id).limit(10) + recordings = ClaimedRecording.joins(:recording) + .where(:recordings => {:owner_id => "#{self.id}"}) + .order('created_at DESC') + .limit(10) + + msh = MusicSessionHistory.where(:user_id => self.id) + .order('created_at DESC') + .limit(10) + recordings.concat(msh) recordings.sort! {|a,b| b.created_at <=> a.created_at}.first(5) end @@ -1000,10 +1007,17 @@ module JamRuby end end - def first_recording_at - Recording.where(:owner_id => self.id).order('created_at ASC').first.try(:created_at) + def facebook_invite! + unless iu = InvitedUser.facebook_invite(self) + iu = InvitedUser.new + iu.sender = self + iu.autofriend = true + iu.invite_medium = InvitedUser::FB_MEDIUM + iu.save + end + iu end - + # devise compatibility #def encrypted_password diff --git a/ruby/lib/jam_ruby/resque/google_analytics_event.rb b/ruby/lib/jam_ruby/resque/google_analytics_event.rb new file mode 100644 index 000000000..30c08084b --- /dev/null +++ b/ruby/lib/jam_ruby/resque/google_analytics_event.rb @@ -0,0 +1,43 @@ +class GoogleAnalyticsEvent + + @queue = 'google_analytics_event' + + @@log = Logging.logger[GoogleAnalyticsEvent] + + def self.perform(category, action) + + @@log.info("starting (#{category}, #{action})") + + run(category, action) + + @@log.info("done (#{category}, #{action})") + + end + + def self.enqueue(category, event) + begin + Resque.enqueue(AudioMixer, category, event) + true + rescue + # implies redis is down. but since there is no retry logic with this, we should at least log a warn in case we've configured something wrong + @@log.warn("unable to enqueue") + false + end + end + + def self.run(category, action) + + raise "no google analytics tracking ID" unless APP_CONFIG.ga_ua + + params = { + v: APP_CONFIG.ga_ua_version, + tid: APP_CONFIG.ga_ua, + cid: APP_CONFIG.ga_anonymous_client_id, + t: "event", + ec: category, + ea: action + } + + RestClient.post(APP_CONFIG.ga_endpoint, params: params, timeout: 8, open_timeout: 8) + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/resque/icecast_config_writer.rb b/ruby/lib/jam_ruby/resque/icecast_config_writer.rb index bbecffa29..a02761e7b 100644 --- a/ruby/lib/jam_ruby/resque/icecast_config_writer.rb +++ b/ruby/lib/jam_ruby/resque/icecast_config_writer.rb @@ -30,6 +30,11 @@ module JamRuby "icecast-#{server_id}" end + def self.lock_timeout + # this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job + 60 + end + def self.perform(icecast_server_id) icecast = IcecastConfigWriter.new() icecast.icecast_server_id = icecast_server_id diff --git a/ruby/lib/jam_ruby/resque/resque_hooks.rb b/ruby/lib/jam_ruby/resque/resque_hooks.rb new file mode 100644 index 000000000..567c931e7 --- /dev/null +++ b/ruby/lib/jam_ruby/resque/resque_hooks.rb @@ -0,0 +1,10 @@ +# https://devcenter.heroku.com/articles/forked-pg-connections +Resque.before_fork do + defined?(ActiveRecord::Base) and + ActiveRecord::Base.connection.disconnect! +end + +Resque.after_fork do + defined?(ActiveRecord::Base) and + ActiveRecord::Base.establish_connection +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/resque/scheduled/IcecastSourceCheck.rb b/ruby/lib/jam_ruby/resque/scheduled/IcecastSourceCheck.rb deleted file mode 100644 index 4d1577637..000000000 --- a/ruby/lib/jam_ruby/resque/scheduled/IcecastSourceCheck.rb +++ /dev/null @@ -1,32 +0,0 @@ -require 'json' -require 'resque' -require 'resque-retry' -require 'net/http' -require 'digest/md5' - -module JamRuby - - # http://blog.bignerdranch.com/1643-never-use-resque-for-serial-jobs/ - # periodically scheduled to find sources that need to be brought down, or alternatively, it seems the client failed to start sourcing - class IcecastSourceCheck - - @queue = :icecast_source_check - - @@log = Logging.logger[IcecastSourceCheck] - - def self.perform - @@log.debug("waking up") - - # if we haven't seen updated_at be tickled in 5 minutes, but config_changed is still set to TRUE, this record has gotten stale - IcecastMount.find_each(:conditions => "sourced_needs_changing_at < (NOW() - interval '#{APP_CONFIG.icecast_max_sourced_changed} second')", :batch_size => 100) do |server| - server.with_lock do - IcecastConfigWriter.enqueue(server.server_id) - end - - end - - @@log.debug("done") - end - end - -end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/resque/scheduled/audiomixer_retry.rb b/ruby/lib/jam_ruby/resque/scheduled/audiomixer_retry.rb index 34e7571cb..7b9b338c9 100644 --- a/ruby/lib/jam_ruby/resque/scheduled/audiomixer_retry.rb +++ b/ruby/lib/jam_ruby/resque/scheduled/audiomixer_retry.rb @@ -8,11 +8,17 @@ module JamRuby # periodically scheduled to find jobs that need retrying class AudioMixerRetry + extend Resque::Plugins::LonelyJob @queue = :audiomixer_retry @@log = Logging.logger[AudioMixerRetry] + def self.lock_timeout + # this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job + 120 + end + def self.perform AudioMixer.queue_jobs_needing_retry end diff --git a/ruby/lib/jam_ruby/resque/scheduled/icecast_config_retry.rb b/ruby/lib/jam_ruby/resque/scheduled/icecast_config_retry.rb index 340e9a05f..cbc7c6209 100644 --- a/ruby/lib/jam_ruby/resque/scheduled/icecast_config_retry.rb +++ b/ruby/lib/jam_ruby/resque/scheduled/icecast_config_retry.rb @@ -8,11 +8,17 @@ module JamRuby # periodically scheduled to find jobs that need retrying class IcecastConfigRetry + extend Resque::Plugins::LonelyJob @queue = :icecast_config_retry @@log = Logging.logger[IcecastConfigRetry] + def self.lock_timeout + # this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job + 120 + end + def self.perform @@log.debug("waking up") diff --git a/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb b/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb index d832f4d2d..236c6814e 100644 --- a/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb +++ b/ruby/lib/jam_ruby/resque/scheduled/icecast_source_check.rb @@ -11,12 +11,14 @@ module JamRuby class IcecastSourceCheck extend Resque::Plugins::LonelyJob - @queue = :icecast_source_check - @@log = Logging.logger[IcecastSourceCheck] + def self.lock_timeout + # this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job + 120 + end def self.perform @@log.debug("waking up") @@ -28,6 +30,7 @@ module JamRuby @@log.debug("done") end + def run # if we haven't seen updated_at be tickled in 5 minutes, but config_changed is still set to TRUE, this record has gotten stale IcecastMount.find_each(lock: true, :conditions => "sourced_needs_changing_at < (NOW() - interval '#{APP_CONFIG.icecast_max_sourced_changed} second')", :batch_size => 100) do |mount| if mount.music_session_id diff --git a/ruby/spec/jam_ruby/models/claimed_recording_spec.rb b/ruby/spec/jam_ruby/models/claimed_recording_spec.rb index bca0b4b0e..9b0026c6e 100644 --- a/ruby/spec/jam_ruby/models/claimed_recording_spec.rb +++ b/ruby/spec/jam_ruby/models/claimed_recording_spec.rb @@ -112,4 +112,17 @@ describe ClaimedRecording do duplicate.errors[:recording_id].should == ['has already been taken'] end end + + describe "remove_non_alpha_num" do + + let(:instance) { ClaimedRecording.new } + + it "removes hyphen" do + instance.remove_non_alpha_num("abc-").should == 'abc' + end + + it "leaves good alone" do + instance.remove_non_alpha_num("JDnfHsimMQ").should == 'JDnfHsimMQ' + end + end end \ No newline at end of file diff --git a/ruby/spec/jam_ruby/models/invited_user_spec.rb b/ruby/spec/jam_ruby/models/invited_user_spec.rb index 0ccf6865e..ca4288939 100644 --- a/ruby/spec/jam_ruby/models/invited_user_spec.rb +++ b/ruby/spec/jam_ruby/models/invited_user_spec.rb @@ -104,4 +104,28 @@ describe InvitedUser do invited_user.valid?.should be_false end + it 'accepts empty emails' do + user1 = FactoryGirl.create(:user) + invited_user = FactoryGirl.create(:invited_user, :sender_id => user1.id, :email => '') + expect(invited_user.valid?).to eq(true) + end + + it 'accepts one facebook invite per user' do + user1 = FactoryGirl.create(:user) + invited_user = FactoryGirl.create(:invited_user, :sender_id => user1.id, :invite_medium => InvitedUser::FB_MEDIUM) + expect(invited_user.valid?).to eq(true) + invited_user.autofriend = !invited_user.autofriend + invited_user.save + expect(invited_user.valid?).to eq(true) + invited_user1 = InvitedUser.new(:email => 'foobar@example.com', :sender_id => user1.id) + invited_user1.autofriend = true + invited_user1.invite_medium = InvitedUser::FB_MEDIUM + invited_user1.save + expect(invited_user1.valid?).to eq(false) + expect(InvitedUser.facebook_invite(user1).id).to eq(invited_user.id) + user2 = FactoryGirl.create(:user) + iu = user1.facebook_invite! + expect(user1.facebook_invite!.id).to eq(iu.id) + end + end diff --git a/ruby/spec/jam_ruby/models/recording_spec.rb b/ruby/spec/jam_ruby/models/recording_spec.rb index 0cc9d3e13..19b9f8f8c 100644 --- a/ruby/spec/jam_ruby/models/recording_spec.rb +++ b/ruby/spec/jam_ruby/models/recording_spec.rb @@ -230,6 +230,15 @@ describe Recording do downloads["downloads"].length.should == 1 end + it "should mark first_recording_at" do + @recording = Recording.start(@music_session, @user) + @recording.stop + @recording.claim(@user, "Recording", "Recording Description", Genre.first, true, true) + @user.first_recording_at.should be_nil + @user.reload + @user.first_recording_at.should_not be_nil + end + describe "chance for everyone to keep or discard" do before(:each) do @user2 = FactoryGirl.create(:user) diff --git a/runadmin b/runadmin new file mode 100755 index 000000000..648a2a9ac --- /dev/null +++ b/runadmin @@ -0,0 +1,6 @@ +#!/bin/bash + +pushd admin +# run jam-admin rails server +bundle exec rails s +popd diff --git a/runjobs b/runjobs new file mode 100755 index 000000000..babe280ff --- /dev/null +++ b/runjobs @@ -0,0 +1,6 @@ +#!/bin/bash + +pushd web +# run all_jobs rake task; this waits on new jobs from the resque queue, i.e., audiomixer, icecast, etc +bundle exec rake all_jobs +popd diff --git a/runtests b/runtests new file mode 100755 index 000000000..8211e4004 --- /dev/null +++ b/runtests @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e +echo "" + +pushd ruby > /dev/null + echo "RUNNING RUBY TESTS" + bundle exec rspec +popd > /dev/null + +echo "" + +pushd web > /dev/null + echo "RUNNING WEB TESTS" + bundle exec rspec +popd > /dev/null + +echo "" + +pushd admin > /dev/null + echo "RUNNING ADMIN TESTS" + bundle exec rspec +popd > /dev/null + +echo "" + +pushd websocket-gateway > /dev/null + echo "RUNNING WEBSOCKET-GATEWAY TESTS" + bundle exec rspec +popd > /dev/null + +echo "TESTS PASSED" diff --git a/web/Gemfile b/web/Gemfile index c99aa6213..884ae244b 100644 --- a/web/Gemfile +++ b/web/Gemfile @@ -17,6 +17,7 @@ else gem 'jampb', "0.1.#{ENV["BUILD_NUMBER"]}" gem 'jam_ruby', "0.1.#{ENV["BUILD_NUMBER"]}" gem 'jam_websockets', "0.1.#{ENV["BUILD_NUMBER"]}" + ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'] ||= "true" end gem 'builder' gem 'rails', '>=3.2.11' @@ -105,6 +106,7 @@ group :test, :cucumber do # gem 'rb-fsevent', '0.9.1', :require => false # gem 'growl', '1.0.3' gem 'poltergeist' + gem 'resque_spec' end diff --git a/web/app/assets/javascripts/band_setup.js b/web/app/assets/javascripts/band_setup.js index 8bb64150e..9ab0aafe7 100644 --- a/web/app/assets/javascripts/band_setup.js +++ b/web/app/assets/javascripts/band_setup.js @@ -198,7 +198,7 @@ } else { band.id = bandId; - rest.updateBand(band, bandId).done(function(response) { + rest.updateBand(band).done(function(response) { createBandInvitations(band.id, function() { context.location = "#/bandProfile/" + band.id; }); diff --git a/web/app/assets/javascripts/createSession.js b/web/app/assets/javascripts/createSession.js index ae3e5ff92..2d2c58f10 100644 --- a/web/app/assets/javascripts/createSession.js +++ b/web/app/assets/javascripts/createSession.js @@ -200,8 +200,8 @@ invitationDialog.showGoogleDialog(); }); - $('div[layout-id="createSession"] .btn-facebook-invitation').click(function() { - invitationDialog.showFacebookDialog(); + $('div[layout-id="createSession"] .btn-facebook-invitation').click(function(e) { + invitationDialog.showFacebookDialog(e); }); $('#friend-input').focus(function() { $(this).val(''); }) diff --git a/web/app/assets/javascripts/ga.js b/web/app/assets/javascripts/ga.js index deb5fdb5e..297f27f76 100644 --- a/web/app/assets/javascripts/ga.js +++ b/web/app/assets/javascripts/ga.js @@ -30,6 +30,53 @@ accept : "Accept" }; + var recordingActions = { + make : "Make", + share : "Share" + }; + + var recordingShareTypes = { + facebook : "Facebook", + syndicationWidget : "SyndWidget", + syndicationUrl: "SyndURL" + }; + + var recordingPlayActions = { + website : "Website", + client : "Client", + facebook : "Facebook", + syndicationWidget : "SyndWidget", + syndicationUrl: "SyndURL" + }; + + var sessionPlayActions = { + website : "Website", + client : "Client", + facebook : "Facebook", + syndicationWidget : "SyndWidget", + syndicationUrl: "SyndURL" + }; + + var userLabels = { + registeredUser : "RegisteredUser", + visitor: "Visitor" + }; + + var bandActions = { + create : "Create", + join : "Join", + session : "Session", + recording : "Recording" + }; + + var jkSocialTargets = { + musician : 'Musician', + band : 'Band', + fan : 'Fan', + recording : 'Recording', + session : 'Session' + }; + var categories = { register : "Register", download : "DownloadClient", @@ -38,7 +85,15 @@ sessionMusicians : "SessionMusicians", invite : "Invite", findSession : "FindSession", - friendConnect : "Connect" + friendConnect : "Connect", + recording : "Recording", + recordingPlay : "RecordingPlay", + sessionPlay : "SessionPlay", + band : "Band", + jkLike : 'jkLike', + jkFollow : 'jkFollow', + jkFavorite : 'jkFavorite', + jkComment : 'jkComment' }; @@ -161,10 +216,56 @@ context.ga('send', 'event', categories.friendConnect, friendConnectType); } + // when someone keeps a recording + function trackMakeRecording() { + context.ga('send', 'event', categories.recording, recordingActions.make); + } + + // when someone shares a recording + function trackShareRecording(shareType) { + assertOneOf(shareType, recordingShareTypes); + + context.ga('send', 'event', categories.recording, recordingActions.share, shareType); + } + + // when someone plays a recording + function trackRecordingPlay(recordingAction) { + assertOneOf(recordingAction, recordingPlayActions); + var label = JK.currentUserId ? userLabels.registeredUser : userLabels.visitor; + + context.ga('send', 'event', categories.recordingPlay, recordingAction, label); + } + + // when someone plays a live session broadcast + function trackSessionPlay(recordingAction) { + assertOneOf(recordingAction, sessionPlayActions); + var label = JK.currentUserId ? userLabels.registeredUser : userLabels.visitor; + + context.ga('send', 'event', categories.sessionPlay, recordingAction, label); + } + + function trackBand(bandAction) { + assertOneOf(bandAction, bandActions); + + context.ga('send', 'event', categories.band, bandAction); + } + + function trackJKSocial(category, target) { + assertOneOf(category, categories); + assertOneOf(target, jkSocialTargets); + + context.ga('send', 'event', category, target); + } + + var GA = {}; + GA.Categories = categories; GA.SessionCreationTypes = sessionCreationTypes; GA.InvitationTypes = invitationTypes; GA.FriendConnectTypes = friendConnectTypes; + GA.RecordingActions = recordingActions; + GA.BandActions = bandActions; + GA.JKSocialTargets = jkSocialTargets; GA.trackRegister = trackRegister; GA.trackDownload = trackDownload; GA.trackFTUECompletion = trackFTUECompletion; @@ -174,6 +275,13 @@ GA.trackFindSessions = trackFindSessions; GA.virtualPageView = virtualPageView; GA.trackFriendConnect = trackFriendConnect; + GA.trackMakeRecording = trackMakeRecording; + GA.trackShareRecording = trackShareRecording; + GA.trackRecordingPlay = trackRecordingPlay; + GA.trackSessionPlay = trackSessionPlay; + GA.trackBand = trackBand; + GA.trackJKSocial = trackJKSocial; + context.JK.GA = GA; diff --git a/web/app/assets/javascripts/invitationDialog.js b/web/app/assets/javascripts/invitationDialog.js index a3c569f59..f268554b7 100644 --- a/web/app/assets/javascripts/invitationDialog.js +++ b/web/app/assets/javascripts/invitationDialog.js @@ -1,5 +1,4 @@ (function(context,$) { - "use strict"; context.JK = context.JK || {}; context.JK.InvitationDialog = function(app) { @@ -7,6 +6,7 @@ var rest = context.JK.Rest(); var waitForUserToStopTypingTimer; var sendingEmail = false; + var fbInviteURL_ = null; function trackMetrics(emails, googleInviteCount) { var allInvitations = emails.length; // all email invites, regardless of how they got in the form @@ -152,49 +152,114 @@ }; window._oauth_win = window.open("/auth/google_login", "_blank", "height=500,width=500,menubar=no,resizable=no,status=no"); } + + ////////////// + // FB handlers - function showFacebookDialog() { - /* - $('#invitation-textarea-container').hide(); - $('#invitation-checkbox-container').show(); - $('#btn-send-invitation').hide(); - $('#btn-next-invitation').show(); - invitationDialog.showDialog(); - $('#invitation-checkboxes').html('