ref: master
app/controllers/public/chat_controller.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
class ChatController < PublicController before_filter :login_required before_filter :check_environment_feature before_filter :can_send_message, :only => :register_message def start_session login = user.jid password = current_user.crypted_password session[:chat] ||= {:rooms => []} begin jid, sid, rid = RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind", :wait => 30, :hold => 1, :window => 5) session_data = { :jid => jid, :sid => sid, :rid => rid } render :text => session_data.to_json, :layout => false, :content_type => 'application/javascript' rescue render :action => 'start_session_error', :layout => false, :status => 500 end end def toggle session[:chat][:status] = session[:chat][:status] == 'opened' ? 'closed' : 'opened' render :nothing => true end def tab session[:chat][:tab_id] = params[:tab_id] render :nothing => true end def join session[:chat][:rooms] << params[:room_id] session[:chat][:rooms].uniq! render :nothing => true end def leave session[:chat][:rooms].delete(params[:room_id]) render :nothing => true end def my_session render :text => session[:chat].to_json, :layout => false end def avatar profile = environment.profiles.find_by(identifier: params[:id]) filename, mimetype = profile_icon(profile, :minor, true) if filename =~ /^(https?:)?\/\// redirect_to filename else data = File.read(File.join(Rails.root, 'public', filename)) render :text => data, :layout => false, :content_type => mimetype expires_in 24.hours end end def avatars profiles = environment.profiles.where(:identifier => params[:profiles]) avatar_map = profiles.inject({}) do |result, profile| result[profile.identifier] = profile_icon(profile, :minor) result end render_json avatar_map end def update_presence_status if request.xhr? current_user.update({:chat_status_at => DateTime.now}.merge(params[:status] || {})) end render :nothing => true end def save_message if request.post? to = environment.profiles.where(:identifier => params[:to]).first body = params[:body] begin ChatMessage.create!(:to => to, :from => user, :body => body) return render_json({:status => 0}) rescue Exception => exception return render_json({:status => 3, :message => exception.to_s, :backtrace => exception.backtrace}) end end end def recent_messages other = environment.profiles.find_by(identifier: params[:identifier]) if other.kind_of?(Organization) messages = ChatMessage.where('to_id=:other', :other => other.id) else messages = ChatMessage.where('(to_id=:other and from_id=:me) or (to_id=:me and from_id=:other)', {:me => user.id, :other => other.id}) end messages = messages.order('created_at DESC').includes(:to, :from).offset(params[:offset]).limit(20) messages_json = messages.map do |message| { :body => message.body, :to => {:id => message.to.identifier, :name => message.to.name}, :from => {:id => message.from.identifier, :name => message.from.name}, :created_at => message.created_at } end render :json => messages_json.reverse end def recent_conversations profiles = Profile.find_by_sql("select profiles.* from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc") jids = profiles.map(&:jid).reverse render :json => jids.to_json end #TODO Ideally this is done through roster table on ejabberd. def rosters rooms = user.memberships.map {|m| {:jid => m.jid, :name => m.name}} friends = user.friends.map {|f| {:jid => f.jid, :name => f.name}} rosters = {:rooms => rooms, :friends => friends} render :text => rosters.to_json end def availabilities current_user.update_column(:chat_status_at, DateTime.now) availabilities = user.friends.map do |friend| status = friend.user.chat_status status = 'offline' if status.blank? || !friend.user.chat_alive? {:jid => friend.jid, :status => status} end render :text => availabilities.to_json end protected def check_environment_feature unless environment.enabled?('xmpp_chat') render_not_found return end end def can_send_message return render_json({:status => 1, :message => 'Missing parameters!'}) if params[:from].nil? || params[:to].nil? || params[:message].nil? return render_json({:status => 2, :message => 'You can not send message as another user!'}) if params[:from] != user.jid # TODO Maybe register the jid in a table someday to avoid this below return render_json({:status => 3, :messsage => 'You can not send messages to strangers!'}) if user.friends.where(:identifier => params[:to].split('@').first).blank? end def render_json(result) render :text => result.to_json end end |