340 lines
7.1 KiB
TypeScript
340 lines
7.1 KiB
TypeScript
![]() |
/**
|
||
|
*/
|
||
|
namespace _zeitbild.frontend.resources.backend
|
||
|
{
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
var _data : _zeitbild.frontend.type_datamodel;
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
export async function init(
|
||
|
) : Promise<void>
|
||
|
{
|
||
|
const path : string = "data.json";
|
||
|
if (_data === undefined) {
|
||
|
_data = lib_plankton.call.convey(
|
||
|
await lib_plankton.file.read(path),
|
||
|
[
|
||
|
lib_plankton.json.decode,
|
||
|
(data_raw : any) => (
|
||
|
({
|
||
|
"users": data_raw["users"],
|
||
|
"calendars": (
|
||
|
data_raw["calendars"]
|
||
|
.map(
|
||
|
(calendar_entry_raw : any) => ({
|
||
|
"id": calendar_entry_raw["id"],
|
||
|
"object": (
|
||
|
((calendar_object_raw) => {
|
||
|
switch (calendar_object_raw["kind"]) {
|
||
|
default: {
|
||
|
return calendar_object_raw;
|
||
|
break;
|
||
|
}
|
||
|
case "concrete": {
|
||
|
return {
|
||
|
"kind": "concrete",
|
||
|
"data": {
|
||
|
"name": calendar_object_raw["data"]["name"],
|
||
|
"private": (
|
||
|
calendar_object_raw["data"]["private"]
|
||
|
??
|
||
|
false
|
||
|
),
|
||
|
"users": calendar_object_raw["data"]["users"],
|
||
|
"events": (
|
||
|
calendar_object_raw["data"]["events"]
|
||
|
.map(
|
||
|
(event_raw : any) => ({
|
||
|
"name": event_raw["name"],
|
||
|
"begin": event_raw["begin"],
|
||
|
"end": (
|
||
|
(
|
||
|
(
|
||
|
event_raw["end"]
|
||
|
??
|
||
|
null
|
||
|
)
|
||
|
===
|
||
|
null
|
||
|
)
|
||
|
?
|
||
|
null
|
||
|
:
|
||
|
event_raw["end"]
|
||
|
),
|
||
|
"location": (
|
||
|
event_raw["location"]
|
||
|
??
|
||
|
null
|
||
|
),
|
||
|
"description": (
|
||
|
event_raw["description"]
|
||
|
??
|
||
|
null
|
||
|
),
|
||
|
})
|
||
|
)
|
||
|
),
|
||
|
},
|
||
|
};
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}) (calendar_entry_raw["object"])
|
||
|
),
|
||
|
})
|
||
|
)
|
||
|
),
|
||
|
}) as type_datamodel
|
||
|
),
|
||
|
]
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
// do nothing
|
||
|
}
|
||
|
return Promise.resolve<void>(undefined);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
export async function calendar_list(
|
||
|
) : Promise<
|
||
|
Array<
|
||
|
{
|
||
|
key : type_calendar_id;
|
||
|
preview : {
|
||
|
name : string;
|
||
|
}
|
||
|
}
|
||
|
>
|
||
|
>
|
||
|
{
|
||
|
await init();
|
||
|
return Promise.resolve(
|
||
|
_data.calendars
|
||
|
.map(
|
||
|
(calendar_entry) => {
|
||
|
switch (calendar_entry.object.kind) {
|
||
|
case "concrete": {
|
||
|
return {
|
||
|
"key": calendar_entry.id,
|
||
|
"preview": {
|
||
|
"name": calendar_entry.object.data.name,
|
||
|
}
|
||
|
};
|
||
|
break;
|
||
|
}
|
||
|
case "collection": {
|
||
|
return {
|
||
|
"key": calendar_entry.id,
|
||
|
"preview": {
|
||
|
"name": calendar_entry.object.data.name,
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
case "caldav": {
|
||
|
return {
|
||
|
"key": calendar_entry.id,
|
||
|
"preview": {
|
||
|
"name": "(imported)",
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*/
|
||
|
export async function calendar_read(
|
||
|
calendar_id : type_calendar_id
|
||
|
) : Promise<type_calendar_object>
|
||
|
{
|
||
|
await init();
|
||
|
const hits = (
|
||
|
_data.calendars
|
||
|
.filter(
|
||
|
(calendar_entry) => (calendar_entry.id === calendar_id)
|
||
|
)
|
||
|
);
|
||
|
if (hits.length <= 0) {
|
||
|
return Promise.reject<type_calendar_object>(new Error("not found"));
|
||
|
}
|
||
|
else {
|
||
|
return Promise.resolve<type_calendar_object>(hits[0].object);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @todo prevent loops
|
||
|
*/
|
||
|
export async function calendar_gather_events(
|
||
|
calendar_id : type_calendar_id,
|
||
|
from_pit : _zeitbild.frontend.helpers.type_pit,
|
||
|
to_pit : _zeitbild.frontend.helpers.type_pit
|
||
|
) : Promise<
|
||
|
Array<
|
||
|
{
|
||
|
calendar_id : type_calendar_id;
|
||
|
calendar_name : string;
|
||
|
event : type_event;
|
||
|
}
|
||
|
>
|
||
|
>
|
||
|
{
|
||
|
await init();
|
||
|
const calendar_object : type_calendar_object = await calendar_read(
|
||
|
calendar_id
|
||
|
);
|
||
|
lib_plankton.log.info(
|
||
|
"calendar_gather_events",
|
||
|
{
|
||
|
"calendar_id": calendar_id,
|
||
|
}
|
||
|
);
|
||
|
switch (calendar_object.kind) {
|
||
|
case "concrete": {
|
||
|
return Promise.resolve(
|
||
|
calendar_object.data.events
|
||
|
.filter(
|
||
|
(event) => _zeitbild.frontend.helpers.pit_is_between(
|
||
|
_zeitbild.frontend.helpers.pit_from_datetime(event.begin),
|
||
|
from_pit,
|
||
|
to_pit
|
||
|
)
|
||
|
)
|
||
|
.map(
|
||
|
(event) => ({
|
||
|
"calendar_id": calendar_id,
|
||
|
"calendar_name": calendar_object.data.name,
|
||
|
"event": event
|
||
|
})
|
||
|
)
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
case "collection": {
|
||
|
return (
|
||
|
Promise.all(
|
||
|
calendar_object.data.sources
|
||
|
.map(
|
||
|
(source_calendar_id) => calendar_gather_events(
|
||
|
source_calendar_id,
|
||
|
from_pit,
|
||
|
to_pit
|
||
|
)
|
||
|
)
|
||
|
)
|
||
|
.then(
|
||
|
(entries) => Promise.resolve(
|
||
|
entries
|
||
|
.reduce(
|
||
|
(x, y) => x.concat(y),
|
||
|
[]
|
||
|
)
|
||
|
)
|
||
|
)
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
case "caldav": {
|
||
|
const url : lib_plankton.url.type_url = lib_plankton.url.decode(
|
||
|
calendar_object.data.source_url
|
||
|
);
|
||
|
const http_request : lib_plankton.http.type_request = {
|
||
|
"version": "HTTP/2",
|
||
|
"scheme": ((url.scheme === "https") ? "https" : "http"),
|
||
|
"host": url.host,
|
||
|
"path": (url.path ?? "/"),
|
||
|
"query": url.query,
|
||
|
"method": lib_plankton.http.enum_method.get,
|
||
|
"headers": {},
|
||
|
"body": null,
|
||
|
};
|
||
|
// TODO: cache?
|
||
|
const http_response : lib_plankton.http.type_response = await lib_plankton.http.call(
|
||
|
http_request,
|
||
|
{
|
||
|
}
|
||
|
);
|
||
|
const vcalendar : lib_plankton.ical.type_vcalendar = lib_plankton.ical.ics_decode(
|
||
|
http_response.body.toString(),
|
||
|
{
|
||
|
}
|
||
|
);
|
||
|
return Promise.resolve(
|
||
|
vcalendar.vevents
|
||
|
.map(
|
||
|
(vevent : lib_plankton.ical.type_vevent) => (
|
||
|
(vevent.dtstart !== undefined)
|
||
|
?
|
||
|
{
|
||
|
"name": (
|
||
|
(vevent.summary !== undefined)
|
||
|
?
|
||
|
vevent.summary
|
||
|
:
|
||
|
"???"
|
||
|
),
|
||
|
"begin": _zeitbild.frontend.helpers.ical_dt_to_own_datetime(vevent.dtstart),
|
||
|
"end": (
|
||
|
(vevent.dtend !== undefined)
|
||
|
?
|
||
|
_zeitbild.frontend.helpers.ical_dt_to_own_datetime(vevent.dtend)
|
||
|
:
|
||
|
null
|
||
|
),
|
||
|
"location": (
|
||
|
(vevent.location !== undefined)
|
||
|
?
|
||
|
vevent.location
|
||
|
:
|
||
|
null
|
||
|
),
|
||
|
"description": (
|
||
|
(vevent.description !== undefined)
|
||
|
?
|
||
|
vevent.description
|
||
|
:
|
||
|
null
|
||
|
),
|
||
|
}
|
||
|
:
|
||
|
null
|
||
|
)
|
||
|
)
|
||
|
.filter(
|
||
|
(event) => (event !== null)
|
||
|
)
|
||
|
.filter(
|
||
|
(event) => _zeitbild.frontend.helpers.pit_is_between(
|
||
|
_zeitbild.frontend.helpers.pit_from_datetime(event.begin),
|
||
|
from_pit,
|
||
|
to_pit
|
||
|
)
|
||
|
)
|
||
|
.map(
|
||
|
(event) => ({
|
||
|
"calendar_id": calendar_id,
|
||
|
"calendar_name": calendar_object.data.name,
|
||
|
"event": event,
|
||
|
})
|
||
|
)
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|