sync_personal_data_task_for.../lib/tasks/sync_asia_personal_data_tas...

451 lines
20 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.user_id(member)
user_id_match = member.email.match(/(.*)@asia\.edu\.tw/)
user_id = user_id_match ? user_id_match[1] : nil
end
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, member)
puts "Journal Paper for user: #{self.user_id(member)}"
journal_papers = query_result["journal"].to_a
jps = JournalPaper.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>journal_papers.map{|v| v["ukey"]})
if !query_result['emp'].blank?
jps.update_all({"$pull" => {member_profile_id: member.id}})
end
return if journal_papers.count == 0
journal_papers.each do |journal_paper|
jp = JournalPaper.where(:rss2_id=> journal_paper["ukey"]).first
if jp && jp.member_profile_id.class != Array
JournalPaper.where(:id=>jp.id).update_all(:member_profile_id=> [member.id])
jp = jp.reload
end
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
if (jp.member_profile_id.nil?)
jp.member_profile_id = []
end
jp.member_profile_id << member.id
puts "Journal Paper #{jp.id} saved" if jp.save
end
end
def self.clear_empty_journal_papers
JournalPaper.where(member_profile_id: [],:rss2_id.ne=>nil).delete
end
# 研討會論文
def self.sync_conference_papers(query_result, member)
puts "Conference Paper for user: #{self.user_id(member)}"
conference_papers = query_result["conference"].to_a
if !query_result['emp'].blank?
WritingConference.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>conference_papers.map{|v| v["ukey"]}).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..-1].join("-"))
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 = member.id
puts "conference paper #{wc.id} saved" if wc.save
end
end
# 研究計畫 Research Grants
def self.sync_projects(query_result, member)
puts "Projects(Research Grants) for user: #{self.user_id(member)}"
projects = query_result["research"].to_a
if !query_result['emp'].blank?
Project.where(member_profile_id: member.id,: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 = 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 = member.id
puts "Project(Research Grants) #{pj.id} saved" if pj.save
end
end
# 專書 books
def self.sync_books(query_result, member)
puts "books for user: #{self.user_id(member)}"
books = query_result["books"].to_a
books1 = query_result["books1"].to_a
if !query_result['emp'].blank?
Book.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>(books + books1).map{|v| v["ukey"]}).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 = member.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 = member.id
puts "books #{bk.id} saved" if bk.save
end
end
#專利 Patents
def self.sync_patents(query_result, member)
puts "Patents for user: #{self.user_id(member)}"
patents = query_result["patent"].to_a
if !query_result['emp'].blank?
Patent.where(member_profile_id: member.id,: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 = 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 = member.id
puts "Patent #{pt.id} saved" if pt.save
end
end
#獲獎(榮譽) Award
def self.sync_honors(query_result, member)
puts "Honors(Awards) for user: #{self.user_id(member)}"
honors = query_result["award"].to_a
if !query_result['emp'].blank?
Honor.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>honors.map{|v| v["ukey"]}).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 = member.id
puts "Honor(Award) #{hn.id} saved" if hn.save
end
end
#教師參與展演活動(展演) Show
def self.sync_activities(query_result, member)
puts "Activities(Shows) for user: #{self.user_id(member)}"
activities = query_result["show"].to_a
if !query_result['emp'].blank?
Activity.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>activities.map{|v| v["ukey"]}).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 = member.id
puts "Activity(Show) #{act.id} saved" if act.save
end
end
#授課課程(教學資料) Course Information
def self.sync_courses(query_result, member)
puts "Courses(Course Information) for user: #{self.user_id(member)}"
courses = query_result["cos_data"].to_a
if !query_result['emp'].blank?
Course.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>courses.map{|v| v["ukey"]}).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 = member.id
puts "Course(Course Information) #{cs.id} saved" if cs.save
end
end
#指導論文(個人研究) Thesis Advisor
def self.sync_researches(query_result, member)
puts "Researches(Thesis Advisor) for user: #{self.user_id(member)}"
researches = query_result["paper_data"].to_a
if !query_result['emp'].blank?
Research.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>researches.map{|v| v["ukey"]}).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 = member.id
puts "Research(Thesis Advisor) #{rs.id} saved" if rs.save
end
end
#創作 Create design
def self.sync_create_designs(query_result, member)
puts "Create Designs for user: #{self.user_id(member)}"
create_designs = query_result["create"].to_a
if !query_result['emp'].blank?
CreateDesign.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>create_designs.map{|v| v["ukey"]}).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 = member.id
puts "Create Design #{cd.id} saved" if cd.save
end
end
#技術轉移
def self.sync_tec_transfers(query_result, member)
puts "Technology Transfers for user: #{self.user_id(member)}"
tec_transfers = query_result["tec_transfer"].to_a
if !query_result['emp'].blank?
TecTransfer.where(member_profile_id: member.id,: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 = 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 = member.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, member)
puts "College Projects for user: #{self.user_id(member)}"
college_projects = query_result["college_data"].to_a
if !query_result['emp'].blank?
CollegeProject.where(member_profile_id: member.id,:rss2_id.ne=>nil).where(:rss2_id.nin=>college_projects.map{|v| v["ukey"]}).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("<br>").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 = member.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
user_ids = YAML.load(args.user_names)
member_ids = MemberProfile.where(:email.in=>user_ids.map{|s| s + '@asia.edu.tw' }).pluck(:id)
User.where(:user_name.in=>user_ids, :member_profile_id.nin=>member_ids).each do |u|
query_result = get_sync_data(u.user_name)
emp = query_result["emp"]
next if emp.blank?
member = u.member_profile
member.update(:email=>"#{u.user_name}@asia.edu.tw")
member_ids << member.id
end
members = MemberProfile.where(:id.in=>member_ids).to_a
else
members = MemberProfile.where(:email=>/@asia\.edu\.tw$/).to_a
members += MemberProfile.where(:id.in=> User.where(:member_profile_id.nin=> members.map(&:id)).pluck(:member_profile_id)).to_a
end
members.each do |member|
user_id = AsiaSyncPlugin.user_id(member) rescue nil
if user_id.blank?
user_id = member.user.user_name rescue nil
if user_id.nil?
next
end
end
puts "Fetching data for #{user_id}..."
query_result = get_sync_data(user_id)
#puts ["query_result",query_result]
AsiaSyncPlugin.sync_journal_papers(query_result, member)
AsiaSyncPlugin.sync_books(query_result, member)
AsiaSyncPlugin.sync_conference_papers(query_result, member)
AsiaSyncPlugin.sync_projects(query_result, member)
AsiaSyncPlugin.sync_patents(query_result, member)
AsiaSyncPlugin.sync_honors(query_result, member)
AsiaSyncPlugin.sync_activities(query_result, member)
AsiaSyncPlugin.sync_courses(query_result, member)
AsiaSyncPlugin.sync_researches(query_result, member)
AsiaSyncPlugin.sync_create_designs(query_result, member)
AsiaSyncPlugin.sync_tec_transfers(query_result, member)
AsiaSyncPlugin.sync_college_projects(query_result, member)
end
AsiaSyncPlugin.clear_empty_journal_papers
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