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:
parent
0b663fb96f
commit
6e34090f8f
31 changed files with 1359 additions and 200 deletions
16
src/utils/date/__tests__/getDayMonthFromText.test.ts
Normal file
16
src/utils/date/__tests__/getDayMonthFromText.test.ts
Normal 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);
|
||||
});
|
||||
});
|
42
src/utils/date/getDateFromText.ts
Normal file
42
src/utils/date/getDateFromText.ts
Normal 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;
|
||||
};
|
85
src/utils/date/getDayMonthFromText.ts
Normal file
85
src/utils/date/getDayMonthFromText.ts
Normal 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);
|
18
src/utils/date/getTimeFromString.ts
Normal file
18
src/utils/date/getTimeFromString.ts
Normal 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];
|
||||
};
|
8
src/utils/text/getSummaryFromText.ts
Normal file
8
src/utils/text/getSummaryFromText.ts
Normal 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) : '';
|
||||
}
|
1
src/utils/text/maybeTrim.ts
Normal file
1
src/utils/text/maybeTrim.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export const maybeTrim = (text: string, maxChars: number) => text.length > maxChars ? `${text.slice(0, maxChars)}...` : text;
|
Loading…
Add table
Add a link
Reference in a new issue