app/controllers/ws_chat_controller.rb
2a61cdcc
 class WsChatController < WsController
 
7a706f0e
     require 'message_builder'
 
1f685c13
     def start_polling_messages
         connection_store[:clients].each do |client|
             client.add_message_callback do |message|
9948b399
                 #noinspection RubyAssignmentExpressionInConditionalInspection
1f685c13
                 if message.body
90472b75
                     process_incoming_message(message.from, message.to, message.body, message.attribute('chat_id').to_s)
fc026409
                 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)
7d2a86e9
                     set_contacts_in_multichat(find_client(message.to.strip.to_s), answer.attribute('chat_id').to_s, message.from.to_s, contacts)
fc026409
                     sync_contacts_frontend(message.from, message.to, answer.attribute('chat_id').to_s, contacts)
e513299a
                 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)
90472b75
                 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)
37ab3198
                 elsif message.attribute('new_owner')
                     make_me_new_owner(message.to, message.attribute('chat_id').to_s)
1f685c13
                 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
 
37ab3198
     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
 
e513299a
     def import_people_in_chat(owner, me, chat_id, contacts)
b1c6b359
         #Rails.logger.debug ['imported chat arrived', message.to_s, chat_id]
e513299a
         client = find_client(me.strip.to_s)
7d2a86e9
         set_contacts_in_multichat(client, chat_id, owner.to_s, contacts)
c6c526f1
 
         send_message 'app.chat.importChat',
e513299a
                      owner:    owner.strip.to_s,
c6c526f1
                      chat_id:  chat_id,
e513299a
                      contacts: strip_all(contacts)
24b129a9
     end
 
94bd8368
     # Owner vytvori najprv u seba novy multichat
24b129a9
     def new_multichat
2a61cdcc
         me = message[:chatOwner]
94bd8368
         hash = Digest::SHA2.hexdigest(me)
0f555f4a
         chat_id = hash + Time.now.to_f.to_s
2a61cdcc
         client = find_client(me)
 
7d2a86e9
         set_contacts_in_multichat(client, chat_id, client.jid.to_s)
2a61cdcc
 
0f555f4a
         trigger_success id: chat_id
2a61cdcc
     end
 
24b129a9
     # Owner posle novemu cloveku informaciu o chat_id a kontaktoch
4e59a143
     def add_to_multichat
2a61cdcc
         client = find_client(message[:chatOwner])
 
24b129a9
         chat_id  = message[:chatId]
296dd1c6
         add      = message[:jid]
e513299a
         add_resource = find_multichat_supported(add)
2a61cdcc
 
e513299a
         if add_resource
             connection_store[:opened_chats][client][chat_id][:attendants] << add_resource
             #Rails.logger.debug ['adding to multichat', add_resource]
24b129a9
 
e513299a
             contacts = connection_store[:opened_chats][client][chat_id][:attendants]
296dd1c6
 
e513299a
             contacts.each do |contact|
                 client.send(MessageBuilder::export_multichat(client.jid.to_s, contact, chat_id, contacts))
             end
94bd8368
 
e513299a
             trigger_success
         else
             #Rails.logger.debug ['adding to multichat failure', connection_store[:presences][add]]
             trigger_failure
         end
2a61cdcc
     end
424fd46f
 
     def send_chat_message
2a61cdcc
         me = message[:from]
         client = find_client(me)
e513299a
         my_jid = client.jid.to_s
2a61cdcc
 
00f00dbe
         if client
24b129a9
             chat_id = message[:chatId]
             if chat_id
b1c6b359
                 attendants = connection_store[:opened_chats][client][chat_id][:attendants] + [connection_store[:opened_chats][client][chat_id][:owner]]
e513299a
                 attendants -= [my_jid]
24b129a9
 
e513299a
                 messages = MessageBuilder::build_multi_messages(message[:message], my_jid, attendants, chat_id)
24b129a9
             else
e513299a
                 messages = [MessageBuilder::build_message(message[:message], my_jid, message[:to])]
24b129a9
             end
2a61cdcc
 
             # Xmpp4r doesn't support XEP-0033 (multicast messages)
             messages.each do |message|
                 client.send(message)
             end
 
d33f6448
             stripped_me = client.jid.strip.to_s
             stripped_to = Jabber::JID.new(message[:to]).strip!.to_s
f6071db7
             if can_save_conversation?(stripped_me, stripped_to, chat_id)
16165255
                 Rails.logger.debug ['saving sent message', stripped_me]
ccddc642
                 save_encrypted_message(message[:message], stripped_me, stripped_me, stripped_to, chat_id)
d33f6448
             end
 
00f00dbe
             trigger_success message[:message]
         else
             trigger_failure
2a61cdcc
         end
     end
 
a0c73ec7
     def request_sync_chat_contacts
24b129a9
         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
 
aa2c1028
     def i_closed_multichat
         chat_id = message[:chatId]
         client  = find_client(message[:me])
90472b75
         me      = client.jid.to_s
aa2c1028
         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|
88c1de39
                 client.send(MessageBuilder::kick_from_multichat(me, attendant, chat_id))
aa2c1028
             end
         else
             changes = {removed: [me]}
             client.send(MessageBuilder::req_update_multichat_contacts(me, owner, chat_id, changes))
         end
2f61d2f6
 
         connection_store[:opened_chats][client].delete(chat_id)
aa2c1028
     end
 
fc026409
     def kick_from_multichat
         chat_id = message[:chatId]
         client  = find_client(message[:me])
         kick_stripped = message[:kick]
 
37ab3198
         kick = find_full_jid_in_multichat(kick_stripped, client, chat_id)
fc026409
 
         return if kick.nil?
 
37ab3198
         contacts = connection_store[:opened_chats][client][chat_id][:attendants]
fc026409
         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
 
37ab3198
     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
 
f6071db7
     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
 
7a706f0e
     def load_history
         me = message[:me]
         attendant = message[:attendant]
         chat_id = message[:chatId]
         page = message[:step]
         per_page = 10
 
16165255
         client = find_client(me)
         trigger_failure unless client
7a706f0e
 
         history = History.page_history(me, attendant || chat_id, page, per_page)
16165255
 
         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
 
7a706f0e
         trigger_success history: history
     end
 
2a61cdcc
     private
 
d33f6448
     def process_incoming_message(from, me, body, chat_id = nil)
         stripped_me = me.strip.to_s
         stripped_from = from.strip.to_s
 
f6071db7
         if can_save_conversation?(stripped_me, stripped_from, chat_id)
d33f6448
             Rails.logger.debug ['saving received message', stripped_me, chat_id]
322b85e2
             id_message = save_encrypted_message(body, stripped_me, stripped_from, stripped_from, chat_id)
         else
             id_message = nil
d33f6448
         end
 
24b129a9
         send_message 'app.chat.messageReceived',
a7decc88
                      from: from.to_s,
d33f6448
                      to: stripped_me,
9948b399
                      message: body,
322b85e2
                      chat_id: chat_id,
                      id_message: id_message
24b129a9
     end
31111b63
 
fc026409
     def send_contacts(to, me, chat_id)
         client = find_client(me.strip.to_s)
24b129a9
         contacts = connection_store[:opened_chats][client][chat_id][:attendants]
fc026409
         client.send(MessageBuilder::send_multichat_contacts(me.to_s, to.to_s, chat_id, contacts))
24b129a9
     end
 
90472b75
     def update_attendants_in_multichat(owner, me, chat_id, removed, added)
         client = find_client(me.strip.to_s)
aa2c1028
 
         contacts = connection_store[:opened_chats][client][chat_id][:attendants]
9948b399
         contacts -= removed
         contacts += added
aa2c1028
 
         connection_store[:opened_chats][client][chat_id][:attendants] = contacts
 
         if contacts.empty?
90472b75
             destroy_multichat(me, chat_id)
aa2c1028
         else
             contacts.each do |contact|
90472b75
                 client.send(MessageBuilder::send_multichat_contacts(me.to_s, contact, chat_id, contacts))
aa2c1028
             end
a0c73ec7
 
90472b75
             sync_contacts_frontend(owner, me, chat_id, contacts)
aa2c1028
         end
     end
37ab3198
 
     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
16165255
 
ccddc642
     def save_encrypted_message(message, stripped_me, stripped_from, stripped_with, chat_id)
16165255
         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)
ccddc642
         History.save_message(stripped_me, stripped_from, encrypted_msg, stripped_with, chat_id)
16165255
     end
424fd46f
 end