Сегодняшний пост не обязательно слишком интересен с точки зрения кода, но он затрагивает некоторые более важные, более широкие темы без сервера, которые я хотел бы затронуть. Несколько недель назад я обнаружил интересный репозиторий GitHub: https://github.com/gadael/icsdb.
Этот репозиторий содержит файлы iCal (например, данные календаря в виде простого текста) для нерабочих дней для всех 50 штатов США и различных европейских стран. Это может быть полезно во многих отношениях, если, конечно, вы можете анализировать данные iCal. Я подумал, что может быть интересно создать простую службу, которая будет принимать URL-адрес, указывающий на данные iCal, и возвращать информацию в форме JSON.
Существует несколько различных способов анализа iCal, но я считаю, что ical.js от Mozilla достаточно хорош. Библиотека ical.js довольно сложна и позволяет вам работать с данными iCal как с компонентом, вызывая различные методы для поиска данных, но она также может просто возвращать простую проанализированную версию текста. Вот код, который я придумал:
const rp = require('request-promise');
const ical = require('ical.js');
function flattenEvent(e) {
let event = {};
for(let i=0;i<e[1].length;i++) {
let prop = e[1][i];
event[prop[0]] = prop[3];
//console.log('e',prop);
}
return event;
}
exports.main = (args) => {
return new Promise((resolve, reject) => {
rp(args.url).then((txt) => {
try {
let parsed = ical.parse(txt);
let events = parsed[2];
let result = [];
events.forEach(e => result.push(flattenEvent(e)));
resolve({events:result});
} catch(e) {
console.log(e);
reject(e.message);
}
})
.catch((e) => {
reject(e);
});
});
}
По сути — высосать удаленный URL и разобрать с помощью библиотеки. Как я уже сказал, есть хороший объектно-ориентированный API, который предоставляет библиотека, но я обнаружил, что могу работать с исходными данными немного проще. Вы можете видеть, где я просто беру третий элемент в массиве, чтобы получить фактические события. Затем я выравниваю данные, используя flattenEvent
. Если вам интересно, данные представлены в форме под названием jCal, которая имеет спецификацию: https://tools.ietf.org/html/draft-ietf-jcardcal-jcal-10. Моя функция flattenEvent
делает некоторые допущения, которые не обязательно всегда работают хорошо, но пока все работает нормально.
Я проверил это, попросив отпуск в Луизиане:
wsk action invoke ical/get --param url https://raw.githubusercontent.com/gadael/icsdb/master/build/en-US/us-louisiana-nonworkingdays.ics -r
А вот и первые пять результатов.
{
"class": "PUBLIC",
"created": "2014-01-09T00:47:56Z",
"description": "",
"dtend": "1970-01-02",
"dtstamp": "2017-06-23T13:53:48Z",
"dtstart": "1970-01-01",
"last-modified": "2017-06-23T13:53:48Z",
"rrule": {
"freq": "YEARLY"
},
"sequence": 0,
"status": "CONFIRMED",
"summary": "New Year's Day",
"transp": "TRANSPARENT",
"uid": "b901ca08-d924-43c3-9166-1d215c9453d6"
},
{
"class": "PUBLIC",
"created": "2014-01-09T00:47:56Z",
"description": "",
"dtend": "1983-01-02",
"dtstamp": "2017-06-23T13:53:48Z",
"dtstart": "1983-01-01",
"last-modified": "2017-06-23T13:53:48Z",
"rrule": {
"byday": "3MO",
"freq": "YEARLY"
},
"sequence": 0,
"status": "CONFIRMED",
"summary": "Marthin Luther King day/Robert E. Lee day",
"transp": "TRANSPARENT",
"uid": "0ae8128a-e360-492c-b2bd-52ed0d6d06fd"
},
{
"categories": "-New Mexico",
"class": "PUBLIC",
"created": "2014-01-09T00:47:56Z",
"description": "",
"dtend": "1970-02-01",
"dtstamp": "2017-06-23T13:53:48Z",
"dtstart": "1970-02-01",
"last-modified": "2017-06-23T13:53:48Z",
"rrule": {
"byday": "3MO",
"freq": "YEARLY"
},
"sequence": 0,
"status": "CONFIRMED",
"summary": "Presidents Day",
"transp": "TRANSPARENT",
"uid": "17425d41-9ed3-4088-adad-4693d1bd44c9"
},
{
"categories": "Louisiana",
"class": "PUBLIC",
"created": "2014-01-09T00:47:56Z",
"description": "",
"dtend": "1970-04-02",
"dtstamp": "2017-06-23T13:53:48Z",
"dtstart": "1970-04-01",
"last-modified": "2017-06-23T13:53:48Z",
"rdate": "1970-02-10",
"sequence": 0,
"status": "CONFIRMED",
"summary": "Mardi gras",
"transp": "TRANSPARENT",
"uid": "7ac45e93-a684-4061-a0c7-948a89e358b0"
},
{
"categories": "Connecticut",
"class": "PUBLIC",
"created": "2014-01-09T00:47:56Z",
"description": "",
"dtend": "1970-04-09",
"dtstamp": "2017-06-23T13:53:48Z",
"dtstart": "1970-04-08",
"last-modified": "2017-06-23T13:53:48Z",
"rdate": "1970-03-26",
"sequence": 0,
"status": "CONFIRMED",
"summary": "Good Friday",
"transp": "TRANSPARENT",
"uid": "3c46243f-00f8-418f-94cf-4eda72ae7cb2"
}
Итак... некоторые данные. Прохладный. Что мне делать дальше? Когда я впервые начал думать об этих данных, моей первой мыслью было, что они могут быть полезным API для веб-приложений. Я веб-разработчик, поэтому все для меня выглядит как веб-источник. Конечно, зачем мне для этого безсерверные? Я мог бы запустить библиотеку iCal в браузере — единственная проблема, с которой я столкнулся бы, — это CORS — возможно. И я всегда мог скопировать файлы iCal на тот же сервер, что и приложение. Но это действительно ограниченное мышление.
Создав это как бессерверное действие, я открыл его для любого источника событий, в Интернете или нет. Как насчет примера чего-то совершенно не связанного с сетью?
Представьте себе службу поддержки, где каждый день мой процесс получает список сотрудников, ответственных за ИТ-работу на случай чрезвычайных ситуаций. Я мог бы представить процесс, с помощью которого, получив список сотрудников, я мог бы сверить родной штат каждого из них со списком праздников для этого штата и определить, не работает ли этот человек сегодня. Это точно такой же код, но я просто использую его в другом контексте.
И здесь важно помнить об этом. Serverless — это не только упрощение создания приложений NodeJS. Вместо этого я создаю ресурс, который можно использовать в различных ситуациях, как прямых (веб-приложение делает запрос), так и косвенных (процесс, выполняемый по расписанию).
Я уже говорил об этом раньше, но мне кажется, что это не так очевидно.
p.s. Вы можете найти исходный код для этой демонстрации здесь: https://github.com/cfjedimaster/Serverless-Examples/blob/master/ical/get.js
Первоначально опубликовано на www.raymondcamden.com 24 августа 2017 г.