require 'net/http' require "base64" module AsiaSyncPlugin 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*') #ok 期刊論文/Journal Papers #ok 專書/Books #ok 專書論文/Book Chapters #ok 專利/Patents #ok 研討會論文/Conference Papers #ok 研究計畫/Research Grant #ok 獲獎/Awards #ok 展演/Exhibitions #ok 指導論文/ Thesis Advisor #ok 授課課程/Course Information # 技術轉移/Technology Transfers #ok 創作/Creative Design # 指導大專生計畫/College Student Participation in Research Projects # ["journal", "books", "books1", "patent", "conference", # "research", "award", ??技術移轉"tec_transfer", "show",創作 "create", # 授課課程(教學資料)"cos_data", ??個人研究"paper_data", xx指導大專生計畫"college_data"] # 缺少個人外掛: 創作 create 、 指導大專生計畫 college_data #未完成: 技術移轉 tec_transfer #待確認: 指導論文(可用個人研究製作) paper_data def self.localize_data(data) in_use_locales = Site.first.in_use_locales rescue [:en,:zh_tw] return in_use_locales.map{|locale| [locale, data] }.to_h end # 期刊論文 def self.sync_journal_papers(query_result, user) puts "Journal Paper for user: #{user.user_name}" journal_papers = query_result["journal"].to_a if !query_result['emp'].blank? JournalPaper.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if journal_papers.count == 0 journal_papers.each do |journal_paper| jp = JournalPaper.where(:rss2_id=> journal_paper["ukey"]).first jp = JournalPaper.new if jp.nil? jp.rss2_id = journal_paper["ukey"] jp.paper_title_translations = localize_data(journal_paper["Thesis_name"]) jp.journal_title_translations = localize_data(journal_paper["Journal_name"]) jp.authors_translations = localize_data(journal_paper["author"]) jp.year = journal_paper["Thesis_year"] journal_paper_type = JournalPaperType.where(:title=>journal_paper["J_class"]).first if journal_paper_type.nil? journal_paper_type = JournalPaperType.create(:title_translations=>localize_data(journal_paper["J_class"])) end jp.journal_paper_type = journal_paper_type jp.member_profile_id = user.member_profile_id puts "Journal Paper #{jp.id} saved" if jp.save end end # 研討會論文 def self.sync_conference_papers(query_result, user) puts "Conference Paper for user: #{user.user_name}" conference_papers = query_result["conference"].to_a if !query_result['emp'].blank? WritingConference.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if conference_papers.count == 0 conference_papers.each do |conference_paper| wc = WritingConference.where(:rss2_id=> conference_paper["ukey"]).first wc = WritingConference.new if wc.nil? wc.rss2_id = conference_paper["ukey"] titles = conference_paper["name"].split("-") wc.paper_title_translations = localize_data(titles[0]) wc.conference_title_translations = localize_data(titles[1]) wc.authors_translations = localize_data(conference_paper["author"]) wc.location_translations = localize_data(conference_paper["Sym_location"].strip) wc.publication_date = DateTime.parse(conference_paper["Sym_YearMonth"].gsub('.','/')) rescue nil wc.member_profile_id = user.member_profile_id puts "conference paper #{wc.id} saved" if wc.save end end # 研究計畫 Research Grants def self.sync_projects(query_result, user) puts "Projects(Research Grants) for user: #{user.user_name}" projects = query_result["research"].to_a if !query_result['emp'].blank? Project.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if projects.count == 0 projects.each do |project| pj = Project.where(:rss2_id=> project["ukey"]).first pj = Project.new if pj.nil? pj.rss2_id = project["ukey"] pj.project_title_translations = localize_data(project["name"]) #計畫名稱 pj.participator_translations = localize_data(project["author"]) #參與人 if project["period"].present? #計畫期間 period = project["period"].split('~').map{|date| DateTime.parse(date.gsub(".","/")) rescue nil } pj.period_start_date = period[0] pj.period_end_date = period[1] end pj.member_profile_id = user.member_profile_id puts "Project(Research Grants) #{pj.id} saved" if pj.save end end # 專書 books def self.sync_books(query_result, user) puts "books for user: #{user.user_name}" books = query_result["books"].to_a books1 = query_result["books1"].to_a if !query_result['emp'].blank? Book.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (books.count == 0 && books1.count == 0) books.each do |book| bk = Book.where(:rss2_id=> book["ukey"]).first bk = Book.new if bk.nil? bk.rss2_id = book["ukey"] bk.book_title_translations = localize_data(book["Books_name"]) #書名 bk.authors_translations = localize_data(book["author"]) #作者 bk.publisher_translations = localize_data(book["Books_publisher"]) #出版社 if !(book["Books_YearMonth"].blank?) #出版日期 if book["Books_YearMonth"].scan(/[\.\/]/).length == 0 # ex: 2021 bk.publish_date = DateTime.parse(book["Books_YearMonth"] + "/1") rescue nil else #ex: 2017.03 bk.publish_date = DateTime.parse(book["Books_YearMonth"].gsub('.','/')) rescue nil end end if bk.publish_date bk.year = bk.publish_date.year end bk.member_profile_id = user.member_profile_id puts "books #{bk.id} saved" if bk.save end books1.each do |book| bk = Book.where(:rss2_id=> book["ukey"]).first bk = Book.new if bk.nil? bk.rss2_id = book["ukey"] bk.book_title_translations = localize_data(book["Books_name"]) #書名 bk.authors_translations = localize_data(book["author"]) #作者 bk.publisher_translations = localize_data(book["Books_publisher"]) #出版社 bk.year = book["Books_year"] if !(book["Books_year"].blank?) #出版年度 bk.publish_date = DateTime.parse(book["Books_year"] + "/1") rescue nil end bk.member_profile_id = user.member_profile_id puts "books #{bk.id} saved" if bk.save end end #專利 Patents def self.sync_patents(query_result, user) puts "Patents for user: #{user.user_name}" patents = query_result["patent"].to_a if !query_result['emp'].blank? Patent.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (patents.count == 0 ) patents.each do |patent| pt = Patent.where(:rss2_id=> patent["ukey"]).first pt = Patent.new if pt.nil? pt.rss2_id = patent["ukey"] pt.patent_title_translations = localize_data(patent["Patent_name"]) #專利名稱 pt.patent_no = patent["Patent_id"] #專利編號 if patent["Patent_class"].present? #專利類別 end if patent["sDate"].present? period = patent["sDate"].split('~').map{|date| DateTime.parse(date) rescue nil} pt.publish_date = period[0] pt.application_date = period[0] pt.end_date = period[1] end pt.member_profile_id = user.member_profile_id puts "Patent #{pt.id} saved" if pt.save end end #獲獎(榮譽) Award def self.sync_honors(query_result, user) puts "Honors(Awards) for user: #{user.user_name}" honors = query_result["award"].to_a if !query_result['emp'].blank? Honor.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (honors.count == 0 ) honors.each do |honor| hn = Honor.where(:rss2_id=> honor["ukey"]).first hn = Honor.new if hn.nil? hn.rss2_id = honor["ukey"] hn.award_name_translations = localize_data(honor["Award_name"]) #獎項名稱 hn.awarding_unit_translations = localize_data(honor["Award_unit"].to_s.gsub("授獎單位:","").strip) #頒獎單位 hn.award_date = DateTime.parse(honor["Award_Date"].gsub('.','/')) rescue nil #獲獎日期 hn.member_profile_id = user.member_profile_id puts "Honor(Award) #{hn.id} saved" if hn.save end end #教師參與展演活動(展演) Show def self.sync_activities(query_result, user) puts "Activities(Shows) for user: #{user.user_name}" activities = query_result["show"].to_a if !query_result['emp'].blank? Activity.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (activities.count == 0 ) activities.each do |activity| act = Activity.where(:rss2_id=> activity["ukey"]).first act = Activity.new if act.nil? act.rss2_id = activity["ukey"] act.activity_name_translations = localize_data(activity["show_name"]) #活動名稱 act.activity_area_translations = localize_data(activity["show_author_local"]) #地點 if activity["period"].present? #展演期間 period = activity["period"].split('~').map{|date| DateTime.parse(date) rescue nil} act.activity_start_date = period[0] act.activity_end_date = period[1] end act.member_profile_id = user.member_profile_id puts "Activity(Show) #{act.id} saved" if act.save end end #授課課程(教學資料) Course Information def self.sync_courses(query_result, user) puts "Courses(Course Information) for user: #{user.user_name}" courses = query_result["cos_data"].to_a if !query_result['emp'].blank? Course.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (courses.count == 0 ) courses.each do |course| cs = Course.where(:rss2_id=> course["ukey"]).first cs = Course.new if cs.nil? cs.rss2_id = course["ukey"] cs.title_translations = localize_data(course["cos_came"]) #課程名稱 cs.objective_translations = localize_data(course["cos_data_nm"]) #課程目標(簡介) course_class = course["cos_data_nm"].split(/[\(\)]/)[1].strip rescue "" #課程類別 if !course_class.blank? course_category = CourseCategory.where(:title => course_class).first if course_category.nil? course_category = CourseCategory.create(:title_translations=>localize_data(course_class)) end cs.course_category = course_category end course_year_semester = course["cos_data_nm"].split(/[【】]/)[1].strip rescue "" #學年度和學期 ex: 第109學年第2學期:A班 if !course_year_semester.blank? year = course_year_semester.split(/[第學]/)[1].strip rescue nil cs.year = year course_semester_title = course_year_semester.split(/[年:]/)[1].strip rescue "" if !course_semester_title.blank? course_semester = CourseSemester.where(:title=>course_semester_title).first if course_semester.nil? course_semester = CourseSemester.create(:title_translations=>localize_data(course_semester_title)) end cs.course_semester = course_semester end end cs.course_code = course["cos_data"] #課程代碼 ex: "ES200023A" cs.member_profile_id = user.member_profile_id puts "Course(Course Information) #{cs.id} saved" if cs.save end end #指導論文(個人研究) Thesis Advisor def self.sync_researches(query_result, user) puts "Researches(Thesis Advisor) for user: #{user.user_name}" researches = query_result["paper_data"].to_a if !query_result['emp'].blank? Research.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (researches.count == 0 ) researches.each do |research| rs = Research.where(:rss2_id=> research["ukey"]).first rs = Research.new if rs.nil? rs.rss2_id = research["ukey"] rs.research_title_translations = localize_data(research["thesis_name"].to_s.gsub("_#{research["chi_name"]}","")) #論文名稱 rs.extracted_chapters_translations = localize_data(research["Paper_unit"]) #系所(摘要) rs.keywords = research["Paper_unit"] #系所(關鍵字) rs.authors_translations = localize_data(research["chi_name"]) #作者 rs.year = research["year"] #年度 rs.member_profile_id = user.member_profile_id puts "Research(Thesis Advisor) #{rs.id} saved" if rs.save end end #創作 Create design def self.sync_create_designs(query_result, user) puts "Create Designs for user: #{user.user_name}" create_designs = query_result["create"].to_a if !query_result['emp'].blank? CreateDesign.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (create_designs.count == 0 ) create_designs.each do |create_design| cd = CreateDesign.where(:rss2_id=> create_design["ukey"]).first cd = CreateDesign.new if cd.nil? cd.rss2_id = create_design["ukey"] cd.design_translations = localize_data(create_design["Create_name"].to_s.split("設計:")[1..-1].join("")) #設計 cd.create_location_translations = localize_data(create_design["Create_location"]) #地點 cd.publish_date = Date.parse(create_design["Create_sdate"].gsub(".","/")) rescue nil #系所(關鍵字) cd.member_profile_id = user.member_profile_id puts "Create Design #{cd.id} saved" if cd.save end end #技術轉移 def self.sync_tec_transfers(query_result, user) puts "Technology Transfers for user: #{user.user_name}" tec_transfers = query_result["tec_transfer"].to_a if !query_result['emp'].blank? TecTransfer.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (tec_transfers.count == 0 ) tec_transfers.each do |tec_transfer| tt = TecTransfer.where(:rss2_id=> tec_transfer["ukey"]).first tt = TecTransfer.new if tt.nil? tt.rss2_id = tec_transfer["ukey"] tt.patent_number = tec_transfer["ukey"] tt.trans_name_translations = localize_data(tec_transfer["Trans_Data_NAME"]) #設計 tt.trans_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.period_start = period[0] tt.period_end = period[1] end tt.member_profile_id = user.member_profile_id puts "Technology Transfer #{tt.id} saved" if tt.save end end #指導大專生計畫 College Student Participation in Research Projects def self.sync_college_projects(query_result, user) puts "College Projects for user: #{user.user_name}" college_projects = query_result["college_data"].to_a if !query_result['emp'].blank? CollegeProject.where(member_profile_id: user.member_profile_id,:rss2_id.ne=>nil).destroy end return if (college_projects.count == 0 ) college_projects.each do |college_project| cp = CollegeProject.where(:rss2_id=> college_project["ukey"]).first cp = CollegeProject.new if cp.nil? cp.rss2_id = college_project["ukey"] cp.year = college_project["college_year_sch"] cp.project_name_translations = localize_data(college_project["College_name"]) #計畫名稱 college_tch_std = college_project["College_tch_std"].to_s.split("
").map{|v| v.split(":")[1..-1].join("").strip} cp.advising_professor_translations = localize_data(college_tch_std[0]) #指導教授 cp.student_name_translations = localize_data(college_tch_std[1]) #學生姓名 cp.department_translations = localize_data(college_project["College_unit_nm"].strip) cp.member_profile_id = user.member_profile_id puts "College Project #{cp.id} saved" if cp.save end end end namespace :sync_asia_personal_plugins do desc 'sync_personal_plugins from Asia' task :sync,[:user_names] => [:environment] do |task,args| if args.user_names users = User.where(:user_name.in=>YAML.load(args.user_names)).to_a else users = User.all.to_a end users.each do |user| puts "Fetching data for #{user.user_name}..." query_result = get_sync_data(user.user_name) #puts ["query_result",query_result] AsiaSyncPlugin.sync_journal_papers(query_result, user) AsiaSyncPlugin.sync_books(query_result, user) AsiaSyncPlugin.sync_conference_papers(query_result, user) AsiaSyncPlugin.sync_projects(query_result, user) AsiaSyncPlugin.sync_patents(query_result, user) AsiaSyncPlugin.sync_honors(query_result, user) AsiaSyncPlugin.sync_activities(query_result, user) AsiaSyncPlugin.sync_courses(query_result, user) AsiaSyncPlugin.sync_researches(query_result, user) AsiaSyncPlugin.sync_create_designs(query_result, user) AsiaSyncPlugin.sync_tec_transfers(query_result, user) AsiaSyncPlugin.sync_college_projects(query_result, user) 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(user_id) uri = URI.parse("https://webap.asia.edu.tw/TchEportfolio/API/Research/Load") @read_timeout = 300 data = "id=#{user_id}" cipher = OpenSSL::Cipher::Cipher.new("des-cbc").encrypt.tap do |obj| obj.iv = AsiaSyncPlugin::IV obj.key = AsiaSyncPlugin::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: AsiaSyncPlugin::SafeHash}) end end