app/controllers/ws_roster_controller.rb
2a61cdcc
 class WsRosterController < WsController
b27f285a
     require 'xmpp4r/roster'
     require 'xmpp4r/vcard'
ff94bdbf
 
b27f285a
     def initialize
         super
d4872cda
 
         @storages_arr = [:clients, :rosters]
         @storages_hash = [:link_roster_client, :presences]
b27f285a
     end
 
     def initialize_storage
d4872cda
         @storages_arr.each do |storage|
93083165
             connection_store[storage] = []
b27f285a
         end
52ef7688
 
d4872cda
         @storages_hash.each do |storage|
             connection_store[storage] = {}
         end
ff94bdbf
     end
 
52ef7688
     ##
     # Pripoj sa na jabber ucty.
70fc03c1
     def connect
b27f285a
         initialize_storage()
 
a615e89f
         # TODO: Pouzit najprv:
         # clients = Token.fing_user_accounts_having_to_token(session[:token])
         # ale toto, az ked budem mat dokonceny multiaccount (settings a popup)
f3618169
         cookies = env['rack.request.cookie_hash'] # TODO: nahlasit bug na websocket-rails, lebo sa neda pristupit ku `cookies'
882090fc
         cipher_key = cookies['key']
         cipher_iv = cookies['iv']
b27f285a
 
882090fc
         clients = session[:users].map do |jid, encrypted_pass|
             decrypted_pass = Security::decrypt(encrypted_pass, cipher_key, cipher_iv)
             {jid: jid, pass: decrypted_pass}
         end
b27f285a
 
882090fc
         clients.each do |client|
b27f285a
             begin
882090fc
                 client = Signin.try_login(client[:jid], client[:pass])
93083165
                 connection_store[:clients] << client
b27f285a
             rescue Signin::LoginError
52ef7688
                 send_message 'app.client.cannot_connect', true
b27f285a
             end
         end
70fc03c1
     end
 
ff94bdbf
     ##
52ef7688
     # Inicializuj roster so zoznamom ludi v nom.
     # Vrat zoznam ludi (ich JID).
     def init_roster
         all_jids = []
 
         connection_store[:clients].each do |client|
             roster = Jabber::Roster::Helper.new(client)
 
             connection_store[:rosters] << roster
             connection_store[:link_roster_client][roster] = client
b27f285a
 
             roster.get_roster()
52ef7688
             roster.wait_for_roster()
b27f285a
 
             roster.items.each do |jid, contact|
6a6ccd01
                 all_jids << {
                     jid: jid.to_s,
                     belongsTo: client.jid.strip.to_s
                 }
b27f285a
             end
         end
 
52ef7688
         trigger_success contacts: all_jids
ff94bdbf
     end
 
52ef7688
     ##
     # Stiahni vcard ludi v rosteri
     def start_fetching_vcards
         connection_store[:rosters].each do |roster|
             client = connection_store[:link_roster_client][roster]
 
             roster.items.each do |jid, contact|
                 Thread.new do
                     vcard = get_vcard(client, jid.to_s)
                     send_message 'app.roster.vcard', jid: jid.to_s, vcard: vcard
                 end
             end
         end
     end
 
     ##
     # Zacni pocuvat zmeny stavov v rosteri
     def start_polling_contacts_state
         connection_store[:rosters].each do |roster|
635339a3
             roster.add_subscription_callback do |roster_item, stanza|
                 # stan unsubscribe = niekto uz ma nesubscribuje
                 # stan unsubscribed = niekto ma uz nesubscribuje a aj si ma vymazal
                 # stan subscribed = niekto moze vidiet moj stav
 
                 client = connection_store[:link_roster_client][roster]
 
                 send_message 'app.roster.subscriptionChanged',
                              action: stanza.type,
                              jid: roster_item.jid.strip.to_s,
                              belongsTo: client.jid.strip.to_s
             end
 
52ef7688
             roster.add_presence_callback do |roster_item, old_presence, new_presence|
                 if new_presence.type == :unavailable
                     result = {status: :offline, message: ''}
                 else
d4872cda
                     status = uniform_presence(new_presence.show)
52ef7688
                     result = { status: status, message: new_presence.status.to_s }
                 end
 
                 send_message 'app.roster.statusChanged',
                              jid: roster_item.jid.strip.to_s, status: result
b27f285a
             end
43ad79fa
         end
     end
52ef7688
 
43ad79fa
     ##
     # Nastav ma ako online
     #
     # Musi sa zavolat az po start_polling_contacts_state, inak sa nemusia
     # zachytit stavy ostatnych v rosteri.
     def set_presence
         connection_store[:clients].each do |client|
d4872cda
             presence = Jabber::Presence.new.set_type(:available)
             client.send(presence)
             connection_store[:presences][client] = presence
         end
     end
 
635339a3
     def remove_contact
         jid = message[:jid]
         client_jid = message[:client]
 
         found_roster_item = nil
         connection_store[:rosters].each do |roster|
             roster_item = roster.find(jid)
             if roster_item.first[1] && connection_store[:link_roster_client][roster].jid.strip.to_s == client_jid
                 found_roster_item = roster_item.first[1]
                 break
             end
         end
 
         found_roster_item && found_roster_item.remove()
     end
 
d4872cda
     ##
     # Ziskaj informacie o mne (meno, stav, status...)
     def myself
         # TODO: v pripade viacerych uctov zjednotit meno a stav
         vcard = {}
         jid = presence = ''
 
         connection_store[:clients].each do |client|
             vcard = get_vcard(client)
             jid = client.jid.strip.to_s
             presence = uniform_presence(connection_store[:presences][client].show)
52ef7688
         end
d4872cda
 
         trigger_success jid: jid, vcard: vcard, status: presence
52ef7688
     end
 
c4a1e746
     def me_update_status
         status_message = message[:message]
         state = message[:state]
 
         xmpp_state = case state
                      when 'away' then :away
                      when 'dnd' then :dnd
                      else nil
         end
 
         presence = Jabber::Presence.new
         presence.show = xmpp_state
         presence.status = status_message
 
         connection_store[:clients].each do |client|
             client.send(presence)
         end
     end
 
     def me_update_vcard
 
     end
 
52ef7688
     def disconnect
         connection_store[:clients] && connection_store[:clients].each do |client|
             client.close()
b27f285a
         end
ff94bdbf
 
4b5bb9c5
         @storages_arr.each do |storage|
             connection_store.delete(storage)
         end
 
         @storages_hash.each do |storage|
b27f285a
             connection_store.delete(storage)
         end
ff94bdbf
     end
70fc03c1
 
7a817e66
     def ask_if_using_this_app
         connection_store[:rosters].each do |roster|
             client = connection_store[:link_roster_client][roster]
 
             roster.items.each do |jid, contact|
                 client.send(MessageBuilder::control_question(client.jid.strip.to_s, jid))
             end
         end
 
         start_polling_control_answer()
     end
 
b27f285a
     ##
     # Pridaj noveho priatela do zoznamu
     def add_friend(data)
70fc03c1
 
23f7b7b2
     end
52ef7688
 
     private
 
d4872cda
     def get_vcard(me, contact_jid = nil)
         vcard = Jabber::Vcard::Helper.get(me, contact_jid)
52ef7688
 
d4872cda
         { name: pull_name_from_vcard(vcard) || contact_jid,
f99e8d29
           avatar: vcard['PHOTO/TYPE'] && ('data:' + vcard['PHOTO/TYPE'] + ';base64,' + vcard['PHOTO/BINVAL']) || ''
52ef7688
         }
     end
d4872cda
 
     def pull_name_from_vcard(vcard)
f99e8d29
         vcard && (vcard['FN'] || vcard['NICKNAME'])
d4872cda
     end
 
     def uniform_presence(xmpp_presence)
         case xmpp_presence
             when :away, :xa then :away
             when :dnd       then :dnd
             else                 :online
         end
     end
7a817e66
 
     def start_polling_control_answer
         connection_store[:clients].each do |client|
             client.add_message_callback do |message|
                 if message.attribute('i_am_using_same_app')
                     send_message 'app.roster.using_this_app',
                                  jid: message.from.node + '@' + message.from.domain
                 elsif message.attribute('are_you_using_my_app')
                     client.send(MessageBuilder::control_answer(client.jid.strip.to_s, message.from))
                 end
             end
         end
     end
ff94bdbf
 end