Skip to content

Instantly share code, notes, and snippets.

@taichunmin
Last active May 17, 2022 04:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taichunmin/3e854e9e118785a7985ec24905ee16ce to your computer and use it in GitHub Desktop.
Save taichunmin/3e854e9e118785a7985ec24905ee16ce to your computer and use it in GitHub Desktop.
從微程式的 Portal 系統中下載通訊錄,需先安裝 Greasemonkey 或 Tampermonkey 才能執行! 下方連結是安裝網址。 https://gist.github.com/taichunmin/3e854e9e118785a7985ec24905ee16ce/raw/mp-contacts.user.js
// ==UserScript==
// @name 微程式通訊錄
// @namespace https://ef.program.com.tw:8443/contacts
// @version 0.24
// @description 從微程式的 Portal 系統中下載通訊錄
// @author taichunmin <taichunmin@gmail.com>
// @website https://gist.github.com/taichunmin/3e854e9e118785a7985ec24905ee16ce/
// @updateURL https://gist.github.com/taichunmin/3e854e9e118785a7985ec24905ee16ce/raw/contacts.user.js
// @downloadURL https://gist.github.com/taichunmin/3e854e9e118785a7985ec24905ee16ce/raw/contacts.user.js
// @match https://ef.program.com.tw:8443/*
// @run-at document-start
// @grant none
// @require https://apis.google.com/js/api.js
// @require https://cdn.jsdelivr.net/npm/axios@0/dist/axios.min.js
// @require https://cdn.jsdelivr.net/npm/jquery@1/dist/jquery.min.js
// @require https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js
// @require https://cdn.jsdelivr.net/npm/papaparse@5/papaparse.min.js
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js
// ==/UserScript==
/* global jQuery, axios */
(function ($) {
'use strict'
const sleep = t => new Promise(resolve => setTimeout(resolve, t))
async function getCsv (url, cachetime = 3e4) {
const csv = _.trim(_.get(await axios.get(url, {
params: { cachebust: _.floor(Date.now() / cachetime) },
}), 'data'))
return _.get(Papa.parse(csv, {
encoding: 'utf8',
header: true,
}), 'data', [])
}
async function fetchPortalPageEmployees (cur) {
const html = _.get(await axios.get(`https://ef.program.com.tw:8443/web/12701/5?p_p_id=11&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_11_struts_action=%2Fdirectory%2Fview&_11_tabs1=users&_11_keywords=&_11_advancedSearch=false&_11_andOperator=true&_11_status=0&_11_emailAddress=&_11_firstName=&_11_lastName=&_11_middleName=&_11_organizationId=0&_11_roleId=0&_11_screenName=&_11_userGroupId=0&_11_orderByCol=last-name&_11_orderByType=asc&_11_resetCur=false&_11_delta=200&cur=${cur ?? 1}`, { responseType: 'document' }), 'data')
console.log({ cur, html })
const rows = []
$('table.taglib-search-iterator', html).find('tr:has(td)').each(function () {
const row = []
$(this).find('td').each(function () {
row.push(_.trim($(this).text()))
})
if (_.endsWith(row[2], '@program.com.tw')) rows.push({
name: row[1],
email: row[2],
mobile: row[3].replace(/\D/g, ''),
mpid: row[4],
})
})
return rows
}
async function fetchPortalEmployees () {
const employees = []
let cur = 1
while (true) {
const pageEmployees = await fetchPortalPageEmployees(cur++)
if (!pageEmployees.length) break
employees.push(...pageEmployees)
await sleep(50)
}
return _.keyBy(employees, 'name')
}
async function fetchContacts() {
return await getCsv('https://us-central1-mp-parking-lot.cloudfunctions.net/gcf-microprogram-contacts/export-csv')
}
function splitName(fullname) {
if (/^[\w\s,.]+$/.test(fullname)) {
return _.split(fullname, ' ', 2)
} else {
return [fullname.substr(1), fullname.substr(0, 1)]
}
}
async function downloadGoogleCsv() {
let [employees, contacts] = await Promise.all([
fetchPortalEmployees(),
fetchContacts(),
])
console.log({ employees, contacts })
contacts = _.filter(_.map(contacts, contact => {
const nameSplited = splitName(contact.name)
const employee = _.get(employees, contact.name)
if (!employee) return
return {
'E-mail 1 - Type': '* Work',
'E-mail 1 - Value': employee.email,
'Family Name': nameSplited[1],
'Given Name': nameSplited[0],
'Phone 1 - Type': employee.mobile ? 'Mobile' : '',
'Phone 1 - Value': employee.mobile,
mpid: employee.mpid,
Name: contact.name,
}
}))
let csv = Papa.unparse(contacts, { header: true })
// console.log(csv)
let blob = new Blob([csv], { type: 'text/csv' })
let url = URL.createObjectURL(blob)
let download = $.parseHTML(`<a style="display: none" href="${url}" download="google.csv"></a>`)[0]
document.body.appendChild(download)
download.click()
URL.revokeObjectURL(url)
}
function repairConsole() {
// <iframe> element
var iframe = document.createElement("iframe");
// Hide it somewhere
iframe.style.position="fixed";
iframe.style.height = iframe.style.width = "1px";
iframe.style.top = iframe.style.left = "-5px";
// No src to prevent loading some data
iframe.src = "about: blank";
// Needs append to work
document.body.appendChild(iframe);
// Get the inner console
window.console = iframe.contentWindow.console;
}
$(function () { // on jQuery ready event
repairConsole() // 恢復 console
// 下載通訊錄按鈕
$($.parseHTML('<li><a class="the-firstlayer">匯出通訊錄</a></li>')).appendTo('ul#navigation-ul').click(downloadGoogleCsv)
})
})(jQuery.noConflict(true))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment