trabajo-afectivo/app/models/calendar.rb

370 lines
8.7 KiB
Ruby
Raw Normal View History

2016-10-19 03:11:36 +00:00
# Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
2015-09-09 06:52:05 +00:00
class Calendar < ApplicationModel
store :business_hours
store :public_holidays
before_create :validate_public_holidays, :fetch_ical
before_update :validate_public_holidays, :fetch_ical
after_create :sync_default, :min_one_check
after_update :sync_default, :min_one_check
after_destroy :min_one_check
notify_clients_support
2015-09-09 06:52:05 +00:00
=begin
2015-09-22 14:48:43 +00:00
set inital default calendar
calendar = Calendar.init_setup
returns calendar object
=end
def self.init_setup(ip = nil)
# ignore client ip if not public ip
if ip && ip =~ /^(::1|127\.|10\.|172\.1[6-9]\.|172\.2[0-9]\.|172\.3[0-1]\.|192\.168\.)/
ip = nil
end
# prevent multible setups for same ip
cache = Cache.get('Calendar.init_setup.done')
return if cache && cache[:ip] == ip
Cache.write('Calendar.init_setup.done', { ip: ip }, { expires_in: 1.hour })
2015-09-22 14:48:43 +00:00
# call for calendar suggestion
calendar_details = Service::GeoCalendar.location(ip)
return if !calendar_details
calendar_details['name'] = Calendar.genrate_uniq_name(calendar_details['name'])
calendar_details['default'] = true
calendar_details['created_by_id'] = 1
calendar_details['updated_by_id'] = 1
# find if auto generated calendar exists
calendar = Calendar.find_by(default: true, updated_by_id: 1, created_by_id: 1)
if calendar
calendar.update_attributes(calendar_details)
return calendar
end
create(calendar_details)
end
=begin
2015-09-09 06:52:05 +00:00
get default calendar
calendar = Calendar.default
returns calendar object
=end
def self.default
find_by(default: true)
end
=begin
returnes preset of ical feeds
feeds = Calendar.ical_feeds
returns
{
2015-09-22 20:29:37 +00:00
'US' => 'http://www.google.com/calendar/ical/en.usa%23holiday%40group.v.calendar.google.com/public/basic.ics',
2015-09-09 06:52:05 +00:00
...
}
=end
def self.ical_feeds
gfeeds = {
'Australia' => 'en.australian',
'Austria' => 'de.austrian',
2015-09-22 20:29:37 +00:00
'Argentina' => 'en.ar',
'Bahamas' => 'en.bs',
'Belarus' => 'en.by',
'Brazil' => 'en.brazilian',
2015-09-22 20:29:37 +00:00
'Bulgaria' => 'en.bulgarian',
'Canada' => 'en.canadian',
2015-09-22 20:29:37 +00:00
'China' => 'en.china',
'Chile' => 'en.cl',
'Costa Rica' => 'en.cr',
'Colombia' => 'en.co',
'Croatia' => 'en.croatian',
'Cuba' => 'en.cu',
'Cyprus' => 'de.cy',
'Switzerland' => 'de.ch',
'Denmark' => 'da.danish',
'Netherlands' => 'nl.dutch',
2015-09-22 20:29:37 +00:00
'Egypt' => 'en.eg',
'Ethiopia' => 'en.et',
'Ecuador' => 'en.ec',
'Estonia' => 'en.ee',
'Finland' => 'en.finnish',
'France' => 'en.french',
'Germany' => 'de.german',
'Greece' => 'en.greek',
2015-09-22 20:29:37 +00:00
'Ghana' => 'en.gh',
'Hong Kong' => 'en.hong_kong',
'Haiti' => 'en.ht',
'Hungary' => 'en.hungarian',
'India' => 'en.indian',
'Indonesia' => 'en.indonesian',
'Iran' => 'en.ir',
'Ireland' => 'en.irish',
'Italy' => 'it.italian',
2015-09-22 20:29:37 +00:00
'Israel' => 'en.jewish',
'Japan' => 'en.japanese',
2015-09-22 20:29:37 +00:00
'Kuwait' => 'en.kw',
'Latvia' => 'en.latvian',
'Liechtenstein' => 'en.li',
'Lithuania' => 'en.lithuanian',
'Luxembourg' => 'en.lu',
'Malaysia' => 'en.malaysia',
'Mexico' => 'en.mexican',
2015-09-22 20:29:37 +00:00
'Morocco' => 'en.ma',
'Mauritius' => 'en.mu',
'Moldova' => 'en.md',
'New Zealand' => 'en.new_zealand',
'Norway' => 'en.norwegian',
2015-09-22 20:29:37 +00:00
'Philippines' => 'en.philippines',
'Poland' => 'en.polish',
'Portugal' => 'en.portuguese',
2015-09-22 20:29:37 +00:00
'Pakistan' => 'en.pk',
'Russia' => 'en.russian',
2015-09-22 20:29:37 +00:00
'Senegal' => 'en.sn',
'Singapore' => 'en.singapore',
'South Africa' => 'en.sa',
'South Korean' => 'en.south_korea',
'Spain' => 'en.spain',
'Slovakia' => 'en.slovak',
'Serbia' => 'en.rs',
'Slovenia' => 'en.slovenian',
'Sweden' => 'en.swedish',
2015-09-22 20:29:37 +00:00
'Taiwan' => 'en.taiwan',
'Thai' => 'en.th',
'Turkey' => 'en.turkish',
'UK' => 'en.uk',
'US' => 'en.usa',
'Ukraine' => 'en.ukrainian',
'Uruguay' => 'en.uy',
'Vietnam' => 'en.vietnamese',
2015-09-22 20:29:37 +00:00
'Venezuela' => 'en.ve',
2015-09-09 06:52:05 +00:00
}
2015-09-16 08:40:18 +00:00
all_feeds = {}
2016-06-30 20:04:48 +00:00
gfeeds.each { |key, name|
all_feeds["http://www.google.com/calendar/ical/#{name}%23holiday%40group.v.calendar.google.com/public/basic.ics"] = key
2015-09-09 06:52:05 +00:00
}
2015-09-16 08:40:18 +00:00
all_feeds
2015-09-09 06:52:05 +00:00
end
=begin
get list of available timezones and UTC offsets
list = Calendar.timezones
returns
{
'America/Los_Angeles' => -7
...
}
=end
def self.timezones
list = {}
TZInfo::Timezone.all_country_zone_identifiers.each { |timezone|
t = TZInfo::Timezone.get(timezone)
diff = t.current_period.utc_total_offset / 60 / 60
list[ timezone ] = diff
}
list
end
=begin
syn all calendars with ical feeds
success = Calendar.sync
returns
true # or false
=end
def self.sync
Calendar.all.each(&:sync)
true
end
=begin
syn one calendars with ical feed
calendar = Calendar.find(4711)
success = calendar.sync
returns
true # or false
=end
2015-09-23 07:10:07 +00:00
def sync(without_save = nil)
2015-09-09 06:52:05 +00:00
return if !ical_url
2016-11-10 15:11:59 +00:00
# only sync every 5 days
cache_key = "CalendarIcal::#{id}"
cache = Cache.get(cache_key)
return if !last_log && cache && cache[:ical_url] == ical_url
2015-09-23 07:10:07 +00:00
begin
events = {}
if ical_url && !ical_url.empty?
events = Calendar.parse(ical_url)
end
2015-09-09 06:52:05 +00:00
2015-09-23 07:10:07 +00:00
# sync with public_holidays
if !public_holidays
self.public_holidays = {}
2015-09-09 06:52:05 +00:00
end
# remove old ical entries if feed has changed
2016-06-30 20:04:48 +00:00
public_holidays.each { |day, meta|
next if !public_holidays[day]['feed']
next if meta['feed'] == Digest::MD5.hexdigest(ical_url)
public_holidays.delete(day)
}
# sync new ical feed dates
2016-06-30 20:04:48 +00:00
events.each { |day, summary|
2015-09-23 07:10:07 +00:00
if !public_holidays[day]
public_holidays[day] = {}
end
# ignore if already added or changed
next if public_holidays[day].key?('active')
# create new entry
public_holidays[day] = {
active: true,
summary: summary,
feed: Digest::MD5.hexdigest(ical_url)
2015-09-23 07:10:07 +00:00
}
2015-09-09 06:52:05 +00:00
}
2015-09-23 07:10:07 +00:00
self.last_log = nil
2016-11-10 15:11:59 +00:00
cache = Cache.write(
cache_key,
{ public_holidays: public_holidays, ical_url: ical_url },
{ expires_in: 5.days },
)
2015-09-23 07:10:07 +00:00
rescue => e
self.last_log = e.inspect
end
2015-09-09 06:52:05 +00:00
self.last_sync = Time.zone.now
2015-09-23 07:10:07 +00:00
if !without_save
save
end
2015-09-09 06:52:05 +00:00
true
end
def self.parse(location)
if location =~ /^http/i
result = UserAgent.get(location)
2015-09-23 07:10:07 +00:00
if !result.success?
2016-03-01 14:26:46 +00:00
raise result.error
2015-09-23 07:10:07 +00:00
end
2015-09-09 06:52:05 +00:00
cal_file = result.body
else
cal_file = File.open(location)
end
2016-07-17 23:05:40 +00:00
cals = Icalendar::Calendar.parse(cal_file)
2015-09-09 06:52:05 +00:00
cal = cals.first
events = {}
2016-06-30 20:04:48 +00:00
cal.events.each { |event|
2015-09-09 06:52:05 +00:00
next if event.dtstart < Time.zone.now - 1.year
2015-11-30 13:29:23 +00:00
next if event.dtstart > Time.zone.now + 3.years
2015-09-09 06:52:05 +00:00
day = "#{event.dtstart.year}-#{format('%02d', event.dtstart.month)}-#{format('%02d', event.dtstart.day)}"
comment = event.summary || event.description
comment = Encode.conv( 'utf8', comment.to_s.force_encoding('utf-8') )
if !comment.valid_encoding?
comment = comment.encode('utf-8', 'binary', invalid: :replace, undef: :replace, replace: '?')
end
2015-09-16 08:40:18 +00:00
# ignore daylight saving time entries
next if comment =~ /(daylight saving|sommerzeit|summertime)/i
2015-09-09 06:52:05 +00:00
events[day] = comment
}
events.sort.to_h
end
private
# if changed calendar is default, set all others default to false
def sync_default
return if !default
2016-06-30 20:04:48 +00:00
Calendar.all.each { |calendar|
next if calendar.id == id
next if !calendar.default
calendar.default = false
calendar.save
}
end
# check if min one is set to default true
def min_one_check
2016-11-10 15:11:59 +00:00
if !Calendar.find_by(default: true)
first = Calendar.order(:created_at, :id).limit(1).first
first.default = true
first.save
end
2015-09-22 23:22:45 +00:00
# check if sla's are refer to an existing calendar
2016-11-10 15:11:59 +00:00
default_calendar = Calendar.find_by(default: true)
2016-06-30 20:04:48 +00:00
Sla.all.each { |sla|
2015-09-22 23:22:45 +00:00
if !sla.calendar_id
2016-11-10 15:11:59 +00:00
sla.calendar_id = default_calendar.id
sla.save!
2015-09-22 23:22:45 +00:00
next
end
if !Calendar.find_by(id: sla.calendar_id)
2016-11-10 15:11:59 +00:00
sla.calendar_id = default_calendar.id
sla.save!
2015-09-22 23:22:45 +00:00
end
}
end
2015-09-23 07:10:07 +00:00
# fetch ical feed
def fetch_ical
sync(true)
end
# validate format of public holidays
def validate_public_holidays
# fillup feed info
2016-11-10 15:11:59 +00:00
before = public_holidays_was
2016-06-30 20:04:48 +00:00
public_holidays.each { |day, meta|
2016-11-10 15:11:59 +00:00
if before && before[day] && before[day]['feed']
meta['feed'] = before[day]['feed']
end
meta['active'] = if meta['active']
true
else
false
end
}
end
2015-09-09 06:52:05 +00:00
end