require 'net/http' require "base64" module AsiaDatabasePlugin InUseLocales = Site.first.in_use_locales rescue [:en,:zh_tw] class SafeHash < Hash attr_accessor :duplicate_check_off def []=(key, value) if !duplicate_check_off && has_key?(key) super(key,Array(self[key])+[value]) else super end end end IV = [0x12, 0x34, 0x56, 0x84, 0x9b, 0xab, 0xcd, 0xef].pack('C*') KEY = "Tch#^837".bytes.pack('C*') def self.localize_data(data, locales=InUseLocales) return locales.map{|locale| [locale, data.dup] }.to_h end # 研究計畫 Research Grants def self.sync_projects(query_result, asia_teacher) email_id = asia_teacher.email_id return if email_id.blank? puts "Projects(Research Grants) for user: #{email_id}" projects = query_result["research"].to_a if !query_result['emp'].blank? AsiaProject.where(asia_teacher: asia_teacher,:rss2_id.ne=>nil).where(:rss2_id.nin=>projects.map{|v| v["ukey"]}).destroy end return if projects.count == 0 projects.each do |project| pj = AsiaProject.where(:rss2_id=> project["ukey"]).first pj = AsiaProject.new if pj.nil? pj.rss2_id = project["ukey"] pj.project_name_translations = localize_data(project["name"]) #計畫名稱 # pj.sponsor = if project["period"].present? period = project["period"].split('~').map{|date| DateTime.parse(date) rescue nil} pj.start_date = period[0] pj.end_date = period[1] else pj.start_date = nil pj.end_date = nil end pj.asia_teacher = asia_teacher puts "Project(Research Grants) #{pj.id} saved" if pj.save end end def self.sync_papers(query_result, asia_teacher) # journal and conference papers email_id = asia_teacher.email_id return if email_id.blank? puts "Paper for user: #{email_id}" journal_papers = query_result["journal"].to_a conference_papers = query_result["conference"].to_a papers = journal_papers + conference_papers if !query_result['emp'].blank? AsiaPaper.where(asia_teacher: asia_teacher,:rss2_id.ne=>nil).where(:rss2_id.nin=>papers.map{|v| v["ukey"]}).destroy end return if papers.count == 0 journal_papers.each do |journal_paper| jp = AsiaPaper.where(:rss2_id=> journal_paper["ukey"]).first jp = AsiaPaper.new if jp.nil? jp.rss2_id = journal_paper["ukey"] jp.paper_name_translations = localize_data(journal_paper["Thesis_name"]) jp.journal_name_translations = localize_data(journal_paper["Journal_name"]) jp.issue_year = journal_paper["Thesis_year"] jp.asia_teacher = asia_teacher puts "Journal Paper #{jp.id} saved" if jp.save end conference_papers.each do |conference_paper| wc = AsiaPaper.where(:rss2_id=> conference_paper["ukey"]).first wc = AsiaPaper.new if wc.nil? wc.rss2_id = conference_paper["ukey"] titles = conference_paper["name"].split("-") wc.paper_name_translations = localize_data(titles[0]) wc.journal_name_translations = localize_data(titles[1..-1].join("-")) wc.issue_year = conference_paper["Thesis_year"] wc.asia_teacher = asia_teacher puts "conference paper #{wc.id} saved" if wc.save end end def self.sync_patents(query_result, asia_teacher) # patents email_id = asia_teacher.email_id return if email_id.blank? puts "Patent for user: #{email_id}" patents = query_result["patent"].to_a if !query_result['emp'].blank? AsiaPatent.where(asia_teacher: asia_teacher,:rss2_id.ne=>nil).where(:rss2_id.nin=>patents.map{|v| v["ukey"]}).destroy end return if patents.count == 0 patents.each do |patent| pt = AsiaPatent.where(:rss2_id=> patent["ukey"]).first pt = AsiaPatent.new if pt.nil? pt.rss2_id = patent["ukey"] pt.patent_name_translations = localize_data(patent["Patent_name"]) pt.patent_country, pt.patent_no = patent["Patent_id"].split(":") #專利國家:專利編號, ex: 中華民國設計專利:D170464 if patent["sDate"].present? period = patent["sDate"].split('~').map{|date| DateTime.parse(date) rescue nil} pt.certification_date = period[0] pt.end_date = period[1] else pt.certification_date = nil pt.end_date = nil end pt.asia_teacher = asia_teacher puts "Patent #{pt.id} saved" if pt.save end end #技術轉移 Technology transfer def self.sync_tec_transfers(query_result, asia_teacher) email_id = asia_teacher.email_id return if email_id.blank? puts "Technology transfer for user: #{email_id}" tec_transfers = query_result["tec_transfer"].to_a if !query_result['emp'].blank? AsiaTecTransfer.where(asia_teacher: asia_teacher,:rss2_id.ne=>nil).where(:rss2_id.nin=>tec_transfers.map{|v| v["ukey"]}).destroy end return if tec_transfers.count == 0 tec_transfers.each do |tec_transfer| tt = AsiaTecTransfer.where(:rss2_id=> tec_transfer["ukey"]).first tt = AsiaTecTransfer.new if tt.nil? tt.rss2_id = tec_transfer["ukey"] tt.tech_transfer_name_translations = localize_data(tec_transfer["Trans_Data_NAME"]) #技轉名稱 tt.receiving_unit_translations = localize_data(tec_transfer["Trans_Unit"]) #技轉對象 if tec_transfer["period"].present? #技轉期間 period = tec_transfer["period"].split('~').map{|date| Date.parse(date) rescue nil} tt.start_date = period[0] tt.end_date = period[1] else tt.start_date = nil tt.end_date = nil end tt.asia_teacher = asia_teacher puts "Technology transfer #{tt.id} saved" if tt.save end end def self.sync_exhibitions(query_result, asia_teacher) # exhibitions email_id = asia_teacher.email_id return if email_id.blank? puts "Exhibition(show) for user: #{email_id}" exhibitions = query_result["show"].to_a if !query_result['emp'].blank? AsiaExhibition.where(asia_teacher: asia_teacher,:rss2_id.ne=>nil).where(:rss2_id.nin=>exhibitions.map{|v| v["ukey"]}).destroy end return if exhibitions.count == 0 exhibitions.each do |exhibition| et = AsiaExhibition.where(:rss2_id=> exhibition["ukey"]).first et = AsiaExhibition.new if et.nil? et.rss2_id = exhibition["ukey"] et.exhibition_name_translations = localize_data(exhibition["show_name"]) et.host_translations = localize_data(exhibition["show_author_local"]) if exhibition["period"].present? #展演期間 period = exhibition["period"].split('~').map{|date| DateTime.parse(date) rescue nil} et.exhibition_start_date = period[0] et.exhibition_end_date = period[1] else et.exhibition_start_date = nil et.exhibition_end_date = nil end et.asia_teacher = asia_teacher puts "Exhibition(show) #{et.id} saved" if et.save end end def self.hashify(data_list, grouping_keys) data_list.each_with_object({}) do |data, result| val = result grouping_keys[0...-1].each_with_index do |key, i| kk = data[key] val[kk] ||= {} val = val[kk] end kk = data[grouping_keys[-1]] val[kk] ||= [] val[kk] << data end end end namespace :asia_database do desc "Sync asia database" task :sync,[:user_names, :only_sync_data] => [:environment] do |task,args| I18n.locale = "zh_tw" if args.user_names.present? asia_teachers = AsiaTeacher.where(:email_id.in=>args.user_names).to_a else if args.only_sync_data.blank? || (args.only_sync_data != 'true' && args.only_sync_data != true) #{"ukey"=>"107100033", "ad"=>"slliu", "emp_nm"=>"劉淑玲", #"emp_enm"=>"LIU, SHU-LING", "emp_typeNm"=>"專任", "dept_id"=>"NS00", #"dept_college"=>"護理學院", "dept_nm"=>"護理學系", "dept_Fullnm"=>"護理學院護理學系", #"dept_Fullenm"=>"Department of Nursing"} asia_depart_teachers = AsiaDatabasePlugin.hashify(get_all_teacher_data, ['emp_typeNm', 'dept_college', 'dept_nm'])['專任'] AsiaAcademy.where(:academy_name.nin => asia_depart_teachers.keys).delete_all puts asia_depart_teachers.keys.inspect email_ids = [] asia_depart_teachers.each do |academy_name, departs_info| academy = AsiaAcademy.where("academy_name.zh_tw"=>academy_name).first if academy.nil? academy = AsiaAcademy.create({:academy_name_translations=>AsiaDatabasePlugin.localize_data(academy_name)}) end puts departs_info.keys.inspect departs_info.each do |depart_name, data_list| depart = AsiaDepartment.where("department_name.zh_tw"=>depart_name, "asia_academy"=>academy).first if depart.nil? depart = AsiaDepartment.create({:department_name_translations=>AsiaDatabasePlugin.localize_data(depart_name), :asia_academy=>academy}) end data_list.each do |teacher_data| email_id = teacher_data['ad'] email_ids << email_id asia_teacher = AsiaTeacher.where(:email_id=>email_id).first if asia_teacher.nil? asia_teacher = AsiaTeacher.new(:email_id=>email_id, :asia_academy=>academy, :asia_department=>depart) else asia_teacher.asia_academy = academy asia_teacher.asia_department = depart end asia_teacher.ukey = teacher_data["ukey"] asia_teacher.teacher_translations = {"zh_tw"=>teacher_data["emp_nm"], "en"=>teacher_data["emp_enm"]} asia_teacher.save end end end AsiaTeacher.where(:email_id.nin => email_ids).delete_all end asia_teachers = AsiaTeacher.all.to_a end asia_teachers.each do |asia_teacher| query_result = get_sync_data(asia_teacher.email_id) discipline_expertise_translations = AsiaDatabasePlugin.localize_data([], ['zh_tw', 'en']) query_result['RshSkill'].to_a.each do |h| tmp = h["RSkill"].to_s.strip tmp2 = h["eRSkill"].to_s.strip discipline_expertise_translations['zh_tw'] << [tmp, tmp2].select{|s| s.present?}.join('/') discipline_expertise_translations['en'] << (tmp2.present? ? tmp2 : tmp) end asia_teacher.discipline_expertise_translations = discipline_expertise_translations asia_teacher.save AsiaDatabasePlugin.sync_projects(query_result, asia_teacher) AsiaDatabasePlugin.sync_papers(query_result, asia_teacher) AsiaDatabasePlugin.sync_patents(query_result, asia_teacher) AsiaDatabasePlugin.sync_tec_transfers(query_result, asia_teacher) AsiaDatabasePlugin.sync_exhibitions(query_result, asia_teacher) end end def net_http_get_response(uri,headers={}) http = Net::HTTP.new(uri.host, uri.port) if uri.scheme == "https" http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.use_ssl = true end http.read_timeout = (@read_timeout.nil? ? 60 : @read_timeout) res = http.get((uri.path.blank? ? "/" : uri.path)+(uri.query.blank? ? '' : "?#{uri.query}")) res.uri = uri res end def get_sync_data(email_id) uri = URI.parse("https://webap.asia.edu.tw/TchEportfolio/API/Research/Load") @read_timeout = 300 data = "id=#{email_id}" cipher = OpenSSL::Cipher::Cipher.new("des-cbc").encrypt.tap do |obj| obj.iv = AsiaDatabasePlugin::IV obj.key = AsiaDatabasePlugin::KEY end encrypt = cipher.update(data) + cipher.final() encrypt_base64 = Base64.encode64(encrypt).strip res = net_http_get_response(uri + "?#{encrypt_base64}") return JSON.parse(res.body,{object_class: AsiaDatabasePlugin::SafeHash}) end def get_all_teacher_data res = net_http_get_response(URI.parse("https://webap.asia.edu.tw/TchEportfolio/API/ResearchTID/Load")) data = JSON.parse(res.body,{object_class: AsiaDatabasePlugin::SafeHash}) if data['emp'] return data['emp'] end return [] end end