module JamRuby class Notification < ActiveRecord::Base self.primary_key = 'id' default_scope order('created_at DESC') 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 :recording, :class_name => "JamRuby::Recording", :foreign_key => "recording_id" def index(user_id) results = Notification.where(:target_user_id => user_id).limit(50) return results end def photo_url unless self.source_user.nil? self.source_user.photo_url end end # used for persisted notifications def formatted_msg # target_user, band, session, recording, invitation, join_request = nil source_user, band = nil unless self.source_user_id.nil? source_user = User.find(self.source_user_id) end unless self.band_id.nil? band = Band.find(self.band_id) end return self.class.format_msg(self.description, source_user, band) end # TODO: MAKE ALL METHODS BELOW ASYNC SO THE CLIENT DOESN'T BLOCK ON NOTIFICATION LOGIC # TODO: ADD TESTS FOR THIS CLASS class << self @@mq_router = MQRouter.new @@message_factory = MessageFactory.new def delete_all(session_id) Notification.delete_all "(session_id = '#{session_id}')" end ################### HELPERS ################### def retrieve_friends(connection, user_id) friend_ids = [] connection.exec("SELECT f.friend_id as friend_id FROM friendships f WHERE f.user_id = $1", [user_id]) do |friend_results| friend_results.each do |friend_result| friend_ids.push(friend_result['friend_id']) end end return friend_ids end def retrieve_user_followers(connection, user_id) follower_ids = [] connection.exec("SELECT uf.follower_id as friend_id FROM users_followers uf WHERE uf.user_id = $1", [user_id]) do |follower_results| follower_results.each do |follower_result| follower_ids.push(follower_result['follower_id']) end end return follower_ids end def retrieve_friends_not_in_session(connection, user_id, session_id) ids = retrieve_friends(connection, user_id) connection.exec("SELECT c.user_id as musician_id FROM connections c WHERE c.music_session_id = $1", [session_id]) do |musicians| musicians.each do |musician_result| # remove users who are in the session ids.reject! {|item| item == musician_result['musician_id']} end end return ids end def retrieve_friends_and_followers(connection, user_id) ids = retrieve_friends(connection, user_id) ids.concat(retrieve_user_followers(connection, user_id)) ids.uniq! {|id| id} return ids end def retrieve_friends_and_followers_not_in_session(connection, user_id, session_id) ids = retrieve_friends_and_followers(connection, user_id) connection.exec("SELECT c.user_id as musician_id FROM connections c WHERE c.music_session_id = $1", [session_id]) do |musicians| musicians.each do |musician_result| # remove users who are in the session ids.reject! {|item| item == musician_result['musician_id']} end end return ids end def retrieve_band_followers(connection, band_id) follower_ids = [] connection.exec("SELECT bf.follower_id as follower_id FROM bands_followers bf WHERE bf.band_id = $1", [band_id]) do |follower_results| follower_results.each do |follower_result| follower_ids.push(follower_result['follower_id']) end end return follower_ids end def format_msg(description, user = nil, band = nil) name = "" unless user.nil? name = user.name else name = "Someone" end case description # friend notifications when NotificationTypes::FRIEND_UPDATE return "#{name} is now " when NotificationTypes::FRIEND_REQUEST return "#{name} has sent you a friend request." when NotificationTypes::FRIEND_REQUEST_ACCEPTED return "#{name} has accepted your friend request." when NotificationTypes::FRIEND_SESSION_JOIN return "#{name} has joined the session." when NotificationTypes::NEW_USER_FOLLOWER return "#{name} is now following you on JamKazam." when NotificationTypes::NEW_BAND_FOLLOWER return "#{name} is now following your band #{band.name} on JamKazam." # session notifications when NotificationTypes::SESSION_INVITATION return "#{name} has invited you to a session." when NotificationTypes::JOIN_REQUEST return "#{name} has requested to join your session." when NotificationTypes::JOIN_REQUEST_APPROVED return "#{name} has approved your request to join the session." when NotificationTypes::JOIN_REQUEST_REJECTED return "We're sorry, but you cannot join the session at this time." # musician notifications when NotificationTypes::MUSICIAN_SESSION_JOIN return "#{name} is now in a session." when NotificationTypes::MUSICIAN_SESSION_DEPART return "#{name} has left the session." # recording notifications when NotificationTypes::MUSICIAN_RECORDING_SAVED return "#{name} has made a new recording." when NotificationTypes::BAND_RECORDING_SAVED return "#{name} has made a new recording." when NotificationTypes::RECORDING_STARTED return "#{name} has started a recording." when NotificationTypes::RECORDING_ENDED return "#{name} has stopped recording." when NotificationTypes::RECORDING_MASTER_MIX_COMPLETE return "This recording has been mastered and mixed and is ready to share." # band notifications when NotificationTypes::BAND_INVITATION return "You have been invited to join the band #{name}." when NotificationTypes::BAND_INVITATION_ACCEPTED return "#{name} has accepted your band invitation." when NotificationTypes::BAND_SESSION_JOIN return "#{name} is now in a session." else return "" end end ################### FRIEND UPDATE ################### def send_friend_update(user_id, online, connection) # (1) get all of this user's friends friend_ids = retrieve_friends(connection, user_id) unless friend_ids.blank? user = User.find(user_id) # (2) create notification online_msg = online ? "online." : "offline." notification_msg = format_msg(NotificationTypes::FRIEND_UPDATE, user) + online_msg msg = @@message_factory.friend_update( user_id, user.name, user.photo_url, online, notification_msg ) # (3) send notification @@mq_router.publish_to_friends(friend_ids, msg, user_id) end end ################### FRIEND REQUEST ################### def send_friend_request(friend_request_id, user_id, friend_id) user = User.find(user_id) friend = User.find(friend_id) # (1) save to database notification = Notification.new notification.description = NotificationTypes::FRIEND_REQUEST notification.source_user_id = user_id notification.target_user_id = friend_id notification.friend_request_id = friend_request_id notification.save notification_msg = format_msg(notification.description, user) # (2) create notification if friend.online msg = @@message_factory.friend_request( friend_request_id, user.id, user.name, user.photo_url, friend.id, notification_msg, notification.id, notification.created_at.to_s ) # (2a) send notification if user is online @@mq_router.publish_to_user(friend_id, msg) else # (2b) send email if user is offline UserMailer.friend_request(friend, notification_msg) end end ############### FRIEND REQUEST ACCEPTED ############### def send_friend_request_accepted(user_id, friend_id) friend = User.find(friend_id) user = User.find(user_id) # (1) save to database notification = Notification.new notification.description = NotificationTypes::FRIEND_REQUEST_ACCEPTED notification.source_user_id = friend_id notification.target_user_id = user_id notification.save notification_msg = format_msg(notification.description, friend) # (2) create notification if user.online msg = @@message_factory.friend_request_accepted( friend.id, friend.name, friend.photo_url, user.id, notification_msg, notification.id, notification.created_at.to_s ) # (3) send notification @@mq_router.publish_to_user(user.id, msg) else # (2b) send email if user is offline UserMailer.friend_request_accepted(user, notification_msg) end end ################## FRIEND SESSION JOIN ################## def send_friend_session_join(db_conn, connection, user) ids = retrieve_friends_not_in_session(db_conn, user.id, connection.music_session.id) unless ids.empty? # (1) bulk save to database notifications = [] ids.each do |id| notification = Notification.new notification.description = NotificationTypes::FRIEND_SESSION_JOIN notification.source_user_id = user.id notification.target_user_id = id notifications << notification end Notification.import notifications # (2) create notification msg = @@message_factory.friend_session_join( connection.music_session.id, user.id, user.name, user.photo_url) # (3) send notification @@mq_router.publish_to_friends(ids, msg, sender = {:client_id => connection.client_id}) end end ############### NEW FOLLOWER ############### def send_new_user_follower(follower, user) # (1) save to database notification = Notification.new notification.description = NotificationTypes::NEW_USER_FOLLOWER notification.source_user_id = follower.id notification.target_user_id = user.id notification.save notification_msg = format_msg(notification.description, follower) # (2) create notification if user.online msg = @@message_factory.new_user_follower( user.id, follower.name, follower.photo_url, notification_msg, notification.id, notification.created_at.to_s ) # (2a) send notification if user is online @@mq_router.publish_to_user(user.id, msg) else # (2b) send email if user is offline UserMailer.new_user_follower(user, notification_msg) end end def send_new_band_follower(follower, band) notifications = [] # these notifications go to each band member band.band_musicians.each.each do |bm| # create notifications (saved below in bulk) notification = Notification.new notification.description = NotificationTypes::NEW_BAND_FOLLOWER notification.source_user_id = follower.id notification.target_user_id = bm.user.id notifications << notification notification_msg = format_msg(notification.description, follower, band) # send notification if bm.user.online msg = @@message_factory.new_user_follower( bm.user_id, follower.name, follower.photo_url, notification_msg, notification.id, notification.created_at.to_s ) # (2a) send notification if user is online @@mq_router.publish_to_user(user.id, msg) else # (2b) send email if user is offline UserMailer.new_band_follower(user, notification_msg) end end Notification.import notifications end ################## SESSION INVITATION ################## def send_session_invitation(receiver, sender, session_id) # (1) save to database notification = Notification.new notification.description = NotificationTypes::SESSION_INVITATION notification.source_user_id = sender.id notification.target_user_id = receiver.id notification.session_id = session_id notification.save # (2) create notification if receiver.online msg = @@message_factory.session_invitation( receiver.id, sender.name, session_id, notification.id, notification.created_at.to_s ) # (2a) send notification @@mq_router.publish_to_user(receiver.id, msg) else # (2b) send email if user is offline UserMailer.session_invitation(receiver, ) end end ################## SESSION ENDED ################## def send_session_ended(music_session, connection) # TODO: this should actually publish to all users who have a notification for this session @@mq_router.server_publish_to_session(music_session, nil, sender = {:client_id => connection.client_id}) end ################## JOIN REQUEST ################## def send_join_request(music_session, join_request, text) # (1) save to database notification = Notification.new notification.description = NotificationTypes::JOIN_REQUEST notification.source_user_id = join_request.user.id notification.target_user_id = music_session.creator.id notification.session_id = music_session.id notification.save # (2) create notification notification_msg = format_msg(notification.description, join_request.user) msg = @@message_factory.join_request( join_request.id, music_session.id, join_request.user.name, join_request.user.photo_url, notification_msg, notification.id, notification.created_at.to_s ) # (3) send notification @@mq_router.publish_to_user(music_session.creator.id, msg) end ################## JOIN REQUEST APPROVED ################## def send_join_request_approved(music_session, join_request) # (1) save to database notification = Notification.new notification.description = NotificationTypes::JOIN_REQUEST_APPROVED notification.source_user_id = music_session.creator.id notification.target_user_id = join_request.user.id notification.session_id = music_session.id notification.save # (2) create notification notification_msg = format_msg(notification.description, music_session.creator) msg = @@message_factory.join_request_approved( join_request.id, music_session.id, music_session.creator.name, music_session.creator.photo_url, notification_msg, notification.id, notification.created_at.to_s ) # (3) send notification @@mq_router.publish_to_user(join_request.user.id, msg) end ################## JOIN REQUEST REJECTED ################## def send_join_request_rejected(music_session, join_request) # (1) save to database notification = Notification.new notification.description = NotificationTypes::JOIN_REQUEST_REJECTED notification.source_user_id = music_session.creator.id notification.target_user_id = join_request.user.id notification.session_id = music_session.id notification.save # (2) create notification notification_msg = format_msg(notification.description, music_session.creator) msg = @@message_factory.join_request_rejected( join_request.id, music_session.id, music_session.creator.name, music_session.creator.photo_url, notification.id, notification.created_at.to_s ) # (3) send notification @@mq_router.publish_to_user(join_request.user.id, msg) end ################## MUSICIAN SESSION JOIN ################## def send_musician_session_join(music_session, connection, user) # (1) create notification msg = @@message_factory.musician_session_join( music_session.id, user.id, user.name, user.photo_url ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => connection.client_id}) end ################## MUSICIAN SESSION DEPART ################## def send_musician_session_depart(music_session, client_id, user, recordingId = nil) # (1) create notification msg = @@message_factory.musician_session_depart( music_session.id, user.id, user.name, user.photo_url, recordingId ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id}) end ################## MUSICIAN RECORDING SAVED ################## def send_musician_recording_saved(recording, user) ids = retrieve_friends_and_followers(connection, user_id) # (1) save to database notification = Notification.new notification.description = NotificationTypes::MUSICIAN_RECORDING_SAVED notification.source_user_id = user.id notification.target_user_id = join_request.user.id notification.session_id = music_session.id notification.save # (2) create notification notification_msg = format_msg(notification.description, user) msg = @@message_factory.join_request_approved( join_request.id, music_session.id, music_session.creator.name, music_session.creator.photo_url, notification_msg, notification.id, notification.created_at.to_s ) # (3) send notification @@mq_router.publish_to_friends(ids, msg, sender = {:client_id => connection.client_id}) end ################## BAND RECORDING SAVED ################## ################## RECORDING STARTED ################## ################## RECORDING ENDED ################## ################## RECORDING MASTER MIX COMPLETE ################## ################## BAND INVITATION ################## def send_band_invitation(band, band_invitation, sender, receiver) # (1) save to database notification = Notification.new notification.band_id = band.id notification.band_invitation_id = band_invitation.id notification.description = NotificationTypes::BAND_INVITATION notification.source_user_id = sender.id notification.target_user_id = receiver.id notification.save notification_msg = format_msg(notification.description, nil, band) # (2) create notification if receiver.online msg = @@message_factory.band_invitation( band_invitation.id, band.id, receiver.id, sender.name, sender.photo_url, band.name, notification_msg, notification.id, notification.created_at.to_s ) # (3) send notification @@mq_router.publish_to_user(receiver.id, msg) else UserMailer.band_invitation(receiver, notification_msg) end end ################## BAND INVITATION ACCEPTED ################## def send_band_invitation_accepted(band, band_invitation, sender, receiver) # (1) save to database notification = Notification.new notification.band_id = band.id notification.description = NotificationTypes::BAND_INVITATION_ACCEPTED notification.source_user_id = sender.id notification.target_user_id = receiver.id notification.save notification_msg = format_msg(notification.description, sender) # (2) create notification if receiver.online msg = @@message_factory.band_invitation_accepted( band_invitation.id, receiver.id, sender.name, sender.photo_url, band.name, notification_msg, notification.id, notification.created_at.to_s ) @@mq_router.publish_to_user(receiver.id, msg) else # (2b) send email if user is offline UserMailer.band_invitation_accepted(receiver, notification_msg) end end ################## BAND SESSION JOIN ################## def send_band_session_join(music_session, band) # (1) save to database notification = Notification.new notification.band_id = band.id notification.description = NotificationTypes::BAND_SESSION_JOIN notification.source_user_id = sender.id notification.target_user_id = receiver.id notification.save # (2) create notification notification_msg = format_msg(notification.description, sender) msg = @@message_factory.band_session_join( music_session.id, receiver.id, sender.name, sender.photo_url, band.name, notification_msg, notification.id, notification.created_at.to_s ) # (3) send notification @@mq_router.publish_to_user(receiver.id, msg) end ################## MUSICIAN SESSION FRESH ################## def send_musician_session_fresh(music_session, client_id, user) # (1) create notification msg = @@message_factory.musician_session_fresh( music_session.id, user.id, user.name, user.photo_url ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id}) end ################## MUSICIAN SESSION STALE ################## def send_musician_session_stale(music_session, client_id, user) # (1) create notification msg = @@message_factory.musician_session_stale( music_session.id, user.id, user.name, user.photo_url ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id}) end end end end