2020-02-02 17:04:16 +00:00
|
|
|
module OnlineStatusTracker
|
2022-04-05 09:50:34 +00:00
|
|
|
# NOTE: You can customise the environment variable to keep your agents/contacts as online for longer
|
|
|
|
PRESENCE_DURATION = ENV.fetch('PRESENCE_DURATION', 20).to_i.seconds
|
2020-07-04 06:12:47 +00:00
|
|
|
|
|
|
|
# presence : sorted set with timestamp as the score & object id as value
|
|
|
|
|
|
|
|
# obj_type: Contact | User
|
|
|
|
def self.update_presence(account_id, obj_type, obj_id)
|
|
|
|
::Redis::Alfred.zadd(presence_key(account_id, obj_type), Time.now.to_i, obj_id)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.get_presence(account_id, obj_type, obj_id)
|
|
|
|
connected_time = ::Redis::Alfred.zscore(presence_key(account_id, obj_type), obj_id)
|
|
|
|
connected_time && connected_time > (Time.zone.now - PRESENCE_DURATION).to_i
|
2020-02-02 17:04:16 +00:00
|
|
|
end
|
|
|
|
|
2020-07-04 06:12:47 +00:00
|
|
|
def self.presence_key(account_id, type)
|
|
|
|
case type
|
|
|
|
when 'Contact'
|
2020-07-07 18:44:07 +00:00
|
|
|
format(::Redis::Alfred::ONLINE_PRESENCE_CONTACTS, account_id: account_id)
|
2020-07-04 06:12:47 +00:00
|
|
|
else
|
2020-07-07 18:44:07 +00:00
|
|
|
format(::Redis::Alfred::ONLINE_PRESENCE_USERS, account_id: account_id)
|
2020-02-02 17:04:16 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-07-04 06:12:47 +00:00
|
|
|
# online status : online | busy | offline
|
|
|
|
# redis hash with obj_id key && status as value
|
|
|
|
|
|
|
|
def self.set_status(account_id, user_id, status)
|
|
|
|
::Redis::Alfred.hset(status_key(account_id), user_id, status)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.get_status(account_id, user_id)
|
|
|
|
::Redis::Alfred.hget(status_key(account_id), user_id)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.status_key(account_id)
|
2020-07-07 18:44:07 +00:00
|
|
|
format(::Redis::Alfred::ONLINE_STATUS, account_id: account_id)
|
2020-07-04 06:12:47 +00:00
|
|
|
end
|
|
|
|
|
2020-10-05 18:00:27 +00:00
|
|
|
def self.get_available_contact_ids(account_id)
|
|
|
|
::Redis::Alfred.zrangebyscore(presence_key(account_id, 'Contact'), (Time.zone.now - PRESENCE_DURATION).to_i, Time.now.to_i)
|
|
|
|
end
|
|
|
|
|
2020-07-04 06:12:47 +00:00
|
|
|
def self.get_available_contacts(account_id)
|
2020-10-05 18:00:27 +00:00
|
|
|
# returns {id1: 'online', id2: 'online'}
|
|
|
|
get_available_contact_ids(account_id).index_with { |_id| 'online' }
|
2020-07-04 06:12:47 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.get_available_users(account_id)
|
2022-08-01 13:32:34 +00:00
|
|
|
user_ids = get_available_user_ids(account_id)
|
|
|
|
|
2020-07-04 14:33:16 +00:00
|
|
|
return {} if user_ids.blank?
|
|
|
|
|
2020-07-04 06:12:47 +00:00
|
|
|
user_availabilities = ::Redis::Alfred.hmget(status_key(account_id), user_ids)
|
|
|
|
user_ids.map.with_index { |id, index| [id, (user_availabilities[index] || 'online')] }.to_h
|
2020-02-02 17:04:16 +00:00
|
|
|
end
|
2022-08-01 13:32:34 +00:00
|
|
|
|
|
|
|
def self.get_available_user_ids(account_id)
|
|
|
|
account = Account.find(account_id)
|
|
|
|
# TODO: to migrate this to zrange as its is being deprecated
|
|
|
|
# https://redis.io/commands/zrangebyscore/
|
|
|
|
user_ids = ::Redis::Alfred.zrangebyscore(presence_key(account_id, 'User'), (Time.zone.now - PRESENCE_DURATION).to_i, Time.now.to_i)
|
|
|
|
# since we are dealing with redis items as string, casting to string
|
|
|
|
user_ids += account.account_users.where(auto_offline: false)&.map(&:user_id)&.map(&:to_s)
|
|
|
|
user_ids.uniq
|
|
|
|
end
|
2020-02-02 17:04:16 +00:00
|
|
|
end
|