[mod]
This commit is contained in:
parent
85f16e3c3b
commit
78014d6a3a
9 changed files with 529 additions and 131 deletions
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"log": [
|
"log": [
|
||||||
{"kind": "stdout", "data": {"threshold": "debug"}}
|
{"kind": "stdout", "data": {"threshold": "info"}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,8 +338,8 @@
|
||||||
"data": {
|
"data": {
|
||||||
"name": "Lixer",
|
"name": "Lixer",
|
||||||
"private": true,
|
"private": true,
|
||||||
"read_only": true,
|
"url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=3&future_months=36",
|
||||||
"source_url": "https://export.kalender.digital/ics/0/3e10dae66950379d4cc8/gesamterkalender.ics?past_months=3&future_months=36"
|
"read_only": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
157
source/api/actions/events.ts
Normal file
157
source/api/actions/events.ts
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
|
||||||
|
namespace _zeitbild.api
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function register_events(
|
||||||
|
rest_subject : lib_plankton.rest.type_rest
|
||||||
|
) : void
|
||||||
|
{
|
||||||
|
register<
|
||||||
|
{
|
||||||
|
from : int;
|
||||||
|
to : int;
|
||||||
|
calendar_ids : (
|
||||||
|
null
|
||||||
|
|
|
||||||
|
Array<_zeitbild.type.calendar_id>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Array<
|
||||||
|
{
|
||||||
|
calendar_id : int;
|
||||||
|
event : _zeitbild.type.event_object;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>(
|
||||||
|
rest_subject,
|
||||||
|
lib_plankton.http.enum_method.post,
|
||||||
|
"/events",
|
||||||
|
{
|
||||||
|
"description": "stellt Veranstaltungen aus verschiedenen Kalendern zusammen",
|
||||||
|
"query_parameters": [
|
||||||
|
],
|
||||||
|
"input_schema": () => ({
|
||||||
|
"type": "object",
|
||||||
|
"nullable": false,
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"from": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": false,
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": false,
|
||||||
|
},
|
||||||
|
"calendar_id": {
|
||||||
|
"type": "array",
|
||||||
|
"nullable": false,
|
||||||
|
"items": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"from",
|
||||||
|
"to",
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
"output_schema": () => ({
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"nullable": false,
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"calendar_id": {
|
||||||
|
"type": "number",
|
||||||
|
"nullable": false,
|
||||||
|
},
|
||||||
|
"event": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
},
|
||||||
|
"begin": {
|
||||||
|
"type": "int",
|
||||||
|
"nullable": false,
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"type": "int",
|
||||||
|
"nullable": true,
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"begin",
|
||||||
|
"end",
|
||||||
|
"location",
|
||||||
|
"description",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"calendar_id",
|
||||||
|
"event",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
"restriction": restriction_none, // TODO
|
||||||
|
"execution": (stuff) => {
|
||||||
|
if (stuff.input === null) {
|
||||||
|
return Promise.resolve({
|
||||||
|
"status_code": 400,
|
||||||
|
"data": null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
(
|
||||||
|
(stuff.input.calendar_ids !== null)
|
||||||
|
?
|
||||||
|
Promise.resolve(stuff.input.calendar_ids)
|
||||||
|
:
|
||||||
|
(
|
||||||
|
_zeitbild.service.calendar.overview(0) // TODO: user_id
|
||||||
|
.then(
|
||||||
|
(x : any) => x.map((y : any) => y.id)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(calendar_ids : Array<_zeitbild.type.calendar_id>) => _zeitbild.service.calendar.gather_events(
|
||||||
|
calendar_ids,
|
||||||
|
// @ts-ignore
|
||||||
|
stuff.input.from,
|
||||||
|
// @ts-ignore
|
||||||
|
stuff.input.to
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(data : any) => Promise.resolve({
|
||||||
|
"status_code": 200,
|
||||||
|
"data": data,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,6 +28,10 @@ namespace _zeitbild.api
|
||||||
{
|
{
|
||||||
_zeitbild.api.register_calendar_list(rest_subject);
|
_zeitbild.api.register_calendar_list(rest_subject);
|
||||||
}
|
}
|
||||||
|
// misc
|
||||||
|
{
|
||||||
|
_zeitbild.api.register_events(rest_subject);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return rest_subject;
|
return rest_subject;
|
||||||
|
|
|
@ -275,5 +275,44 @@ namespace _zeitbild.repository.calendar
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function overview(
|
||||||
|
user_id : _zeitbild.type.user_id
|
||||||
|
) : Promise<
|
||||||
|
Array<
|
||||||
|
{
|
||||||
|
id : _zeitbild.type.calendar_id;
|
||||||
|
name : string;
|
||||||
|
public : boolean;
|
||||||
|
role : (null | _zeitbild.type.role);
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
_zeitbild.database.get_implementation().query_free_get(
|
||||||
|
{
|
||||||
|
"template": "SELECT x.id AS id, x.name AS name, x.public AS public, MAX(y.role) AS role FROM calendars AS x LEFT OUTER JOIN calendar_members AS y ON (x.id = y.calendar_id) WHERE (x.public OR (y.user_id = $user_id)) GROUP BY x.id;",
|
||||||
|
"arguments": {
|
||||||
|
"user_id": user_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(rows) => Promise.resolve(
|
||||||
|
rows.map(
|
||||||
|
(row) => ({
|
||||||
|
"id": row["id"],
|
||||||
|
"name": row["name"],
|
||||||
|
"public": row["public"],
|
||||||
|
"role": row["role"],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -284,7 +284,7 @@ namespace _zeitbild.repository.resource
|
||||||
{
|
{
|
||||||
"kind": "local",
|
"kind": "local",
|
||||||
"data": {
|
"data": {
|
||||||
"events": datasets_extra_local_events.map(x => decode_event(x)),
|
"events": datasets_extra_local_events.map(x => decode_event(x.preview)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -31,6 +31,25 @@ namespace _zeitbild.service.calendar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function overview(
|
||||||
|
user_id : _zeitbild.type.user_id
|
||||||
|
) : Promise<
|
||||||
|
Array<
|
||||||
|
{
|
||||||
|
id : _zeitbild.type.calendar_id;
|
||||||
|
name : string;
|
||||||
|
public : boolean;
|
||||||
|
role : (null | _zeitbild.type.role);
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
return _zeitbild.repository.calendar.overview(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export async function get(
|
export async function get(
|
||||||
|
@ -39,14 +58,133 @@ namespace _zeitbild.service.calendar
|
||||||
{
|
{
|
||||||
return _zeitbild.repository.calendar.read(calendar_id);
|
return _zeitbild.repository.calendar.read(calendar_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
async function gather_events(
|
async function get_events(
|
||||||
calendar_ids : Array<_zeitbild.type.calendar_id>,
|
calendar_id : _zeitbild.type.calendar_id,
|
||||||
from_pit : _zeitbild.helpers.type_pit,
|
from_pit : _zeitbild.helpers.type_pit,
|
||||||
to_pit : _zeitbild.helpers.type_pit
|
to_pit : _zeitbild.helpers.type_pit
|
||||||
|
) : Promise<
|
||||||
|
Array<
|
||||||
|
_zeitbild.type.event_object
|
||||||
|
>
|
||||||
|
>
|
||||||
|
{
|
||||||
|
const calendar_object : _zeitbild.type.calendar_object = await _zeitbild.repository.calendar.read(calendar_id);
|
||||||
|
const resource_object : _zeitbild.type.resource_object = await _zeitbild.repository.resource.read(calendar_object.resource_id);
|
||||||
|
switch (resource_object.kind) {
|
||||||
|
case "local": {
|
||||||
|
return Promise.resolve(
|
||||||
|
resource_object.data.events
|
||||||
|
.filter(
|
||||||
|
(event : _zeitbild.type.event_object) => _zeitbild.helpers.pit_is_between(
|
||||||
|
_zeitbild.helpers.pit_from_datetime(event.begin),
|
||||||
|
from_pit,
|
||||||
|
to_pit
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "caldav": {
|
||||||
|
// TODO readonly
|
||||||
|
const url : lib_plankton.url.type_url = lib_plankton.url.decode(
|
||||||
|
resource_object.data.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.helpers.ical_dt_to_own_datetime(vevent.dtstart),
|
||||||
|
"end": (
|
||||||
|
(vevent.dtend !== undefined)
|
||||||
|
?
|
||||||
|
_zeitbild.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.helpers.pit_is_between(
|
||||||
|
_zeitbild.helpers.pit_from_datetime(event.begin),
|
||||||
|
from_pit,
|
||||||
|
to_pit
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error("invalid resource kind: " + resource_object["kind"])
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo user id
|
||||||
|
*/
|
||||||
|
export async function gather_events(
|
||||||
|
calendar_ids : Array<_zeitbild.type.calendar_id>,
|
||||||
|
from_pit : _zeitbild.helpers.type_pit,
|
||||||
|
to_pit : _zeitbild.helpers.type_pit,
|
||||||
) : Promise<
|
) : Promise<
|
||||||
Array<
|
Array<
|
||||||
{
|
{
|
||||||
|
@ -56,136 +194,34 @@ namespace _zeitbild.service.calendar
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
let result : Array<
|
return (
|
||||||
{
|
Promise.all(
|
||||||
calendar_id : _zeitbild.type.calendar_id;
|
calendar_ids
|
||||||
event : _zeitbild.type.event_object;
|
.map(
|
||||||
}
|
(calendar_id) => get_events(
|
||||||
> = [];
|
calendar_id,
|
||||||
for await (const calendar_id of calendar_ids) {
|
from_pit,
|
||||||
const calendar_object : _zeitbild.type.calendar_object = await _zeitbild.repository.calendar.read(calendar_id);
|
to_pit
|
||||||
const resource_object : _zeitbild.type.resource_object = await _zeitbild.repository.resource.read(calendar_object.resource_id);
|
)
|
||||||
switch (resource_object.kind) {
|
.then(
|
||||||
case "local": {
|
(events) => Promise.resolve(
|
||||||
result = (
|
events.map(
|
||||||
result
|
|
||||||
.concat(
|
|
||||||
resource_object.data.events
|
|
||||||
.filter(
|
|
||||||
(event : _zeitbild.type.event_object) => _zeitbild.helpers.pit_is_between(
|
|
||||||
_zeitbild.helpers.pit_from_datetime(event.begin),
|
|
||||||
from_pit,
|
|
||||||
to_pit
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.map(
|
|
||||||
(event : _zeitbild.type.event_object) => ({
|
|
||||||
"calendar_id": calendar_id,
|
|
||||||
"event": event,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "caldav": {
|
|
||||||
// TODO readonly
|
|
||||||
const url : lib_plankton.url.type_url = lib_plankton.url.decode(
|
|
||||||
calendar_object.data.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(),
|
|
||||||
{
|
|
||||||
}
|
|
||||||
);
|
|
||||||
result = (
|
|
||||||
result
|
|
||||||
.concat(
|
|
||||||
vcalendar.vevents
|
|
||||||
.map(
|
|
||||||
(vevent : lib_plankton.ical.type_vevent) => (
|
|
||||||
(vevent.dtstart !== undefined)
|
|
||||||
?
|
|
||||||
{
|
|
||||||
"name": (
|
|
||||||
(vevent.summary !== undefined)
|
|
||||||
?
|
|
||||||
vevent.summary
|
|
||||||
:
|
|
||||||
"???"
|
|
||||||
),
|
|
||||||
"begin": _zeitbild.helpers.ical_dt_to_own_datetime(vevent.dtstart),
|
|
||||||
"end": (
|
|
||||||
(vevent.dtend !== undefined)
|
|
||||||
?
|
|
||||||
_zeitbild.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.helpers.pit_is_between(
|
|
||||||
_zeitbild.helpers.pit_from_datetime(event.begin),
|
|
||||||
from_pit,
|
|
||||||
to_pit
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.map(
|
|
||||||
(event) => ({
|
(event) => ({
|
||||||
"calendar_id": calendar_id,
|
"calendar_id": calendar_id,
|
||||||
"event": event,
|
"event": event,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
break;
|
)
|
||||||
}
|
)
|
||||||
default: {
|
.then(
|
||||||
return Promise.reject(
|
(sub_results) => sub_results.reduce(
|
||||||
new Error("invalid resource kind: " + resource_object["kind"])
|
(x, y) => x.concat(y),
|
||||||
);
|
[]
|
||||||
break;
|
)
|
||||||
}
|
)
|
||||||
}
|
);
|
||||||
}
|
|
||||||
return Promise.resolve(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
161
tools/convert
Executable file
161
tools/convert
Executable file
|
@ -0,0 +1,161 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import json as _json
|
||||||
|
import datetime as _datetime
|
||||||
|
|
||||||
|
|
||||||
|
def sql_format(
|
||||||
|
value
|
||||||
|
):
|
||||||
|
if (value is None):
|
||||||
|
return "NULL"
|
||||||
|
else:
|
||||||
|
if (type(value) == bool):
|
||||||
|
return ('TRUE' if value else 'FALSE')
|
||||||
|
elif (type(value) == int):
|
||||||
|
return ("%u" % value)
|
||||||
|
elif (type(value) == str):
|
||||||
|
return ("'%s'" % value)
|
||||||
|
else:
|
||||||
|
raise ValueError("unhandled type: " + str(type(value)))
|
||||||
|
|
||||||
|
|
||||||
|
def string_coin(
|
||||||
|
template,
|
||||||
|
arguments
|
||||||
|
):
|
||||||
|
result = template
|
||||||
|
for (key, value, ) in arguments.items():
|
||||||
|
result = result.replace("{{%s}}" % key, value)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def file_read(
|
||||||
|
path
|
||||||
|
):
|
||||||
|
handle = open(path, "r")
|
||||||
|
content = handle.read()
|
||||||
|
handle.close()
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def datetime_convert(
|
||||||
|
datetime
|
||||||
|
):
|
||||||
|
return (
|
||||||
|
None
|
||||||
|
if
|
||||||
|
(datetime is None)
|
||||||
|
else
|
||||||
|
string_coin(
|
||||||
|
"{{timezone_shift}}|{{year}}-{{month}}-{{day}}{{macro_time}}",
|
||||||
|
{
|
||||||
|
"timezone_shift": ("%02u" % datetime["timezone_shift"]),
|
||||||
|
"year": ("%04u" % datetime["date"]["year"]),
|
||||||
|
"month": ("%02u" % datetime["date"]["month"]),
|
||||||
|
"day": ("%02u" % datetime["date"]["day"]),
|
||||||
|
"macro_time": (
|
||||||
|
""
|
||||||
|
if
|
||||||
|
(datetime["time"] is None)
|
||||||
|
else
|
||||||
|
string_coin(
|
||||||
|
"T{{hour}}:{{minute}}:{{second}}",
|
||||||
|
{
|
||||||
|
"hour": ("%02u" % datetime["time"]["hour"]),
|
||||||
|
"minute": ("%02u" % datetime["time"]["minute"]),
|
||||||
|
"second": ("%02u" % datetime["time"]["second"]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main(
|
||||||
|
):
|
||||||
|
data = _json.loads(file_read("data/example.kal.json"))
|
||||||
|
for user in data["users"]:
|
||||||
|
print(
|
||||||
|
string_coin(
|
||||||
|
"INSERT INTO users(id,name) VALUES ({{id}},{{name}});\n",
|
||||||
|
{
|
||||||
|
"id": sql_format(user["id"]),
|
||||||
|
"name": sql_format(user["object"]["name"]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
ids = {
|
||||||
|
"local_resource": 0,
|
||||||
|
"caldav_resource": 0,
|
||||||
|
}
|
||||||
|
for calendar in data["calendars"]:
|
||||||
|
if (calendar["object"]["kind"] == "concrete"):
|
||||||
|
ids["local_resource"] += 1
|
||||||
|
print(
|
||||||
|
string_coin(
|
||||||
|
"INSERT INTO local_resources(id) VALUES ({{id}});\n",
|
||||||
|
{
|
||||||
|
"id": sql_format(ids["local_resource"])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
for event in calendar["object"]["data"]["events"]:
|
||||||
|
print(
|
||||||
|
string_coin(
|
||||||
|
"INSERT INTO local_resource_events(local_resource_id,name,begin,end,location,description) VALUES ({{local_resource_id}},{{name}},{{begin}},{{end}},{{location}},{{description}});\n",
|
||||||
|
{
|
||||||
|
"local_resource_id": sql_format(ids["local_resource"]),
|
||||||
|
"name": sql_format(event["name"]),
|
||||||
|
"begin": sql_format(datetime_convert(event["begin"])),
|
||||||
|
"end": sql_format(datetime_convert(event["end"])),
|
||||||
|
"location": sql_format(event["location"]),
|
||||||
|
"description": sql_format(event["description"]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
string_coin(
|
||||||
|
"INSERT INTO resources(kind,sub_id) VALUES ({{kind}},{{sub_id}});\n",
|
||||||
|
{
|
||||||
|
"kind": sql_format("local"),
|
||||||
|
"sub_id": sql_format(ids["local_resource"])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif (calendar["object"]["kind"] == "caldav"):
|
||||||
|
ids["caldav_resource"] += 1
|
||||||
|
print(
|
||||||
|
string_coin(
|
||||||
|
"INSERT INTO caldav_resources(id,url,read_only) VALUES ({{id}},{{url}},{{read_only}});\n",
|
||||||
|
{
|
||||||
|
"id": sql_format(ids["caldav_resource"]),
|
||||||
|
"url": sql_format(calendar["object"]["data"]["url"]),
|
||||||
|
"read_only": sql_format(calendar["object"]["data"]["read_only"]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
string_coin(
|
||||||
|
"INSERT INTO resources(kind,sub_id) VALUES ({{kind}},{{sub_id}});\n",
|
||||||
|
{
|
||||||
|
"kind": sql_format("caldav"),
|
||||||
|
"sub_id": sql_format(ids["caldav_resource"])
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise ValueError("invalid")
|
||||||
|
print(
|
||||||
|
string_coin(
|
||||||
|
"INSERT INTO calendars(name,public,resource_id) VALUES ({{name}},{{public}},LAST_INSERT_ROWID());\n",
|
||||||
|
{
|
||||||
|
"name": sql_format(calendar["object"]["data"]["name"]),
|
||||||
|
"public": sql_format(not calendar["object"]["data"]["private"]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
|
@ -33,6 +33,7 @@ ${dir_temp}/zeitbild-unlinked.js: \
|
||||||
${dir_source}/api/actions/meta_ping.ts \
|
${dir_source}/api/actions/meta_ping.ts \
|
||||||
${dir_source}/api/actions/meta_spec.ts \
|
${dir_source}/api/actions/meta_spec.ts \
|
||||||
${dir_source}/api/actions/calendar_list.ts \
|
${dir_source}/api/actions/calendar_list.ts \
|
||||||
|
${dir_source}/api/actions/events.ts \
|
||||||
${dir_source}/api/functions.ts \
|
${dir_source}/api/functions.ts \
|
||||||
${dir_source}/main.ts
|
${dir_source}/main.ts
|
||||||
@ ${cmd_log} "compile …"
|
@ ${cmd_log} "compile …"
|
||||||
|
|
Loading…
Add table
Reference in a new issue