1
0
Fork 0
mirror of https://github.com/muerwre/vk-tg-bot.git synced 2025-04-25 15:06:41 +07:00

added calendar service

This commit is contained in:
Fedor Katurov 2024-01-10 21:31:06 +07:00
parent 0b663fb96f
commit 6e34090f8f
31 changed files with 1359 additions and 200 deletions

View file

@ -0,0 +1,16 @@
import { getDayMonthFromText } from "../getDayMonthFromText";
describe("getDayMonthFromText", () => {
const cases = [
{
text:
"Попытка номер два.\n\nСегодня. Старт в 19:32 от ГПНТБ. 80км. Асфальт. Темп бодрый. Две остановки на поесть и передохнуть. Маршрут тот же. Автоматическая отмена поката при граде размером более 0.5см.\n\nhttps://map.vault48.org/04092023_razmyatsya_po_asfaltu",
created: new Date("2023-09-06T04:24:53.000Z"),
expected: [6, 8],
},
];
it.each(cases)("$text", ({ text, created, expected }) => {
expect(getDayMonthFromText(text, created)).toEqual(expected);
});
});

View file

@ -0,0 +1,42 @@
import { getDayMonthFromText } from "./getDayMonthFromText";
import { getTimeFromString } from "./getTimeFromString";
export const getDateFromText = (
val: string,
createdAt: Date
): Date | undefined => {
const text = val.toLowerCase();
const time = getTimeFromString(text);
if (!time) {
return;
}
const dayMonth = getDayMonthFromText(text, createdAt);
if (!dayMonth) {
return;
}
const date = new Date(
createdAt.getFullYear(),
dayMonth[1],
dayMonth[0],
time[0],
time[1]
);
// TODO: handle jan and feb posts from december or november
// if createdAt is december and date is in January or February
// like this:
// if (isBefore(date, createdAt) && differenceInMonths(addYears(date, 1), createdAt) < 3) {
// return addYears(date, 1)
// }
// if (isBefore(date, createdAt)) {
// const diff = differenceInMonths(date, createdAt);
// return diff > 9 && dayMonth[1] >= 10
// ? addYears(date, 1)
// : undefined;
// }
return date;
};

View file

@ -0,0 +1,85 @@
import { addDays } from "date-fns";
const months = [
"янв",
"фев",
"мар",
"апр",
"мая",
"июн",
"июл",
"авг",
"сент",
"октя",
"нояб",
];
type DayMonth = [number, number];
/** Searches for strings like 1 января */
const byText = (val: string): DayMonth | undefined => {
const text = val.toLowerCase();
const match = text.match(
/(\d{1,2})\s?(янв|фев|мар|апр|мая|июн|июл|авг|сент|октя|нояб).*/
);
if (!match?.length) {
return;
}
const day = parseInt(match[1]);
const month = months.indexOf(match[2]);
if (
!Number.isFinite(day) ||
!Number.isFinite(month) ||
day < 0 ||
day > 31 ||
month < 0 ||
month >= months.length
) {
return;
}
return [day, month];
};
const byNumber = (val: string): DayMonth | undefined => {
const text = val.toLowerCase();
const match = text.match(/\b([0-2]?[0-9]|31)\.([1]?[0-2]|0?[0-9])\b/);
if (!match?.length) {
return;
}
const day = parseInt(match[1]);
const month = parseInt(match[2]);
if (
!Number.isFinite(day) ||
!Number.isFinite(month) ||
day < 1 ||
day > 31 ||
month < 1 ||
month > 12
) {
return;
}
return [day, month];
};
const byToday = (val: string, refDate: Date): DayMonth | undefined => {
const text = val.toLowerCase();
if (text.match(/сегодня/)) {
return [refDate.getDate(), refDate.getMonth()];
}
if (text.match(/завтра/)) {
const tomorrow = addDays(refDate, 1);
return [tomorrow.getDate(), tomorrow.getMonth()];
}
return;
};
export const getDayMonthFromText = (val: string, refDate: Date) =>
byText(val) || byNumber(val) || byToday(val, refDate);

View file

@ -0,0 +1,18 @@
export const getTimeFromString = (
val: string
): [number, number] | undefined => {
const matches = val.match(/\b([01]?[0-9]|2[0-3])[:\-]([0-5][0-9])\b/);
if (!matches?.length) {
return;
}
const hours = parseInt(matches[1]);
const minutes = parseInt(matches[2]);
if (hours < 0 || hours > 24 || minutes < 0 || minutes > 60) {
return;
}
return [hours, minutes];
};

View file

@ -0,0 +1,8 @@
import { maybeTrim } from './maybeTrim';
/** Makes summary from first 3 strings of text */
export const getSummaryFromText = (text: string) => {
const match = text.match(/(.*\n?){0,3}/)
return match?.[0] ? maybeTrim(match[0].replace(/\n/gm, ''), 96) : '';
}

View file

@ -0,0 +1 @@
export const maybeTrim = (text: string, maxChars: number) => text.length > maxChars ? `${text.slice(0, maxChars)}...` : text;