2a61cdcc |
class WsRosterController < WsController |
b27f285a |
require 'xmpp4r/roster'
require 'xmpp4r/vcard' |
6fb9497e |
require 'RMagick' |
ff94bdbf |
|
b27f285a |
def initialize
super |
d4872cda |
@storages_arr = [:clients, :rosters] |
dbe4bff6 |
@storages_hash = [:link_roster_client, :my_presences, :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()
|
f3618169 |
cookies = env['rack.request.cookie_hash'] # TODO: nahlasit bug na websocket-rails, lebo sa neda pristupit ku `cookies' |
16165255 |
connection_store[:cipher_key] = cipher_key = cookies['key']
connection_store[:cipher_iv] = cipher_iv = cookies['iv'] |
b27f285a |
|
0c651ead |
credentials = User.crendentials_for_token(session[:token])
clients = credentials.map do |tuple|
decrypted_pass = Security::decrypt(tuple['pass'], cipher_key, cipher_iv)
{jid: tuple['jid'], pass: decrypted_pass} |
882090fc |
end |
b27f285a |
|
882090fc |
clients.each do |client| |
9234acc2 |
Thread.new do
begin
client = Signin.try_login(client[:jid], client[:pass])
connection_store[:clients] << client
send_message 'app.client.connected', client.jid.strip.to_s
#Rails.logger.debug '!!!!! finished for ' + client_id.to_s
rescue Signin::LoginError
#Rails.logger.debug '!!!!! finished FAILED for ' + client_id.to_s |
51a7baf2 |
#TODO: poslat na domovsku stranku a vymazat cookies |
9234acc2 |
send_message 'app.client.cannot_connect', client.jid.strip.to_s
end |
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 |
910e0f23 |
vcard = get_vcard_info(client, jid.to_s) |
52ef7688 |
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 |
2fe6ba99 |
start_polling_control_answer() |
dbe4bff6 |
|
2fe6ba99 |
connection_store[:rosters].each do |roster|
start_polling_subscription(roster)
start_polling_presence(roster) |
910e0f23 |
start_polling_friend_requests(roster) |
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) |
dbe4bff6 |
connection_store[:my_presences][client] = presence |
d4872cda |
end
end
|
635339a3 |
def remove_contact
jid = message[:jid]
client_jid = message[:client]
|
0ec320b3 |
found_roster_items = [] |
635339a3 |
connection_store[:rosters].each do |roster|
roster_item = roster.find(jid) |
0ec320b3 |
contact_obj = roster_item.first[1]
if contact_obj
if client_jid && connection_store[:link_roster_client][roster].jid.strip.to_s == client_jid
found_roster_items = [ contact_obj ]
break
else
found_roster_items.push(contact_obj)
end |
635339a3 |
end
end
|
0ec320b3 |
found_roster_items.each do |contact|
contact.remove()
end |
635339a3 |
end
|
d4872cda |
##
# Ziskaj informacie o mne (meno, stav, status...)
def myself
# TODO: v pripade viacerych uctov zjednotit meno a stav
connection_store[:clients].each do |client| |
910e0f23 |
vcard = get_vcard_info(client) |
d4872cda |
jid = client.jid.strip.to_s |
dbe4bff6 |
presence = uniform_presence(connection_store[:my_presences][client].show) |
d4872cda |
|
8287edd6 |
trigger_success jid: jid,
vcard: vcard,
status: presence,
is_facebook: Signin.is_facebook(client.jid)
end |
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 |
6347ea28 |
connection_store[:clients].each do |client| |
6fb9497e |
Thread.new do
my_vcard = Jabber::Vcard::Helper.get(client)
if message[:name]
my_vcard['FN'] = my_vcard['NICKNAME'] = message[:name]
end
if message[:avatar]
begin
im = Magick::Image::read_inline(message[:avatar]).first
type = im.format.downcase
allowed_types = %w(png jpeg pjpeg gif webp)
return unless allowed_types.include? type
im.resize_to_fit! 128,128
base64 = Base64.encode64(im.to_blob)
my_vcard['PHOTO/TYPE'] = 'image/' + type
my_vcard['PHOTO/BINVAL'] = base64
rescue
# ignored
end
end
Jabber::Vcard::Helper.set(client, my_vcard)
end |
6347ea28 |
end |
c4a1e746 |
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 |
|
910e0f23 |
def add_contact(jid = nil)
new_jid = message[:jid] || jid
if is_valid_jid? new_jid
connection_store[:rosters].each do |roster|
Thread.new do
roster.add(new_jid, nil, true)
end
end
end
end |
70fc03c1 |
|
910e0f23 |
def answer_friend_request
jid = message[:jid]
answer = message[:answer] |
70fc03c1 |
|
910e0f23 |
connection_store[:rosters].each do |roster|
if answer
roster.accept_subscription(jid)
add_contact(jid)
else
roster.decline_subscription(jid)
end
end |
23f7b7b2 |
end |
52ef7688 |
private
|
dbe4bff6 |
def select_most_online_status(jid_stripped)
if connection_store[:presences][jid_stripped].nil? || connection_store[:presences][jid_stripped].empty?
return uniform_presence(:offline)
end
statuses = { offline: 0, dnd: 1, away: 2, online: 3 }
Hash[connection_store[:presences][jid_stripped].map do |jid, data|
[ statuses[data[:status]], data[:status] ]
end].max.second
end
|
910e0f23 |
def get_vcard_info(me, contact_jid = nil) |
d4872cda |
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 |
dbe4bff6 |
when :offline then :offline |
d4872cda |
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') |
e513299a |
connection_store[:presences][message.from.strip.to_s][message.from.to_s.to_sym][:multichat] = true |
79fff9ad |
|
7a817e66 |
send_message 'app.roster.using_this_app', |
79fff9ad |
jid: message.from.strip.to_s |
7a817e66 |
elsif message.attribute('are_you_using_my_app') |
79fff9ad |
client.send(MessageBuilder::control_answer(client.jid.to_s, message.from.to_s)) |
7a817e66 |
end
end
end
end |
79fff9ad |
|
2fe6ba99 |
def start_polling_presence(roster)
roster.add_presence_callback do |roster_item, old_presence, new_presence|
if new_presence.type == :unavailable
result = {message: ''}
unless connection_store[:presences][roster_item.jid.strip.to_s].nil?
connection_store[:presences][roster_item.jid.strip.to_s.to_sym].delete(new_presence.from.to_s)
end
|
bc02cb76 |
client = connection_store[:link_roster_client][roster] |
2fe6ba99 |
# mozno treba vyhodit cloveka z multichatu, ak som jeho owner |
bc02cb76 |
kick_from_all_multichats(client, new_presence.from)
# mozno treba sa odpojit z multichatu, ak sa odpojil jeho owner
kick_myself_from_multichat(client, new_presence.from) |
2fe6ba99 |
else
status = uniform_presence(new_presence.show)
result = {message: new_presence.status.to_s}
if connection_store[:presences][roster_item.jid.strip.to_s.to_sym].nil?
connection_store[:presences][roster_item.jid.strip.to_s.to_sym] = Hash.new()
end
connection_store[:presences][roster_item.jid.strip.to_s][new_presence.from.to_s.to_sym] = {
status: status, |
9ba34cc7 |
multichat: false,
priority: new_presence.priority |
2fe6ba99 |
}
|
e513299a |
ask_if_using_this_app(connection_store[:link_roster_client][roster], new_presence.from.to_s) |
2fe6ba99 |
end
result[:status] = select_most_online_status(roster_item.jid.strip.to_s)
send_message 'app.roster.statusChanged',
jid: roster_item.jid.strip.to_s, status: result
end
end
def start_polling_subscription(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
end
|
910e0f23 |
def start_polling_friend_requests(roster)
client = connection_store[:link_roster_client][roster]
roster.add_subscription_request_callback do |roster_item, stanza|
jid = stanza.from.to_s
send_message 'app.roster.friendRequest',
jid: jid,
name: get_vcard_info(client, jid)[:name]
end
end
|
79fff9ad |
def ask_if_using_this_app(client, contact) |
e513299a |
client.send(MessageBuilder::control_question(client.jid.to_s, contact)) |
79fff9ad |
end |
910e0f23 |
def is_valid_jid?(jid)
!! jid.scan(/^\w+@\w+\.\w+$/).first
end |
ff94bdbf |
end |