2025-10-13 10:48:47 +02:00
|
|
|
/*
|
|
|
|
|
This file is part of »zeitbild«.
|
|
|
|
|
|
|
|
|
|
Copyright 2025 'kcf' <fenris@folksprak.org>
|
|
|
|
|
|
|
|
|
|
»zeitbild« is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
»zeitbild« is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU Lesser General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
along with »zeitbild«. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace _zeitbild.sample
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
type type_date_absolute = {
|
|
|
|
|
year : int;
|
|
|
|
|
month : int;
|
|
|
|
|
day : int;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
type type_date_relative = Array<
|
|
|
|
|
{
|
|
|
|
|
action : "trunc_week";
|
|
|
|
|
args : [int];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
action : "shift_week";
|
|
|
|
|
args : [int];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
action : "shift_day";
|
|
|
|
|
args : [int];
|
|
|
|
|
}
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
type type_ywd = {
|
|
|
|
|
year : int;
|
|
|
|
|
week : int;
|
|
|
|
|
day : int;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
type type_time = {
|
|
|
|
|
hour : int;
|
|
|
|
|
minute : int;
|
|
|
|
|
second : int;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
type type_datetime = (
|
|
|
|
|
{
|
|
|
|
|
timezone_shift : int;
|
|
|
|
|
time : (null | type_time);
|
|
|
|
|
}
|
|
|
|
|
&
|
|
|
|
|
(
|
|
|
|
|
{
|
|
|
|
|
date_absolute : type_date_absolute;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
date_relative : type_date_relative;
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
type type_data = {
|
|
|
|
|
users : Array<
|
|
|
|
|
{
|
|
|
|
|
id : int;
|
|
|
|
|
name : string;
|
|
|
|
|
email_address : string;
|
|
|
|
|
dav_token : (null | string);
|
|
|
|
|
password : string;
|
|
|
|
|
}
|
|
|
|
|
>;
|
|
|
|
|
calendars : Array<
|
|
|
|
|
{
|
|
|
|
|
id : int;
|
|
|
|
|
name : string;
|
|
|
|
|
access : {
|
|
|
|
|
public ?: boolean;
|
|
|
|
|
default_level : ("none" | "view" | "edit" | "admin");
|
|
|
|
|
attributed : Array<
|
|
|
|
|
{
|
|
|
|
|
user_id : int;
|
|
|
|
|
level : ("none" | "view" | "edit" | "admin");
|
|
|
|
|
}
|
|
|
|
|
>;
|
|
|
|
|
};
|
|
|
|
|
resource : (
|
|
|
|
|
{
|
|
|
|
|
kind : "local";
|
|
|
|
|
data : {
|
|
|
|
|
events : Array<
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* @todo rename to "title"
|
|
|
|
|
*/
|
|
|
|
|
name : string;
|
|
|
|
|
begin : type_datetime;
|
|
|
|
|
end : (
|
|
|
|
|
null
|
|
|
|
|
|
|
|
|
|
|
type_datetime
|
|
|
|
|
);
|
|
|
|
|
location : (
|
|
|
|
|
null
|
|
|
|
|
|
|
|
|
|
|
string
|
|
|
|
|
);
|
|
|
|
|
link : (
|
|
|
|
|
null
|
|
|
|
|
|
|
|
|
|
|
string
|
|
|
|
|
);
|
|
|
|
|
description : (
|
|
|
|
|
null
|
|
|
|
|
|
|
|
|
|
|
string
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
kind : "ics_feed";
|
|
|
|
|
data : {
|
|
|
|
|
url : string;
|
|
|
|
|
from_fucked_up_wordpress ?: boolean;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
);
|
2025-10-13 13:19:33 +02:00
|
|
|
hue ?: (null | float);
|
2025-10-13 10:48:47 +02:00
|
|
|
}
|
|
|
|
|
>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2025-10-13 13:19:33 +02:00
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
const phi : float = ((Math.sqrt(5) - 1) / 2);
|
|
|
|
|
|
|
|
|
|
|
2025-10-13 10:48:47 +02:00
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
function decode_datetime(
|
|
|
|
|
datetime : type_datetime
|
|
|
|
|
) : lib_plankton.pit.type_datetime
|
|
|
|
|
{
|
|
|
|
|
if ("date_relative" in datetime)
|
|
|
|
|
{
|
|
|
|
|
return {
|
|
|
|
|
"timezone_shift": datetime.timezone_shift,
|
|
|
|
|
"date": lib_plankton.call.convey(
|
|
|
|
|
lib_plankton.pit.now(),
|
|
|
|
|
(
|
|
|
|
|
datetime.date_relative.map<(x : any) => any>(
|
|
|
|
|
entry => {
|
|
|
|
|
switch (entry.action)
|
|
|
|
|
{
|
|
|
|
|
// default: {throw (new Error("unhandled action: " + entry.action));}
|
|
|
|
|
case "trunc_week": {return (x => lib_plankton.pit.trunc_week(x));}
|
|
|
|
|
case "shift_week": {return (x => lib_plankton.pit.shift_week(x, entry.args[0]));}
|
|
|
|
|
case "shift_day": {return (x => lib_plankton.pit.shift_day(x, entry.args[0]));}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
.concat(
|
|
|
|
|
[
|
|
|
|
|
lib_plankton.pit.to_datetime,
|
|
|
|
|
x => x.date,
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
"time": datetime.time,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return {
|
|
|
|
|
"timezone_shift": datetime.timezone_shift,
|
|
|
|
|
"date": datetime.date_absolute,
|
|
|
|
|
"time": datetime.time,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*/
|
|
|
|
|
export async function init(
|
|
|
|
|
data : type_data
|
|
|
|
|
) : Promise<void>
|
|
|
|
|
{
|
|
|
|
|
let track : {
|
|
|
|
|
user : Record<
|
|
|
|
|
int,
|
|
|
|
|
_zeitbild.type_user_id
|
|
|
|
|
>;
|
|
|
|
|
calendar : Record<
|
|
|
|
|
int,
|
|
|
|
|
_zeitbild.type_user_id
|
|
|
|
|
>;
|
|
|
|
|
} = {
|
|
|
|
|
"user": {},
|
|
|
|
|
"calendar": {},
|
|
|
|
|
};
|
|
|
|
|
for await (const user_raw of data.users)
|
|
|
|
|
{
|
|
|
|
|
const user_object : _zeitbild.type_user_object = {
|
|
|
|
|
"name": user_raw.name,
|
|
|
|
|
"email_address": user_raw.email_address,
|
|
|
|
|
"dav_token": user_raw.dav_token,
|
|
|
|
|
};
|
|
|
|
|
const user_id : _zeitbild.type_user_id = await _zeitbild.service.user.add(
|
|
|
|
|
user_object
|
|
|
|
|
);
|
|
|
|
|
await _zeitbild.service.auth_internal.set(
|
|
|
|
|
user_raw.name,
|
|
|
|
|
user_raw.password
|
|
|
|
|
);
|
|
|
|
|
track.user[user_raw.id] = user_id;
|
|
|
|
|
}
|
|
|
|
|
for await (const calendar_raw of data.calendars)
|
|
|
|
|
{
|
|
|
|
|
let resource_object : _zeitbild.type_resource_object;
|
|
|
|
|
let resource_id : _zeitbild.type_resource_id;
|
|
|
|
|
switch (calendar_raw.resource.kind)
|
|
|
|
|
{
|
|
|
|
|
case "local":
|
|
|
|
|
{
|
|
|
|
|
resource_object = {
|
|
|
|
|
"kind": "local",
|
|
|
|
|
"data": {
|
|
|
|
|
"event_ids": [],
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
resource_id = await _zeitbild.service.resource.add(
|
|
|
|
|
resource_object
|
|
|
|
|
);
|
|
|
|
|
/*const event_ids : Array<_zeitbild.type_local_resource_event_id> = */await Promise.all(
|
|
|
|
|
calendar_raw.resource.data.events
|
|
|
|
|
.map(
|
|
|
|
|
(event_raw) => {
|
|
|
|
|
const event : _zeitbild.type_event_object = {
|
|
|
|
|
"name": event_raw.name,
|
|
|
|
|
"begin": decode_datetime(event_raw.begin),
|
|
|
|
|
"end": (
|
|
|
|
|
(event_raw.end === null)
|
|
|
|
|
?
|
|
|
|
|
null
|
|
|
|
|
:
|
|
|
|
|
decode_datetime(event_raw.end)
|
|
|
|
|
),
|
|
|
|
|
"location": event_raw.location,
|
|
|
|
|
"link": event_raw.link,
|
|
|
|
|
"description": event_raw.description,
|
|
|
|
|
};
|
|
|
|
|
return _zeitbild.service.resource.event_add(resource_id, event);
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "ics_feed":
|
|
|
|
|
{
|
|
|
|
|
resource_object = {
|
|
|
|
|
"kind": "ics_feed",
|
|
|
|
|
"data": {
|
|
|
|
|
"url": calendar_raw.resource.data.url,
|
|
|
|
|
"from_fucked_up_wordpress": (calendar_raw.resource.data.from_fucked_up_wordpress ?? false),
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
resource_id = await _zeitbild.service.resource.add(
|
|
|
|
|
resource_object
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const calendar_object : _zeitbild.type_calendar_object =
|
|
|
|
|
{
|
|
|
|
|
"name": calendar_raw.name,
|
2025-10-13 13:19:33 +02:00
|
|
|
"hue": (
|
|
|
|
|
calendar_raw.hue
|
|
|
|
|
??
|
|
|
|
|
((calendar_raw.id * phi) % 1)
|
|
|
|
|
),
|
2025-10-13 10:48:47 +02:00
|
|
|
"access": {
|
|
|
|
|
"public": (calendar_raw.access.public ?? false),
|
|
|
|
|
"default_level": _zeitbild.value_object.access_level.from_string(calendar_raw.access.default_level),
|
|
|
|
|
"attributed": lib_plankton.map.hashmap.implementation_map(
|
|
|
|
|
lib_plankton.map.hashmap.make(
|
|
|
|
|
x => x.toFixed(0),
|
|
|
|
|
{
|
|
|
|
|
"pairs": (
|
|
|
|
|
calendar_raw.access.attributed
|
|
|
|
|
.map(
|
|
|
|
|
(entry) => ({
|
|
|
|
|
"key": track.user[entry.user_id],
|
|
|
|
|
"value": _zeitbild.value_object.access_level.from_string(entry.level),
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
"resource_id": resource_id,
|
|
|
|
|
};
|
|
|
|
|
const calendar_id : _zeitbild.type_calendar_id = await _zeitbild.service.calendar.add(
|
|
|
|
|
calendar_object
|
|
|
|
|
);
|
|
|
|
|
track.calendar[calendar_raw.id] = calendar_id;
|
|
|
|
|
}
|
|
|
|
|
return Promise.resolve<void>(undefined);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|