Skip to content

Commit 93c2570

Browse files
Add script to convert poems from txt to json
1 parent 639c4da commit 93c2570

File tree

5 files changed

+128
-7
lines changed

5 files changed

+128
-7
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,7 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
3434
.DS_Store
3535

3636
# Persisted app metadata
37-
data/meta.json
37+
data/meta.json
38+
39+
# Scratchpad
40+
scratch.txt

data/poems.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,26 @@
4343
"title": "АРЕСТАНТЫ",
4444
"dedicatedTo": "В. П. Поливанову",
4545
"text": "Много, брат, перенесли\nНа веку с тобою бурь мы.\nПомнишь – в город нас свезли.\nПод конвоем гнали в тюрьмы.\n\nБила ливнем нас гроза.\nИ одежда перемокла.\nШел ты, в даль вперив глаза,\nНеподвижные, как стекла.\n\nЗаковали ноги нам\nВ цепи.\nВспоминали по утрам\nСтепи.\n\nЗа решеткой в голубом\nБыстро ласточки скользили.\nКоротал я время сном\nВ желтых клубах душной пыли.\n\nТы не раз меня будил.\nПриносил нам сторож водки.\nТихий вечер золотил\nОкон ржавые решетки.\n\nКак с убийцей, с босяком,\nС вором,\nРаспевали вечерком\nХором.\n\nЗдесь, на воле, меж степей\nВспомним душные палаты,\nНеумолчный лязг цепей,\nНаши серые халаты.\n\nНе кручинься, брат, о том,\nЧто морщины лоб изрыли.\nВсе забудем: отдохнем –\nЗдесь, в волнах седой ковыли."
46+
},
47+
{
48+
"id": "53cad6d6-c5e8-46ee-b559-7820f2d0f53b",
49+
"author": {
50+
"id": "a32a5d55-95fd-4d47-8e9c-5b50277f3798",
51+
"name": "Андрей Белый"
52+
},
53+
"date": "1917",
54+
"location": "Дедово",
55+
"title": "«Я»",
56+
"text": "В себе, – собой объятый\n(Как мглой небытия), –\nВ себе самом разъятый,\nСветлею светом \"я\".\n\nВ огромном темном мире\nМоя рука растет;\nВ бессолнечные шири\nЯ солнечно простерт, –\n\nИ зрею, зрею зовом:\n\"Воистину воскрес\"\nВ просвете бирюзовом\nЯснеющих небес.\n\nБерезы в вешнем лесе,\nРосея в серебре, –\nПровеяли: \"воскресе\"\nНа розовой заре...\n\n\"Я\" – это Ты, Грядущий\nИз дней во мне – ко мне –\nВ раскинутые кущи\nНад: \"Ты Ecи на не-бе-си!\""
57+
},
58+
{
59+
"id": "93dd8452-1a8e-45e3-881a-16a6da9d7e7a",
60+
"author": {
61+
"id": "a32a5d55-95fd-4d47-8e9c-5b50277f3798",
62+
"name": "Андрей Белый"
63+
},
64+
"title": "«Я». Поется с балалайкой",
65+
"text": "1\n\nЗлое поле мглой\nОдето.\n\nЗлой\nТуман ползет: у ног...\n\nГде-то\nВ поле – без\nОтвета –\n\nМглой\nВ туман – восстонет\nРог: –\n\n – \"Где –\n Вы –\n Духи?\n\n – Где –\n Вы –\n Души?\n\n – Где –\n Ты –\n Бог!\" –\n\n – Лая\n В уши,\n Старым Богом\n Изнемог\n Он. –\n\n\n2\n\nГлухи –\nДухи!..\n\n\n3\n\nМесяц, –\n – Злая\n Рукоять, –\nВ этот час –\nКрасный тать:\n\nОстрым рогом\nИз тумана – там, на нас\nГрозится\nВстать.\n\nЗлое\nПоле –\nНе маячь: –\n – В сердце –\n Плач:\n Сердце, –\n Плачь!..\n\n\n4\n\nОко, –\n – Лопнувший пузырь –\nРазрывай\nВ ночные шири: –\n\nШире,\nШире,\nШире\nШирь –\n – Око –\n – Лопнувший пузырь!\n\n\n5\n\nВ мире, охнувшем\nОт муки –\nРазрывались,\nИскрошились\nПрахом\nСуши:\nИскажались,\nИсказились\nСтрахом\nЛики: –\n – Тише,\n Медленнее ночи\n Без дороги –\n – В мире, охнувшем\n От муки.\n\nВ ухе,\nГлохнувшем\nОт скуки, –\nРаздавались –\n – Строги,\n Глухи,\n Дики\n Крики\n Рога –\n – \"Души,\n Души,\n Души!\"\n \n – \"Боги,\n Боги,\n Боги!\"\n\n – \"Духи,\n Духи,\n Духи!\" –\n\n – Глуше\n Глуше,\n Глуше...\n\n\n6\n\nВремя, –\n – Плещущие\n Воды –\n – Унимай\n Свои праздный скач:\n\nПоднимай, –\n – В пустые годы,\n В пусто блещущие\n Своды –\n – Красный тать –\n Рукоять:\n\n Ты –\n Палач!..\n\n\n7\n\nПусть разматывают нити:\nВ нить событий –\nВплетено\nНебытие!\n\nУтопатывать\nНам\nВ ночи, –\nПротопатывать\nТам\nГоды –\n – Суждено!\n\nВ нить\nСобытий –\nВплетено:\nНебытие!\n\n\n8\n\nОбволакивает очи,\nВ ночь обматывает\nТьмой: –\n – Уволакивает в ночи,\n Приборматывает: –\n – \"Мой!\"\n\nБормочи, ночная прялка:\nМне тебя не превозмочь!\n\nНочь, –\n – Лиловая фиалка, –\n – Вейся\n Шорохом –\n У\n Ног!\n\n\n9\n\nЛейся\nВ ночи\nВихрем клочий\nМногоногий людогон, –\n – Зрея\n В души\n Вея\n В очи: –\n – Вея\n Ворохом\n Времен…"
4666
}
4767
]
4868
}

scripts/txt-to-json.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { readFile, writeFile } from "node:fs/promises";
2+
import { resolve } from "path";
3+
import { randomUUID } from "crypto";
4+
import type { UUID } from "node:crypto";
5+
6+
import type { PoemsCollection } from "../src/poem";
7+
8+
type PoemsFile = PoemsCollection;
9+
type JsonPoem = PoemsCollection["poems"][number];
10+
11+
const AUTHOR_IDS: Record<string, UUID> = {
12+
"Андрей Белый": "a32a5d55-95fd-4d47-8e9c-5b50277f3798",
13+
};
14+
15+
function poemToJson(
16+
poem: string,
17+
{
18+
authorName,
19+
title,
20+
date,
21+
location,
22+
dedicatedTo,
23+
}: {
24+
authorName: string;
25+
title: string;
26+
date?: string;
27+
location?: string;
28+
dedicatedTo?: string;
29+
},
30+
): JsonPoem {
31+
return {
32+
id: randomUUID(),
33+
author: {
34+
id: AUTHOR_IDS[authorName] ?? randomUUID(),
35+
name: authorName,
36+
},
37+
title,
38+
text: poem.trim(),
39+
...(date ? { date } : {}),
40+
...(location ? { location } : {}),
41+
...(dedicatedTo ? { dedicatedTo } : {}),
42+
};
43+
}
44+
45+
async function main() {
46+
const [inputFile, authorName, title, date, location, dedicatedTo] = Bun.argv.slice(2);
47+
48+
if (!inputFile || !authorName || !title) {
49+
console.error("Usage: bun run poem-to-json.ts <poem.txt> <authorName> <title> [date] [location] [dedicatedTo]");
50+
process.exit(1);
51+
}
52+
53+
const filePath = resolve(inputFile);
54+
const poemText = await readFile(filePath, "utf8");
55+
56+
const jsonPoem = poemToJson(poemText, {
57+
authorName,
58+
title,
59+
date,
60+
location,
61+
dedicatedTo,
62+
});
63+
64+
const poemsFilePath = resolve("data/poems.json");
65+
let poemsFile: PoemsFile;
66+
67+
try {
68+
const existing = await readFile(poemsFilePath, "utf8");
69+
poemsFile = JSON.parse(existing);
70+
if (!Array.isArray(poemsFile.poems)) {
71+
throw new TypeError("Invalid poems.json format: missing 'poems' array");
72+
}
73+
} catch {
74+
// If file doesn't exist or is invalid, start fresh
75+
poemsFile = { poems: [] };
76+
}
77+
78+
poemsFile.poems.push(jsonPoem);
79+
80+
await writeFile(poemsFilePath, JSON.stringify(poemsFile, null, 4), "utf8");
81+
82+
console.log(`✅ Poem added to ${poemsFilePath}`);
83+
}
84+
85+
main();

src/main.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import cron from "node-cron";
22
import { Telegraf } from "telegraf";
33

4-
import { getDailyPoem } from "./poems";
4+
import { getDailyPoem, getRandomPoem } from "./poems";
55

66
const BOT_TOKEN = process.env.BOT_TOKEN;
77
const GROUP_ID = process.env.GROUP_ID;
@@ -13,16 +13,16 @@ const bot = new Telegraf(BOT_TOKEN);
1313

1414
// Command to test poems manually
1515
bot.command("poem", async (ctx) => {
16-
const poem = await getDailyPoem();
16+
const poem = getRandomPoem();
1717

1818
if (!poem) {
19-
await ctx.reply("No poem available!");
20-
console.log("Could not find a daily poem to send.");
19+
await ctx.reply("No poems available!");
20+
console.log("Could not find a random poem to send.");
2121
return;
2222
}
2323

2424
await ctx.reply(poem.formatted);
25-
console.log(`Daily poem sent with id: ${poem.id}, author: ${poem.author}, title: ${poem.title}`);
25+
console.log(`Random poem sent with id: ${poem.id}, author: ${poem.author}, title: ${poem.title}`);
2626
});
2727

2828
cron.schedule(
@@ -41,7 +41,7 @@ cron.schedule(
4141
{ timezone: "Europe/Moscow" },
4242
);
4343

44-
await bot.telegram.setMyCommands([{ command: "poem", description: "Get a daily poem" }]);
44+
await bot.telegram.setMyCommands([{ command: "poem", description: "Get a random poem" }]);
4545

4646
bot.launch();
4747
console.log("🚀 Bot started!");

src/poems.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ export const getDailyPoem = async (): Promise<DailyPoem | undefined> => {
6060
};
6161
};
6262

63+
export const getRandomPoem = (): DailyPoem | undefined => {
64+
const randomPoem = poems.at(Math.floor(Math.random() * poems.length));
65+
66+
if (!randomPoem) return;
67+
68+
return {
69+
id: randomPoem.id,
70+
author: randomPoem.author.name,
71+
title: randomPoem.title,
72+
formatted: formatPoem(randomPoem),
73+
};
74+
};
75+
6376
const formatPoem = (poem: JsonPoem) => {
6477
if (poem.dedicatedTo) {
6578
return fmt`

0 commit comments

Comments
 (0)