mirror of
https://github.com/ershisan99/flashcards-admin-bot.git
synced 2025-12-16 20:59:25 +00:00
add basic functionality for frontend, json db
This commit is contained in:
BIN
data/database.db
Normal file
BIN
data/database.db
Normal file
Binary file not shown.
@@ -13,6 +13,10 @@ export const actions = {
|
|||||||
|
|
||||||
fillPreregistered: async () => {
|
fillPreregistered: async () => {
|
||||||
await fetch('http://localhost:3000/fill-preregistered');
|
await fetch('http://localhost:3000/fill-preregistered');
|
||||||
|
},
|
||||||
|
|
||||||
|
sendGroupInfo: async () => {
|
||||||
|
await fetch('http://localhost:3000/send-group-info');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,6 +29,21 @@ export type UserData = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Data = {
|
export type Data = {
|
||||||
rawData: Record<string, UserData>;
|
users: User[];
|
||||||
groups: UserData[][];
|
groups: Group[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type User = {
|
||||||
|
availableFrom: number;
|
||||||
|
availableTo: number;
|
||||||
|
chatId: string;
|
||||||
|
groupId?: any;
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
tgUsername: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Group = {
|
||||||
|
id: number;
|
||||||
|
users: User[];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,10 +11,18 @@
|
|||||||
TableHeader
|
TableHeader
|
||||||
} from '$lib/components/ui/table';
|
} from '$lib/components/ui/table';
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
|
|
||||||
|
function getAvailableTime(from: number, to: number | null) {
|
||||||
|
if (from === 0 && to === 10) return 'До 10 часов';
|
||||||
|
if (from === 10 && to === 20) return '10-20 часов';
|
||||||
|
if (from === 20 && to === 30) return '20-30 часов';
|
||||||
|
if (from === 30 && to === 40) return '30-40 часов';
|
||||||
|
if (from === 40) return 'Более 40 часов';
|
||||||
|
return 'Unknown time';
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<h1 class="mb-4 text-3xl font-bold">Группы</h1>
|
|
||||||
<div class="mb-4 flex items-center gap-6">
|
<div class="mb-4 flex items-center gap-6">
|
||||||
<form method="POST" action="?/prepareDb">
|
<form method="POST" action="?/prepareDb">
|
||||||
<Button type="submit">Подготовить базу данных</Button>
|
<Button type="submit">Подготовить базу данных</Button>
|
||||||
@@ -25,11 +33,13 @@
|
|||||||
<form method="POST" action="?/generateGroups">
|
<form method="POST" action="?/generateGroups">
|
||||||
<Button type="submit">Сгенерировать группы</Button>
|
<Button type="submit">Сгенерировать группы</Button>
|
||||||
</form>
|
</form>
|
||||||
<form>
|
<form method="POST" action="?/sendGroupInfo">
|
||||||
<Button>Отправить информацию в Telegram</Button>
|
<Button type="submit">Отправить информацию в Telegram</Button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{#if Object.keys(data.rawData).length}
|
{#if data.users.length > 0}
|
||||||
|
<h2 class="mb-4 text-3xl font-bold">Зарегистрированные пользователи</h2>
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
@@ -40,11 +50,11 @@
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{#each Object.entries(data.rawData) as [_, user]}
|
{#each data.users as user}
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>{user.name}</TableCell>
|
<TableCell>{user.name}</TableCell>
|
||||||
<TableCell style="width: 200px"
|
<TableCell style="width: 200px"
|
||||||
>{user.availableTime.from} - {user.availableTime.to}</TableCell
|
>{getAvailableTime(user.availableFrom, user.availableTo)}</TableCell
|
||||||
>
|
>
|
||||||
<TableCell style="width: 200px">{user.tgUsername}</TableCell>
|
<TableCell style="width: 200px">{user.tgUsername}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -54,7 +64,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="space-y-10">
|
<div class="space-y-10">
|
||||||
{#each data.groups as group}
|
{#if data.groups.length > 0}
|
||||||
|
<h2 class="mb-4 text-3xl font-bold">Группы</h2>
|
||||||
|
|
||||||
|
{#each data.groups as group (group.id)}
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
@@ -64,17 +77,18 @@
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{#each group as el}
|
{#each group.users as user (user.id)}
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>{el.name}</TableCell>
|
<TableCell>{user.name}</TableCell>
|
||||||
<TableCell style="width: 200px"
|
<TableCell style="width: 200px"
|
||||||
>{el.availableTime.from} - {el.availableTime.to}</TableCell
|
>{getAvailableTime(user.availableFrom, user.availableTo)}</TableCell
|
||||||
>
|
>
|
||||||
<TableCell style="width: 200px">{el.tgUsername}</TableCell>
|
<TableCell style="width: 200px">{user.tgUsername}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{/each}
|
{/each}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
{/each}
|
{/each}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@telegraf/types": "^6.9.1",
|
"@telegraf/types": "^6.9.1",
|
||||||
|
"@types/better-sqlite3": "^7.6.10",
|
||||||
"@types/jest": "~29.5",
|
"@types/jest": "~29.5",
|
||||||
"@types/node": "~20",
|
"@types/node": "~20",
|
||||||
"@typescript-eslint/eslint-plugin": "~6.15",
|
"@typescript-eslint/eslint-plugin": "~6.15",
|
||||||
@@ -44,8 +45,10 @@
|
|||||||
"author": "Jakub Synowiec <jsynowiec@users.noreply.github.com>",
|
"author": "Jakub Synowiec <jsynowiec@users.noreply.github.com>",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"better-sqlite3": "^10.0.0",
|
||||||
"fastify": "^4.27.0",
|
"fastify": "^4.27.0",
|
||||||
"remeda": "^1.33.0",
|
"remeda": "^1.33.0",
|
||||||
|
"sqlite3": "^5.1.7",
|
||||||
"telegraf": "^4.15.3",
|
"telegraf": "^4.15.3",
|
||||||
"tslib": "~2.6"
|
"tslib": "~2.6"
|
||||||
}
|
}
|
||||||
|
|||||||
833
pnpm-lock.yaml
generated
833
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,17 @@
|
|||||||
import { UserData } from '../types.js';
|
|
||||||
import { FmtString } from 'telegraf/format';
|
import { FmtString } from 'telegraf/format';
|
||||||
|
import { Group } from '../db.js';
|
||||||
|
|
||||||
export function sendGroupInfo(
|
export function sendGroupInfo(
|
||||||
data: UserData[][],
|
groups: Group[],
|
||||||
sendMessage: (
|
sendMessage: (
|
||||||
chatId: number | string,
|
chatId: number | string,
|
||||||
text: string | FmtString,
|
text: string | FmtString,
|
||||||
extra?: any,
|
extra?: any,
|
||||||
) => void,
|
) => void,
|
||||||
) {
|
) {
|
||||||
data.forEach((group) => {
|
groups.forEach((group) => {
|
||||||
group.forEach((user, i, arr) => {
|
group.users.forEach((user, i, arr) => {
|
||||||
const otherUsers = group.filter((u) => u.userId !== user.userId);
|
const otherUsers = group.users.filter((u) => u.chatId !== user.chatId);
|
||||||
if (otherUsers.length === 0) {
|
if (otherUsers.length === 0) {
|
||||||
sendMessage(user.chatId, 'К сожалению, в твою группу не попал никто.');
|
sendMessage(user.chatId, 'К сожалению, в твою группу не попал никто.');
|
||||||
return;
|
return;
|
||||||
@@ -19,12 +19,9 @@ export function sendGroupInfo(
|
|||||||
let message = `Привет, ${user.name}! Твои напарники:\n\n${otherUsers
|
let message = `Привет, ${user.name}! Твои напарники:\n\n${otherUsers
|
||||||
.map(
|
.map(
|
||||||
(u) =>
|
(u) =>
|
||||||
`- <a href="tg://user?id=${u.userId}">${u.name}</a> @${
|
`- <a href="tg://user?id=${u.chatId}">${u.name}</a> @${
|
||||||
u.tgUsername
|
u.tgUsername
|
||||||
}. Время: ${getAvailableTime(
|
}. Время: ${getAvailableTime(u.availableFrom, u.availableTo)}`,
|
||||||
u.availableTime.from,
|
|
||||||
u.availableTime.to,
|
|
||||||
)}`,
|
|
||||||
)
|
)
|
||||||
.join(' \n')}`;
|
.join(' \n')}`;
|
||||||
|
|
||||||
|
|||||||
@@ -153,8 +153,11 @@ const superWizard = new WizardScene<any>(
|
|||||||
|
|
||||||
export const stage = new Stage([superWizard]);
|
export const stage = new Stage([superWizard]);
|
||||||
|
|
||||||
async function updateData({ ...rest }: UserData) {
|
async function updateData({ availableTime, ...user }: UserData) {
|
||||||
const data = await db.readData();
|
await db.addUser({
|
||||||
data.rawData[rest.userId] = rest;
|
...user,
|
||||||
await db.writeData(data);
|
availableFrom: availableTime.from,
|
||||||
|
availableTo: availableTime.to,
|
||||||
|
chatId: user.chatId.toString(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
174
src/db.ts
174
src/db.ts
@@ -1,55 +1,149 @@
|
|||||||
import { promises as fsp } from 'node:fs';
|
import Database from 'better-sqlite3';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
|
||||||
export type UserData = {
|
|
||||||
name: string;
|
|
||||||
availableTime: { from: number; to: number | null };
|
|
||||||
tgUsername: string;
|
|
||||||
userId: string;
|
|
||||||
chatId: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Data = {
|
|
||||||
rawData: Record<string, UserData>;
|
|
||||||
groups: UserData[][];
|
|
||||||
};
|
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const rootDir = path.join(__dirname, '../..');
|
const rootDir = path.join(__dirname, '../..');
|
||||||
const dataDir = path.join(rootDir, 'data');
|
const dataDir = path.join(rootDir, 'data');
|
||||||
const dataFilePath = path.join(dataDir, 'data.json');
|
const dbPath = path.join(dataDir, 'database.db');
|
||||||
|
|
||||||
const initialData: Data = {
|
const db = new Database(dbPath);
|
||||||
rawData: {},
|
|
||||||
groups: [],
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT,
|
||||||
|
availableFrom INTEGER,
|
||||||
|
availableTo INTEGER,
|
||||||
|
tgUsername TEXT,
|
||||||
|
chatId TEXT UNIQUE,
|
||||||
|
groupId INTEGER,
|
||||||
|
FOREIGN KEY (groupId) REFERENCES groups(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS groups (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
availableFrom: number;
|
||||||
|
availableTo: number;
|
||||||
|
tgUsername: string;
|
||||||
|
chatId: string;
|
||||||
|
groupId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateUserParams = Omit<User, 'id'>;
|
||||||
|
|
||||||
|
export interface Group {
|
||||||
|
id: number;
|
||||||
|
users: User[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearDatabase = async (): Promise<void> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
// const stmt = db.prepare('DELETE FROM users');
|
||||||
|
// stmt.run();
|
||||||
|
const stmt2 = db.prepare('DELETE FROM groups');
|
||||||
|
stmt2.run();
|
||||||
|
resolve();
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function readData(): Promise<Data> {
|
const getUsers = async (): Promise<User[]> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const data = await fsp.readFile(dataFilePath, 'utf-8');
|
const stmt = db.prepare('SELECT * FROM users');
|
||||||
return JSON.parse(data);
|
const users = stmt.all() as User[];
|
||||||
|
resolve(users);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 'ENOENT') {
|
reject(error);
|
||||||
try {
|
|
||||||
await writeData(initialData);
|
|
||||||
return initialData;
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
throw error;
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function writeData(data: Data): Promise<void> {
|
const getGroups = async (): Promise<Group[]> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const jsonData = JSON.stringify(data, null, 2);
|
const stmt = db.prepare('SELECT * FROM groups');
|
||||||
await fsp.writeFile(dataFilePath, jsonData, 'utf-8');
|
const groups = stmt.all() as { id: number }[];
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { readData, writeData, initialData };
|
const groupsWithUsers = groups.map((group) => {
|
||||||
|
const usersStmt = db.prepare('SELECT * FROM users WHERE groupId = ?');
|
||||||
|
const users = usersStmt.all(group.id) as User[];
|
||||||
|
return { id: group.id, users };
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve(groupsWithUsers);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const addUser = async (user: CreateUserParams): Promise<void> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const stmt = db.prepare(`
|
||||||
|
INSERT INTO users (name, availableFrom, availableTo, tgUsername, chatId)
|
||||||
|
VALUES (@name, @availableFrom, @availableTo, @tgUsername, @chatId)
|
||||||
|
`);
|
||||||
|
stmt.run(user);
|
||||||
|
resolve();
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const modifyUser = async (groupId: number, id: number): Promise<void> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const stmt = db.prepare(`
|
||||||
|
UPDATE users
|
||||||
|
SET groupId = @groupId
|
||||||
|
WHERE id = @id
|
||||||
|
`);
|
||||||
|
stmt.run({ groupId, id });
|
||||||
|
resolve();
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const addGroup = async (userIds: string[]): Promise<void> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const insertGroupStmt = db.prepare('INSERT INTO groups DEFAULT VALUES');
|
||||||
|
const result = insertGroupStmt.run();
|
||||||
|
const groupId = result.lastInsertRowid as number;
|
||||||
|
|
||||||
|
const updateUserStmt = db.prepare(
|
||||||
|
'UPDATE users SET groupId = ? WHERE id = ?',
|
||||||
|
);
|
||||||
|
const transaction = db.transaction(
|
||||||
|
(userIds: string[], groupId: number) => {
|
||||||
|
for (const userId of userIds) {
|
||||||
|
updateUserStmt.run(groupId, userId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
transaction(userIds, groupId);
|
||||||
|
resolve();
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getUsers, getGroups, addUser, addGroup, clearDatabase, modifyUser };
|
||||||
|
export default db;
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import { Data, UserData } from './types.js';
|
|
||||||
|
|
||||||
generateGroups();
|
|
||||||
|
|
||||||
function generateGroups() {
|
|
||||||
const data = fs.readFileSync('./data.json', 'utf8');
|
|
||||||
const dataObj = JSON.parse(data) as Data;
|
|
||||||
const groupedUsers = groupByTime(dataObj.rawData);
|
|
||||||
fs.writeFileSync('./groups.json', JSON.stringify(groupedUsers), 'utf8');
|
|
||||||
generateJsFile(groupedUsers);
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateJsFile(users: UserData[][]) {
|
|
||||||
const template = fs.readFileSync('./index.js.template', 'utf8');
|
|
||||||
const usersString = JSON.stringify(users);
|
|
||||||
const jsFile = template.replace('/* USERS */', usersString);
|
|
||||||
|
|
||||||
fs.writeFileSync('./index.js', jsFile, 'utf8');
|
|
||||||
}
|
|
||||||
|
|
||||||
function groupByTime(users: Record<string, UserData>): UserData[][] {
|
|
||||||
const allUsers = Object.values(users);
|
|
||||||
|
|
||||||
// First, sort all users by their available time from low to high
|
|
||||||
allUsers.sort((a, b) => a.availableTime.from - b.availableTime.from);
|
|
||||||
|
|
||||||
const groups: UserData[][] = [];
|
|
||||||
let currentGroup: UserData[] = [];
|
|
||||||
|
|
||||||
allUsers.forEach((user) => {
|
|
||||||
currentGroup.push(user);
|
|
||||||
|
|
||||||
// If the current group reaches 3 members, start a new group
|
|
||||||
if (currentGroup.length === 3) {
|
|
||||||
groups.push(currentGroup);
|
|
||||||
currentGroup = []; // Reset for next group
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add the last group if it has less than 3 members and is not empty
|
|
||||||
if (currentGroup.length > 0) {
|
|
||||||
groups.push(currentGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,19 @@
|
|||||||
import { UserData } from '../types.js';
|
import { User } from '../db.js';
|
||||||
|
|
||||||
export function groupByTime(users: Record<string, UserData>): UserData[][] {
|
|
||||||
const allUsers = Object.values(users);
|
|
||||||
|
|
||||||
|
export function groupByTime(users: User[]): User[][] {
|
||||||
// First, sort all users by their available time from low to high
|
// First, sort all users by their available time from low to high
|
||||||
allUsers.sort((a, b) => a.availableTime.from - b.availableTime.from);
|
users.sort((a, b) => a.availableFrom - b.availableFrom);
|
||||||
|
|
||||||
const groups: UserData[][] = [];
|
const groups: User[][] = [];
|
||||||
let currentGroup: UserData[] = [];
|
let currentGroup: User[] = [];
|
||||||
|
|
||||||
allUsers.forEach((user) => {
|
if (users.length % 3 === 1) {
|
||||||
|
const lastGroup = [users.at(-1), users.at(-2)];
|
||||||
|
groups.push(lastGroup);
|
||||||
|
users = users.slice(0, -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
users.forEach((user) => {
|
||||||
currentGroup.push(user);
|
currentGroup.push(user);
|
||||||
|
|
||||||
// If the current group reaches 3 members, start a new group
|
// If the current group reaches 3 members, start a new group
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const bot = new Telegraf(BOT_TOKEN);
|
|||||||
|
|
||||||
const data = fs.readFileSync('./groups.json', 'utf8');
|
const data = fs.readFileSync('./groups.json', 'utf8');
|
||||||
const userData = JSON.parse(data) as UserData[][];
|
const userData = JSON.parse(data) as UserData[][];
|
||||||
sendGroupInfo(userData, bot.telegram.sendMessage);
|
// sendGroupInfo(userData, bot.telegram.sendMessage);
|
||||||
|
|
||||||
process.once('SIGINT', () => bot.stop('SIGINT'));
|
process.once('SIGINT', () => bot.stop('SIGINT'));
|
||||||
process.once('SIGTERM', () => bot.stop('SIGTERM'));
|
process.once('SIGTERM', () => bot.stop('SIGTERM'));
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { session, Telegraf } from 'telegraf';
|
|||||||
import { stage } from './bot/setup-wizard-stage.js';
|
import { stage } from './bot/setup-wizard-stage.js';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { sendGroupInfo } from './bot/send-group-info.js';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const rootDir = path.join(__dirname, '../..');
|
const rootDir = path.join(__dirname, '../..');
|
||||||
@@ -37,12 +38,14 @@ const fastify = Fastify({
|
|||||||
});
|
});
|
||||||
|
|
||||||
fastify.get('/', async function handler(request, reply) {
|
fastify.get('/', async function handler(request, reply) {
|
||||||
return await db.readData();
|
const users = await db.getUsers();
|
||||||
|
const groups = await db.getGroups();
|
||||||
|
return reply.code(200).send({ users, groups });
|
||||||
});
|
});
|
||||||
|
|
||||||
fastify.get('/prepare-db', async function handler(request, reply) {
|
fastify.get('/prepare-db', async function handler(request, reply) {
|
||||||
try {
|
try {
|
||||||
await db.writeData(db.initialData);
|
await db.clearDatabase();
|
||||||
return reply.code(200).send();
|
return reply.code(200).send();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -52,9 +55,12 @@ fastify.get('/prepare-db', async function handler(request, reply) {
|
|||||||
|
|
||||||
fastify.get('/generate-groups', async function handler(request, reply) {
|
fastify.get('/generate-groups', async function handler(request, reply) {
|
||||||
try {
|
try {
|
||||||
const data = await db.readData();
|
const users = await db.getUsers();
|
||||||
data.groups = groupByTime(data.rawData);
|
const groups = groupByTime(users);
|
||||||
await db.writeData(data);
|
|
||||||
|
for (const group of groups) {
|
||||||
|
await db.addGroup(group.map((user) => user.id));
|
||||||
|
}
|
||||||
return reply.code(200).send();
|
return reply.code(200).send();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -68,8 +74,22 @@ fastify.get('/fill-preregistered', async function handler(request, reply) {
|
|||||||
preregisteredFilePath,
|
preregisteredFilePath,
|
||||||
'utf-8',
|
'utf-8',
|
||||||
);
|
);
|
||||||
const parsedPreregisteredData = JSON.parse(preregisteredData);
|
const parsedPreregisteredData = JSON.parse(
|
||||||
await db.writeData(parsedPreregisteredData);
|
preregisteredData,
|
||||||
|
) as Preregistered;
|
||||||
|
for (const user of Object.values(parsedPreregisteredData.rawData)) {
|
||||||
|
try {
|
||||||
|
await db.addUser({
|
||||||
|
chatId: user.chatId.toString(),
|
||||||
|
name: user.name,
|
||||||
|
availableFrom: user.availableTime.from,
|
||||||
|
availableTo: user.availableTime.to,
|
||||||
|
tgUsername: user.tgUsername,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
return reply.code(200).send();
|
return reply.code(200).send();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -77,6 +97,27 @@ fastify.get('/fill-preregistered', async function handler(request, reply) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fastify.get('/send-group-info', async function handler(request, reply) {
|
||||||
|
try {
|
||||||
|
const groups = await db.getGroups();
|
||||||
|
sendGroupInfo(groups, (...rest) => bot.telegram.sendMessage(...rest));
|
||||||
|
return reply.code(200).send();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return reply.code(500).send(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get('/fix', async (req, reply) => {
|
||||||
|
try {
|
||||||
|
await db.modifyUser(4, 14);
|
||||||
|
|
||||||
|
return reply.code(200).send();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return reply.code(500).send(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
void bot.launch();
|
void bot.launch();
|
||||||
|
|
||||||
process.once('SIGINT', () => bot.stop('SIGINT'));
|
process.once('SIGINT', () => bot.stop('SIGINT'));
|
||||||
@@ -89,3 +130,23 @@ try {
|
|||||||
fastify.log.error(err);
|
fastify.log.error(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AvailableTime = {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PUser = {
|
||||||
|
name: string;
|
||||||
|
availableTime: AvailableTime;
|
||||||
|
tgUsername: string;
|
||||||
|
chatId: number;
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RawData = Record<string, PUser>;
|
||||||
|
|
||||||
|
export type Preregistered = {
|
||||||
|
rawData: RawData;
|
||||||
|
groups: any[];
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user