UNPKG

hkopendata

Version:

Access different Opendata API and data in Hong Kong

144 lines (136 loc) 4.42 kB
// https://www.legco.gov.hk/datagovhk/data-dictionary-webcast-db-en.pdf const cmn = require("../../common"); const moment = require("../../moment"); const BASE_URL = "https://app.legco.gov.hk/wcod/odata/V{type}"; const VALID = { type: /^(LiveMeeting|ArchiveMeeting|MeetingInfo)$/ }; const VALID_OPT = { $format: /^(json|xml)$/, $top: /^[0-9]+$/, $skip: /^[0-9]+$/, $orderby: /^.+$/, $filter: /^.+$/, $inlinecount: /^(allpages)$/, sortorder: /^(asc|desc)$/, }; const PARAMS = { type: "LiveMeeting", $format: "json", $top: 20, } const FIELDS = { text: { "MeetingID": "id", "MeetDate": "date", "MeetTime": "time", "link": "website", "AgendaTime": "actualTime", "AgendaRunningTime": "elapsedTime", } } const SEARCH_CONFIG = { value: { type: { accepted: ["LiveMeeting", "ArchiveMeeting", "MeetingInfo"] } }, rename: { limit: "$top", offset: "$skip", sortby: "$orderby" } } const KEY_TO_NAME = { id: "MeetingID", name: "MeetName", date: "MeetDate", time: "MeetTime", room: "MeetRoomName" } function validateParameters(params) { params = cmn.ParseSearchFields(params, SEARCH_CONFIG); let result = cmn.ValidateParameters(params, VALID, VALID_OPT), substr = (name, val, chi) => { return `substringof('${val}',${chi ? "Chi" :""}${KEY_TO_NAME[name]})` }; if (params.$orderby && !/(asc|desc)/.test(params.$orderby)) { let sortorder = params.sortorder || "asc"; let name = KEY_TO_NAME[params.$orderby] || params.$orderby; if (params.$orderby == "date") { params.$orderby = `${name} ${sortorder}, ${KEY_TO_NAME.time} ${sortorder}`; } else { params.$orderby = `${name} ${sortorder}`; } } if (!params.$filter && params.filter) { let filter = []; for (let key in params.filter) { if (key == "id") { filter.push(substr(key, params.filter[key])); } else if (/^(name|room)^/.test(key)) { filter.push(`(${substr(key, params.filter[key])} or ${substr(key, params.filter[key], true)})`); } else if (/^(from|to)^/.test(key)) { filter.push(`${KEY_TO_NAME.date} ${key == "from" ? "ge" : "le"} datetime'${params.filter[key]}'`); } } if (filter.length > 0) params.$filter = filter.join(" and "); } ["filter", "sortorder"].map(v => delete params[v]); if (!result.error) { result.data = { ...params } } return result; } function search(data, opts) { return new Promise((resolve, reject) => { let processed = validateParameters({ ...PARAMS, ...data }); if (processed.error) { reject(processed); } else { params = processed.data; cmn.APIRequest(cmn.ReplaceURL(BASE_URL, processed.data), params) .then((res) => { resolve(processData(res)); }) .catch((err) => reject(err)) } }) } function processData(data) { let result = []; data.value.map(item => { let temp = {}; item = cmn.RenameFields(item, FIELDS); for (let key in item) { let m, val = item[key]; if (typeof val === "string") val = val.trimChar("\r\n"); if (!val) continue; if (m = key.match(/^(Chi)?(.*)Name$/)) { let lang = m[1] ? "tc" : "en", k = m[2].toCamelCase(); if (!(k in temp)) temp[k] = {}; temp[k][lang] = val; } else if (key == "actualTime") { temp[key] = moment(item[key]).format("YYYY-MM-DD HH:mm:ss"); } else if (key == "elapsedTime") { temp[key] = moment.duration(moment(item[key], "HH:mm:ss").diff(moment("00:00:00", "HH:mm:ss"))).asSeconds(); } else { temp[key.toCamelCase()] = val; } } if (temp.date && temp.time) { temp.time = `${moment(temp.date).format("YYYY-MM-DD")} ${moment(temp.time).format("HH:mm")}` delete temp.date; } result.push(temp); }) return result; } module.exports = search;