class BulletinFeed include Mongoid::Document include Mongoid::Timestamps include Slug field :title, as: :slug_title, type: String, localize: true field :tag_ids, type: Array, default: [] field :category_ids, type: Array, default: [] before_save do BulletinFeedCache.where(uid: self.uid).each do |cache| cache.regenerate end end def self.create_feed_cache(bulletin=nil,bulletin_feed=nil) Thread.new do if !bulletin.nil? BulletinFeed.where(:tag_ids.in => Array(bulletin.tag_ids).collect{|v| v.to_s}).each do |bulletin_feed| uid = bulletin_feed.uid BulletinFeedCache.where(:uid => uid).each do |cache| cache.regenerate end end elsif !bulletin_feed.nil? uid = bulletin_feed.uid BulletinFeedCache.where(:uid => uid).each do |cache| cache.regenerate end end end end def generate_one_cache_timeout(startdt: nil,enddt: nil,dt: nil, base_url: nil, timeout: nil) begin if timeout.nil? feed_cache_content = self.generate_one_cache(startdt: startdt,enddt: enddt,dt: dt,base_url: base_url) else Timeout::timeout(timeout) do feed_cache_content = nil thread = Thread.new do feed_cache_content = self.generate_one_cache(startdt: startdt,enddt: enddt,dt: dt,base_url: base_url) end (1..(timeout.to_i+1)).each do sleep(1) break if !feed_cache_content.nil? && !thread.alive? end feed_cache_content end end rescue=> e puts [e,e.backtrace] nil end end def generate_one_cache(startdt: nil,enddt: nil,dt: nil, base_url: nil) base_url = Site.first.root_url if base_url.nil? uid = self.uid bf = self if !bf.nil? tags = bf.tag_ids categories = bf.category_ids if !(categories.empty? && tags.empty?) anns_before_filter = Bulletin.is_approved_and_show can_display_and_sorted_flag = false if !dt.nil? dt = DateTime.parse(dt) dtt = dt + 1.day anns_before_filter = anns_before_filter.where(:postdate.gt => dt, :postdate.lt => dtt) elsif !startdt.blank? && enddt.blank? startdt = DateTime.parse(startdt) enddt = DateTime.now anns_before_filter = anns_before_filter.where(:postdate.gt => startdt, :postdate.lt => enddt) elsif !startdt.blank? && !enddt.blank? startdt = DateTime.parse(startdt) enddt = DateTime.parse(enddt) + 1.day anns_before_filter = anns_before_filter.where(:postdate.gt => startdt, :postdate.lt => enddt) else can_display_and_sorted_flag = true end if !tags.empty? anns_before_filter = anns_before_filter.filter_by_tags(tags) end if !categories.empty? anns_before_filter = anns_before_filter.filter_by_categories(categories,paginate=false) end anns_before_filter.selector = {"$and"=>[anns_before_filter.selector,{"$or"=>(I18n.available_locales.map{|v| {"title.#{v}"=>{"$nin"=>["", nil]}}})}]} if can_display_and_sorted_flag announcements = anns_before_filter.valid_time_range.to_a else announcements = anns_before_filter.to_a end else announcements = [] end end all_anns = [] tag_names = [] category_titles = [] tag_ids = [] category_ids = [] first_postdate = anns_before_filter.open_in_future.limit(1).pluck(:postdate)[0] first_deadline = nil cat_ids = announcements.collect{|a| a.category_id.blank? ? nil : a.category_id.to_s}.compact.uniq tag_ids = announcements.collect{|a| a.tag_ids.collect{|v| v.blank? ? nil : v.to_s}}.flatten.compact.uniq basic_query = {:module => 'announcement',:enabled_for=>I18n.locale} if !cat_ids.blank? query = basic_query.merge({:categories.all => cat_ids}) else query = basic_query.clone end if !tag_ids.blank? query = query.merge({:tags.all => tag_ids}) end page = Page.where(query).first || Page.where(basic_query).first more_url = page ? page.get_url : nil announcements.each_with_index do |anns,i| deadline = anns.deadline if !deadline.blank? if first_deadline.nil? || first_deadline>deadline first_deadline = deadline end end user = User.find(anns.create_user_id) rescue nil if !user.nil? author = user.member_name || user.user_name else author = "" end a = {} if more_url a['show_url'] = "#{more_url}/#{anns.to_param}" end a["id"] = anns.uid a["title_translations"] = anns.title_translations a["subtitle_translations"] = anns.subtitle_translations a["text_translations"] = {} text_translations = anns.text_translations a["text_translations"]["en"] = self.class.smart_convertor(text_translations["en"],base_url) if !text_translations["en"].blank? a["text_translations"]["zh_tw"] = self.class.smart_convertor(text_translations["zh_tw"],base_url) if !text_translations["zh_tw"].blank? a["postdate"] = anns.postdate a["image_description_translations"] = anns.image_description_translations a["image"] = {} a["display_img"] = anns.display_img a["image"]["original"] = ("#{base_url}" + anns.image.url rescue "") a["image"]["thumb"] = ("#{base_url}" + anns.image.thumb.url rescue "") a["image"]["mobile"] = ("#{base_url}" + anns.image.mobile.url rescue "") a["tags"] = [] a["category"] = {} a["author"] = author a["params"] = anns.to_param a["subtitle_ann"] = anns.subtitle if anns.display_subtitle? a["bulletin_links"] = [] a["bulletin_files"] = [] a["bulletin_carousel_images"] = anns.bulletin_carousel_images.map{|image| {"src"=>"#{base_url}" + image.file.url,"description"=>image.description.to_s,"description_text"=>image.description_text }} a["external_link"] = anns["is_external_link"] ? anns.external_link : nil anns.tags.each do |tag| if !tag_ids.include?(tag.id.to_s) tag_ids << tag.id.to_s tag_names << {"name_translations" => tag.name_translations} end a["tags"] << {"name_translations" => tag.name_translations} end cat = anns.category if (!category_ids.include?(cat.id.to_s) rescue false) category_ids << cat.id.to_s category_titles << {"title_translations" => cat.title_translations} end a["category"] = {"title_translations" => (cat.title_translations rescue {})} anns.bulletin_links.each do |bl| b = {} b["url"] = bl.url b["title_translations"] = bl.title_translations a["bulletin_links"] << b end anns.bulletin_files.each do |bf| b = {} b["description_translations"] = bf.description_translations b["title_translations"] = bf.title_translations b["url"] = ("#{base_url}" + bf.file.url rescue "") a["bulletin_files"] << b end all_anns << a end invalid_date = [first_postdate,first_deadline].compact.sort[0] anns = { "announcements" => all_anns, "tags" => tag_names, "categories" => category_titles }.to_json BulletinFeedCache.where(uid: uid,start: startdt,end: enddt,date: dt).destroy feed_cache = BulletinFeedCache.create(uid: uid,content: anns,start: startdt,end: enddt,date: dt,invalid_date: invalid_date) anns end def self.smart_convertor(text,url) doc = Nokogiri.HTML(text) doc.search('a[href]').each do |link| if link['href'].nil? link.delete 'href' elsif link['href'].start_with?('/') link['href'] = url + link['href'] elsif link['href'].start_with?('../') link['href'] = url + link['href'][3..-1] end end doc.search('img[src]').each do |link| if link['src'].nil? link.delete 'src' elsif link['src'].start_with?('/') link['src'] = url + link['src'] elsif link['src'].start_with?('../') link['src'] = url + link['src'][3..-1] end end return doc.css('body').inner_html end end