mirror of
https://github.com/ershisan99/flashcards-admin-bot.git
synced 2025-12-16 05:09:25 +00:00
add fastify server, add prepare-data endpoint (working)
This commit is contained in:
@@ -1 +1 @@
|
||||
{"320185869":{"userId":"320185869","name":"Евгений Березкин","availableTime":{"from":10,"to":20},"tgUsername":"breznovic","chatId":320185869},"347996326":{"userId":"347996326","name":"Михаил Польшин","availableTime":{"from":20,"to":30},"tgUsername":"notMikle","chatId":347996326},"384611325":{"userId":"384611325","name":"Бог Бог","availableTime":{"from":40,"to":null},"tgUsername":"GoldDeDennis","chatId":384611325},"398100433":{"userId":"398100433","name":"Sergeev Dmitry","availableTime":{"from":10,"to":20},"tgUsername":"Dmitry_Sergeev_14","chatId":398100433},"453233884":{"userId":"453233884","name":"А Ю","availableTime":{"from":40,"to":null},"tgUsername":"MrUnderSan","chatId":453233884},"519261981":{"userId":"519261981","name":"Береснев Михаил","availableTime":{"from":20,"to":30},"tgUsername":"MikeJ0","chatId":519261981},"547121990":{"userId":"547121990","name":"Пучков Иван Иванович","availableTime":{"from":30,"to":40},"tgUsername":"lvrshn_a","chatId":547121990},"558491754":{"userId":"558491754","name":"Андрей Задорожный","availableTime":{"from":0,"to":10},"tgUsername":"andrei_zadorozhnyi","chatId":558491754},"738507170":{"userId":"738507170","name":"Евгений Нестеренко","availableTime":{"from":20,"to":30},"tgUsername":"EugeneNest","chatId":738507170},"836228560":{"userId":"836228560","name":"Рудакян Илья Арменович","availableTime":{"from":20,"to":30},"tgUsername":"Asap_Alh","chatId":836228560},"950709136":{"userId":"950709136","name":"Лукашевич Евгений","availableTime":{"from":20,"to":30},"tgUsername":"elukas21","chatId":950709136},"1003766210":{"userId":"1003766210","name":"Виталик Кожуров","availableTime":{"from":30,"to":40},"tgUsername":"vitalik_kazhurou","chatId":1003766210}}
|
||||
{"74330176":{"userId":"74330176","name":"Герман Владислав","availableTime":{"from":30,"to":40},"tgUsername":"vladloot","chatId":74330176},"178615283":{"userId":"178615283","name":"Артур Ислакаев","availableTime":{"from":20,"to":30},"tgUsername":"kven_a","chatId":178615283},"212999392":{"userId":"212999392","name":"Листопад Георгий","availableTime":{"from":30,"to":40},"tgUsername":"thencatchfinally","chatId":212999392},"257862776":{"userId":"257862776","name":"Катя Разуева","availableTime":{"from":10,"to":20},"tgUsername":"ekate_25","chatId":257862776},"320185869":{"userId":"320185869","name":"Евгений Березкин","availableTime":{"from":10,"to":20},"tgUsername":"breznovic","chatId":320185869},"484619169":{"userId":"484619169","name":"Владислав Беляев","availableTime":{"from":10,"to":20},"tgUsername":"buladzislau","chatId":484619169},"550022173":{"userId":"550022173","name":"Садов Артем","availableTime":{"from":10,"to":20},"tgUsername":"SadovArtem","chatId":550022173},"855517731":{"userId":"855517731","name":"/add_to_team","availableTime":{"from":30,"to":40},"tgUsername":"go_phase","chatId":855517731},"1111257233":{"userId":"1111257233","name":"Александр Черемных","availableTime":{"from":20,"to":30},"chatId":1111257233},"1534716020":{"userId":"1534716020","name":"Игорь Шаргин","availableTime":{"from":10,"to":20},"tgUsername":"Igor_Shargin","chatId":1534716020}}
|
||||
1
data/data.json
Normal file
1
data/data.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -1 +1 @@
|
||||
[[{"userId":"558491754","name":"Андрей Задорожный","availableTime":{"from":0,"to":10},"tgUsername":"andrei_zadorozhnyi","chatId":558491754},{"userId":"320185869","name":"Евгений Березкин","availableTime":{"from":10,"to":20},"tgUsername":"breznovic","chatId":320185869},{"userId":"398100433","name":"Sergeev Dmitry","availableTime":{"from":10,"to":20},"tgUsername":"Dmitry_Sergeev_14","chatId":398100433}],[{"userId":"347996326","name":"Михаил Польшин","availableTime":{"from":20,"to":30},"tgUsername":"notMikle","chatId":347996326},{"userId":"519261981","name":"Береснев Михаил","availableTime":{"from":20,"to":30},"tgUsername":"MikeJ0","chatId":519261981},{"userId":"738507170","name":"Евгений Нестеренко","availableTime":{"from":20,"to":30},"tgUsername":"EugeneNest","chatId":738507170}],[{"userId":"836228560","name":"Рудакян Илья Арменович","availableTime":{"from":20,"to":30},"tgUsername":"Asap_Alh","chatId":836228560},{"userId":"950709136","name":"Лукашевич Евгений","availableTime":{"from":20,"to":30},"tgUsername":"elukas21","chatId":950709136},{"userId":"547121990","name":"Пучков Иван Иванович","availableTime":{"from":30,"to":40},"tgUsername":"lvrshn_a","chatId":547121990}],[{"userId":"1003766210","name":"Виталик Кожуров","availableTime":{"from":30,"to":40},"tgUsername":"vitalik_kazhurou","chatId":1003766210},{"userId":"384611325","name":"Бог Бог","availableTime":{"from":40,"to":null},"tgUsername":"GoldDeDennis","chatId":384611325},{"userId":"453233884","name":"А Ю","availableTime":{"from":40,"to":null},"tgUsername":"MrUnderSan","chatId":453233884}]]
|
||||
[[{"userId":"257862776","name":"Катя Разуева","availableTime":{"from":10,"to":20},"tgUsername":"ekate_25","chatId":257862776},{"userId":"320185869","name":"Евгений Березкин","availableTime":{"from":10,"to":20},"tgUsername":"breznovic","chatId":320185869},{"userId":"484619169","name":"Владислав Беляев","availableTime":{"from":10,"to":20},"tgUsername":"buladzislau","chatId":484619169}],[{"userId":"550022173","name":"Садов Артем","availableTime":{"from":10,"to":20},"tgUsername":"SadovArtem","chatId":550022173},{"userId":"1534716020","name":"Игорь Шаргин","availableTime":{"from":10,"to":20},"tgUsername":"Igor_Shargin","chatId":1534716020},{"userId":"178615283","name":"Артур Ислакаев","availableTime":{"from":20,"to":30},"tgUsername":"kven_a","chatId":178615283}],[{"userId":"1111257233","name":"Александр Черемных","availableTime":{"from":20,"to":30},"chatId":1111257233},{"userId":"74330176","name":"Герман Владислав","availableTime":{"from":30,"to":40},"tgUsername":"vladloot","chatId":74330176},{"userId":"212999392","name":"Листопад Георгий","availableTime":{"from":30,"to":40},"tgUsername":"thencatchfinally","chatId":212999392}],[{"userId":"855517731","name":"/add_to_team","availableTime":{"from":30,"to":40},"tgUsername":"go_phase","chatId":855517731}]]
|
||||
100
index.js
100
index.js
@@ -1,12 +1,88 @@
|
||||
const data = [
|
||||
[
|
||||
{
|
||||
userId: '257862776',
|
||||
name: 'Катя Разуева',
|
||||
availableTime: { from: 10, to: 20 },
|
||||
tgUsername: 'ekate_25',
|
||||
chatId: 257862776,
|
||||
},
|
||||
{
|
||||
userId: '320185869',
|
||||
name: 'Евгений Березкин',
|
||||
availableTime: { from: 10, to: 20 },
|
||||
tgUsername: 'breznovic',
|
||||
chatId: 320185869,
|
||||
},
|
||||
{
|
||||
userId: '484619169',
|
||||
name: 'Владислав Беляев',
|
||||
availableTime: { from: 10, to: 20 },
|
||||
tgUsername: 'buladzislau',
|
||||
chatId: 484619169,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
userId: '550022173',
|
||||
name: 'Садов Артем',
|
||||
availableTime: { from: 10, to: 20 },
|
||||
tgUsername: 'SadovArtem',
|
||||
chatId: 550022173,
|
||||
},
|
||||
{
|
||||
userId: '1534716020',
|
||||
name: 'Игорь Шаргин',
|
||||
availableTime: { from: 10, to: 20 },
|
||||
tgUsername: 'Igor_Shargin',
|
||||
chatId: 1534716020,
|
||||
},
|
||||
{
|
||||
userId: '178615283',
|
||||
name: 'Артур Ислакаев',
|
||||
availableTime: { from: 20, to: 30 },
|
||||
tgUsername: 'kven_a',
|
||||
chatId: 178615283,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
userId: '1111257233',
|
||||
name: 'Александр Черемных',
|
||||
availableTime: { from: 20, to: 30 },
|
||||
chatId: 1111257233,
|
||||
},
|
||||
{
|
||||
userId: '74330176',
|
||||
name: 'Герман Владислав',
|
||||
availableTime: { from: 30, to: 40 },
|
||||
tgUsername: 'vladloot',
|
||||
chatId: 74330176,
|
||||
},
|
||||
{
|
||||
userId: '212999392',
|
||||
name: 'Листопад Георгий',
|
||||
availableTime: { from: 30, to: 40 },
|
||||
tgUsername: 'thencatchfinally',
|
||||
chatId: 212999392,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
userId: '855517731',
|
||||
name: '/add_to_team',
|
||||
availableTime: { from: 30, to: 40 },
|
||||
tgUsername: 'go_phase',
|
||||
chatId: 855517731,
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
const root = document.getElementById('root');
|
||||
async function getData() {
|
||||
const data1 = await fetch('./groups.json').then((res) => res.json());
|
||||
root.innerHTML = getHtml(data1);
|
||||
}
|
||||
function getHtml(data) {
|
||||
return `<div>${data
|
||||
.map((group) => {
|
||||
return `<table><thead>
|
||||
|
||||
const html = `<div>${data
|
||||
.map((group) => {
|
||||
return `<table><thead>
|
||||
<tr>
|
||||
<th>Имя</th>
|
||||
<th>Время</th>
|
||||
@@ -23,7 +99,7 @@ function getHtml(data) {
|
||||
})
|
||||
.join('')}</tbody>
|
||||
</table>`;
|
||||
})
|
||||
.join('')}</div>`;
|
||||
}
|
||||
getData();
|
||||
})
|
||||
.join('')}</div>`;
|
||||
|
||||
root.innerHTML = html;
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
"typescript": "~5.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node build/src/main.js",
|
||||
"gen": "node build/src/generate-groups.js",
|
||||
"open-html": "npx -y serve",
|
||||
"reset": "node scripts/reset-data.cjs",
|
||||
@@ -45,6 +44,7 @@
|
||||
"author": "Jakub Synowiec <jsynowiec@users.noreply.github.com>",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"fastify": "^4.27.0",
|
||||
"remeda": "^1.33.0",
|
||||
"telegraf": "^4.15.3",
|
||||
"tslib": "~2.6"
|
||||
|
||||
4538
pnpm-lock.yaml
generated
4538
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
49
src/bot/send-group-info.ts
Normal file
49
src/bot/send-group-info.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { UserData } from '../types.js';
|
||||
import { FmtString } from 'telegraf/format';
|
||||
|
||||
export function sendGroupInfo(
|
||||
data: UserData[][],
|
||||
sendMessage: (
|
||||
chatId: number | string,
|
||||
text: string | FmtString,
|
||||
extra?: any,
|
||||
) => void,
|
||||
) {
|
||||
data.forEach((group) => {
|
||||
group.forEach((user, i, arr) => {
|
||||
const otherUsers = group.filter((u) => u.userId !== user.userId);
|
||||
if (otherUsers.length === 0) {
|
||||
sendMessage(user.chatId, 'К сожалению, в твою группу не попал никто.');
|
||||
return;
|
||||
}
|
||||
let message = `Привет, ${user.name}! Твои напарники:\n\n${otherUsers
|
||||
.map(
|
||||
(u) =>
|
||||
`- <a href="tg://user?id=${u.userId}">${u.name}</a> @${
|
||||
u.tgUsername
|
||||
}. Время: ${getAvailableTime(
|
||||
u.availableTime.from,
|
||||
u.availableTime.to,
|
||||
)}`,
|
||||
)
|
||||
.join(' \n')}`;
|
||||
|
||||
if (i === 0) {
|
||||
message +=
|
||||
'\n\nТебя выбрали ответственным(ой) за первоначальную коммуникацию. Создай, пожалуйста, группу в телеграме и пригласи в нее своих напарников.';
|
||||
} else {
|
||||
message += `\n\n${arr[0].name} был(а) выбран(а) ответственным за первоначальную коммуникацию. Он(а) создаст группу в телеграме и пригласит в нее всех участников.`;
|
||||
}
|
||||
sendMessage(user.chatId, message, { parse_mode: 'HTML' });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
161
src/bot/setup-wizard-stage.ts
Normal file
161
src/bot/setup-wizard-stage.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
import { Stage, WizardScene } from 'telegraf/scenes';
|
||||
import { Data, UserData } from '../types.js';
|
||||
import fs from 'fs';
|
||||
|
||||
const superWizard = new WizardScene<any>(
|
||||
'add_to_team_wizard',
|
||||
async (ctx) => {
|
||||
console.log('step 0');
|
||||
|
||||
await ctx.reply(
|
||||
'Введи свое имя и фамилию, пожалуйста. Например, Иван Иванов',
|
||||
);
|
||||
ctx.wizard.state.data = {};
|
||||
return ctx.wizard.next();
|
||||
},
|
||||
async (ctx) => {
|
||||
console.log('step 1');
|
||||
if (ctx.message?.text) {
|
||||
ctx.wizard.state.data.name = ctx.message.text;
|
||||
}
|
||||
await ctx.reply(
|
||||
'Сколько часов ты можешь уделять проекту в среднем в неделю?',
|
||||
{
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{
|
||||
text: 'До 10',
|
||||
callback_data: JSON.stringify({ from: 0, to: 10 }),
|
||||
},
|
||||
{
|
||||
text: '10-20',
|
||||
callback_data: JSON.stringify({ from: 10, to: 20 }),
|
||||
},
|
||||
{
|
||||
text: '20-30',
|
||||
callback_data: JSON.stringify({ from: 20, to: 30 }),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
text: '30-40',
|
||||
callback_data: JSON.stringify({ from: 30, to: 40 }),
|
||||
},
|
||||
{
|
||||
text: 'Более 40',
|
||||
callback_data: JSON.stringify({ from: 40, to: null }),
|
||||
},
|
||||
{
|
||||
text: '< Назад',
|
||||
callback_data: 'back',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
return ctx.wizard.next();
|
||||
},
|
||||
async (ctx) => {
|
||||
if (!ctx.callbackQuery) {
|
||||
await ctx.reply(
|
||||
'Что-то пошло не так, попробуй выбрать один из предложенных вариантов',
|
||||
);
|
||||
return ctx.wizard.selectStep(2);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'back') {
|
||||
console.log('step 2');
|
||||
await ctx.answerCbQuery('back');
|
||||
await ctx.wizard.selectStep(ctx.wizard.cursor - 2);
|
||||
return ctx.wizard.steps[ctx.wizard.cursor](ctx);
|
||||
}
|
||||
const data = JSON.parse(ctx.callbackQuery.data);
|
||||
|
||||
ctx.wizard.state.data.availableTime = data;
|
||||
await ctx.answerCbQuery(
|
||||
`You are willing to dedicate from ${data.from} to ${
|
||||
data.to ?? 'infinity'
|
||||
} hours per week`,
|
||||
);
|
||||
await ctx.reply(
|
||||
`Перепроверь, пожалуйста, все ли верно. Если все верно, нажми "Да", если нет, нажми "Нет" или "< Назад"
|
||||
Имя: ${ctx.wizard.state.data.name}
|
||||
Время: ${data.from} - ${data.to ?? 'infinity'}
|
||||
`,
|
||||
{
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{
|
||||
text: 'Да',
|
||||
callback_data: 'yes',
|
||||
},
|
||||
{
|
||||
text: 'Нет',
|
||||
callback_data: 'no',
|
||||
},
|
||||
{
|
||||
text: '< Назад',
|
||||
callback_data: 'back',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
return ctx.wizard.next();
|
||||
},
|
||||
async (ctx) => {
|
||||
if (!ctx.callbackQuery) {
|
||||
await ctx.reply(
|
||||
'Что-то пошло не так, попробуй выбрать один из предложенных вариантов',
|
||||
);
|
||||
return ctx.wizard.selectStep(3);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'back') {
|
||||
console.log('step 3');
|
||||
await ctx.answerCbQuery('back');
|
||||
await ctx.wizard.selectStep(ctx.wizard.cursor - 2);
|
||||
return ctx.wizard.steps[ctx.wizard.cursor](ctx);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'no') {
|
||||
console.log('step 0');
|
||||
await ctx.answerCbQuery('no');
|
||||
await ctx.wizard.selectStep(0);
|
||||
return ctx.wizard.steps[ctx.wizard.cursor](ctx);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'yes') {
|
||||
console.log('step 4');
|
||||
await ctx.answerCbQuery('yes');
|
||||
const data = ctx.wizard.state.data;
|
||||
const userId = ctx.from?.id;
|
||||
const chatId = ctx.callbackQuery.message.chat.id;
|
||||
const dataWithTgUsername = {
|
||||
...data,
|
||||
tgUsername: ctx.from?.username,
|
||||
chatId,
|
||||
};
|
||||
|
||||
updateData({ userId: userId?.toString() ?? '', ...dataWithTgUsername });
|
||||
await ctx.reply(
|
||||
`Спасибо за регистрацию! Мы свяжемся с тобой в ближайшее время.`,
|
||||
);
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
await ctx.reply(
|
||||
'Что-то пошло не так, попробуй выбрать один из предложенных вариантов',
|
||||
);
|
||||
return ctx.wizard.selectStep(3);
|
||||
},
|
||||
);
|
||||
|
||||
export const stage = new Stage([superWizard]);
|
||||
|
||||
function updateData({ ...rest }: UserData) {
|
||||
const data = fs.readFileSync('./data.json', 'utf8');
|
||||
const dataObj = JSON.parse(data) as Data;
|
||||
dataObj[rest.userId] = rest;
|
||||
const newDataStr = JSON.stringify(dataObj);
|
||||
fs.writeFileSync('./data.json', newDataStr, 'utf8');
|
||||
}
|
||||
162
src/main.ts
162
src/main.ts
@@ -1,9 +1,7 @@
|
||||
import dotenv from 'dotenv';
|
||||
import { session, Telegraf } from 'telegraf';
|
||||
|
||||
import { Stage, WizardScene } from 'telegraf/scenes';
|
||||
import * as fs from 'fs';
|
||||
import { Data, UserData } from './types.js';
|
||||
import { stage } from './bot/setup-wizard-stage.js';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
@@ -13,156 +11,6 @@ if (!BOT_TOKEN) {
|
||||
throw new Error('BOT_TOKEN is required!');
|
||||
}
|
||||
|
||||
const superWizard = new WizardScene<any>(
|
||||
'add_to_team_wizard',
|
||||
async (ctx) => {
|
||||
console.log('step 0');
|
||||
|
||||
await ctx.reply(
|
||||
'Введи свое имя и фамилию, пожалуйста. Например, Иван Иванов',
|
||||
);
|
||||
ctx.wizard.state.data = {};
|
||||
return ctx.wizard.next();
|
||||
},
|
||||
async (ctx) => {
|
||||
console.log('step 1');
|
||||
if (ctx.message?.text) {
|
||||
ctx.wizard.state.data.name = ctx.message.text;
|
||||
}
|
||||
await ctx.reply(
|
||||
'Сколько часов ты можешь уделять проекту в среднем в неделю?',
|
||||
{
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{
|
||||
text: 'До 10',
|
||||
callback_data: JSON.stringify({ from: 0, to: 10 }),
|
||||
},
|
||||
{
|
||||
text: '10-20',
|
||||
callback_data: JSON.stringify({ from: 10, to: 20 }),
|
||||
},
|
||||
{
|
||||
text: '20-30',
|
||||
callback_data: JSON.stringify({ from: 20, to: 30 }),
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
text: '30-40',
|
||||
callback_data: JSON.stringify({ from: 30, to: 40 }),
|
||||
},
|
||||
{
|
||||
text: 'Более 40',
|
||||
callback_data: JSON.stringify({ from: 40, to: null }),
|
||||
},
|
||||
{
|
||||
text: '< Назад',
|
||||
callback_data: 'back',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
return ctx.wizard.next();
|
||||
},
|
||||
async (ctx) => {
|
||||
if (!ctx.callbackQuery) {
|
||||
await ctx.reply(
|
||||
'Что-то пошло не так, попробуй выбрать один из предложенных вариантов',
|
||||
);
|
||||
return ctx.wizard.selectStep(2);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'back') {
|
||||
console.log('step 2');
|
||||
await ctx.answerCbQuery('back');
|
||||
await ctx.wizard.selectStep(ctx.wizard.cursor - 2);
|
||||
return ctx.wizard.steps[ctx.wizard.cursor](ctx);
|
||||
}
|
||||
const data = JSON.parse(ctx.callbackQuery.data);
|
||||
|
||||
ctx.wizard.state.data.availableTime = data;
|
||||
await ctx.answerCbQuery(
|
||||
`You are willing to dedicate from ${data.from} to ${
|
||||
data.to ?? 'infinity'
|
||||
} hours per week`,
|
||||
);
|
||||
await ctx.reply(
|
||||
`Перепроверь, пожалуйста, все ли верно. Если все верно, нажми "Да", если нет, нажми "Нет" или "< Назад"
|
||||
Имя: ${ctx.wizard.state.data.name}
|
||||
Время: ${data.from} - ${data.to ?? 'infinity'}
|
||||
`,
|
||||
{
|
||||
reply_markup: {
|
||||
inline_keyboard: [
|
||||
[
|
||||
{
|
||||
text: 'Да',
|
||||
callback_data: 'yes',
|
||||
},
|
||||
{
|
||||
text: 'Нет',
|
||||
callback_data: 'no',
|
||||
},
|
||||
{
|
||||
text: '< Назад',
|
||||
callback_data: 'back',
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
return ctx.wizard.next();
|
||||
},
|
||||
async (ctx) => {
|
||||
if (!ctx.callbackQuery) {
|
||||
await ctx.reply(
|
||||
'Что-то пошло не так, попробуй выбрать один из предложенных вариантов',
|
||||
);
|
||||
return ctx.wizard.selectStep(3);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'back') {
|
||||
console.log('step 3');
|
||||
await ctx.answerCbQuery('back');
|
||||
await ctx.wizard.selectStep(ctx.wizard.cursor - 2);
|
||||
return ctx.wizard.steps[ctx.wizard.cursor](ctx);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'no') {
|
||||
console.log('step 0');
|
||||
await ctx.answerCbQuery('no');
|
||||
await ctx.wizard.selectStep(0);
|
||||
return ctx.wizard.steps[ctx.wizard.cursor](ctx);
|
||||
}
|
||||
if (ctx.callbackQuery.data === 'yes') {
|
||||
console.log('step 4');
|
||||
await ctx.answerCbQuery('yes');
|
||||
const data = ctx.wizard.state.data;
|
||||
const userId = ctx.from?.id;
|
||||
const chatId = ctx.callbackQuery.message.chat.id;
|
||||
const dataWithTgUsername = {
|
||||
...data,
|
||||
tgUsername: ctx.from?.username,
|
||||
chatId,
|
||||
};
|
||||
|
||||
updateData({ userId: userId?.toString() ?? '', ...dataWithTgUsername });
|
||||
await ctx.reply(
|
||||
`Спасибо за регистрацию! Мы свяжемся с тобой в ближайшее время.`,
|
||||
);
|
||||
return ctx.scene.leave();
|
||||
}
|
||||
await ctx.reply(
|
||||
'Что-то пошло не так, попробуй выбрать один из предложенных вариантов',
|
||||
);
|
||||
return ctx.wizard.selectStep(3);
|
||||
},
|
||||
);
|
||||
|
||||
const stage = new Stage([superWizard]);
|
||||
|
||||
const bot = new Telegraf(BOT_TOKEN);
|
||||
bot.use(session());
|
||||
bot.use(stage.middleware());
|
||||
@@ -175,11 +23,3 @@ void bot.launch();
|
||||
|
||||
process.once('SIGINT', () => bot.stop('SIGINT'));
|
||||
process.once('SIGTERM', () => bot.stop('SIGTERM'));
|
||||
|
||||
function updateData({ ...rest }: UserData) {
|
||||
const data = fs.readFileSync('./data.json', 'utf8');
|
||||
const dataObj = JSON.parse(data) as Data;
|
||||
dataObj[rest.userId] = rest;
|
||||
const newDataStr = JSON.stringify(dataObj);
|
||||
fs.writeFileSync('./data.json', newDataStr, 'utf8');
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import dotenv from 'dotenv';
|
||||
import { Telegraf } from 'telegraf';
|
||||
import * as fs from 'fs';
|
||||
import { UserData } from './types.js';
|
||||
import { sendGroupInfo } from './bot/send-group-info.js';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
@@ -15,46 +16,7 @@ const bot = new Telegraf(BOT_TOKEN);
|
||||
|
||||
const data = fs.readFileSync('./groups.json', 'utf8');
|
||||
const userData = JSON.parse(data) as UserData[][];
|
||||
userData.forEach((group) => {
|
||||
group.forEach((user, i, arr) => {
|
||||
const otherUsers = group.filter((u) => u.userId !== user.userId);
|
||||
if (otherUsers.length === 0) {
|
||||
bot.telegram.sendMessage(
|
||||
user.chatId,
|
||||
'К сожалению, в твою группу не попал никто.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
let message = `Привет, ${user.name}! Твои напарники:\n\n${otherUsers
|
||||
.map(
|
||||
(u) =>
|
||||
`- <a href="tg://user?id=${u.userId}">${u.name}</a> @${
|
||||
u.tgUsername
|
||||
}. Время: ${getAvailableTime(
|
||||
u.availableTime.from,
|
||||
u.availableTime.to,
|
||||
)}`,
|
||||
)
|
||||
.join(' \n')}`;
|
||||
|
||||
if (i === 0) {
|
||||
message +=
|
||||
'\n\nТебя выбрали ответственным(ой) за первоначальную коммуникацию. Создай, пожалуйста, группу в телеграме и пригласи в нее своих напарников.';
|
||||
} else {
|
||||
message += `\n\n${arr[0].name} был(а) выбран(а) ответственным за первоначальную коммуникацию. Он(а) создаст группу в телеграме и пригласит в нее всех участников.`;
|
||||
}
|
||||
bot.telegram.sendMessage(user.chatId, message, { parse_mode: 'HTML' });
|
||||
});
|
||||
});
|
||||
sendGroupInfo(userData, bot.telegram.sendMessage);
|
||||
|
||||
process.once('SIGINT', () => bot.stop('SIGINT'));
|
||||
process.once('SIGTERM', () => bot.stop('SIGTERM'));
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
38
src/server.ts
Normal file
38
src/server.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
// Import the framework and instantiate it
|
||||
import Fastify from 'fastify';
|
||||
import fs from 'fs';
|
||||
import { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import path from 'node:path';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const rootDir = path.join(__dirname, '../..');
|
||||
const dataDir = path.join(rootDir, 'data');
|
||||
|
||||
const fastify = Fastify({
|
||||
logger: true,
|
||||
});
|
||||
|
||||
// Declare a route
|
||||
fastify.get('/', async function handler(request, reply) {
|
||||
return { hello: 'world' };
|
||||
});
|
||||
|
||||
// Declare a route
|
||||
fastify.get('/prepare-db', async function handler(request, reply) {
|
||||
try {
|
||||
fs.writeFileSync(path.join(dataDir, 'data.json'), '{}', 'utf8');
|
||||
return reply.code(200).send('ok');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return reply.code(500).send(err);
|
||||
}
|
||||
});
|
||||
|
||||
// Run the server!
|
||||
try {
|
||||
await fastify.listen({ port: 3000 });
|
||||
} catch (err) {
|
||||
fastify.log.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user