class WsChatController < WsController require 'message_builder' def start_polling_messages connection_store[:clients].each do |client| client.add_message_callback do |message| #noinspection RubyAssignmentExpressionInConditionalInspection if message.body process_incoming_message(message.from, message.to, message.body, message.attribute('chat_id').to_s) elsif request = message.first_element('sync_contacts_request') # toto mozem prijat len ako admin multichatu send_contacts(message.from, message.to, request.attribute('chat_id').to_s) elsif answer = message.first_element('synced_contacts') # toto mozem prijat len ako ucastnik multichatu (nie admin) contacts = xml_contacts_to_array(answer) set_contacts_in_multichat(find_client(message.to.strip.to_s), answer.attribute('chat_id').to_s, message.from.to_s, contacts) sync_contacts_frontend(message.from, message.to, answer.attribute('chat_id').to_s, contacts) elsif answer = message.first_element('exported_chat') contacts = xml_contacts_to_array(message.first_element('exported_chat')) import_people_in_chat(message.from, message.to, answer.attribute('chat_id').to_s, contacts) elsif message.attribute('destroy_multichat') destroy_multichat(message.to, message.attribute('chat_id').to_s) elsif message.attribute('req_update_contacts') added = xml_contacts_to_array(message.first_element('added')) removed = xml_contacts_to_array(message.first_element('removed')) update_attendants_in_multichat(message.from, message.to, message.attribute('chat_id').to_s, removed, added) elsif message.attribute('new_owner') make_me_new_owner(message.to, message.attribute('chat_id').to_s) end #TODO: upozornit na pisanie spravy #TODO: odoslat informaciu o tom, ze pisem spravu #else # send_message 'app.chat.messageState', # state: message.chat_state, # from: message.from.strip.to_s, # to: message.to.strip.to_s, # message: message.body, # chat_id: if message.attribute(:is_simulating) then message.attribute(:chat_id) end end end end def make_me_new_owner(me, chat_id) client = find_client(me.strip.to_s) connection_store[:opened_chats][client][chat_id][:attendants] -= [me.to_s] connection_store[:opened_chats][client][chat_id][:attendants] += [connection_store[:opened_chats][client][chat_id][:owner]] connection_store[:opened_chats][client][chat_id][:owner] = me.to_s contacts = connection_store[:opened_chats][client][chat_id][:attendants] contacts.each do |contact| client.send(MessageBuilder::send_multichat_contacts(client.jid.to_s, contact, chat_id, contacts)) end send_message 'app.chat.makeMeNewOwner', me: me.strip.to_s, chat_id: chat_id end def import_people_in_chat(owner, me, chat_id, contacts) #Rails.logger.debug ['imported chat arrived', message.to_s, chat_id] client = find_client(me.strip.to_s) set_contacts_in_multichat(client, chat_id, owner.to_s, contacts) send_message 'app.chat.importChat', owner: owner.strip.to_s, chat_id: chat_id, contacts: strip_all(contacts) end # Owner vytvori najprv u seba novy multichat def new_multichat me = message[:chatOwner] hash = Digest::SHA2.hexdigest(me) chat_id = hash + Time.now.to_f.to_s client = find_client(me) set_contacts_in_multichat(client, chat_id, client.jid.to_s) trigger_success id: chat_id end # Owner posle novemu cloveku informaciu o chat_id a kontaktoch def add_to_multichat client = find_client(message[:chatOwner]) chat_id = message[:chatId] add = message[:jid] add_resource = find_multichat_supported(add) if add_resource connection_store[:opened_chats][client][chat_id][:attendants] << add_resource #Rails.logger.debug ['adding to multichat', add_resource] contacts = connection_store[:opened_chats][client][chat_id][:attendants] contacts.each do |contact| client.send(MessageBuilder::export_multichat(client.jid.to_s, contact, chat_id, contacts)) end trigger_success else #Rails.logger.debug ['adding to multichat failure', connection_store[:presences][add]] trigger_failure end end def send_chat_message me = message[:from] client = find_client(me) my_jid = client.jid.to_s if client chat_id = message[:chatId] if chat_id attendants = connection_store[:opened_chats][client][chat_id][:attendants] + [connection_store[:opened_chats][client][chat_id][:owner]] attendants -= [my_jid] messages = MessageBuilder::build_multi_messages(message[:message], my_jid, attendants, chat_id) else messages = [MessageBuilder::build_message(message[:message], my_jid, message[:to])] end # Xmpp4r doesn't support XEP-0033 (multicast messages) messages.each do |message| client.send(message) end stripped_me = client.jid.strip.to_s stripped_to = Jabber::JID.new(message[:to]).strip!.to_s if can_save_conversation?(stripped_me, stripped_to, chat_id) Rails.logger.debug ['saving sent message', stripped_me] save_encrypted_message(message[:message], stripped_me, stripped_me, stripped_to, chat_id) end trigger_success message[:message] else trigger_failure end end def request_sync_chat_contacts client = find_client(message[:me]) chat_id = message[:chatId] owner = connection_store[:opened_chats][client][chat_id][:owner] client.send(MessageBuilder::ask_for_multichat_contacts(client.jid.strip.to_s, owner, chat_id)) end def i_closed_multichat chat_id = message[:chatId] client = find_client(message[:me]) me = client.jid.to_s owner = connection_store[:opened_chats][client][chat_id][:owner] if owner == me attendants = connection_store[:opened_chats][client][chat_id][:attendants] attendants.each do |attendant| client.send(MessageBuilder::kick_from_multichat(me, attendant, chat_id)) end else changes = {removed: [me]} client.send(MessageBuilder::req_update_multichat_contacts(me, owner, chat_id, changes)) end connection_store[:opened_chats][client].delete(chat_id) end def kick_from_multichat chat_id = message[:chatId] client = find_client(message[:me]) kick_stripped = message[:kick] kick = find_full_jid_in_multichat(kick_stripped, client, chat_id) return if kick.nil? contacts = connection_store[:opened_chats][client][chat_id][:attendants] contacts -= [kick] connection_store[:opened_chats][client][chat_id][:attendants] = contacts client.send(MessageBuilder::kick_from_multichat(client.jid.to_s, kick, chat_id)) if contacts.empty? connection_store[:opened_chats][client].delete(chat_id) send_message 'app.chat.destroyMultichat', chat_id: chat_id else contacts.each do |contact| client.send(MessageBuilder::send_multichat_contacts(client.jid.to_s, contact, chat_id, contacts)) end end end def switch_ownership chat_id = message[:chatId] client = find_client(message[:me]) new_owner = message[:newOwner] new_owner_jid = find_full_jid_in_multichat(new_owner, client, chat_id) client.send(MessageBuilder::make_new_owner(client.jid.to_s, new_owner_jid, chat_id)) if new_owner_jid end def can_save_conversation?(stripped_me = nil, stripped_attendant = nil, chat_id = nil) me = message[:me] || stripped_me attendant = message[:attendant] || stripped_attendant _chat_id = message[:chatId] || chat_id result = User.can_save_conversation?(me, attendant, _chat_id) if message[:me] trigger_success result else result end end def set_history_saving save = message[:enable] me = message[:me] attendant = message[:attendant] chat_id = message[:chatId] trigger_failure unless find_client(me) save = save.is_a?(FalseClass) ? 0 : 1 User.set_history_saving(save, me, attendant, chat_id) && trigger_success end def load_history me = message[:me] attendant = message[:attendant] chat_id = message[:chatId] page = message[:step] per_page = 10 client = find_client(me) trigger_failure unless client history = History.page_history(me, attendant || chat_id, page, per_page) credentials = User.crendentials_for_token(session[:token]) found_account = credentials.detect do |c| c['jid'] == client.jid.strip.to_s end user_pass = Security::decrypt(found_account['pass'], connection_store[:cipher_key], connection_store[:cipher_iv]) history.each do |record| record['message'] = Security::decrypt(record['message'], Security::create_key_from_pass(user_pass), Rails.application.config.aes_iv) end trigger_success history: history end private def process_incoming_message(from, me, body, chat_id = nil) stripped_me = me.strip.to_s stripped_from = from.strip.to_s if can_save_conversation?(stripped_me, stripped_from, chat_id) Rails.logger.debug ['saving received message', stripped_me, chat_id] id_message = save_encrypted_message(body, stripped_me, stripped_from, stripped_from, chat_id) else id_message = nil end send_message 'app.chat.messageReceived', from: from.to_s, to: stripped_me, message: body, chat_id: chat_id, id_message: id_message end def send_contacts(to, me, chat_id) client = find_client(me.strip.to_s) contacts = connection_store[:opened_chats][client][chat_id][:attendants] client.send(MessageBuilder::send_multichat_contacts(me.to_s, to.to_s, chat_id, contacts)) end def update_attendants_in_multichat(owner, me, chat_id, removed, added) client = find_client(me.strip.to_s) contacts = connection_store[:opened_chats][client][chat_id][:attendants] contacts -= removed contacts += added connection_store[:opened_chats][client][chat_id][:attendants] = contacts if contacts.empty? destroy_multichat(me, chat_id) else contacts.each do |contact| client.send(MessageBuilder::send_multichat_contacts(me.to_s, contact, chat_id, contacts)) end sync_contacts_frontend(owner, me, chat_id, contacts) end end def find_full_jid_in_multichat(kick_stripped, client, chat_id) contacts = connection_store[:opened_chats][client][chat_id][:attendants] contacts.find do |contact| contact =~ /^#{kick_stripped}/ end end def save_encrypted_message(message, stripped_me, stripped_from, stripped_with, chat_id) credentials = User.crendentials_for_token(session[:token]) found_account = credentials.detect do |c| c['jid'] == stripped_me end user_pass = Security::decrypt(found_account['pass'], connection_store[:cipher_key], connection_store[:cipher_iv]) encrypted_msg = Security::encrypt(message, user_pass, Rails.application.config.aes_iv) History.save_message(stripped_me, stripped_from, encrypted_msg, stripped_with, chat_id) end end