const { hasPath, pathOr, props } = require('ramda'); const parseArgs = require('minimist'); const process = require('process'); const page_url = (page_id) => `https://www.facebook.com/${page_id}`; const page_events_url = (page_id) => page_url(page_id) + '/events/'; const fs = require('fs').promises; const filesystem = require('fs'); const flatten_string = (page_id) => { if (page_id.startsWith('"') && page_id.endsWith('"')) { return page_id.slice(1, page_id.length - 1); } if (page_id.startsWith("'") && page_id.endsWith("'")) { return page_id.slice(1, page_id.length - 1); } return page_id; }; const parse_output = (argv) => { let [res = ''] = props(['output', 'o'], argv).filter( (item) => item !== undefined, ); res = flatten_string(res); if (res === '') { res = null; } return res; }; const parse_args = (args) => { const argv = parseArgs(args); const has_help_param = hasPath(['h'], argv) || hasPath(['help'], argv) || hasPath(['?'], argv); if (has_help_param) { process.exit(1); } const away_empty_strings = (str) => str.length !== 0; const page_id_to_page_events_url = page_events_url; const parse_param = (param) => flatten_string(pathOr([''], [param], argv).pop()) .split(',') .filter(away_empty_strings) .map(page_id_to_page_events_url); let events = flatten_string(pathOr('', ['events'], argv)); if (events === '') { events = null; } const output = parse_output(argv); const get_upcoming_events = !pathOr(false, ['skip-upcoming-events'], argv); const get_past_events = pathOr(false, ['past-events'], argv); const headless = pathOr(true, ['headless'], argv); return { page_id: `${argv._}`, events, output, get_upcoming_events, get_past_events, headless, }; }; const get_upcoming_events_from_page = pathOr(null, [ 'data', 'page', 'upcoming_events', ]); const get_page_info = pathOr({ end_cursor: null, has_next_page: false }, [ 'page_info', ]); const get_edges = pathOr([], ['edges']); const get_past_events_from_page = pathOr(null, ['data', 'page', 'past_events']); const to_unique_events = (acc, current) => [ ...acc.filter((event) => event.id !== current.id), current, ]; const get_city_name = (event) => pathOr('', ['event_place', 'city', 'contextual_name'], event); const get_event_host = (event) => pathOr('', ['event_place', 'contextual_name'], event); const read_previous_events = (path) => { if (path !== null) { if (filesystem.existsSync(path)) { return fs .readFile(path, { encoding: 'utf-8' }) .then((content) => JSON.parse(content)) .catch((error) => { console.error(error); process.exit(1); }); } } return Promise.resolve([]); }; const write_events = (path, events) => fs.writeFile(path, JSON.stringify(events)); const map_event = ({ node: event }) => { const ticket_url = pathOr('', ['event_buy_ticket_url'], event); const city = get_city_name(event); const host = get_event_host(event); const canceled = pathOr(false, ['is_canceled'], event); const start = pathOr(0, ['start_timestamp'], event) * 1000; const updated = pathOr(0, ['updated_time'], event) * 1000; return { canceled, host, id: event.id, location: city, name: event.name, ticket_url, date: { start, updated }, }; }; const has_upcoming_events = (body) => body.includes('upcoming events') && !body.includes('not have any upcoming events'); const has_past_events = (body) => body.includes('past events') && !body.includes('not have any past events'); const by_date = (a, b) => { const b_date = b.date.start; const a_date = a.date.start; if (a_date > b_date) { return 1; } if (a_date == b_date) { return 0; } return -1; }; const event_date_to_date_obj = (event) => { const start = pathOr(null, ['date', 'start'], event); const updated = pathOr(null, ['date', 'updated'], event); if (start !== null) { try { event.date.start = new Date(start); event.date.updated = new Date(updated); } catch (e) { console.error(e); return event; } } return event; }; const sleep = (s) => new Promise((res) => setTimeout(res, s * 1000)); module.exports = { by_date, event_date_to_date_obj, get_past_events_from_page, get_upcoming_events_from_page, has_past_events, has_upcoming_events, get_page_info, get_edges, map_event, parse_args, read_previous_events, to_unique_events, write_events, sleep, };