#247 [calendar] ics
This commit is contained in:
parent
a47d7fcfe4
commit
be09e8a3fd
|
@ -21,6 +21,15 @@
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="!day">
|
||||||
|
<p class="mb-0">
|
||||||
|
iCalendar:
|
||||||
|
</p>
|
||||||
|
<a :href="`/api/calendar/queer-calendar-${year.year}.ics`" class="btn btn-outline-primary m-1">
|
||||||
|
<Icon v="calendar-plus"/>
|
||||||
|
ICS
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="mb-0">
|
<p class="mb-0">
|
||||||
<T>calendar.image.header</T>:
|
<T>calendar.image.header</T>:
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"express-session": "^1.17.1",
|
"express-session": "^1.17.1",
|
||||||
"grant": "^5.4.5",
|
"grant": "^5.4.5",
|
||||||
"html-loader": "^1.3.2",
|
"html-loader": "^1.3.2",
|
||||||
|
"ics": "^2.31.0",
|
||||||
"js-base64": "^3.5.2",
|
"js-base64": "^3.5.2",
|
||||||
"js-md5": "^0.7.3",
|
"js-md5": "^0.7.3",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
|
|
|
@ -99,6 +99,7 @@ app.use(require('./routes/names').default);
|
||||||
|
|
||||||
app.use(require('./routes/images').default);
|
app.use(require('./routes/images').default);
|
||||||
app.use(require('./routes/blog').default);
|
app.use(require('./routes/blog').default);
|
||||||
|
app.use(require('./routes/calendar').default);
|
||||||
|
|
||||||
app.use(function (err, req, res, next) {
|
app.use(function (err, req, res, next) {
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { Router } from 'express';
|
||||||
|
import {handleErrorAsync} from "../../src/helpers";
|
||||||
|
import { createEvents } from 'ics';
|
||||||
|
import { calendar } from '../../src/calendar/calendar';
|
||||||
|
import {loadSuml} from "../loader";
|
||||||
|
import { clearLinkedText } from '../../src/helpers';
|
||||||
|
// TODO caching? // import { caches } from "../../src/cache";
|
||||||
|
|
||||||
|
const translations = loadSuml('translations');
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.get('/calendar/queer-calendar-:year.ics', handleErrorAsync(async (req, res) => {
|
||||||
|
const year = calendar.getYear(req.params.year);
|
||||||
|
if (!year) {
|
||||||
|
return res.status(404).json({error: 'Not found'});
|
||||||
|
}
|
||||||
|
const events = year.events
|
||||||
|
.map(e => e.toIcs(req.params.year, translations, clearLinkedText))
|
||||||
|
.filter(e => e !== null);
|
||||||
|
|
||||||
|
createEvents(events, (error, value) => {
|
||||||
|
if (error) {
|
||||||
|
console.error(error);
|
||||||
|
return res.status(500).json({error: 'Unexpected server error'});
|
||||||
|
}
|
||||||
|
|
||||||
|
res.header('Content-type', 'text/calendar');
|
||||||
|
res.send(value);
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default router;
|
|
@ -16,6 +16,10 @@ class Day {
|
||||||
return Day.fromDate(new Date);
|
return Day.fromDate(new Date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toDate() {
|
||||||
|
return new Date(this.year, this.month - 1, this.day);
|
||||||
|
}
|
||||||
|
|
||||||
equals(other) {
|
equals(other) {
|
||||||
return other && this.year === other.year && this.month === other.month && this.day === other.day;
|
return other && this.year === other.year && this.month === other.month && this.day === other.day;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +32,18 @@ class Day {
|
||||||
toInt() {
|
toInt() {
|
||||||
return parseInt(`${this.year}${this.month.toString().padStart(2, '0')}${this.day.toString().padStart(2, '0')}`);
|
return parseInt(`${this.year}${this.month.toString().padStart(2, '0')}${this.day.toString().padStart(2, '0')}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next() {
|
||||||
|
let d = this.toDate();
|
||||||
|
d.setDate(d.getDate() + 1);
|
||||||
|
return Day.fromDate(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev() {
|
||||||
|
let d = this.toDate();
|
||||||
|
d.setDate(d.getDate() - 1);
|
||||||
|
return Day.fromDate(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
module.exports.Day = Day;
|
module.exports.Day = Day;
|
||||||
|
|
||||||
|
@ -60,6 +76,7 @@ module.exports.Event = class {
|
||||||
}
|
}
|
||||||
|
|
||||||
getDays(year) {
|
getDays(year) {
|
||||||
|
year = parseInt(year);
|
||||||
if (this.daysMemoise[year] === undefined) {
|
if (this.daysMemoise[year] === undefined) {
|
||||||
this.daysMemoise[year] = [...this.generator(iterateMonth(year, this.month))];
|
this.daysMemoise[year] = [...this.generator(iterateMonth(year, this.month))];
|
||||||
}
|
}
|
||||||
|
@ -86,6 +103,28 @@ module.exports.Event = class {
|
||||||
isFirstDay(day) {
|
isFirstDay(day) {
|
||||||
return this.getDays(day.year)[0].equals(day);
|
return this.getDays(day.year)[0].equals(day);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toIcs(year, translations, clearLinkedText) {
|
||||||
|
const days = this.getDays(year);
|
||||||
|
const first = days[0];
|
||||||
|
const last = days[days.length - 1].next();
|
||||||
|
|
||||||
|
let [name, param] = this.name.split('$');
|
||||||
|
if (translations.calendar.events[name] !== undefined) {
|
||||||
|
name = translations.calendar.events[name];
|
||||||
|
}
|
||||||
|
if (param) {
|
||||||
|
name = name.replace(/%param%/g, param);
|
||||||
|
}
|
||||||
|
name = clearLinkedText(name);
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: name,
|
||||||
|
start: [first.year, first.month, first.day],
|
||||||
|
end: [last.year, last.month, last.day],
|
||||||
|
calName: translations.calendar.headerLong,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.day = function (dayOfMonth) {
|
module.exports.day = function (dayOfMonth) {
|
||||||
|
|
58
yarn.lock
58
yarn.lock
|
@ -824,6 +824,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.15.4":
|
||||||
|
version "7.15.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
|
||||||
|
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/template@^7.12.13":
|
"@babel/template@^7.12.13":
|
||||||
version "7.12.13"
|
version "7.12.13"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327"
|
||||||
|
@ -1310,6 +1317,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
|
||||||
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
|
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
|
||||||
|
|
||||||
|
"@types/lodash@^4.14.175":
|
||||||
|
version "4.14.176"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.176.tgz#641150fc1cda36fbfa329de603bbb175d7ee20c0"
|
||||||
|
integrity sha512-xZmuPTa3rlZoIbtDUyJKZQimJV3bxCmzMIO2c9Pz9afyDro6kr7R79GwcB6mRhuoPmV2p1Vb66WOJH7F886WKQ==
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "14.14.31"
|
version "14.14.31"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.31.tgz#72286bd33d137aa0d152d47ec7c1762563d34055"
|
||||||
|
@ -5112,6 +5124,14 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3"
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
|
ics@^2.31.0:
|
||||||
|
version "2.31.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ics/-/ics-2.31.0.tgz#4c26b755d017ee64c963cfbaa5ea9766e604ceec"
|
||||||
|
integrity sha512-3pW62uD097nl6LfFXIt92eBZtbwDESXsaRcgZPn3NO01zpUUM+L2G6fjf6qXhiyFcGIrJjsGuNB/y3AV58CvFg==
|
||||||
|
dependencies:
|
||||||
|
nanoid "^3.1.23"
|
||||||
|
yup "^0.32.9"
|
||||||
|
|
||||||
icss-utils@^4.0.0, icss-utils@^4.1.1:
|
icss-utils@^4.0.0, icss-utils@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
|
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
|
||||||
|
@ -5905,6 +5925,11 @@ locate-path@^6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
p-locate "^5.0.0"
|
p-locate "^5.0.0"
|
||||||
|
|
||||||
|
lodash-es@^4.17.21:
|
||||||
|
version "4.17.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||||
|
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||||
|
|
||||||
lodash._reinterpolate@^3.0.0:
|
lodash._reinterpolate@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||||
|
@ -6494,11 +6519,21 @@ nan@^2.12.1, nan@^2.14.0:
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||||
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
||||||
|
|
||||||
|
nanoclone@^0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
|
||||||
|
integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==
|
||||||
|
|
||||||
nanoid@^3.1.20:
|
nanoid@^3.1.20:
|
||||||
version "3.1.20"
|
version "3.1.20"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
|
||||||
integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
|
integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
|
||||||
|
|
||||||
|
nanoid@^3.1.23:
|
||||||
|
version "3.1.30"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362"
|
||||||
|
integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==
|
||||||
|
|
||||||
nanomatch@^1.2.9:
|
nanomatch@^1.2.9:
|
||||||
version "1.2.13"
|
version "1.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||||
|
@ -8111,6 +8146,11 @@ proper-lockfile@^4.1.2:
|
||||||
retry "^0.12.0"
|
retry "^0.12.0"
|
||||||
signal-exit "^3.0.2"
|
signal-exit "^3.0.2"
|
||||||
|
|
||||||
|
property-expr@^2.0.4:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910"
|
||||||
|
integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==
|
||||||
|
|
||||||
protocols@^1.1.0, protocols@^1.4.0:
|
protocols@^1.1.0, protocols@^1.4.0:
|
||||||
version "1.4.8"
|
version "1.4.8"
|
||||||
resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
|
resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
|
||||||
|
@ -9702,6 +9742,11 @@ toidentifier@1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||||
|
|
||||||
|
toposort@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
|
||||||
|
integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
|
||||||
|
|
||||||
totalist@^1.0.0:
|
totalist@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
|
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
|
||||||
|
@ -10571,6 +10616,19 @@ yocto-queue@^0.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||||
|
|
||||||
|
yup@^0.32.9:
|
||||||
|
version "0.32.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"
|
||||||
|
integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.15.4"
|
||||||
|
"@types/lodash" "^4.14.175"
|
||||||
|
lodash "^4.17.21"
|
||||||
|
lodash-es "^4.17.21"
|
||||||
|
nanoclone "^0.2.1"
|
||||||
|
property-expr "^2.0.4"
|
||||||
|
toposort "^2.0.2"
|
||||||
|
|
||||||
zh_cn_zh_tw@^1.0.7:
|
zh_cn_zh_tw@^1.0.7:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/zh_cn_zh_tw/-/zh_cn_zh_tw-1.0.7.tgz#dc6fa59f4964cc2b65e6b4b525771f286890447d"
|
resolved "https://registry.yarnpkg.com/zh_cn_zh_tw/-/zh_cn_zh_tw-1.0.7.tgz#dc6fa59f4964cc2b65e6b4b525771f286890447d"
|
||||||
|
|
Reference in New Issue