class WsRosterController < WsController require 'xmpp4r/roster' require 'xmpp4r/vcard' def initialize super @storages_arr = [:clients, :rosters] @storages_hash = [:link_roster_client, :presences] end def initialize_storage @storages_arr.each do |storage| connection_store[storage] = [] end @storages_hash.each do |storage| connection_store[storage] = {} end end ## # Pripoj sa na jabber ucty. def connect initialize_storage() # TODO: Pouzit najprv: # clients = Token.fing_user_accounts_having_to_token(session[:token]) # ale toto, az ked budem mat dokonceny multiaccount (settings a popup) # TODO: skusit zrychlit cookies = env['rack.request.cookie_hash'] # TODO: nahlasit bug na websocket-rails, lebo sa neda pristupit ku `cookies' cipher_key = cookies['key'] cipher_iv = cookies['iv'] clients = session[:users].map do |jid, encrypted_pass| decrypted_pass = Security::decrypt(encrypted_pass, cipher_key, cipher_iv) {jid: jid, pass: decrypted_pass} end clients.each do |client| begin client = Signin.try_login(client[:jid], client[:pass]) connection_store[:clients] << client rescue Signin::LoginError send_message 'app.client.cannot_connect', true end end end ## # 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 roster.get_roster() roster.wait_for_roster() roster.items.each do |jid, contact| all_jids << { jid: jid.to_s, belongsTo: client.jid.strip.to_s } end end trigger_success contacts: all_jids end ## # 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| 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 roster.add_presence_callback do |roster_item, old_presence, new_presence| if new_presence.type == :unavailable result = {status: :offline, message: ''} # mozno treba vyhodit cloveka z multichatu, ak som jeho owner #kick_from_multichat2(roster_item.jid.strip.to_s) else status = uniform_presence(new_presence.show) result = { status: status, message: new_presence.status.to_s } end send_message 'app.roster.statusChanged', jid: roster_item.jid.strip.to_s, status: result end end end ## # 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| presence = Jabber::Presence.new.set_type(:available) client.send(presence) connection_store[:presences][client] = presence end end 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 ## # 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) end trigger_success jid: jid, vcard: vcard, status: presence end 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 def disconnect connection_store[:clients] && connection_store[:clients].each do |client| client.close() end @storages_arr.each do |storage| connection_store.delete(storage) end @storages_hash.each do |storage| connection_store.delete(storage) end end 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 ## # Pridaj noveho priatela do zoznamu def add_friend(data) end private def get_vcard(me, contact_jid = nil) vcard = Jabber::Vcard::Helper.get(me, contact_jid) { name: pull_name_from_vcard(vcard) || contact_jid, avatar: vcard['PHOTO/TYPE'] && ('data:' + vcard['PHOTO/TYPE'] + ';base64,' + vcard['PHOTO/BINVAL']) || '' } end def pull_name_from_vcard(vcard) vcard && (vcard['FN'] || vcard['NICKNAME']) end def uniform_presence(xmpp_presence) case xmpp_presence when :away, :xa then :away when :dnd then :dnd else :online end end 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 end