9 Commits

Author SHA1 Message Date
melod1n 51db4ba9b5 fix using wrong dirs 2026-02-16 20:05:21 +03:00
melod1n c98528a54f fix 2026-02-16 20:00:25 +03:00
melod1n 2f0f10eed9 fix mkdir dirs 2026-02-16 19:57:35 +03:00
melod1n 8bec34413f some code cleanup 2026-02-16 19:52:28 +03:00
melod1n b8b3895310 update openAiGenImage params 2026-02-16 19:52:08 +03:00
melod1n 5b84376dc7 improve cache storage and cleanup (+ recursively) 2026-02-16 19:51:43 +03:00
melod1n 69ae37e05e /ae command now available if specifically set to 2026-02-16 19:50:07 +03:00
melod1n edcc0ddc91 Revert "move to debian-based runtime"
This reverts commit 751a0a1e15.
2026-02-16 16:40:28 +03:00
melod1n 751a0a1e15 move to debian-based runtime 2026-02-16 16:29:38 +03:00
7 changed files with 60 additions and 71 deletions
+6 -9
View File
@@ -2,7 +2,7 @@ import {ChatCommand} from "../base/chat-command";
import {Message} from "typescript-telegram-bot-api";
import {Requirements} from "../base/requirements";
import {Requirement} from "../base/requirement";
import {bot, openAi, photoDir} from "../index";
import {bot, openAi, photoGenDir} from "../index";
import fs from "node:fs";
import path from "node:path";
import {editMessageText, logError, replyToMessage} from "../util/utils";
@@ -27,14 +27,9 @@ export class OpenAIGenImage extends ChatCommand {
try {
const totalParts = 3;
const model = Environment.OPENAI_IMAGE_MODEL;
const size = "1024x1024";
const fileFullName = `${msg.chat.id}_${msg.message_id}.png`;
const getFileLocation = (fn: string) => {
const genRoot = path.join(photoDir, "gen");
if (!fs.existsSync(genRoot)) {
fs.mkdirSync(genRoot);
}
return path.join(genRoot, fn);
return path.join(photoGenDir, fn);
};
waitMessage = await replyToMessage({message: msg, text: "🌈 Генерирую изображение..."});
@@ -43,9 +38,11 @@ export class OpenAIGenImage extends ChatCommand {
model: model,
prompt: prompt,
n: 1,
size: size,
size: "auto",
stream: true,
partial_images: totalParts,
moderation: "low",
output_format: "png",
});
const then = Date.now();
@@ -89,7 +86,7 @@ export class OpenAIGenImage extends ChatCommand {
media: {
type: "photo",
media: imageBuffer,
caption: `🌈 Изображение по запросу "${prompt}" сгенерировано моделью "${model}" размеров ${size} за ${diff}ms`
caption: `🌈 Изображение по запросу "${prompt}" сгенерировано моделью "${model}" размеров ${event.size} за ${diff}ms`
}
});
break;
+3 -9
View File
@@ -12,8 +12,7 @@ import {
getUserAvatar,
logError,
makeDarkGradientBgFancy,
oldReplyToMessage,
oldSendMessage
replyToMessage
} from "../util/utils";
import {Requirements} from "../base/requirements";
import {Requirement} from "../base/requirement";
@@ -50,15 +49,10 @@ export class Quote extends Command {
const chatId = msg.chat.id;
const reply = msg.reply_to_message;
if (!reply) {
await oldReplyToMessage(msg, "Сделай /quote реплаем на сообщение 🙂").catch(logError);
return;
}
try {
const quoteRaw = (msg.quote?.text ?? reply.text ?? reply.caption ?? "").trim();
if (quoteRaw.length === 0) {
await oldReplyToMessage(msg, "Не нашёл в сообщении текста 😢").catch(logError);
await replyToMessage({message: msg, text: "Не нашёл в сообщении текста 😢"}).catch(logError);
return;
}
@@ -76,7 +70,7 @@ export class Quote extends Command {
}).catch(logError);
} catch (e) {
logError(e);
await oldSendMessage(msg, "Не смог собрать цитату 😢").catch(logError);
await replyToMessage({message: msg, text: "Не смог собрать цитату 😢"}).catch(logError);
}
}
}
+4
View File
@@ -19,6 +19,8 @@ export class Environment {
static ONLY_FOR_CREATOR_MODE: boolean;
static ENABLE_UNSAFE_EVAL: boolean;
static ANSWERS: Answers;
static USE_NAMES_IN_PROMPT: boolean;
@@ -65,6 +67,8 @@ export class Environment {
Environment.ONLY_FOR_CREATOR_MODE = ifTrue(process.env.ONLY_FOR_CREATOR_MODE);
Environment.ENABLE_UNSAFE_EVAL = ifTrue(process.env.ENABLE_UNSAFE_EVAL);
Environment.USE_NAMES_IN_PROMPT = ifTrue(process.env.USE_NAMES_IN_PROMPT);
Environment.MAX_PHOTO_SIZE = Number(process.env.MAX_PHOTO_SIZE || "1280");
+18 -12
View File
@@ -4,7 +4,6 @@ import {TelegramBot, User} from "typescript-telegram-bot-api";
import {Command} from "./base/command";
import {
delay,
ignore,
initSystemSpecs,
logError,
processCallbackQuery,
@@ -132,7 +131,6 @@ export const commands: Command[] = [
new Start(),
new Help(),
new Test(),
new Ae(),
new Ignore(),
new Unignore(),
new Ping(),
@@ -168,6 +166,10 @@ export const commands: Command[] = [
new YouTubeDownload()
];
if (Environment.ENABLE_UNSAFE_EVAL) {
commands.push(new Ae());
}
export const callbackCommands: CallbackCommand[] = [
new OllamaCancel()
];
@@ -215,8 +217,10 @@ if (Environment.OPENAI_API_KEY) {
);
}
export const photoDir = path.join(Environment.DATA_PATH, "photo");
export const videoDir = path.join(Environment.DATA_PATH, "video");
export const cacheDir = path.join(Environment.DATA_PATH, "cache");
export const photoDir = path.join(cacheDir, "photo");
export const photoGenDir = path.join(photoDir, "gen");
export const videoDir = path.join(cacheDir, "video");
let isShuttingDown = false;
@@ -246,8 +250,12 @@ async function main() {
`DEFAULT_AI_PROVIDER: ${Environment.DEFAULT_AI_PROVIDER}`
);
fs.mkdir(photoDir, ignore);
fs.mkdir(videoDir, ignore);
const dirsToCheck = [cacheDir, photoDir, photoGenDir, videoDir];
dirsToCheck.forEach(dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
});
const now = new Date();
@@ -256,15 +264,13 @@ async function main() {
midnight.setDate(now.getDate() + 1);
const diff = midnight.getTime() - now.getTime();
console.log("Clearing up videos and photos will be started in " + diff + "ms");
console.log("Clearing up cache will be started in " + diff + "ms");
clearUpFolderFromOldFiles(videoDir);
clearUpFolderFromOldFiles(photoDir);
clearUpFolderFromOldFiles(cacheDir);
delay(diff).then(() => {
setInterval(() => {
console.log("Started clearing up videos and photos");
clearUpFolderFromOldFiles(videoDir);
clearUpFolderFromOldFiles(photoDir);
console.log("Started clearing up cache");
clearUpFolderFromOldFiles(cacheDir);
}, 1000 * 60 * 60 * 24);
});
+18 -15
View File
@@ -2,7 +2,7 @@ import {logError} from "./utils";
import fs from "node:fs";
import path from "node:path";
export function clearUpFolderFromOldFiles(folder: string) {
export function clearUpFolderFromOldFiles(folder: string, recursive = true) {
fs.readdir(folder, (err, files) => {
if (err) {
logError(err);
@@ -11,32 +11,35 @@ export function clearUpFolderFromOldFiles(folder: string) {
const filenamesToDelete: string[] = [];
files.forEach((filename, index) => {
fs.stat(path.join(folder, filename), (err, stats) => {
if (err) {
logError(err);
files.forEach(filename => {
const fullPath = path.join(folder, filename);
try {
const stats = fs.statSync(fullPath);
if (stats.isDirectory() && recursive) {
clearUpFolderFromOldFiles(fullPath, recursive);
} else {
const then = stats.mtime.getTime() / 1000;
const now = Date.now() / 1000;
const diff = Math.abs(now - then);
const moreThanOneDay = diff >= 60 * 60 * 24;
if (moreThanOneDay) {
filenamesToDelete.push(filename);
}
if (index === files.length - 1) {
if (stats.isFile() && moreThanOneDay) {
filenamesToDelete.push(fullPath);
}
}
} catch (e) {
logError(e);
}
});
console.log("filenamesToDelete", filenamesToDelete);
if (filenamesToDelete.length) {
filenamesToDelete.forEach((filename) => {
const fullPath = path.join(folder, filename);
fs.rm(fullPath, (e) => {
fs.rm(filename, (e) => {
if (e) logError(e);
});
});
}
}
}
});
});
});
}
+5 -15
View File
@@ -15,7 +15,7 @@ import {
} from "typescript-telegram-bot-api";
import {Environment} from "../common/environment";
import {TelegramError} from "typescript-telegram-bot-api/dist/errors";
import {bot, botUser, callbackCommands, commands, messageDao, ollama} from "../index";
import {bot, botUser, callbackCommands, commands, messageDao, ollama, photoDir} from "../index";
import os from "os";
import axios from "axios";
import {MessagePart} from "../common/message-part";
@@ -538,12 +538,7 @@ export async function loadImagesIfExists(msg: Message | StoredMessage): Promise<
const maxSize = await mapPhotoSizeToMax(getPhotoMaxSize(msg.photo));
if (maxSize) {
const imagePath = path.join(Environment.DATA_PATH, "photo");
if (!fs.existsSync(imagePath)) {
fs.mkdirSync(imagePath);
}
let imageFilePath = path.join(imagePath, maxSize.unique_file_id + ".jpg");
let imageFilePath = path.join(photoDir, maxSize.unique_file_id + ".jpg");
if (!fs.existsSync(imageFilePath)) {
const res = await axios.get<ArrayBuffer>(maxSize.url, {responseType: "arraybuffer"});
const src = Buffer.from(res.data);
@@ -567,11 +562,6 @@ export async function loadImagesIfExists(msg: Message | StoredMessage): Promise<
export async function loadImagesFromFileIds(sizes: PhotoSize[]): Promise<string[] | null> {
if (!sizes?.length) return null;
const dataPath = path.join(Environment.DATA_PATH, "photo");
if (!fs.existsSync(dataPath)) {
fs.mkdirSync(dataPath);
}
const existing =
sizes.filter(s => fs.existsSync(photoPathByUniqueId(s.file_unique_id)))
.map(s => s.file_unique_id);
@@ -589,7 +579,7 @@ export async function loadImagesFromFileIds(sizes: PhotoSize[]): Promise<string[
const paths = responses.map((res, index) => {
try {
const uniqueFileId = maxSizes[index].unique_file_id;
const imageFilePath = path.join(dataPath, uniqueFileId + ".jpg");
const imageFilePath = path.join(photoDir, uniqueFileId + ".jpg");
const src = Buffer.from(res.data);
fs.writeFileSync(imageFilePath, src);
return uniqueFileId;
@@ -1063,7 +1053,7 @@ async function processAlbum(groupId: string): Promise<string[]> {
}
export function photoPathByUniqueId(uniqueId: string): string {
return path.join(Environment.DATA_PATH, "photo", uniqueId + ".jpg");
return path.join(photoDir, uniqueId + ".jpg");
}
export function getCurrentModel(): string {
@@ -1149,7 +1139,7 @@ export async function processNewMessage(msg: Message): Promise<void> {
logError(e);
}
if ((msg.new_chat_members?.length || 0 > 0)) {
if ((msg.new_chat_members?.length)) {
await bot.sendMessage({chat_id: msg.chat.id, text: randomValue(Environment.ANSWERS.invite)}).catch(logError);
return;
}
+2 -7
View File
@@ -1,7 +1,7 @@
import Innertube, {Platform, Types, Utils} from "youtubei.js";
import fs, {createWriteStream} from "node:fs";
import path from "node:path";
import {Environment} from "../common/environment";
import {videoDir} from "../index";
export function getYouTubeVideoId(url: string): string {
const regex = /(?:(?:youtube\.com|music\.youtube\.com)\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?|shorts|clip)\/|.*[?&]v=)|youtu\.be\/)([^"&?/\s]{11})/i;
@@ -20,12 +20,7 @@ export async function downloadVideoFromYouTube(url: string, targetQuality: strin
try {
const videoId = getYouTubeVideoId(url);
const videoFolder = path.join(Environment.DATA_PATH, "video");
if (!fs.existsSync(videoFolder)) {
fs.mkdirSync(videoFolder);
}
const filePath = path.join(videoFolder, `${videoId}.mp4`);
const filePath = path.join(videoDir, `${videoId}.mp4`);
if (fs.existsSync(filePath)) {
const buffer = Buffer.from(fs.readFileSync(filePath));
return {