Created
September 29, 2016 11:56
-
-
Save rubypirate/8946bf4a6b8b1b045622a292c86e35a7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module EwsCore | |
def ews_watch | |
if params["Envelope"] | |
cal_ids = [] | |
subscription_id = find_all_values_for(params, 'SubscriptionId').first | |
if subscription_id | |
exchange_subscription = Exchange::Subscription.where(subscription_id: subscription_id).first | |
if exchange_subscription | |
exchange_subscription.update_attributes(push_count: exchange_subscription.push_count.to_i+1, last_push: Time.now) | |
cal = exchange_subscription.cal | |
if cal.ews_email && cal.ews_email != '' | |
EwsGetCalJob.perform_async(cal.id) | |
end | |
end | |
end | |
######## this is important because if we didn't respond OK EWS is not going to move the que | |
render text: %{<?xml version="1.0" encoding="utf-8"?> | |
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope"> | |
<soap:Body> | |
<SendNotificationResult xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"> | |
<SubscriptionStatus>OK</SubscriptionStatus> | |
</SendNotificationResult> | |
</soap:Body> | |
</soap:Envelope>} | |
else | |
render text: '' | |
end | |
end | |
# returns an array of folders ids | |
def ews_folder_ids params | |
if params['Envelope'] && params['Envelope']['Body'] && | |
params['Envelope']['Body']['SendNotification'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['ResponseClass'] == 'Success' && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification'] | |
notification = params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification'] | |
all_events = {} | |
folder_ids = [] | |
if notification['CreatedEvent'] && notification['CreatedEvent'].any? | |
folder_ids << notification['CreatedEvent']['ParentFolderId']['Id'] | |
#all_events['created_events'] = notification['CreatedEvent'].map {|event| event } | |
end | |
if notification['ModifiedEvent'] && notification['ModifiedEvent'].any? | |
folder_ids << notification['ModifiedEvent']['ParentFolderId']['Id'] | |
#all_events['modified_events'] = notification['ModifiedEvent'].map {|event| event } | |
end | |
if notification['DeletedEvent'] && notification['DeletedEvent'].any? | |
folder_ids << notification['DeletedEvent']['ParentFolderId']['Id'] | |
#all_events['deleted_events'] = notification['DeletedEvent'].map {|event| event } | |
end | |
#return all_events | |
return folder_ids.uniq | |
end | |
return false | |
end | |
# returns a hash of created_events, modified_events and deleted_events | |
def ews_extract_events params | |
if params['Envelope'] && params['Envelope']['Body'] && | |
params['Envelope']['Body']['SendNotification'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['ResponseClass'] == 'Success' && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification'] | |
notification = params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification'] | |
all_events = {} | |
if notification['CreatedEvent'] && notification['CreatedEvent'].any? | |
all_events['created_events'] = notification['CreatedEvent'].map {|event| event } | |
end | |
if notification['ModifiedEvent'] && notification['ModifiedEvent'].any? | |
all_events['modified_events'] = notification['ModifiedEvent'].map {|event| event } | |
end | |
if notification['DeletedEvent'] && notification['DeletedEvent'].any? | |
all_events['deleted_events'] = notification['DeletedEvent'].map {|event| event } | |
end | |
return all_events | |
end | |
return false | |
end | |
# returns push subscription request confirmation watermark | |
def ews_subscription_confirmation_watermark params | |
if params['Envelope'] && params['Envelope']['Body'] && | |
params['Envelope']['Body']['SendNotification'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['ResponseClass'] == 'Success' && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification']['StatusEvent'] && | |
params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification']['StatusEvent']['Watermark'] | |
return params['Envelope']['Body']['SendNotification']['ResponseMessages']['SendNotificationResponseMessage']['Notification']['StatusEvent']['Watermark'] | |
end | |
return false | |
end | |
def subscribe_to_calendar(cal) | |
client = cal.company.base_company.conf_connection.init_viewpoint_client(cal.ews_email) if cal.company.base_company.conf_connection | |
return [] unless client | |
# delete existing subscription if it's old enough | |
if cal.exchange_subscription | |
cal.exchange_subscription.destroy if cal.exchange_subscription.last_push && (cal.exchange_subscription.last_push <= (Time.now - 2.days)) | |
end | |
if cal.company && cal.company.conf_connection && cal.company.conf_connection.ews_impersonation? | |
calendar_folder = client.get_folder(:calendar) | |
else | |
calendar_folder = client.get_folder(:calendar, opts = {act_as: ews_email}) | |
end | |
if calendar_folder && calendar_folder.id && !calendar_folder.id.empty? | |
subscription_response = client.ews.push_subscribe_folder( | |
{id: calendar_folder.id, change_key: calendar_folder.change_key}, | |
%w{CopiedEvent CreatedEvent DeletedEvent MovedEvent}, "https://#{get_domain}/ews_watch", 1) | |
if subscription_response && subscription_response.response_messages && subscription_response.response_messages.any? | |
ex_sub = cal.exchange_subscription ? cal.exchange_subscription : Exchange::Subscription.new | |
ex_sub.subscription_id = subscription_response.response_messages.first.subscription_id | |
ex_sub.folder_id = calendar_folder.id | |
ex_sub.cal_id = cal.id | |
ex_sub.save! | |
end | |
end | |
end | |
### client.get_user_availability works fine directly or as a delegate | |
def ews_busy cal | |
return nil if cal.ews_email.blank? || !cal.company.base_company.conf_connection | |
base_conn = cal.company.base_company.conf_connection | |
if base_conn.email && base_conn.email["ews"] && base_conn.email["ews"]["last_sync"] && base_conn.email["ews"]["last_sync"] != '' | |
cache_time_in_seconds = Rails.env.development? ? (Time.now-5) : (Time.now-10) | |
conf_last_sync = base_conn.email["ews"]["last_sync"].to_datetime | |
end | |
### initialize EWS client | |
ignore_impersonation = base_conn.email["ews"]["ignore_impersonation_for_user_availability"] | |
client = base_conn.init_viewpoint_client(cal.ews_email, ignore_impersonation) if base_conn | |
out = "" | |
if client | |
step = base_conn.ews_availability_range | |
(-base_conn.ews_days_in_past).step(base_conn.ews_days_in_future, step) do |start_day| | |
start_time = (Time.now + start_day.days).utc.iso8601 | |
end_day = start_day + step | |
end_day = base_conn.ews_days_in_future if end_day > base_conn.ews_days_in_future | |
end_time = end_day.days.from_now.utc.iso8601 | |
time_zone_opts = {:bias => base_conn.email['ews']['time_zone_bias'].to_i, :standard_time => {:bias => 0}, | |
:daylight_time => {:bias => (base_conn.ews_do_daylight_saving? ? -60 : 0)}} | |
Rails.logger.info "Params for EWS call: ews_busy" | |
Rails.logger.info [[cal.ews_email], ({start_time: start_time, end_time: end_time, requested_view: :detailed, time_zone: time_zone_opts})] | |
begin | |
busy_times = client.get_user_availability([cal.ews_email], start_time: start_time, end_time: end_time, requested_view: :detailed, time_zone: time_zone_opts) | |
rescue => error | |
if Rails.env.production? | |
# catch errors and only tell airbrake | |
Rails.logger.info 'Error - ews_busy' | |
Rails.logger.info error | |
Airbrake.notify(error, | |
{:backtrace => error.backtrace, | |
:error_class => error.class, | |
:error_message => error.message, | |
:parameters => {:username => client.username, :ews_email => cal.ews_email} | |
} | |
) | |
else | |
raise error | |
end | |
return "" | |
end | |
Rails.logger.info "EWS Response:" | |
Rails.logger.info busy_times.inspect | |
begin | |
busy_times.calendar_event_array.each do |event| | |
Rails.logger.info "EWS Event:" | |
Rails.logger.info event.inspect | |
if event[:calendar_event][:elems][2] && | |
event[:calendar_event][:elems][2][:busy_type] && | |
event[:calendar_event][:elems][2][:busy_type][:text].present? && | |
event[:calendar_event][:elems][2][:busy_type][:text] == "Free" | |
next | |
end | |
if base_conn.skip_tentative? && event[:calendar_event][:elems][2] && | |
event[:calendar_event][:elems][2][:busy_type] && | |
event[:calendar_event][:elems][2][:busy_type][:text].present? && | |
event[:calendar_event][:elems][2][:busy_type][:text] == "Tentative" | |
next | |
end | |
if event[:calendar_event][:elems][3] && event[:calendar_event][:elems][3][:calendar_event_details][:elems] && event[:calendar_event][:elems][3][:calendar_event_details][:elems][1] && event[:calendar_event][:elems][3][:calendar_event_details][:elems][1][:subject] | |
subject = event[:calendar_event][:elems][3][:calendar_event_details][:elems][1][:subject][:text].to_s.gsub(/\n/, " ") | |
else | |
subject = 'Blocked' | |
end | |
if subject.include? "BBID:" | |
next | |
id = subject.split(" - ")[0][5..-1] | |
space = Space.find_by_id(id) | |
if space && space.slot && space.slot.person_id | |
person = Person.where(cal_id: cal.id).first | |
next if person && (space.slot.person_id == person.id) | |
end | |
end | |
if subject.include? "BBEID:" | |
next | |
id = subject.split(" - ")[0][6..-1] | |
session = Session.find_by_id(id) | |
if session && session.person_id | |
person = Person.where(cal_id: cal.id).first | |
next if person && (session.person_id == person.id) | |
end | |
end | |
if [1, 2].include?(base_conn.email["ews"]["ignore_daylight_saving"]) | |
if base_conn.ews_do_daylight_saving? | |
offset = -60.minutes | |
else | |
offset = 0.minutes | |
end | |
else | |
### auto detect | |
offset = Time.parse(client.event_start_time(event)).isdst ? -60.minutes : 0.minutes | |
end | |
d1 = client.event_start_time(event).to_datetime+offset | |
d2 = client.event_end_time(event).to_datetime+offset | |
out += d1.utc.strftime("%Y%m%dT%H%M") + "-" + d2.utc.strftime("%Y%m%dT%H%M") + "\n" | |
out += "-" + subject + "\n" | |
end | |
rescue => error | |
if Rails.env.production? | |
Rails.logger.info "EWS Error - ews_busy" | |
Rails.logger.info error.inspect | |
# catch errors and only tell airbrake | |
Airbrake.notify(error, | |
{:backtrace => error.backtrace, | |
:error_class => error.class, | |
:error_message => error.message, | |
:parameters =>([[cal.ews_email], ({start_time: start_time, end_time:end_time, requested_view: :detailed, time_zone: time_zone_opts})])} | |
) | |
else | |
Rails.logger.info "EWS Response2:" | |
Rails.logger.info out.inspect | |
end | |
return "" | |
end | |
end | |
return out | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment